From fdf9614ba793a023d9b6c0f6a078beded8143771 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 12 Feb 2021 15:01:09 +0100 Subject: build: move "libnm-core/" to "src/" and split it "libnm-core/" is rather complicated. It provides a static library that is linked into libnm.so and NetworkManager. It also contains public headers (like "nm-setting.h") which are part of public libnm API. Then we have helper libraries ("libnm-core/nm-libnm-core-*/") which only rely on public API of libnm-core, but are themself static libraries that can be used by anybody who uses libnm-core. And "libnm-core/nm-libnm-core-intern" is used by libnm-core itself. Move "libnm-core/" to "src/". But also split it in different directories so that they have a clearer purpose. The goal is to have a flat directory hierarchy. The "src/libnm-core*/" directories correspond to the different modules (static libraries and set of headers that we have). We have different kinds of such modules because of how we combine various code together. The directory layout now reflects this. --- .gitignore | 33 +- Makefile.am | 1020 +- Makefile.examples | 14 +- clients/cli/general.c | 2 +- clients/cli/meson.build | 10 +- clients/cli/settings.c | 2 +- clients/cloud-setup/main.c | 2 +- clients/cloud-setup/meson.build | 6 +- clients/cloud-setup/tests/meson.build | 3 +- .../cloud-setup/tests/test-cloud-setup-general.c | 2 +- clients/common/meson.build | 2 +- clients/common/nm-client-utils.h | 2 +- clients/common/nm-meta-setting-desc.c | 6 +- clients/common/nm-polkit-listener.c | 2 +- clients/common/tests/meson.build | 7 +- clients/common/tests/test-libnm-core-aux.c | 4 +- clients/meson.build | 1 + clients/tui/meson.build | 4 + clients/tui/nmt-mac-entry.c | 2 +- clients/tui/nmt-page-bond.c | 2 +- configure.ac | 2 +- dispatcher/meson.build | 3 +- dispatcher/nm-dispatcher-utils.c | 2 +- dispatcher/nm-dispatcher.c | 2 +- dispatcher/tests/meson.build | 2 +- dispatcher/tests/test-dispatcher-envp.c | 2 +- docs/api/Makefile.am | 4 +- docs/api/network-manager-docs.xml | 4 +- docs/libnm/Makefile.am | 16 +- docs/libnm/meson.build | 10 +- examples/C/qt/meson.build | 16 +- libnm-core/meson.build | 280 - libnm-core/nm-connection-private.h | 40 - libnm-core/nm-connection.c | 3391 ------ libnm-core/nm-connection.h | 224 - libnm-core/nm-core-internal.h | 930 -- libnm-core/nm-core-types-internal.h | 23 - libnm-core/nm-core-types.h | 73 - libnm-core/nm-crypto-gnutls.c | 415 - libnm-core/nm-crypto-impl.h | 53 - libnm-core/nm-crypto-nss.c | 548 - libnm-core/nm-crypto.c | 1084 -- libnm-core/nm-crypto.h | 107 - libnm-core/nm-dbus-interface.h | 1284 --- libnm-core/nm-dbus-utils.c | 259 - libnm-core/nm-default-libnm-core.h | 22 - libnm-core/nm-errors.c | 55 - libnm-core/nm-errors.h | 319 - libnm-core/nm-keyfile-internal.h | 124 - libnm-core/nm-keyfile-utils.c | 684 -- libnm-core/nm-keyfile-utils.h | 95 - libnm-core/nm-keyfile.c | 4443 -------- libnm-core/nm-keyfile.h | 165 - libnm-core/nm-libnm-core-aux/README.md | 21 - libnm-core/nm-libnm-core-aux/nm-dispatcher-api.h | 45 - libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.c | 436 - libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.h | 38 - libnm-core/nm-libnm-core-intern/README.md | 21 - libnm-core/nm-libnm-core-intern/nm-auth-subject.c | 468 - libnm-core/nm-libnm-core-intern/nm-auth-subject.h | 59 - libnm-core/nm-libnm-core-intern/nm-common-macros.h | 65 - .../nm-libnm-core-intern/nm-libnm-core-utils.c | 387 - .../nm-libnm-core-intern/nm-libnm-core-utils.h | 162 - libnm-core/nm-meta-setting-base-impl.c | 641 -- libnm-core/nm-meta-setting-base-impl.h | 187 - libnm-core/nm-meta-setting-base.h | 10 - libnm-core/nm-property-compare.c | 136 - libnm-core/nm-property-compare.h | 16 - libnm-core/nm-setting-6lowpan.c | 228 - libnm-core/nm-setting-6lowpan.h | 44 - libnm-core/nm-setting-8021x.c | 4683 -------- libnm-core/nm-setting-8021x.h | 366 - libnm-core/nm-setting-adsl.c | 439 - libnm-core/nm-setting-adsl.h | 73 - libnm-core/nm-setting-bluetooth.c | 332 - libnm-core/nm-setting-bluetooth.h | 82 - libnm-core/nm-setting-bond.c | 1185 --- libnm-core/nm-setting-bond.h | 99 - libnm-core/nm-setting-bridge-port.c | 589 - libnm-core/nm-setting-bridge-port.h | 80 - libnm-core/nm-setting-bridge.c | 2292 ---- libnm-core/nm-setting-bridge.h | 183 - libnm-core/nm-setting-cdma.c | 358 - libnm-core/nm-setting-cdma.h | 65 - libnm-core/nm-setting-connection.c | 2529 ----- libnm-core/nm-setting-connection.h | 219 - libnm-core/nm-setting-dcb.c | 1281 --- libnm-core/nm-setting-dcb.h | 146 - libnm-core/nm-setting-dummy.c | 66 - libnm-core/nm-setting-dummy.h | 52 - libnm-core/nm-setting-ethtool.c | 378 - libnm-core/nm-setting-ethtool.h | 70 - libnm-core/nm-setting-generic.c | 62 - libnm-core/nm-setting-generic.h | 52 - libnm-core/nm-setting-gsm.c | 868 -- libnm-core/nm-setting-gsm.h | 93 - libnm-core/nm-setting-hostname.c | 339 - libnm-core/nm-setting-hostname.h | 53 - libnm-core/nm-setting-infiniband.c | 521 - libnm-core/nm-setting-infiniband.h | 66 - libnm-core/nm-setting-ip-config.c | 6284 ----------- libnm-core/nm-setting-ip-config.h | 494 - libnm-core/nm-setting-ip-tunnel.c | 867 -- libnm-core/nm-setting-ip-tunnel.h | 122 - libnm-core/nm-setting-ip4-config.c | 1033 -- libnm-core/nm-setting-ip4-config.h | 109 - libnm-core/nm-setting-ip6-config.c | 1085 -- libnm-core/nm-setting-ip6-config.h | 174 - libnm-core/nm-setting-macsec.c | 671 -- libnm-core/nm-setting-macsec.h | 118 - libnm-core/nm-setting-macvlan.c | 332 - libnm-core/nm-setting-macvlan.h | 87 - libnm-core/nm-setting-match.c | 899 -- libnm-core/nm-setting-match.h | 107 - libnm-core/nm-setting-olpc-mesh.c | 274 - libnm-core/nm-setting-olpc-mesh.h | 61 - libnm-core/nm-setting-ovs-bridge.c | 374 - libnm-core/nm-setting-ovs-bridge.h | 57 - libnm-core/nm-setting-ovs-dpdk.c | 152 - libnm-core/nm-setting-ovs-dpdk.h | 44 - libnm-core/nm-setting-ovs-external-ids.c | 551 - libnm-core/nm-setting-ovs-external-ids.h | 68 - libnm-core/nm-setting-ovs-interface.c | 427 - libnm-core/nm-setting-ovs-interface.h | 47 - libnm-core/nm-setting-ovs-patch.c | 188 - libnm-core/nm-setting-ovs-patch.h | 44 - libnm-core/nm-setting-ovs-port.c | 467 - libnm-core/nm-setting-ovs-port.h | 59 - libnm-core/nm-setting-ppp.c | 778 -- libnm-core/nm-setting-ppp.h | 88 - libnm-core/nm-setting-pppoe.c | 358 - libnm-core/nm-setting-pppoe.h | 64 - libnm-core/nm-setting-private.h | 184 - libnm-core/nm-setting-proxy.c | 383 - libnm-core/nm-setting-proxy.h | 80 - libnm-core/nm-setting-serial.c | 336 - libnm-core/nm-setting-serial.h | 77 - libnm-core/nm-setting-sriov.c | 1372 --- libnm-core/nm-setting-sriov.h | 118 - libnm-core/nm-setting-tc-config.c | 1863 ---- libnm-core/nm-setting-tc-config.h | 162 - libnm-core/nm-setting-team-port.c | 685 -- libnm-core/nm-setting-team-port.h | 89 - libnm-core/nm-setting-team.c | 1818 ---- libnm-core/nm-setting-team.h | 226 - libnm-core/nm-setting-tun.c | 397 - libnm-core/nm-setting-tun.h | 85 - libnm-core/nm-setting-user.c | 594 -- libnm-core/nm-setting-user.h | 55 - libnm-core/nm-setting-veth.c | 194 - libnm-core/nm-setting-veth.h | 41 - libnm-core/nm-setting-vlan.c | 983 -- libnm-core/nm-setting-vlan.h | 134 - libnm-core/nm-setting-vpn.c | 1233 --- libnm-core/nm-setting-vpn.h | 90 - libnm-core/nm-setting-vrf.c | 164 - libnm-core/nm-setting-vrf.h | 38 - libnm-core/nm-setting-vxlan.c | 816 -- libnm-core/nm-setting-vxlan.h | 101 - libnm-core/nm-setting-wifi-p2p.c | 304 - libnm-core/nm-setting-wifi-p2p.h | 59 - libnm-core/nm-setting-wimax.c | 255 - libnm-core/nm-setting-wimax.h | 60 - libnm-core/nm-setting-wired.c | 1647 --- libnm-core/nm-setting-wired.h | 142 - libnm-core/nm-setting-wireguard.c | 2591 ----- libnm-core/nm-setting-wireguard.h | 202 - libnm-core/nm-setting-wireless-security.c | 1967 ---- libnm-core/nm-setting-wireless-security.h | 239 - libnm-core/nm-setting-wireless.c | 1932 ---- libnm-core/nm-setting-wireless.h | 216 - libnm-core/nm-setting-wpan.c | 393 - libnm-core/nm-setting-wpan.h | 57 - libnm-core/nm-setting.c | 2834 ----- libnm-core/nm-setting.h | 353 - libnm-core/nm-simple-connection.c | 152 - libnm-core/nm-simple-connection.h | 52 - libnm-core/nm-team-utils.c | 2866 ----- libnm-core/nm-team-utils.h | 271 - libnm-core/nm-utils-private.h | 61 - libnm-core/nm-utils.c | 6056 ----------- libnm-core/nm-utils.h | 259 - libnm-core/nm-version-macros.h.in | 91 - libnm-core/nm-version.h | 301 - libnm-core/nm-vpn-dbus-interface.h | 302 - libnm-core/nm-vpn-editor-plugin.c | 518 - libnm-core/nm-vpn-editor-plugin.h | 159 - libnm-core/nm-vpn-plugin-info.c | 1354 --- libnm-core/nm-vpn-plugin-info.h | 105 - libnm-core/tests/certs/ca-no-ending-newline.pem | 15 - libnm-core/tests/certs/pkcs8-decrypted.der | Bin 1194 -> 0 bytes libnm-core/tests/certs/pkcs8-enc-key.pem | 29 - libnm-core/tests/certs/pkcs8-noenc-key.pem | 28 - libnm-core/tests/certs/test-aes-128-key.pem | 30 - libnm-core/tests/certs/test-aes-256-key.pem | 54 - libnm-core/tests/certs/test-ca-cert.pem | 27 - libnm-core/tests/certs/test-cert.p12 | Bin 4092 -> 0 bytes libnm-core/tests/certs/test-key-and-cert.pem | 118 - libnm-core/tests/certs/test-key-only-decrypted.der | Bin 1192 -> 0 bytes libnm-core/tests/certs/test-key-only-decrypted.pem | 27 - libnm-core/tests/certs/test-key-only.pem | 92 - libnm-core/tests/certs/test-tpm2wrapped-key.pem | 14 - libnm-core/tests/certs/test2-cert.p12 | Bin 4136 -> 0 bytes libnm-core/tests/certs/test2_ca_cert.pem | 27 - libnm-core/tests/certs/test2_key_and_cert.pem | 119 - libnm-core/tests/certs/test_ca_cert.der | Bin 1162 -> 0 bytes libnm-core/tests/certs/test_ca_cert.pem | 27 - libnm-core/tests/certs/test_key_and_cert.pem | 119 - libnm-core/tests/meson.build | 41 - .../tests/nm-core-tests-enum-types.c.template | 35 - .../tests/nm-core-tests-enum-types.h.template | 21 - libnm-core/tests/test-compare.c | 231 - libnm-core/tests/test-crypto.c | 455 - libnm-core/tests/test-general-enums.h | 35 - libnm-core/tests/test-general.c | 10654 ------------------- libnm-core/tests/test-keyfile.c | 909 -- libnm-core/tests/test-secrets.c | 681 -- libnm-core/tests/test-setting.c | 4356 -------- libnm-core/tests/test-settings-defaults.c | 109 - libnm/meson.build | 26 +- libnm/nm-active-connection.c | 2 +- libnm/nm-checkpoint.c | 2 +- libnm/nm-client.c | 4 +- libnm/nm-device-bond.c | 2 +- libnm/nm-device-bridge.c | 2 +- libnm/nm-device-ip-tunnel.c | 2 +- libnm/nm-device-ovs-bridge.c | 2 +- libnm/nm-device-ovs-port.c | 2 +- libnm/nm-device-team.c | 2 +- libnm/nm-device-wifi-p2p.c | 2 +- libnm/nm-device-wifi.c | 2 +- libnm/nm-device.c | 2 +- libnm/nm-dns-manager.c | 2 +- libnm/nm-ip-config.c | 2 +- libnm/nm-libnm-utils.c | 2 +- libnm/nm-object.c | 2 +- libnm/nm-remote-connection.c | 2 +- libnm/nm-secret-agent-old.c | 2 +- libnm/nm-vpn-plugin-old.c | 2 +- libnm/nm-vpn-service-plugin.c | 2 +- libnm/tests/meson.build | 7 +- libnm/tests/test-libnm.c | 2 +- meson.build | 3 +- po/POTFILES.in | 140 +- shared/meson.build | 24 +- shared/nm-glib-aux/tests/meson.build | 4 +- src/core/NetworkManagerUtils.c | 4 +- src/core/devices/bluetooth/meson.build | 5 + src/core/devices/bluetooth/nm-bluez-manager.c | 2 +- src/core/devices/bluetooth/nm-device-bt.c | 2 +- src/core/devices/nm-device-bond.c | 2 +- src/core/devices/nm-device-bridge.c | 2 +- src/core/devices/nm-device-dummy.c | 2 +- src/core/devices/nm-device-ethernet.c | 2 +- src/core/devices/nm-device-factory.c | 2 +- src/core/devices/nm-device-generic.c | 2 +- src/core/devices/nm-device-infiniband.c | 2 +- src/core/devices/nm-device-ip-tunnel.c | 2 +- src/core/devices/nm-device-macsec.c | 2 +- src/core/devices/nm-device-tun.c | 2 +- src/core/devices/nm-device-veth.c | 2 +- src/core/devices/nm-device-vlan.c | 2 +- src/core/devices/nm-device-vrf.c | 2 +- src/core/devices/nm-device-vxlan.c | 2 +- src/core/devices/nm-device-wireguard.c | 2 +- src/core/devices/nm-device-wpan.c | 2 +- src/core/devices/nm-device.c | 4 +- src/core/devices/ovs/nm-device-ovs-bridge.c | 2 +- src/core/devices/ovs/nm-ovs-factory.c | 2 +- src/core/devices/ovs/nm-ovsdb.c | 2 +- src/core/devices/team/nm-device-team.c | 2 +- src/core/devices/team/nm-team-factory.c | 2 +- src/core/devices/wifi/nm-device-iwd.c | 4 +- src/core/devices/wifi/nm-device-wifi-p2p.c | 2 +- src/core/devices/wifi/nm-device-wifi.c | 4 +- src/core/devices/wifi/nm-iwd-manager.c | 2 +- src/core/devices/wifi/nm-wifi-ap.c | 2 +- src/core/devices/wifi/nm-wifi-p2p-peer.c | 2 +- src/core/devices/wifi/nm-wifi-utils.c | 2 +- src/core/devices/wifi/tests/test-devices-wifi.c | 2 +- src/core/devices/wwan/nm-device-modem.c | 2 +- src/core/devices/wwan/nm-modem-broadband.c | 2 +- src/core/devices/wwan/nm-modem-ofono.c | 2 +- src/core/devices/wwan/nm-modem.c | 2 +- src/core/dhcp/nm-dhcp-listener.c | 2 +- src/core/dhcp/nm-dhcp-utils.c | 2 +- src/core/dns/nm-dns-dnsmasq.c | 2 +- src/core/dns/nm-dns-manager.c | 2 +- src/core/dns/nm-dns-plugin.c | 2 +- src/core/dns/nm-dns-systemd-resolved.c | 2 +- src/core/dnsmasq/nm-dnsmasq-manager.c | 2 +- src/core/initrd/meson.build | 2 + src/core/initrd/nm-initrd-generator.c | 4 +- src/core/initrd/nmi-cmdline-reader.c | 2 +- src/core/initrd/nmi-dt-reader.c | 2 +- src/core/initrd/nmi-ibft-reader.c | 2 +- src/core/initrd/tests/test-cmdline-reader.c | 2 +- src/core/initrd/tests/test-dt-reader.c | 2 +- src/core/initrd/tests/test-ibft-reader.c | 2 +- src/core/main.c | 2 +- src/core/meson.build | 43 +- src/core/nm-act-request.c | 2 +- src/core/nm-active-connection.c | 6 +- src/core/nm-audit-manager.c | 2 +- src/core/nm-auth-manager.c | 2 +- src/core/nm-auth-manager.h | 2 +- src/core/nm-auth-utils.c | 2 +- src/core/nm-checkpoint.c | 2 +- src/core/nm-config-data.c | 6 +- src/core/nm-config.c | 6 +- src/core/nm-connectivity.c | 2 +- src/core/nm-core-utils.c | 2 +- src/core/nm-dbus-manager.c | 4 +- src/core/nm-dispatcher.c | 4 +- src/core/nm-hostname-manager.c | 4 +- src/core/nm-iface-helper.c | 2 +- src/core/nm-ip4-config.c | 2 +- src/core/nm-ip6-config.c | 2 +- src/core/nm-l3-config-data.c | 2 +- src/core/nm-manager.c | 4 +- src/core/nm-netns.c | 2 +- src/core/nm-policy.c | 2 +- src/core/nm-proxy-config.c | 2 +- src/core/nm-sleep-monitor.c | 2 +- src/core/nm-test-utils-core.h | 2 +- src/core/platform/nm-linux-platform.c | 2 +- src/core/platform/nm-platform.c | 2 +- src/core/platform/nm-platform.h | 2 +- src/core/platform/wifi/nm-wifi-utils-wext.c | 2 +- src/core/ppp/meson.build | 6 +- src/core/ppp/nm-ppp-manager.c | 2 +- src/core/settings/nm-agent-manager.c | 4 +- src/core/settings/nm-secret-agent.c | 4 +- src/core/settings/nm-settings-connection.c | 4 +- src/core/settings/nm-settings-plugin.c | 2 +- src/core/settings/nm-settings.c | 8 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c | 2 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 2 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-storage.c | 2 +- .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 2 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 2 +- src/core/settings/plugins/ifcfg-rh/shvar.c | 2 +- .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 2 +- .../plugins/ifupdown/nms-ifupdown-parser.c | 2 +- .../plugins/ifupdown/nms-ifupdown-plugin.c | 2 +- .../plugins/ifupdown/tests/test-ifupdown.c | 2 +- .../settings/plugins/keyfile/nms-keyfile-plugin.c | 4 +- .../settings/plugins/keyfile/nms-keyfile-reader.c | 2 +- .../settings/plugins/keyfile/nms-keyfile-storage.c | 2 +- .../settings/plugins/keyfile/nms-keyfile-utils.c | 2 +- .../settings/plugins/keyfile/nms-keyfile-writer.c | 2 +- .../plugins/keyfile/tests/test-keyfile-settings.c | 2 +- src/core/supplicant/nm-supplicant-config.c | 4 +- src/core/supplicant/nm-supplicant-interface.c | 2 +- src/core/supplicant/nm-supplicant-manager.c | 2 +- src/core/supplicant/tests/test-supplicant-config.c | 2 +- src/core/systemd/meson.build | 11 +- src/core/systemd/nm-sd-utils-core.c | 2 +- src/core/tests/meson.build | 1 + src/core/tests/test-core.c | 2 +- src/core/vpn/nm-vpn-connection.c | 2 +- src/core/vpn/nm-vpn-connection.h | 2 +- src/core/vpn/nm-vpn-manager.c | 2 +- src/libnm-core-aux-extern/README.md | 11 + src/libnm-core-aux-extern/meson.build | 34 + src/libnm-core-aux-extern/nm-dispatcher-api.h | 45 + src/libnm-core-aux-extern/nm-libnm-core-aux.c | 436 + src/libnm-core-aux-extern/nm-libnm-core-aux.h | 38 + src/libnm-core-aux-intern/README.md | 28 + src/libnm-core-aux-intern/meson.build | 34 + src/libnm-core-aux-intern/nm-auth-subject.c | 468 + src/libnm-core-aux-intern/nm-auth-subject.h | 59 + src/libnm-core-aux-intern/nm-common-macros.h | 65 + src/libnm-core-aux-intern/nm-libnm-core-utils.c | 387 + src/libnm-core-aux-intern/nm-libnm-core-utils.h | 162 + src/libnm-core-impl/README.md | 22 + src/libnm-core-impl/meson.build | 132 + src/libnm-core-impl/nm-connection-private.h | 40 + src/libnm-core-impl/nm-connection.c | 3391 ++++++ src/libnm-core-impl/nm-crypto-gnutls.c | 415 + src/libnm-core-impl/nm-crypto-impl.h | 49 + src/libnm-core-impl/nm-crypto-nss.c | 548 + src/libnm-core-impl/nm-crypto.c | 1084 ++ src/libnm-core-impl/nm-crypto.h | 103 + src/libnm-core-impl/nm-dbus-utils.c | 259 + src/libnm-core-impl/nm-default-libnm-core.h | 22 + src/libnm-core-impl/nm-errors.c | 55 + src/libnm-core-impl/nm-keyfile-utils.c | 684 ++ src/libnm-core-impl/nm-keyfile.c | 4443 ++++++++ src/libnm-core-impl/nm-meta-setting-base-impl.c | 641 ++ src/libnm-core-impl/nm-property-compare.c | 136 + src/libnm-core-impl/nm-property-compare.h | 16 + src/libnm-core-impl/nm-setting-6lowpan.c | 228 + src/libnm-core-impl/nm-setting-8021x.c | 4683 ++++++++ src/libnm-core-impl/nm-setting-adsl.c | 439 + src/libnm-core-impl/nm-setting-bluetooth.c | 332 + src/libnm-core-impl/nm-setting-bond.c | 1185 +++ src/libnm-core-impl/nm-setting-bridge-port.c | 589 + src/libnm-core-impl/nm-setting-bridge.c | 2292 ++++ src/libnm-core-impl/nm-setting-cdma.c | 358 + src/libnm-core-impl/nm-setting-connection.c | 2529 +++++ src/libnm-core-impl/nm-setting-dcb.c | 1281 +++ src/libnm-core-impl/nm-setting-dummy.c | 66 + src/libnm-core-impl/nm-setting-ethtool.c | 378 + src/libnm-core-impl/nm-setting-generic.c | 62 + src/libnm-core-impl/nm-setting-gsm.c | 868 ++ src/libnm-core-impl/nm-setting-hostname.c | 339 + src/libnm-core-impl/nm-setting-infiniband.c | 521 + src/libnm-core-impl/nm-setting-ip-config.c | 6284 +++++++++++ src/libnm-core-impl/nm-setting-ip-tunnel.c | 867 ++ src/libnm-core-impl/nm-setting-ip4-config.c | 1033 ++ src/libnm-core-impl/nm-setting-ip6-config.c | 1085 ++ src/libnm-core-impl/nm-setting-macsec.c | 671 ++ src/libnm-core-impl/nm-setting-macvlan.c | 332 + src/libnm-core-impl/nm-setting-match.c | 899 ++ src/libnm-core-impl/nm-setting-olpc-mesh.c | 274 + src/libnm-core-impl/nm-setting-ovs-bridge.c | 374 + src/libnm-core-impl/nm-setting-ovs-dpdk.c | 152 + src/libnm-core-impl/nm-setting-ovs-external-ids.c | 551 + src/libnm-core-impl/nm-setting-ovs-interface.c | 427 + src/libnm-core-impl/nm-setting-ovs-patch.c | 188 + src/libnm-core-impl/nm-setting-ovs-port.c | 467 + src/libnm-core-impl/nm-setting-ppp.c | 778 ++ src/libnm-core-impl/nm-setting-pppoe.c | 358 + src/libnm-core-impl/nm-setting-private.h | 184 + src/libnm-core-impl/nm-setting-proxy.c | 383 + src/libnm-core-impl/nm-setting-serial.c | 336 + src/libnm-core-impl/nm-setting-sriov.c | 1372 +++ src/libnm-core-impl/nm-setting-tc-config.c | 1863 ++++ src/libnm-core-impl/nm-setting-team-port.c | 685 ++ src/libnm-core-impl/nm-setting-team.c | 1818 ++++ src/libnm-core-impl/nm-setting-tun.c | 397 + src/libnm-core-impl/nm-setting-user.c | 594 ++ src/libnm-core-impl/nm-setting-veth.c | 194 + src/libnm-core-impl/nm-setting-vlan.c | 983 ++ src/libnm-core-impl/nm-setting-vpn.c | 1233 +++ src/libnm-core-impl/nm-setting-vrf.c | 164 + src/libnm-core-impl/nm-setting-vxlan.c | 816 ++ src/libnm-core-impl/nm-setting-wifi-p2p.c | 304 + src/libnm-core-impl/nm-setting-wimax.c | 255 + src/libnm-core-impl/nm-setting-wired.c | 1647 +++ src/libnm-core-impl/nm-setting-wireguard.c | 2591 +++++ src/libnm-core-impl/nm-setting-wireless-security.c | 1967 ++++ src/libnm-core-impl/nm-setting-wireless.c | 1932 ++++ src/libnm-core-impl/nm-setting-wpan.c | 393 + src/libnm-core-impl/nm-setting.c | 2834 +++++ src/libnm-core-impl/nm-simple-connection.c | 152 + src/libnm-core-impl/nm-team-utils.c | 2866 +++++ src/libnm-core-impl/nm-team-utils.h | 271 + src/libnm-core-impl/nm-utils-private.h | 61 + src/libnm-core-impl/nm-utils.c | 6056 +++++++++++ src/libnm-core-impl/nm-vpn-editor-plugin.c | 518 + src/libnm-core-impl/nm-vpn-plugin-info.c | 1354 +++ .../tests/certs/ca-no-ending-newline.pem | 15 + .../tests/certs/pkcs8-decrypted.der | Bin 0 -> 1194 bytes src/libnm-core-impl/tests/certs/pkcs8-enc-key.pem | 29 + .../tests/certs/pkcs8-noenc-key.pem | 28 + .../tests/certs/test-aes-128-key.pem | 30 + .../tests/certs/test-aes-256-key.pem | 54 + src/libnm-core-impl/tests/certs/test-ca-cert.pem | 27 + src/libnm-core-impl/tests/certs/test-cert.p12 | Bin 0 -> 4092 bytes .../tests/certs/test-key-and-cert.pem | 118 + .../tests/certs/test-key-only-decrypted.der | Bin 0 -> 1192 bytes .../tests/certs/test-key-only-decrypted.pem | 27 + src/libnm-core-impl/tests/certs/test-key-only.pem | 92 + .../tests/certs/test-tpm2wrapped-key.pem | 14 + src/libnm-core-impl/tests/certs/test2-cert.p12 | Bin 0 -> 4136 bytes src/libnm-core-impl/tests/certs/test2_ca_cert.pem | 27 + .../tests/certs/test2_key_and_cert.pem | 119 + src/libnm-core-impl/tests/certs/test_ca_cert.der | Bin 0 -> 1162 bytes src/libnm-core-impl/tests/certs/test_ca_cert.pem | 27 + .../tests/certs/test_key_and_cert.pem | 119 + src/libnm-core-impl/tests/meson.build | 45 + .../tests/nm-core-tests-enum-types.c.template | 35 + .../tests/nm-core-tests-enum-types.h.template | 21 + src/libnm-core-impl/tests/test-compare.c | 231 + src/libnm-core-impl/tests/test-crypto.c | 455 + src/libnm-core-impl/tests/test-general-enums.h | 35 + src/libnm-core-impl/tests/test-general.c | 10654 +++++++++++++++++++ src/libnm-core-impl/tests/test-keyfile.c | 909 ++ src/libnm-core-impl/tests/test-secrets.c | 681 ++ src/libnm-core-impl/tests/test-setting.c | 4356 ++++++++ src/libnm-core-impl/tests/test-settings-defaults.c | 109 + src/libnm-core-intern/README.md | 19 + src/libnm-core-intern/meson.build | 10 + src/libnm-core-intern/nm-core-internal.h | 930 ++ src/libnm-core-intern/nm-core-types-internal.h | 23 + src/libnm-core-intern/nm-keyfile-internal.h | 124 + src/libnm-core-intern/nm-keyfile-utils.h | 95 + src/libnm-core-intern/nm-meta-setting-base-impl.h | 187 + src/libnm-core-intern/nm-meta-setting-base.h | 10 + src/libnm-core-public/README.md | 24 + src/libnm-core-public/meson.build | 128 + src/libnm-core-public/nm-connection.h | 224 + src/libnm-core-public/nm-core-types.h | 73 + src/libnm-core-public/nm-dbus-interface.h | 1284 +++ src/libnm-core-public/nm-errors.h | 319 + src/libnm-core-public/nm-keyfile.h | 165 + src/libnm-core-public/nm-setting-6lowpan.h | 44 + src/libnm-core-public/nm-setting-8021x.h | 366 + src/libnm-core-public/nm-setting-adsl.h | 73 + src/libnm-core-public/nm-setting-bluetooth.h | 82 + src/libnm-core-public/nm-setting-bond.h | 99 + src/libnm-core-public/nm-setting-bridge-port.h | 80 + src/libnm-core-public/nm-setting-bridge.h | 183 + src/libnm-core-public/nm-setting-cdma.h | 65 + src/libnm-core-public/nm-setting-connection.h | 219 + src/libnm-core-public/nm-setting-dcb.h | 146 + src/libnm-core-public/nm-setting-dummy.h | 52 + src/libnm-core-public/nm-setting-ethtool.h | 70 + src/libnm-core-public/nm-setting-generic.h | 52 + src/libnm-core-public/nm-setting-gsm.h | 93 + src/libnm-core-public/nm-setting-hostname.h | 53 + src/libnm-core-public/nm-setting-infiniband.h | 66 + src/libnm-core-public/nm-setting-ip-config.h | 494 + src/libnm-core-public/nm-setting-ip-tunnel.h | 122 + src/libnm-core-public/nm-setting-ip4-config.h | 109 + src/libnm-core-public/nm-setting-ip6-config.h | 174 + src/libnm-core-public/nm-setting-macsec.h | 118 + src/libnm-core-public/nm-setting-macvlan.h | 87 + src/libnm-core-public/nm-setting-match.h | 107 + src/libnm-core-public/nm-setting-olpc-mesh.h | 61 + src/libnm-core-public/nm-setting-ovs-bridge.h | 57 + src/libnm-core-public/nm-setting-ovs-dpdk.h | 44 + .../nm-setting-ovs-external-ids.h | 68 + src/libnm-core-public/nm-setting-ovs-interface.h | 47 + src/libnm-core-public/nm-setting-ovs-patch.h | 44 + src/libnm-core-public/nm-setting-ovs-port.h | 59 + src/libnm-core-public/nm-setting-ppp.h | 88 + src/libnm-core-public/nm-setting-pppoe.h | 64 + src/libnm-core-public/nm-setting-proxy.h | 80 + src/libnm-core-public/nm-setting-serial.h | 77 + src/libnm-core-public/nm-setting-sriov.h | 118 + src/libnm-core-public/nm-setting-tc-config.h | 162 + src/libnm-core-public/nm-setting-team-port.h | 89 + src/libnm-core-public/nm-setting-team.h | 226 + src/libnm-core-public/nm-setting-tun.h | 85 + src/libnm-core-public/nm-setting-user.h | 55 + src/libnm-core-public/nm-setting-veth.h | 41 + src/libnm-core-public/nm-setting-vlan.h | 134 + src/libnm-core-public/nm-setting-vpn.h | 90 + src/libnm-core-public/nm-setting-vrf.h | 38 + src/libnm-core-public/nm-setting-vxlan.h | 101 + src/libnm-core-public/nm-setting-wifi-p2p.h | 59 + src/libnm-core-public/nm-setting-wimax.h | 60 + src/libnm-core-public/nm-setting-wired.h | 142 + src/libnm-core-public/nm-setting-wireguard.h | 202 + .../nm-setting-wireless-security.h | 239 + src/libnm-core-public/nm-setting-wireless.h | 216 + src/libnm-core-public/nm-setting-wpan.h | 57 + src/libnm-core-public/nm-setting.h | 353 + src/libnm-core-public/nm-simple-connection.h | 52 + src/libnm-core-public/nm-utils.h | 259 + src/libnm-core-public/nm-version-macros.h.in | 91 + src/libnm-core-public/nm-version.h | 301 + src/libnm-core-public/nm-vpn-dbus-interface.h | 302 + src/libnm-core-public/nm-vpn-editor-plugin.h | 159 + src/libnm-core-public/nm-vpn-plugin-info.h | 105 + src/meson.build | 10 + tools/check-docs.sh | 4 +- tools/check-tree.sh | 4 +- tools/generate-docs-nm-property-infos.pl | 3 +- 562 files changed, 109138 insertions(+), 108882 deletions(-) delete mode 100644 libnm-core/meson.build delete mode 100644 libnm-core/nm-connection-private.h delete mode 100644 libnm-core/nm-connection.c delete mode 100644 libnm-core/nm-connection.h delete mode 100644 libnm-core/nm-core-internal.h delete mode 100644 libnm-core/nm-core-types-internal.h delete mode 100644 libnm-core/nm-core-types.h delete mode 100644 libnm-core/nm-crypto-gnutls.c delete mode 100644 libnm-core/nm-crypto-impl.h delete mode 100644 libnm-core/nm-crypto-nss.c delete mode 100644 libnm-core/nm-crypto.c delete mode 100644 libnm-core/nm-crypto.h delete mode 100644 libnm-core/nm-dbus-interface.h delete mode 100644 libnm-core/nm-dbus-utils.c delete mode 100644 libnm-core/nm-default-libnm-core.h delete mode 100644 libnm-core/nm-errors.c delete mode 100644 libnm-core/nm-errors.h delete mode 100644 libnm-core/nm-keyfile-internal.h delete mode 100644 libnm-core/nm-keyfile-utils.c delete mode 100644 libnm-core/nm-keyfile-utils.h delete mode 100644 libnm-core/nm-keyfile.c delete mode 100644 libnm-core/nm-keyfile.h delete mode 100644 libnm-core/nm-libnm-core-aux/README.md delete mode 100644 libnm-core/nm-libnm-core-aux/nm-dispatcher-api.h delete mode 100644 libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.c delete mode 100644 libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.h delete mode 100644 libnm-core/nm-libnm-core-intern/README.md delete mode 100644 libnm-core/nm-libnm-core-intern/nm-auth-subject.c delete mode 100644 libnm-core/nm-libnm-core-intern/nm-auth-subject.h delete mode 100644 libnm-core/nm-libnm-core-intern/nm-common-macros.h delete mode 100644 libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c delete mode 100644 libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h delete mode 100644 libnm-core/nm-meta-setting-base-impl.c delete mode 100644 libnm-core/nm-meta-setting-base-impl.h delete mode 100644 libnm-core/nm-meta-setting-base.h delete mode 100644 libnm-core/nm-property-compare.c delete mode 100644 libnm-core/nm-property-compare.h delete mode 100644 libnm-core/nm-setting-6lowpan.c delete mode 100644 libnm-core/nm-setting-6lowpan.h delete mode 100644 libnm-core/nm-setting-8021x.c delete mode 100644 libnm-core/nm-setting-8021x.h delete mode 100644 libnm-core/nm-setting-adsl.c delete mode 100644 libnm-core/nm-setting-adsl.h delete mode 100644 libnm-core/nm-setting-bluetooth.c delete mode 100644 libnm-core/nm-setting-bluetooth.h delete mode 100644 libnm-core/nm-setting-bond.c delete mode 100644 libnm-core/nm-setting-bond.h delete mode 100644 libnm-core/nm-setting-bridge-port.c delete mode 100644 libnm-core/nm-setting-bridge-port.h delete mode 100644 libnm-core/nm-setting-bridge.c delete mode 100644 libnm-core/nm-setting-bridge.h delete mode 100644 libnm-core/nm-setting-cdma.c delete mode 100644 libnm-core/nm-setting-cdma.h delete mode 100644 libnm-core/nm-setting-connection.c delete mode 100644 libnm-core/nm-setting-connection.h delete mode 100644 libnm-core/nm-setting-dcb.c delete mode 100644 libnm-core/nm-setting-dcb.h delete mode 100644 libnm-core/nm-setting-dummy.c delete mode 100644 libnm-core/nm-setting-dummy.h delete mode 100644 libnm-core/nm-setting-ethtool.c delete mode 100644 libnm-core/nm-setting-ethtool.h delete mode 100644 libnm-core/nm-setting-generic.c delete mode 100644 libnm-core/nm-setting-generic.h delete mode 100644 libnm-core/nm-setting-gsm.c delete mode 100644 libnm-core/nm-setting-gsm.h delete mode 100644 libnm-core/nm-setting-hostname.c delete mode 100644 libnm-core/nm-setting-hostname.h delete mode 100644 libnm-core/nm-setting-infiniband.c delete mode 100644 libnm-core/nm-setting-infiniband.h delete mode 100644 libnm-core/nm-setting-ip-config.c delete mode 100644 libnm-core/nm-setting-ip-config.h delete mode 100644 libnm-core/nm-setting-ip-tunnel.c delete mode 100644 libnm-core/nm-setting-ip-tunnel.h delete mode 100644 libnm-core/nm-setting-ip4-config.c delete mode 100644 libnm-core/nm-setting-ip4-config.h delete mode 100644 libnm-core/nm-setting-ip6-config.c delete mode 100644 libnm-core/nm-setting-ip6-config.h delete mode 100644 libnm-core/nm-setting-macsec.c delete mode 100644 libnm-core/nm-setting-macsec.h delete mode 100644 libnm-core/nm-setting-macvlan.c delete mode 100644 libnm-core/nm-setting-macvlan.h delete mode 100644 libnm-core/nm-setting-match.c delete mode 100644 libnm-core/nm-setting-match.h delete mode 100644 libnm-core/nm-setting-olpc-mesh.c delete mode 100644 libnm-core/nm-setting-olpc-mesh.h delete mode 100644 libnm-core/nm-setting-ovs-bridge.c delete mode 100644 libnm-core/nm-setting-ovs-bridge.h delete mode 100644 libnm-core/nm-setting-ovs-dpdk.c delete mode 100644 libnm-core/nm-setting-ovs-dpdk.h delete mode 100644 libnm-core/nm-setting-ovs-external-ids.c delete mode 100644 libnm-core/nm-setting-ovs-external-ids.h delete mode 100644 libnm-core/nm-setting-ovs-interface.c delete mode 100644 libnm-core/nm-setting-ovs-interface.h delete mode 100644 libnm-core/nm-setting-ovs-patch.c delete mode 100644 libnm-core/nm-setting-ovs-patch.h delete mode 100644 libnm-core/nm-setting-ovs-port.c delete mode 100644 libnm-core/nm-setting-ovs-port.h delete mode 100644 libnm-core/nm-setting-ppp.c delete mode 100644 libnm-core/nm-setting-ppp.h delete mode 100644 libnm-core/nm-setting-pppoe.c delete mode 100644 libnm-core/nm-setting-pppoe.h delete mode 100644 libnm-core/nm-setting-private.h delete mode 100644 libnm-core/nm-setting-proxy.c delete mode 100644 libnm-core/nm-setting-proxy.h delete mode 100644 libnm-core/nm-setting-serial.c delete mode 100644 libnm-core/nm-setting-serial.h delete mode 100644 libnm-core/nm-setting-sriov.c delete mode 100644 libnm-core/nm-setting-sriov.h delete mode 100644 libnm-core/nm-setting-tc-config.c delete mode 100644 libnm-core/nm-setting-tc-config.h delete mode 100644 libnm-core/nm-setting-team-port.c delete mode 100644 libnm-core/nm-setting-team-port.h delete mode 100644 libnm-core/nm-setting-team.c delete mode 100644 libnm-core/nm-setting-team.h delete mode 100644 libnm-core/nm-setting-tun.c delete mode 100644 libnm-core/nm-setting-tun.h delete mode 100644 libnm-core/nm-setting-user.c delete mode 100644 libnm-core/nm-setting-user.h delete mode 100644 libnm-core/nm-setting-veth.c delete mode 100644 libnm-core/nm-setting-veth.h delete mode 100644 libnm-core/nm-setting-vlan.c delete mode 100644 libnm-core/nm-setting-vlan.h delete mode 100644 libnm-core/nm-setting-vpn.c delete mode 100644 libnm-core/nm-setting-vpn.h delete mode 100644 libnm-core/nm-setting-vrf.c delete mode 100644 libnm-core/nm-setting-vrf.h delete mode 100644 libnm-core/nm-setting-vxlan.c delete mode 100644 libnm-core/nm-setting-vxlan.h delete mode 100644 libnm-core/nm-setting-wifi-p2p.c delete mode 100644 libnm-core/nm-setting-wifi-p2p.h delete mode 100644 libnm-core/nm-setting-wimax.c delete mode 100644 libnm-core/nm-setting-wimax.h delete mode 100644 libnm-core/nm-setting-wired.c delete mode 100644 libnm-core/nm-setting-wired.h delete mode 100644 libnm-core/nm-setting-wireguard.c delete mode 100644 libnm-core/nm-setting-wireguard.h delete mode 100644 libnm-core/nm-setting-wireless-security.c delete mode 100644 libnm-core/nm-setting-wireless-security.h delete mode 100644 libnm-core/nm-setting-wireless.c delete mode 100644 libnm-core/nm-setting-wireless.h delete mode 100644 libnm-core/nm-setting-wpan.c delete mode 100644 libnm-core/nm-setting-wpan.h delete mode 100644 libnm-core/nm-setting.c delete mode 100644 libnm-core/nm-setting.h delete mode 100644 libnm-core/nm-simple-connection.c delete mode 100644 libnm-core/nm-simple-connection.h delete mode 100644 libnm-core/nm-team-utils.c delete mode 100644 libnm-core/nm-team-utils.h delete mode 100644 libnm-core/nm-utils-private.h delete mode 100644 libnm-core/nm-utils.c delete mode 100644 libnm-core/nm-utils.h delete mode 100644 libnm-core/nm-version-macros.h.in delete mode 100644 libnm-core/nm-version.h delete mode 100644 libnm-core/nm-vpn-dbus-interface.h delete mode 100644 libnm-core/nm-vpn-editor-plugin.c delete mode 100644 libnm-core/nm-vpn-editor-plugin.h delete mode 100644 libnm-core/nm-vpn-plugin-info.c delete mode 100644 libnm-core/nm-vpn-plugin-info.h delete mode 100644 libnm-core/tests/certs/ca-no-ending-newline.pem delete mode 100644 libnm-core/tests/certs/pkcs8-decrypted.der delete mode 100644 libnm-core/tests/certs/pkcs8-enc-key.pem delete mode 100644 libnm-core/tests/certs/pkcs8-noenc-key.pem delete mode 100644 libnm-core/tests/certs/test-aes-128-key.pem delete mode 100644 libnm-core/tests/certs/test-aes-256-key.pem delete mode 100644 libnm-core/tests/certs/test-ca-cert.pem delete mode 100644 libnm-core/tests/certs/test-cert.p12 delete mode 100644 libnm-core/tests/certs/test-key-and-cert.pem delete mode 100644 libnm-core/tests/certs/test-key-only-decrypted.der delete mode 100644 libnm-core/tests/certs/test-key-only-decrypted.pem delete mode 100644 libnm-core/tests/certs/test-key-only.pem delete mode 100644 libnm-core/tests/certs/test-tpm2wrapped-key.pem delete mode 100644 libnm-core/tests/certs/test2-cert.p12 delete mode 100644 libnm-core/tests/certs/test2_ca_cert.pem delete mode 100644 libnm-core/tests/certs/test2_key_and_cert.pem delete mode 100644 libnm-core/tests/certs/test_ca_cert.der delete mode 100644 libnm-core/tests/certs/test_ca_cert.pem delete mode 100644 libnm-core/tests/certs/test_key_and_cert.pem delete mode 100644 libnm-core/tests/meson.build delete mode 100644 libnm-core/tests/nm-core-tests-enum-types.c.template delete mode 100644 libnm-core/tests/nm-core-tests-enum-types.h.template delete mode 100644 libnm-core/tests/test-compare.c delete mode 100644 libnm-core/tests/test-crypto.c delete mode 100644 libnm-core/tests/test-general-enums.h delete mode 100644 libnm-core/tests/test-general.c delete mode 100644 libnm-core/tests/test-keyfile.c delete mode 100644 libnm-core/tests/test-secrets.c delete mode 100644 libnm-core/tests/test-setting.c delete mode 100644 libnm-core/tests/test-settings-defaults.c create mode 100644 src/libnm-core-aux-extern/README.md create mode 100644 src/libnm-core-aux-extern/meson.build create mode 100644 src/libnm-core-aux-extern/nm-dispatcher-api.h create mode 100644 src/libnm-core-aux-extern/nm-libnm-core-aux.c create mode 100644 src/libnm-core-aux-extern/nm-libnm-core-aux.h create mode 100644 src/libnm-core-aux-intern/README.md create mode 100644 src/libnm-core-aux-intern/meson.build create mode 100644 src/libnm-core-aux-intern/nm-auth-subject.c create mode 100644 src/libnm-core-aux-intern/nm-auth-subject.h create mode 100644 src/libnm-core-aux-intern/nm-common-macros.h create mode 100644 src/libnm-core-aux-intern/nm-libnm-core-utils.c create mode 100644 src/libnm-core-aux-intern/nm-libnm-core-utils.h create mode 100644 src/libnm-core-impl/README.md create mode 100644 src/libnm-core-impl/meson.build create mode 100644 src/libnm-core-impl/nm-connection-private.h create mode 100644 src/libnm-core-impl/nm-connection.c create mode 100644 src/libnm-core-impl/nm-crypto-gnutls.c create mode 100644 src/libnm-core-impl/nm-crypto-impl.h create mode 100644 src/libnm-core-impl/nm-crypto-nss.c create mode 100644 src/libnm-core-impl/nm-crypto.c create mode 100644 src/libnm-core-impl/nm-crypto.h create mode 100644 src/libnm-core-impl/nm-dbus-utils.c create mode 100644 src/libnm-core-impl/nm-default-libnm-core.h create mode 100644 src/libnm-core-impl/nm-errors.c create mode 100644 src/libnm-core-impl/nm-keyfile-utils.c create mode 100644 src/libnm-core-impl/nm-keyfile.c create mode 100644 src/libnm-core-impl/nm-meta-setting-base-impl.c create mode 100644 src/libnm-core-impl/nm-property-compare.c create mode 100644 src/libnm-core-impl/nm-property-compare.h create mode 100644 src/libnm-core-impl/nm-setting-6lowpan.c create mode 100644 src/libnm-core-impl/nm-setting-8021x.c create mode 100644 src/libnm-core-impl/nm-setting-adsl.c create mode 100644 src/libnm-core-impl/nm-setting-bluetooth.c create mode 100644 src/libnm-core-impl/nm-setting-bond.c create mode 100644 src/libnm-core-impl/nm-setting-bridge-port.c create mode 100644 src/libnm-core-impl/nm-setting-bridge.c create mode 100644 src/libnm-core-impl/nm-setting-cdma.c create mode 100644 src/libnm-core-impl/nm-setting-connection.c create mode 100644 src/libnm-core-impl/nm-setting-dcb.c create mode 100644 src/libnm-core-impl/nm-setting-dummy.c create mode 100644 src/libnm-core-impl/nm-setting-ethtool.c create mode 100644 src/libnm-core-impl/nm-setting-generic.c create mode 100644 src/libnm-core-impl/nm-setting-gsm.c create mode 100644 src/libnm-core-impl/nm-setting-hostname.c create mode 100644 src/libnm-core-impl/nm-setting-infiniband.c create mode 100644 src/libnm-core-impl/nm-setting-ip-config.c create mode 100644 src/libnm-core-impl/nm-setting-ip-tunnel.c create mode 100644 src/libnm-core-impl/nm-setting-ip4-config.c create mode 100644 src/libnm-core-impl/nm-setting-ip6-config.c create mode 100644 src/libnm-core-impl/nm-setting-macsec.c create mode 100644 src/libnm-core-impl/nm-setting-macvlan.c create mode 100644 src/libnm-core-impl/nm-setting-match.c create mode 100644 src/libnm-core-impl/nm-setting-olpc-mesh.c create mode 100644 src/libnm-core-impl/nm-setting-ovs-bridge.c create mode 100644 src/libnm-core-impl/nm-setting-ovs-dpdk.c create mode 100644 src/libnm-core-impl/nm-setting-ovs-external-ids.c create mode 100644 src/libnm-core-impl/nm-setting-ovs-interface.c create mode 100644 src/libnm-core-impl/nm-setting-ovs-patch.c create mode 100644 src/libnm-core-impl/nm-setting-ovs-port.c create mode 100644 src/libnm-core-impl/nm-setting-ppp.c create mode 100644 src/libnm-core-impl/nm-setting-pppoe.c create mode 100644 src/libnm-core-impl/nm-setting-private.h create mode 100644 src/libnm-core-impl/nm-setting-proxy.c create mode 100644 src/libnm-core-impl/nm-setting-serial.c create mode 100644 src/libnm-core-impl/nm-setting-sriov.c create mode 100644 src/libnm-core-impl/nm-setting-tc-config.c create mode 100644 src/libnm-core-impl/nm-setting-team-port.c create mode 100644 src/libnm-core-impl/nm-setting-team.c create mode 100644 src/libnm-core-impl/nm-setting-tun.c create mode 100644 src/libnm-core-impl/nm-setting-user.c create mode 100644 src/libnm-core-impl/nm-setting-veth.c create mode 100644 src/libnm-core-impl/nm-setting-vlan.c create mode 100644 src/libnm-core-impl/nm-setting-vpn.c create mode 100644 src/libnm-core-impl/nm-setting-vrf.c create mode 100644 src/libnm-core-impl/nm-setting-vxlan.c create mode 100644 src/libnm-core-impl/nm-setting-wifi-p2p.c create mode 100644 src/libnm-core-impl/nm-setting-wimax.c create mode 100644 src/libnm-core-impl/nm-setting-wired.c create mode 100644 src/libnm-core-impl/nm-setting-wireguard.c create mode 100644 src/libnm-core-impl/nm-setting-wireless-security.c create mode 100644 src/libnm-core-impl/nm-setting-wireless.c create mode 100644 src/libnm-core-impl/nm-setting-wpan.c create mode 100644 src/libnm-core-impl/nm-setting.c create mode 100644 src/libnm-core-impl/nm-simple-connection.c create mode 100644 src/libnm-core-impl/nm-team-utils.c create mode 100644 src/libnm-core-impl/nm-team-utils.h create mode 100644 src/libnm-core-impl/nm-utils-private.h create mode 100644 src/libnm-core-impl/nm-utils.c create mode 100644 src/libnm-core-impl/nm-vpn-editor-plugin.c create mode 100644 src/libnm-core-impl/nm-vpn-plugin-info.c create mode 100644 src/libnm-core-impl/tests/certs/ca-no-ending-newline.pem create mode 100644 src/libnm-core-impl/tests/certs/pkcs8-decrypted.der create mode 100644 src/libnm-core-impl/tests/certs/pkcs8-enc-key.pem create mode 100644 src/libnm-core-impl/tests/certs/pkcs8-noenc-key.pem create mode 100644 src/libnm-core-impl/tests/certs/test-aes-128-key.pem create mode 100644 src/libnm-core-impl/tests/certs/test-aes-256-key.pem create mode 100644 src/libnm-core-impl/tests/certs/test-ca-cert.pem create mode 100644 src/libnm-core-impl/tests/certs/test-cert.p12 create mode 100644 src/libnm-core-impl/tests/certs/test-key-and-cert.pem create mode 100644 src/libnm-core-impl/tests/certs/test-key-only-decrypted.der create mode 100644 src/libnm-core-impl/tests/certs/test-key-only-decrypted.pem create mode 100644 src/libnm-core-impl/tests/certs/test-key-only.pem create mode 100644 src/libnm-core-impl/tests/certs/test-tpm2wrapped-key.pem create mode 100644 src/libnm-core-impl/tests/certs/test2-cert.p12 create mode 100644 src/libnm-core-impl/tests/certs/test2_ca_cert.pem create mode 100644 src/libnm-core-impl/tests/certs/test2_key_and_cert.pem create mode 100644 src/libnm-core-impl/tests/certs/test_ca_cert.der create mode 100644 src/libnm-core-impl/tests/certs/test_ca_cert.pem create mode 100644 src/libnm-core-impl/tests/certs/test_key_and_cert.pem create mode 100644 src/libnm-core-impl/tests/meson.build create mode 100644 src/libnm-core-impl/tests/nm-core-tests-enum-types.c.template create mode 100644 src/libnm-core-impl/tests/nm-core-tests-enum-types.h.template create mode 100644 src/libnm-core-impl/tests/test-compare.c create mode 100644 src/libnm-core-impl/tests/test-crypto.c create mode 100644 src/libnm-core-impl/tests/test-general-enums.h create mode 100644 src/libnm-core-impl/tests/test-general.c create mode 100644 src/libnm-core-impl/tests/test-keyfile.c create mode 100644 src/libnm-core-impl/tests/test-secrets.c create mode 100644 src/libnm-core-impl/tests/test-setting.c create mode 100644 src/libnm-core-impl/tests/test-settings-defaults.c create mode 100644 src/libnm-core-intern/README.md create mode 100644 src/libnm-core-intern/meson.build create mode 100644 src/libnm-core-intern/nm-core-internal.h create mode 100644 src/libnm-core-intern/nm-core-types-internal.h create mode 100644 src/libnm-core-intern/nm-keyfile-internal.h create mode 100644 src/libnm-core-intern/nm-keyfile-utils.h create mode 100644 src/libnm-core-intern/nm-meta-setting-base-impl.h create mode 100644 src/libnm-core-intern/nm-meta-setting-base.h create mode 100644 src/libnm-core-public/README.md create mode 100644 src/libnm-core-public/meson.build create mode 100644 src/libnm-core-public/nm-connection.h create mode 100644 src/libnm-core-public/nm-core-types.h create mode 100644 src/libnm-core-public/nm-dbus-interface.h create mode 100644 src/libnm-core-public/nm-errors.h create mode 100644 src/libnm-core-public/nm-keyfile.h create mode 100644 src/libnm-core-public/nm-setting-6lowpan.h create mode 100644 src/libnm-core-public/nm-setting-8021x.h create mode 100644 src/libnm-core-public/nm-setting-adsl.h create mode 100644 src/libnm-core-public/nm-setting-bluetooth.h create mode 100644 src/libnm-core-public/nm-setting-bond.h create mode 100644 src/libnm-core-public/nm-setting-bridge-port.h create mode 100644 src/libnm-core-public/nm-setting-bridge.h create mode 100644 src/libnm-core-public/nm-setting-cdma.h create mode 100644 src/libnm-core-public/nm-setting-connection.h create mode 100644 src/libnm-core-public/nm-setting-dcb.h create mode 100644 src/libnm-core-public/nm-setting-dummy.h create mode 100644 src/libnm-core-public/nm-setting-ethtool.h create mode 100644 src/libnm-core-public/nm-setting-generic.h create mode 100644 src/libnm-core-public/nm-setting-gsm.h create mode 100644 src/libnm-core-public/nm-setting-hostname.h create mode 100644 src/libnm-core-public/nm-setting-infiniband.h create mode 100644 src/libnm-core-public/nm-setting-ip-config.h create mode 100644 src/libnm-core-public/nm-setting-ip-tunnel.h create mode 100644 src/libnm-core-public/nm-setting-ip4-config.h create mode 100644 src/libnm-core-public/nm-setting-ip6-config.h create mode 100644 src/libnm-core-public/nm-setting-macsec.h create mode 100644 src/libnm-core-public/nm-setting-macvlan.h create mode 100644 src/libnm-core-public/nm-setting-match.h create mode 100644 src/libnm-core-public/nm-setting-olpc-mesh.h create mode 100644 src/libnm-core-public/nm-setting-ovs-bridge.h create mode 100644 src/libnm-core-public/nm-setting-ovs-dpdk.h create mode 100644 src/libnm-core-public/nm-setting-ovs-external-ids.h create mode 100644 src/libnm-core-public/nm-setting-ovs-interface.h create mode 100644 src/libnm-core-public/nm-setting-ovs-patch.h create mode 100644 src/libnm-core-public/nm-setting-ovs-port.h create mode 100644 src/libnm-core-public/nm-setting-ppp.h create mode 100644 src/libnm-core-public/nm-setting-pppoe.h create mode 100644 src/libnm-core-public/nm-setting-proxy.h create mode 100644 src/libnm-core-public/nm-setting-serial.h create mode 100644 src/libnm-core-public/nm-setting-sriov.h create mode 100644 src/libnm-core-public/nm-setting-tc-config.h create mode 100644 src/libnm-core-public/nm-setting-team-port.h create mode 100644 src/libnm-core-public/nm-setting-team.h create mode 100644 src/libnm-core-public/nm-setting-tun.h create mode 100644 src/libnm-core-public/nm-setting-user.h create mode 100644 src/libnm-core-public/nm-setting-veth.h create mode 100644 src/libnm-core-public/nm-setting-vlan.h create mode 100644 src/libnm-core-public/nm-setting-vpn.h create mode 100644 src/libnm-core-public/nm-setting-vrf.h create mode 100644 src/libnm-core-public/nm-setting-vxlan.h create mode 100644 src/libnm-core-public/nm-setting-wifi-p2p.h create mode 100644 src/libnm-core-public/nm-setting-wimax.h create mode 100644 src/libnm-core-public/nm-setting-wired.h create mode 100644 src/libnm-core-public/nm-setting-wireguard.h create mode 100644 src/libnm-core-public/nm-setting-wireless-security.h create mode 100644 src/libnm-core-public/nm-setting-wireless.h create mode 100644 src/libnm-core-public/nm-setting-wpan.h create mode 100644 src/libnm-core-public/nm-setting.h create mode 100644 src/libnm-core-public/nm-simple-connection.h create mode 100644 src/libnm-core-public/nm-utils.h create mode 100644 src/libnm-core-public/nm-version-macros.h.in create mode 100644 src/libnm-core-public/nm-version.h create mode 100644 src/libnm-core-public/nm-vpn-dbus-interface.h create mode 100644 src/libnm-core-public/nm-vpn-editor-plugin.h create mode 100644 src/libnm-core-public/nm-vpn-plugin-info.h create mode 100644 src/meson.build diff --git a/.gitignore b/.gitignore index 2b49984ac7..8d50a621be 100644 --- a/.gitignore +++ b/.gitignore @@ -141,17 +141,17 @@ test-*.trs /introspection/org.freedesktop.NetworkManager*.[ch] -/libnm-core/tests/test-compare -/libnm-core/tests/test-crypto -/libnm-core/tests/test-settings-defaults -/libnm-core/tests/test-general -/libnm-core/tests/test-keyfile -/libnm-core/tests/test-need-secrets -/libnm-core/tests/test-secrets -/libnm-core/tests/test-setting -/libnm-core/nm-dbus-types.xml -/libnm-core/nm-version-macros.h -/libnm-core/nm-vpn-dbus-types.xml +/src/libnm-core-public/nm-version-macros.h +/src/libnm-core-public/nm-dbus-types.xml +/src/libnm-core-public/nm-vpn-dbus-types.xml +/src/libnm-core-impl/tests/test-compare +/src/libnm-core-impl/tests/test-crypto +/src/libnm-core-impl/tests/test-settings-defaults +/src/libnm-core-impl/tests/test-general +/src/libnm-core-impl/tests/test-keyfile +/src/libnm-core-impl/tests/test-need-secrets +/src/libnm-core-impl/tests/test-secrets +/src/libnm-core-impl/tests/test-setting /libnm/nm-property-infos-dbus.xml /libnm/nm-property-infos-ifcfg-rh.xml @@ -323,6 +323,17 @@ test-*.trs /libnm-core/tests/test-setting-8021x /libnm-core/tests/test-setting-bond /libnm-core/tests/test-setting-dcb +/libnm-core/tests/test-compare +/libnm-core/tests/test-crypto +/libnm-core/tests/test-settings-defaults +/libnm-core/tests/test-general +/libnm-core/tests/test-keyfile +/libnm-core/tests/test-need-secrets +/libnm-core/tests/test-secrets +/libnm-core/tests/test-setting +/libnm-core/nm-dbus-types.xml +/libnm-core/nm-version-macros.h +/libnm-core/nm-vpn-dbus-types.xml /libnm-glib/libnm-glib-test /libnm-glib/nm-secret-agent-glue.h /libnm-glib/nm-vpn-plugin-glue.h diff --git a/Makefile.am b/Makefile.am index 9e35298b3d..e888ac6cca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -110,20 +110,22 @@ include config-extra.h.mk DISTCLEANFILES += config-extra.h -$(libnm_core_lib_h_pub_mkenums): config-extra.h -libnm-core/.dirstamp: config-extra.h -shared/.dirstamp: config-extra.h -shared/nm-base/.dirstamp: config-extra.h -shared/nm-glib-aux/.dirstamp: config-extra.h -shared/nm-glib-aux/tests/.dirstamp: config-extra.h -shared/nm-platform/.dirstamp: config-extra.h -shared/nm-platform/tests/.dirstamp: config-extra.h -shared/nm-std-aux/.dirstamp: config-extra.h -shared/nm-udev-aux/.dirstamp: config-extra.h -shared/systemd/.dirstamp: config-extra.h -shared/systemd/src/basic/.dirstamp: config-extra.h -shared/systemd/src/shared/.dirstamp: config-extra.h -src/core/dhcp/.dirstamp: config-extra.h +$(src_libnm_core_public_mkenums_h): config-extra.h +$(src_libnm_core_public_mkenums_c): config-extra.h +src/libnm-core-impl/.dirstamp: config-extra.h +src/libnm-core-impl/.dirstamp: config-extra.h +shared/.dirstamp: config-extra.h +shared/nm-base/.dirstamp: config-extra.h +shared/nm-glib-aux/.dirstamp: config-extra.h +shared/nm-glib-aux/tests/.dirstamp: config-extra.h +shared/nm-platform/.dirstamp: config-extra.h +shared/nm-platform/tests/.dirstamp: config-extra.h +shared/nm-std-aux/.dirstamp: config-extra.h +shared/nm-udev-aux/.dirstamp: config-extra.h +shared/systemd/.dirstamp: config-extra.h +shared/systemd/src/basic/.dirstamp: config-extra.h +shared/systemd/src/shared/.dirstamp: config-extra.h +src/core/dhcp/.dirstamp: config-extra.h ############################################################################### @@ -582,75 +584,82 @@ EXTRA_DIST += \ ############################################################################### -noinst_LTLIBRARIES += libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la +noinst_LTLIBRARIES += src/libnm-core-aux-intern/libnm-core-aux-intern.la -libnm_core_nm_libnm_core_intern_libnm_libnm_core_intern_la_CPPFLAGS = \ +src_libnm_core_aux_intern_libnm_core_aux_intern_la_CPPFLAGS = \ $(dflt_cppflags) \ - -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ + -I$(srcdir)/shared \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ $(CODE_COVERAGE_CFLAGS) \ $(GLIB_CFLAGS) \ $(SANITIZER_LIB_CFLAGS) \ -DG_LOG_DOMAIN=\""libnm"\" \ $(NULL) -libnm_core_nm_libnm_core_intern_libnm_libnm_core_intern_la_SOURCES = \ - libnm-core/nm-libnm-core-intern/nm-auth-subject.c \ - libnm-core/nm-libnm-core-intern/nm-auth-subject.h \ - libnm-core/nm-libnm-core-intern/nm-common-macros.h \ - libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c \ - libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h \ +src_libnm_core_aux_intern_libnm_core_aux_intern_la_SOURCES = \ + src/libnm-core-aux-intern/nm-auth-subject.c \ + src/libnm-core-aux-intern/nm-auth-subject.h \ + src/libnm-core-aux-intern/nm-common-macros.h \ + src/libnm-core-aux-intern/nm-libnm-core-utils.c \ + src/libnm-core-aux-intern/nm-libnm-core-utils.h \ $(NULL) -libnm_core_nm_libnm_core_intern_libnm_libnm_core_intern_la_LDFLAGS = \ +src_libnm_core_aux_intern_libnm_core_aux_intern_la_LDFLAGS = \ $(CODE_COVERAGE_LDFLAGS) \ $(SANITIZER_LIB_LDFLAGS) \ $(NULL) -libnm_core_nm_libnm_core_intern_libnm_libnm_core_intern_la_LIBADD = \ +src_libnm_core_aux_intern_libnm_core_aux_intern_la_LIBADD = \ $(GLIB_LIBS) \ $(NULL) -$(libnm_core_nm_libnm_core_intern_libnm_libnm_core_intern_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_libnm_core_aux_intern_libnm_core_aux_intern_la_OBJECTS): $(src_libnm_core_public_mkenums_h) -EXTRA_DIST += libnm-core/nm-libnm-core-intern/README.md +EXTRA_DIST += \ + src/libnm-core-aux-intern/README.md \ + src/libnm-core-aux-intern/meson.build \ + $(NULL) ############################################################################### -noinst_LTLIBRARIES += libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la +noinst_LTLIBRARIES += src/libnm-core-aux-extern/libnm-core-aux-extern.la -libnm_core_nm_libnm_core_aux_libnm_libnm_core_aux_la_CPPFLAGS = \ +src_libnm_core_aux_extern_libnm_core_aux_extern_la_CPPFLAGS = \ $(dflt_cppflags) \ - -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ + -I$(srcdir)/shared \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ + -I$(srcdir)/src \ $(CODE_COVERAGE_CFLAGS) \ $(GLIB_CFLAGS) \ $(SANITIZER_LIB_CFLAGS) \ -DG_LOG_DOMAIN=\""libnm"\" \ $(NULL) -libnm_core_nm_libnm_core_aux_libnm_libnm_core_aux_la_SOURCES = \ - libnm-core/nm-libnm-core-aux/nm-dispatcher-api.h \ - libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.c \ - libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.h \ +src_libnm_core_aux_extern_libnm_core_aux_extern_la_SOURCES = \ + src/libnm-core-aux-extern/nm-dispatcher-api.h \ + src/libnm-core-aux-extern/nm-libnm-core-aux.c \ + src/libnm-core-aux-extern/nm-libnm-core-aux.h \ $(NULL) -libnm_core_nm_libnm_core_aux_libnm_libnm_core_aux_la_LDFLAGS = \ +src_libnm_core_aux_extern_libnm_core_aux_extern_la_LDFLAGS = \ $(CODE_COVERAGE_LDFLAGS) \ $(SANITIZER_LIB_LDFLAGS) \ $(NULL) -libnm_core_nm_libnm_core_aux_libnm_libnm_core_aux_la_LIBADD = \ +src_libnm_core_aux_extern_libnm_core_aux_extern_la_LIBADD = \ $(GLIB_LIBS) \ $(NULL) -$(libnm_core_nm_libnm_core_aux_libnm_libnm_core_aux_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_libnm_core_aux_extern_libnm_core_aux_extern_la_OBJECTS): $(src_libnm_core_public_mkenums_h) -EXTRA_DIST += libnm-core/nm-libnm-core-aux/README.md +EXTRA_DIST += \ + src/libnm-core-aux-extern/README.md \ + src/libnm-core-aux-extern/meson.build \ + $(NULL) ############################################################################### @@ -660,8 +669,8 @@ libnm_nm_libnm_aux_libnm_libnm_aux_la_CPPFLAGS = \ $(dflt_cppflags) \ -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ -I$(srcdir)/libnm \ -I$(builddir)/libnm \ $(CODE_COVERAGE_CFLAGS) \ @@ -685,7 +694,7 @@ libnm_nm_libnm_aux_libnm_libnm_aux_la_LIBADD = \ libnm/libnm.la \ $(NULL) -$(libnm_nm_libnm_aux_libnm_libnm_aux_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(libnm_nm_libnm_aux_libnm_libnm_aux_la_OBJECTS): $(src_libnm_core_public_mkenums_h) $(libnm_nm_libnm_aux_libnm_libnm_aux_la_OBJECTS): $(libnm_lib_h_pub_mkenums) EXTRA_DIST += libnm/nm-libnm-aux/README.md @@ -1002,172 +1011,182 @@ check_local += check-docs ############################################################################### -libnm_core_lib_h_pub_real = \ - libnm-core/nm-connection.h \ - libnm-core/nm-core-types.h \ - libnm-core/nm-dbus-interface.h \ - libnm-core/nm-errors.h \ - libnm-core/nm-keyfile.h \ - libnm-core/nm-setting-6lowpan.h \ - libnm-core/nm-setting-8021x.h \ - libnm-core/nm-setting-adsl.h \ - libnm-core/nm-setting-bluetooth.h \ - libnm-core/nm-setting-bond.h \ - libnm-core/nm-setting-bridge-port.h \ - libnm-core/nm-setting-bridge.h \ - libnm-core/nm-setting-cdma.h \ - libnm-core/nm-setting-connection.h \ - libnm-core/nm-setting-dcb.h \ - libnm-core/nm-setting-dummy.h \ - libnm-core/nm-setting-ethtool.h \ - libnm-core/nm-setting-generic.h \ - libnm-core/nm-setting-gsm.h \ - libnm-core/nm-setting-hostname.h \ - libnm-core/nm-setting-infiniband.h \ - libnm-core/nm-setting-ip-config.h \ - libnm-core/nm-setting-ip-tunnel.h \ - libnm-core/nm-setting-ip4-config.h \ - libnm-core/nm-setting-ip6-config.h \ - libnm-core/nm-setting-macsec.h \ - libnm-core/nm-setting-macvlan.h \ - libnm-core/nm-setting-match.h \ - libnm-core/nm-setting-olpc-mesh.h \ - libnm-core/nm-setting-ovs-bridge.h \ - libnm-core/nm-setting-ovs-dpdk.h \ - libnm-core/nm-setting-ovs-external-ids.h \ - libnm-core/nm-setting-ovs-interface.h \ - libnm-core/nm-setting-ovs-patch.h \ - libnm-core/nm-setting-ovs-port.h \ - libnm-core/nm-setting-ppp.h \ - libnm-core/nm-setting-pppoe.h \ - libnm-core/nm-setting-proxy.h \ - libnm-core/nm-setting-serial.h \ - libnm-core/nm-setting-sriov.h \ - libnm-core/nm-setting-tc-config.h \ - libnm-core/nm-setting-team-port.h \ - libnm-core/nm-setting-team.h \ - libnm-core/nm-setting-tun.h \ - libnm-core/nm-setting-user.h \ - libnm-core/nm-setting-veth.h \ - libnm-core/nm-setting-vlan.h \ - libnm-core/nm-setting-vpn.h \ - libnm-core/nm-setting-vrf.h \ - libnm-core/nm-setting-vxlan.h \ - libnm-core/nm-setting-wifi-p2p.h \ - libnm-core/nm-setting-wimax.h \ - libnm-core/nm-setting-wired.h \ - libnm-core/nm-setting-wireguard.h \ - libnm-core/nm-setting-wireless-security.h \ - libnm-core/nm-setting-wireless.h \ - libnm-core/nm-setting-wpan.h \ - libnm-core/nm-setting.h \ - libnm-core/nm-simple-connection.h \ - libnm-core/nm-utils.h \ - libnm-core/nm-version-macros.h \ - libnm-core/nm-version.h \ - libnm-core/nm-vpn-dbus-interface.h \ - libnm-core/nm-vpn-editor-plugin.h \ - libnm-core/nm-vpn-plugin-info.h \ - $(NULL) -libnm_core_lib_h_pub_mkenums = \ - libnm-core/nm-core-enum-types.h \ - $(NULL) -libnm_core_lib_h_priv = \ - libnm-core/nm-connection-private.h \ - libnm-core/nm-core-internal.h \ - libnm-core/nm-core-types-internal.h \ - libnm-core/nm-crypto-impl.h \ - libnm-core/nm-crypto.h \ - libnm-core/nm-default-libnm-core.h \ - libnm-core/nm-keyfile-internal.h \ - libnm-core/nm-keyfile-utils.h \ - libnm-core/nm-meta-setting-base-impl.h \ - libnm-core/nm-meta-setting-base.h \ - libnm-core/nm-property-compare.h \ - libnm-core/nm-setting-private.h \ - libnm-core/nm-team-utils.h \ - libnm-core/nm-utils-private.h \ - $(NULL) -libnm_core_lib_c_settings_real = \ - libnm-core/nm-setting-6lowpan.c \ - libnm-core/nm-setting-8021x.c \ - libnm-core/nm-setting-adsl.c \ - libnm-core/nm-setting-bluetooth.c \ - libnm-core/nm-setting-bond.c \ - libnm-core/nm-setting-bridge-port.c \ - libnm-core/nm-setting-bridge.c \ - libnm-core/nm-setting-cdma.c \ - libnm-core/nm-setting-connection.c \ - libnm-core/nm-setting-dcb.c \ - libnm-core/nm-setting-dummy.c \ - libnm-core/nm-setting-ethtool.c \ - libnm-core/nm-setting-generic.c \ - libnm-core/nm-setting-gsm.c \ - libnm-core/nm-setting-hostname.c \ - libnm-core/nm-setting-infiniband.c \ - libnm-core/nm-setting-ip-config.c \ - libnm-core/nm-setting-ip-tunnel.c \ - libnm-core/nm-setting-ip4-config.c \ - libnm-core/nm-setting-ip6-config.c \ - libnm-core/nm-setting-macsec.c \ - libnm-core/nm-setting-macvlan.c \ - libnm-core/nm-setting-match.c \ - libnm-core/nm-setting-olpc-mesh.c \ - libnm-core/nm-setting-ovs-bridge.c \ - libnm-core/nm-setting-ovs-dpdk.c \ - libnm-core/nm-setting-ovs-external-ids.c \ - libnm-core/nm-setting-ovs-interface.c \ - libnm-core/nm-setting-ovs-patch.c \ - libnm-core/nm-setting-ovs-port.c \ - libnm-core/nm-setting-ppp.c \ - libnm-core/nm-setting-pppoe.c \ - libnm-core/nm-setting-proxy.c \ - libnm-core/nm-setting-serial.c \ - libnm-core/nm-setting-sriov.c \ - libnm-core/nm-setting-tc-config.c \ - libnm-core/nm-setting-team-port.c \ - libnm-core/nm-setting-team.c \ - libnm-core/nm-setting-tun.c \ - libnm-core/nm-setting-user.c \ - libnm-core/nm-setting-veth.c \ - libnm-core/nm-setting-vlan.c \ - libnm-core/nm-setting-vpn.c \ - libnm-core/nm-setting-vrf.c \ - libnm-core/nm-setting-vxlan.c \ - libnm-core/nm-setting-wifi-p2p.c \ - libnm-core/nm-setting-wimax.c \ - libnm-core/nm-setting-wired.c \ - libnm-core/nm-setting-wireguard.c \ - libnm-core/nm-setting-wireless-security.c \ - libnm-core/nm-setting-wireless.c \ - libnm-core/nm-setting-wpan.c \ - $(NULL) -libnm_core_lib_c_real = \ - $(libnm_core_lib_c_settings_real) \ - libnm-core/nm-connection.c \ - libnm-core/nm-crypto.c \ - libnm-core/nm-dbus-utils.c \ - libnm-core/nm-errors.c \ - libnm-core/nm-keyfile-utils.c \ - libnm-core/nm-keyfile.c \ - libnm-core/nm-meta-setting-base-impl.c \ - libnm-core/nm-property-compare.c \ - libnm-core/nm-setting.c \ - libnm-core/nm-simple-connection.c \ - libnm-core/nm-team-utils.c \ - libnm-core/nm-utils.c \ - libnm-core/nm-vpn-editor-plugin.c \ - libnm-core/nm-vpn-plugin-info.c \ - $(NULL) - -libnm_core_lib_c_mkenums = \ - libnm-core/nm-core-enum-types.c +src_libnm_core_impl_lib_h_pub_real = \ + src/libnm-core-public/nm-connection.h \ + src/libnm-core-public/nm-core-types.h \ + src/libnm-core-public/nm-dbus-interface.h \ + src/libnm-core-public/nm-errors.h \ + src/libnm-core-public/nm-keyfile.h \ + src/libnm-core-public/nm-setting-6lowpan.h \ + src/libnm-core-public/nm-setting-8021x.h \ + src/libnm-core-public/nm-setting-adsl.h \ + src/libnm-core-public/nm-setting-bluetooth.h \ + src/libnm-core-public/nm-setting-bond.h \ + src/libnm-core-public/nm-setting-bridge-port.h \ + src/libnm-core-public/nm-setting-bridge.h \ + src/libnm-core-public/nm-setting-cdma.h \ + src/libnm-core-public/nm-setting-connection.h \ + src/libnm-core-public/nm-setting-dcb.h \ + src/libnm-core-public/nm-setting-dummy.h \ + src/libnm-core-public/nm-setting-ethtool.h \ + src/libnm-core-public/nm-setting-generic.h \ + src/libnm-core-public/nm-setting-gsm.h \ + src/libnm-core-public/nm-setting-hostname.h \ + src/libnm-core-public/nm-setting-infiniband.h \ + src/libnm-core-public/nm-setting-ip-config.h \ + src/libnm-core-public/nm-setting-ip-tunnel.h \ + src/libnm-core-public/nm-setting-ip4-config.h \ + src/libnm-core-public/nm-setting-ip6-config.h \ + src/libnm-core-public/nm-setting-macsec.h \ + src/libnm-core-public/nm-setting-macvlan.h \ + src/libnm-core-public/nm-setting-match.h \ + src/libnm-core-public/nm-setting-olpc-mesh.h \ + src/libnm-core-public/nm-setting-ovs-bridge.h \ + src/libnm-core-public/nm-setting-ovs-dpdk.h \ + src/libnm-core-public/nm-setting-ovs-external-ids.h \ + src/libnm-core-public/nm-setting-ovs-interface.h \ + src/libnm-core-public/nm-setting-ovs-patch.h \ + src/libnm-core-public/nm-setting-ovs-port.h \ + src/libnm-core-public/nm-setting-ppp.h \ + src/libnm-core-public/nm-setting-pppoe.h \ + src/libnm-core-public/nm-setting-proxy.h \ + src/libnm-core-public/nm-setting-serial.h \ + src/libnm-core-public/nm-setting-sriov.h \ + src/libnm-core-public/nm-setting-tc-config.h \ + src/libnm-core-public/nm-setting-team-port.h \ + src/libnm-core-public/nm-setting-team.h \ + src/libnm-core-public/nm-setting-tun.h \ + src/libnm-core-public/nm-setting-user.h \ + src/libnm-core-public/nm-setting-veth.h \ + src/libnm-core-public/nm-setting-vlan.h \ + src/libnm-core-public/nm-setting-vpn.h \ + src/libnm-core-public/nm-setting-vrf.h \ + src/libnm-core-public/nm-setting-vxlan.h \ + src/libnm-core-public/nm-setting-wifi-p2p.h \ + src/libnm-core-public/nm-setting-wimax.h \ + src/libnm-core-public/nm-setting-wired.h \ + src/libnm-core-public/nm-setting-wireguard.h \ + src/libnm-core-public/nm-setting-wireless-security.h \ + src/libnm-core-public/nm-setting-wireless.h \ + src/libnm-core-public/nm-setting-wpan.h \ + src/libnm-core-public/nm-setting.h \ + src/libnm-core-public/nm-simple-connection.h \ + src/libnm-core-public/nm-utils.h \ + src/libnm-core-public/nm-version-macros.h \ + src/libnm-core-public/nm-version.h \ + src/libnm-core-public/nm-vpn-dbus-interface.h \ + src/libnm-core-public/nm-vpn-editor-plugin.h \ + src/libnm-core-public/nm-vpn-plugin-info.h \ + $(NULL) +src_libnm_core_public_mkenums_h = \ + src/libnm-core-public/nm-core-enum-types.h \ + $(NULL) +src_libnm_core_impl_lib_h_priv = \ + src/libnm-core-impl/nm-connection-private.h \ + src/libnm-core-impl/nm-crypto-impl.h \ + src/libnm-core-impl/nm-crypto.h \ + src/libnm-core-impl/nm-default-libnm-core.h \ + src/libnm-core-impl/nm-property-compare.h \ + src/libnm-core-impl/nm-setting-private.h \ + src/libnm-core-impl/nm-team-utils.h \ + src/libnm-core-impl/nm-utils-private.h \ + src/libnm-core-intern/nm-core-internal.h \ + src/libnm-core-intern/nm-core-types-internal.h \ + src/libnm-core-intern/nm-keyfile-internal.h \ + src/libnm-core-intern/nm-keyfile-utils.h \ + src/libnm-core-intern/nm-meta-setting-base-impl.h \ + src/libnm-core-intern/nm-meta-setting-base.h \ + $(NULL) +src_libnm_core_impl_lib_c_settings_real = \ + src/libnm-core-impl/nm-setting-6lowpan.c \ + src/libnm-core-impl/nm-setting-8021x.c \ + src/libnm-core-impl/nm-setting-adsl.c \ + src/libnm-core-impl/nm-setting-bluetooth.c \ + src/libnm-core-impl/nm-setting-bond.c \ + src/libnm-core-impl/nm-setting-bridge-port.c \ + src/libnm-core-impl/nm-setting-bridge.c \ + src/libnm-core-impl/nm-setting-cdma.c \ + src/libnm-core-impl/nm-setting-connection.c \ + src/libnm-core-impl/nm-setting-dcb.c \ + src/libnm-core-impl/nm-setting-dummy.c \ + src/libnm-core-impl/nm-setting-ethtool.c \ + src/libnm-core-impl/nm-setting-generic.c \ + src/libnm-core-impl/nm-setting-gsm.c \ + src/libnm-core-impl/nm-setting-hostname.c \ + src/libnm-core-impl/nm-setting-infiniband.c \ + src/libnm-core-impl/nm-setting-ip-config.c \ + src/libnm-core-impl/nm-setting-ip-tunnel.c \ + src/libnm-core-impl/nm-setting-ip4-config.c \ + src/libnm-core-impl/nm-setting-ip6-config.c \ + src/libnm-core-impl/nm-setting-macsec.c \ + src/libnm-core-impl/nm-setting-macvlan.c \ + src/libnm-core-impl/nm-setting-match.c \ + src/libnm-core-impl/nm-setting-olpc-mesh.c \ + src/libnm-core-impl/nm-setting-ovs-bridge.c \ + src/libnm-core-impl/nm-setting-ovs-dpdk.c \ + src/libnm-core-impl/nm-setting-ovs-external-ids.c \ + src/libnm-core-impl/nm-setting-ovs-interface.c \ + src/libnm-core-impl/nm-setting-ovs-patch.c \ + src/libnm-core-impl/nm-setting-ovs-port.c \ + src/libnm-core-impl/nm-setting-ppp.c \ + src/libnm-core-impl/nm-setting-pppoe.c \ + src/libnm-core-impl/nm-setting-proxy.c \ + src/libnm-core-impl/nm-setting-serial.c \ + src/libnm-core-impl/nm-setting-sriov.c \ + src/libnm-core-impl/nm-setting-tc-config.c \ + src/libnm-core-impl/nm-setting-team-port.c \ + src/libnm-core-impl/nm-setting-team.c \ + src/libnm-core-impl/nm-setting-tun.c \ + src/libnm-core-impl/nm-setting-user.c \ + src/libnm-core-impl/nm-setting-veth.c \ + src/libnm-core-impl/nm-setting-vlan.c \ + src/libnm-core-impl/nm-setting-vpn.c \ + src/libnm-core-impl/nm-setting-vrf.c \ + src/libnm-core-impl/nm-setting-vxlan.c \ + src/libnm-core-impl/nm-setting-wifi-p2p.c \ + src/libnm-core-impl/nm-setting-wimax.c \ + src/libnm-core-impl/nm-setting-wired.c \ + src/libnm-core-impl/nm-setting-wireguard.c \ + src/libnm-core-impl/nm-setting-wireless-security.c \ + src/libnm-core-impl/nm-setting-wireless.c \ + src/libnm-core-impl/nm-setting-wpan.c \ + $(NULL) +src_libnm_core_impl_lib_c_real = \ + $(src_libnm_core_impl_lib_c_settings_real) \ + src/libnm-core-impl/nm-connection.c \ + src/libnm-core-impl/nm-crypto.c \ + src/libnm-core-impl/nm-dbus-utils.c \ + src/libnm-core-impl/nm-errors.c \ + src/libnm-core-impl/nm-keyfile-utils.c \ + src/libnm-core-impl/nm-keyfile.c \ + src/libnm-core-impl/nm-meta-setting-base-impl.c \ + src/libnm-core-impl/nm-property-compare.c \ + src/libnm-core-impl/nm-setting.c \ + src/libnm-core-impl/nm-simple-connection.c \ + src/libnm-core-impl/nm-team-utils.c \ + src/libnm-core-impl/nm-utils.c \ + src/libnm-core-impl/nm-vpn-editor-plugin.c \ + src/libnm-core-impl/nm-vpn-plugin-info.c \ + $(NULL) + +src_libnm_core_public_mkenums_c = \ + src/libnm-core-public/nm-core-enum-types.c \ + $(NULL) libnminclude_HEADERS += \ - $(libnm_core_lib_h_pub_real) + $(src_libnm_core_impl_lib_h_pub_real) nodist_libnminclude_HEADERS += \ - $(libnm_core_lib_h_pub_mkenums) + $(src_libnm_core_public_mkenums_h) + +EXTRA_DIST += \ + src/libnm-core-impl/README.md \ + src/libnm-core-impl/meson.build \ + src/libnm-core-intern/README.md \ + src/libnm-core-intern/meson.build \ + src/libnm-core-public/README.md \ + src/libnm-core-public/meson.build \ + $(NULL) ############################################################################### @@ -1175,119 +1194,123 @@ dflt_cppflags_libnm_core = \ $(dflt_cppflags) \ -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ + -I$(srcdir)/src \ $(CODE_COVERAGE_CFLAGS) \ $(GLIB_CFLAGS) \ $(LIBUDEV_CFLAGS) \ $(SANITIZER_LIB_CFLAGS) \ $(NULL) -noinst_LTLIBRARIES += libnm-core/libnm-core.la +noinst_LTLIBRARIES += src/libnm-core-impl/libnm-core-impl.la GLIB_GENERATED += \ - $(libnm_core_lib_h_pub_mkenums) \ - $(libnm_core_lib_c_mkenums) -nm_core_enum_types_sources = $(libnm_core_lib_h_pub_real) - -nm_core_enum_types_MKENUMS_C_FLAGS = --identifier-prefix NM --fhead '\#include "libnm-core/nm-default-libnm-core.h"\n' - -libnm-core/nm-core-enum-types.h.stamp: libnm-core/.dirstamp -libnm-core/nm-core-enum-types.c.stamp: libnm-core/.dirstamp - -$(dispatcher_libnm_dispatcher_core_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(dispatcher_nm_dispatcher_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_core_libnm_core_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_libnm_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_tests_libnm_vpn_plugin_utils_test_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_NetworkManager_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_devices_adsl_libnm_device_plugin_adsl_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_devices_bluetooth_libnm_device_plugin_bluetooth_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_devices_team_libnm_device_plugin_team_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_devices_wifi_libnm_device_plugin_wifi_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_devices_wwan_libnm_device_plugin_wwan_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_devices_ovs_libnm_device_plugin_ovs_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) - -libnm_core_libnm_core_la_CPPFLAGS = \ + $(src_libnm_core_public_mkenums_h) \ + $(src_libnm_core_public_mkenums_c) \ + $(NULL) +nm_core_enum_types_sources = $(src_libnm_core_impl_lib_h_pub_real) + +nm_core_enum_types_MKENUMS_C_FLAGS = --identifier-prefix NM --fhead '\#include "src/libnm-core-impl/nm-default-libnm-core.h"\n' + +src/libnm-core-public/nm-core-enum-types.h.stamp: src/libnm-core-public/.dirstamp +src/libnm-core-public/nm-core-enum-types.c.stamp: src/libnm-core-public/.dirstamp + +$(dispatcher_libnm_dispatcher_core_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(dispatcher_nm_dispatcher_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_libnm_core_impl_libnm_core_impl_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(libnm_libnm_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(libnm_tests_libnm_vpn_plugin_utils_test_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_NetworkManager_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_devices_adsl_libnm_device_plugin_adsl_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_devices_bluetooth_libnm_device_plugin_bluetooth_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_devices_team_libnm_device_plugin_team_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_devices_wifi_libnm_device_plugin_wifi_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_devices_wwan_libnm_device_plugin_wwan_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_devices_ovs_libnm_device_plugin_ovs_la_OBJECTS): $(src_libnm_core_public_mkenums_h) + +src_libnm_core_impl_libnm_core_impl_la_CPPFLAGS = \ $(dflt_cppflags_libnm_core) \ + -I$(srcdir)/src/libnm-core-intern/ \ -DG_LOG_DOMAIN=\""libnm"\" \ $(NULL) -libnm_core_libnm_core_la_SOURCES = \ - $(libnm_core_lib_h_pub_real) \ - $(libnm_core_lib_h_priv) \ - $(libnm_core_lib_c_real) +src_libnm_core_impl_libnm_core_impl_la_SOURCES = \ + $(src_libnm_core_impl_lib_h_pub_real) \ + $(src_libnm_core_impl_lib_h_priv) \ + $(src_libnm_core_impl_lib_c_real) -nodist_libnm_core_libnm_core_la_SOURCES = \ - $(libnm_core_lib_h_pub_mkenums) \ - $(libnm_core_lib_c_mkenums) +nodist_src_libnm_core_impl_libnm_core_impl_la_SOURCES = \ + $(src_libnm_core_public_mkenums_h) \ + $(src_libnm_core_public_mkenums_c) \ + $(NULL) -libnm_core_libnm_core_la_LIBADD = \ +src_libnm_core_impl_libnm_core_impl_la_LIBADD = \ $(GLIB_LIBS) \ $(UUID_LIBS) \ $(NULL) -libnm_core_libnm_core_la_LDFLAGS = \ +src_libnm_core_impl_libnm_core_impl_la_LDFLAGS = \ $(CODE_COVERAGE_LDFLAGS) \ $(SANITIZER_LIB_LDFLAGS) \ $(NULL) EXTRA_DIST += \ - libnm-core/nm-crypto-gnutls.c \ - libnm-core/nm-crypto-nss.c \ - libnm-core/meson.build \ + src/libnm-core-impl/nm-crypto-gnutls.c \ + src/libnm-core-impl/nm-crypto-nss.c \ + src/libnm-core-impl/meson.build \ $(NULL) -libnm-core/nm-vpn-dbus-types.xml: libnm-core/nm-vpn-dbus-interface.h tools/enums-to-docbook.pl - @$(MKDIR_P) libnm-core/ +src/libnm-core-public/nm-vpn-dbus-types.xml: src/libnm-core-public/nm-vpn-dbus-interface.h tools/enums-to-docbook.pl + @$(MKDIR_P) src/libnm-core-public/ $(AM_V_GEN) @PERL@ $(srcdir)/tools/enums-to-docbook.pl 'nm-vpn-dbus-types' 'VPN Plugin D-Bus API Types' $< >$@ -libnm-core/nm-dbus-types.xml: libnm-core/nm-dbus-interface.h tools/enums-to-docbook.pl - @$(MKDIR_P) libnm-core/ +src/libnm-core-public/nm-dbus-types.xml: src/libnm-core-public/nm-dbus-interface.h tools/enums-to-docbook.pl + @$(MKDIR_P) src/libnm-core-public/ $(AM_V_GEN) @PERL@ $(srcdir)/tools/enums-to-docbook.pl 'nm-dbus-types' 'NetworkManager D-Bus API Types' $< >$@ BUILT_SOURCES += \ - libnm-core/nm-vpn-dbus-types.xml \ - libnm-core/nm-dbus-types.xml + src/libnm-core-public/nm-vpn-dbus-types.xml \ + src/libnm-core-public/nm-dbus-types.xml dist_dependencies += \ - libnm-core/nm-vpn-dbus-types.xml \ - libnm-core/nm-dbus-types.xml + src/libnm-core-public/nm-vpn-dbus-types.xml \ + src/libnm-core-public/nm-dbus-types.xml ############################################################################### if HAVE_CRYPTO_GNUTLS if WITH_GNUTLS -libnm_crypto_lib = libnm-core/libnm-crypto-gnutls.la +libnm_crypto_lib = src/libnm-core-impl/libnm-crypto-gnutls.la else -check_ltlibraries += libnm-core/libnm-crypto-gnutls.la +check_ltlibraries += src/libnm-core-impl/libnm-crypto-gnutls.la endif -libnm_core_libnm_crypto_gnutls_la_SOURCES = libnm-core/nm-crypto-gnutls.c -libnm_core_libnm_crypto_gnutls_la_CPPFLAGS = \ - $(libnm_core_libnm_core_la_CPPFLAGS) \ +src_libnm_core_impl_libnm_crypto_gnutls_la_SOURCES = src/libnm-core-impl/nm-crypto-gnutls.c +src_libnm_core_impl_libnm_crypto_gnutls_la_CPPFLAGS = \ + $(src_libnm_core_impl_libnm_core_impl_la_CPPFLAGS) \ $(GNUTLS_CFLAGS) -libnm_core_libnm_crypto_gnutls_la_LDFLAGS = \ - $(libnm_core_libnm_core_la_LDFLAGS) -libnm_core_libnm_crypto_gnutls_la_LIBADD = \ +src_libnm_core_impl_libnm_crypto_gnutls_la_LDFLAGS = \ + $(src_libnm_core_impl_libnm_core_impl_la_LDFLAGS) +src_libnm_core_impl_libnm_crypto_gnutls_la_LIBADD = \ $(GLIB_LIBS) \ $(GNUTLS_LIBS) endif if HAVE_CRYPTO_NSS if WITH_NSS -libnm_crypto_lib = libnm-core/libnm-crypto-nss.la +libnm_crypto_lib = src/libnm-core-impl/libnm-crypto-nss.la else -check_ltlibraries += libnm-core/libnm-crypto-nss.la +check_ltlibraries += src/libnm-core-impl/libnm-crypto-nss.la endif -libnm_core_libnm_crypto_nss_la_SOURCES = libnm-core/nm-crypto-nss.c -libnm_core_libnm_crypto_nss_la_CPPFLAGS = \ - $(libnm_core_libnm_core_la_CPPFLAGS) \ +src_libnm_core_impl_libnm_crypto_nss_la_SOURCES = src/libnm-core-impl/nm-crypto-nss.c +src_libnm_core_impl_libnm_crypto_nss_la_CPPFLAGS = \ + $(src_libnm_core_impl_libnm_core_impl_la_CPPFLAGS) \ $(NSS_CFLAGS) -libnm_core_libnm_crypto_nss_la_LDFLAGS = \ - $(libnm_core_libnm_core_la_LDFLAGS) -libnm_core_libnm_crypto_nss_la_LIBADD = \ +src_libnm_core_impl_libnm_crypto_nss_la_LDFLAGS = \ + $(src_libnm_core_impl_libnm_core_impl_la_LDFLAGS) +src_libnm_core_impl_libnm_crypto_nss_la_LIBADD = \ $(GLIB_LIBS) \ $(NSS_LIBS) endif @@ -1297,56 +1320,57 @@ noinst_LTLIBRARIES += $(libnm_crypto_lib) ############################################################################### check_programs += \ - libnm-core/tests/test-compare \ - libnm-core/tests/test-crypto \ - libnm-core/tests/test-general \ - libnm-core/tests/test-keyfile \ - libnm-core/tests/test-secrets \ - libnm-core/tests/test-setting \ - libnm-core/tests/test-settings-defaults + src/libnm-core-impl/tests/test-compare \ + src/libnm-core-impl/tests/test-crypto \ + src/libnm-core-impl/tests/test-general \ + src/libnm-core-impl/tests/test-keyfile \ + src/libnm-core-impl/tests/test-secrets \ + src/libnm-core-impl/tests/test-setting \ + src/libnm-core-impl/tests/test-settings-defaults GLIB_GENERATED += \ - libnm-core/tests/nm-core-tests-enum-types.h \ - libnm-core/tests/nm-core-tests-enum-types.c -nm_core_tests_enum_types_sources = libnm-core/tests/test-general-enums.h -nm_core_tests_enum_types_MKENUMS_C_FLAGS = --fhead '\#include "libnm-core/nm-default-libnm-core.h"\n' + src/libnm-core-impl/tests/nm-core-tests-enum-types.h \ + src/libnm-core-impl/tests/nm-core-tests-enum-types.c +nm_core_tests_enum_types_sources = src/libnm-core-impl/tests/test-general-enums.h +nm_core_tests_enum_types_MKENUMS_C_FLAGS = --fhead '\#include "src/libnm-core-impl/nm-default-libnm-core.h"\n' -libnm-core/tests/nm-core-tests-enum-types.h.stamp: libnm-core/tests/.dirstamp -libnm-core/tests/nm-core-tests-enum-types.c.stamp: libnm-core/tests/.dirstamp +src/libnm-core-impl/tests/nm-core-tests-enum-types.h.stamp: src/libnm-core-impl/tests/.dirstamp +src/libnm-core-impl/tests/nm-core-tests-enum-types.c.stamp: src/libnm-core-impl/tests/.dirstamp -$(libnm_core_tests_test_general_OBJECTS): libnm-core/tests/nm-core-tests-enum-types.h +$(src_libnm_core_impl_tests_test_general_OBJECTS): src/libnm-core-impl/tests/nm-core-tests-enum-types.h -libnm_core_tests_cppflags = \ - -I$(srcdir)/libnm-core/tests \ - -I$(builddir)/libnm-core/tests \ +src_libnm_core_impl_tests_cppflags = \ + -I$(builddir)/src/libnm-core-impl/tests \ + -I$(srcdir)/src/libnm-core-impl/tests \ + -I$(srcdir)/src/libnm-core-impl \ $(dflt_cppflags_libnm_core) \ -DG_LOG_DOMAIN=\""test"\" \ $(SANITIZER_EXEC_CFLAGS) \ $(NULL) -libnm_core_tests_test_compare_CPPFLAGS = $(libnm_core_tests_cppflags) -libnm_core_tests_test_crypto_CPPFLAGS = $(libnm_core_tests_cppflags) -libnm_core_tests_test_general_CPPFLAGS = $(libnm_core_tests_cppflags) -libnm_core_tests_test_keyfile_CPPFLAGS = $(libnm_core_tests_cppflags) -libnm_core_tests_test_secrets_CPPFLAGS = $(libnm_core_tests_cppflags) -libnm_core_tests_test_setting_CPPFLAGS = $(libnm_core_tests_cppflags) -libnm_core_tests_test_settings_defaults_CPPFLAGS = $(libnm_core_tests_cppflags) +src_libnm_core_impl_tests_test_compare_CPPFLAGS = $(src_libnm_core_impl_tests_cppflags) +src_libnm_core_impl_tests_test_crypto_CPPFLAGS = $(src_libnm_core_impl_tests_cppflags) +src_libnm_core_impl_tests_test_general_CPPFLAGS = $(src_libnm_core_impl_tests_cppflags) +src_libnm_core_impl_tests_test_keyfile_CPPFLAGS = $(src_libnm_core_impl_tests_cppflags) +src_libnm_core_impl_tests_test_secrets_CPPFLAGS = $(src_libnm_core_impl_tests_cppflags) +src_libnm_core_impl_tests_test_setting_CPPFLAGS = $(src_libnm_core_impl_tests_cppflags) +src_libnm_core_impl_tests_test_settings_defaults_CPPFLAGS = $(src_libnm_core_impl_tests_cppflags) -libnm_core_tests_test_general_SOURCES = \ - libnm-core/tests/test-general-enums.h \ - libnm-core/tests/test-general.c \ +src_libnm_core_impl_tests_test_general_SOURCES = \ + src/libnm-core-impl/tests/test-general-enums.h \ + src/libnm-core-impl/tests/test-general.c \ $(NULL) -nodist_libnm_core_tests_test_general_SOURCES = \ - libnm-core/tests/nm-core-tests-enum-types.c \ - libnm-core/tests/nm-core-tests-enum-types.h \ +nodist_src_libnm_core_impl_tests_test_general_SOURCES = \ + src/libnm-core-impl/tests/nm-core-tests-enum-types.c \ + src/libnm-core-impl/tests/nm-core-tests-enum-types.h \ $(NULL) -libnm_core_tests_ldadd = \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/libnm-core.la \ +src_libnm_core_impl_tests_ldadd = \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-impl/libnm-core-impl.la \ $(libnm_crypto_lib) \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-base/libnm-base.la \ shared/systemd/libnm-systemd-shared.la \ shared/systemd/libnm-systemd-logging-stub.la \ @@ -1356,33 +1380,33 @@ libnm_core_tests_ldadd = \ $(GLIB_LIBS) \ $(NULL) -libnm_core_tests_ldflags = \ +src_libnm_core_impl_tests_ldflags = \ $(SANITIZER_EXEC_LDFLAGS) \ $(NULL) -libnm_core_tests_test_compare_LDADD = $(libnm_core_tests_ldadd) -libnm_core_tests_test_crypto_LDADD = $(libnm_core_tests_ldadd) -libnm_core_tests_test_general_LDADD = $(libnm_core_tests_ldadd) -libnm_core_tests_test_keyfile_LDADD = $(libnm_core_tests_ldadd) -libnm_core_tests_test_secrets_LDADD = $(libnm_core_tests_ldadd) -libnm_core_tests_test_setting_LDADD = $(libnm_core_tests_ldadd) -libnm_core_tests_test_settings_defaults_LDADD = $(libnm_core_tests_ldadd) - -libnm_core_tests_test_compare_LDFLAGS = $(libnm_core_tests_ldflags) -libnm_core_tests_test_crypto_LDFLAGS = $(libnm_core_tests_ldflags) -libnm_core_tests_test_general_LDFLAGS = $(libnm_core_tests_ldflags) -libnm_core_tests_test_keyfile_LDFLAGS = $(libnm_core_tests_ldflags) -libnm_core_tests_test_secrets_LDFLAGS = $(libnm_core_tests_ldflags) -libnm_core_tests_test_setting_LDFLAGS = $(libnm_core_tests_ldflags) -libnm_core_tests_test_settings_defaults_LDFLAGS = $(libnm_core_tests_ldflags) - -$(libnm_core_tests_test_compare_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_core_tests_test_crypto_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_core_tests_test_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_core_tests_test_keyfile_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_core_tests_test_secrets_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_core_tests_test_setting_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_core_tests_test_settings_defaults_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +src_libnm_core_impl_tests_test_compare_LDADD = $(src_libnm_core_impl_tests_ldadd) +src_libnm_core_impl_tests_test_crypto_LDADD = $(src_libnm_core_impl_tests_ldadd) +src_libnm_core_impl_tests_test_general_LDADD = $(src_libnm_core_impl_tests_ldadd) +src_libnm_core_impl_tests_test_keyfile_LDADD = $(src_libnm_core_impl_tests_ldadd) +src_libnm_core_impl_tests_test_secrets_LDADD = $(src_libnm_core_impl_tests_ldadd) +src_libnm_core_impl_tests_test_setting_LDADD = $(src_libnm_core_impl_tests_ldadd) +src_libnm_core_impl_tests_test_settings_defaults_LDADD = $(src_libnm_core_impl_tests_ldadd) + +src_libnm_core_impl_tests_test_compare_LDFLAGS = $(src_libnm_core_impl_tests_ldflags) +src_libnm_core_impl_tests_test_crypto_LDFLAGS = $(src_libnm_core_impl_tests_ldflags) +src_libnm_core_impl_tests_test_general_LDFLAGS = $(src_libnm_core_impl_tests_ldflags) +src_libnm_core_impl_tests_test_keyfile_LDFLAGS = $(src_libnm_core_impl_tests_ldflags) +src_libnm_core_impl_tests_test_secrets_LDFLAGS = $(src_libnm_core_impl_tests_ldflags) +src_libnm_core_impl_tests_test_setting_LDFLAGS = $(src_libnm_core_impl_tests_ldflags) +src_libnm_core_impl_tests_test_settings_defaults_LDFLAGS = $(src_libnm_core_impl_tests_ldflags) + +$(src_libnm_core_impl_tests_test_compare_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_libnm_core_impl_tests_test_crypto_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_libnm_core_impl_tests_test_general_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_libnm_core_impl_tests_test_keyfile_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_libnm_core_impl_tests_test_secrets_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_libnm_core_impl_tests_test_setting_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_libnm_core_impl_tests_test_settings_defaults_OBJECTS): $(src_libnm_core_public_mkenums_h) # test-cert.p12 created with: # @@ -1394,28 +1418,28 @@ $(libnm_core_tests_test_settings_defaults_OBJECTS): $(libnm_core_lib_h_pub_mkenu # -out test-cert.p12 EXTRA_DIST += \ - libnm-core/tests/certs/ca-no-ending-newline.pem \ - libnm-core/tests/certs/pkcs8-decrypted.der \ - libnm-core/tests/certs/pkcs8-enc-key.pem \ - libnm-core/tests/certs/pkcs8-noenc-key.pem \ - libnm-core/tests/certs/test2_ca_cert.pem \ - libnm-core/tests/certs/test2-cert.p12 \ - libnm-core/tests/certs/test2_key_and_cert.pem \ - libnm-core/tests/certs/test-aes-128-key.pem \ - libnm-core/tests/certs/test-aes-256-key.pem \ - libnm-core/tests/certs/test_ca_cert.der \ - libnm-core/tests/certs/test_ca_cert.pem \ - libnm-core/tests/certs/test-ca-cert.pem \ - libnm-core/tests/certs/test-cert.p12 \ - libnm-core/tests/certs/test_key_and_cert.pem \ - libnm-core/tests/certs/test-key-and-cert.pem \ - libnm-core/tests/certs/test-key-only-decrypted.der \ - libnm-core/tests/certs/test-key-only-decrypted.pem \ - libnm-core/tests/certs/test-key-only.pem \ - libnm-core/tests/certs/test-tpm2wrapped-key.pem \ - libnm-core/tests/nm-core-tests-enum-types.c.template \ - libnm-core/tests/nm-core-tests-enum-types.h.template \ - libnm-core/tests/meson.build + src/libnm-core-impl/tests/certs/ca-no-ending-newline.pem \ + src/libnm-core-impl/tests/certs/pkcs8-decrypted.der \ + src/libnm-core-impl/tests/certs/pkcs8-enc-key.pem \ + src/libnm-core-impl/tests/certs/pkcs8-noenc-key.pem \ + src/libnm-core-impl/tests/certs/test2_ca_cert.pem \ + src/libnm-core-impl/tests/certs/test2-cert.p12 \ + src/libnm-core-impl/tests/certs/test2_key_and_cert.pem \ + src/libnm-core-impl/tests/certs/test-aes-128-key.pem \ + src/libnm-core-impl/tests/certs/test-aes-256-key.pem \ + src/libnm-core-impl/tests/certs/test_ca_cert.der \ + src/libnm-core-impl/tests/certs/test_ca_cert.pem \ + src/libnm-core-impl/tests/certs/test-ca-cert.pem \ + src/libnm-core-impl/tests/certs/test-cert.p12 \ + src/libnm-core-impl/tests/certs/test_key_and_cert.pem \ + src/libnm-core-impl/tests/certs/test-key-and-cert.pem \ + src/libnm-core-impl/tests/certs/test-key-only-decrypted.der \ + src/libnm-core-impl/tests/certs/test-key-only-decrypted.pem \ + src/libnm-core-impl/tests/certs/test-key-only.pem \ + src/libnm-core-impl/tests/certs/test-tpm2wrapped-key.pem \ + src/libnm-core-impl/tests/nm-core-tests-enum-types.c.template \ + src/libnm-core-impl/tests/nm-core-tests-enum-types.h.template \ + src/libnm-core-impl/tests/meson.build ############################################################################### @@ -1543,13 +1567,6 @@ libnm_lib_c_real = \ libnm_lib_c_mkenums = \ libnm/nm-enum-types.c -libnm_lib_cppflags = \ - -I$(srcdir)/libnm \ - -I$(builddir)/libnm \ - $(dflt_cppflags_libnm_core) \ - -DG_LOG_DOMAIN=\""libnm"\" \ - $(NULL) - libnminclude_HEADERS += \ $(libnm_lib_h_pub_real) @@ -1561,8 +1578,12 @@ nodist_libnminclude_HEADERS += \ noinst_LTLIBRARIES += libnm/libnm_static.la libnm_libnm_static_la_CPPFLAGS = \ + -I$(builddir)/libnm \ + -I$(srcdir)/libnm \ + -I$(srcdir)/src \ + $(dflt_cppflags_libnm_core) \ + -DG_LOG_DOMAIN=\""libnm"\" \ $(INTROSPECTION_CFLAGS) \ - $(libnm_lib_cppflags) \ $(NULL) libnm_libnm_static_la_SOURCES = \ @@ -1575,10 +1596,10 @@ nodist_libnm_libnm_static_la_SOURCES = \ $(NULL) libnm_libnm_static_la_LIBADD = \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/libnm-core.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-impl/libnm-core-impl.la \ $(libnm_crypto_lib) \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-base/libnm-base.la \ introspection/libnmdbus.la \ shared/nm-glib-aux/libnm-glib-aux.la \ @@ -1594,7 +1615,7 @@ libnm_libnm_static_la_LIBADD = \ $(NULL) $(libnm_libnm_static_la_OBJECTS) : $(libnm_lib_h_pub_mkenums) -$(libnm_libnm_static_la_OBJECTS) : $(libnm_core_lib_h_pub_mkenums) +$(libnm_libnm_static_la_OBJECTS) : $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -1612,10 +1633,14 @@ nm_enum_types_MKENUMS_C_FLAGS = --identifier-prefix NM --fhead '\#include "libnm $(dispatcher_nm_dispatcher_OBJECTS): $(libnm_lib_h_pub_mkenums) $(dispatcher_libnm_dispatcher_core_la_OBJECTS): $(libnm_lib_h_pub_mkenums) $(libnm_libnm_la_OBJECTS): $(libnm_lib_h_pub_mkenums) -$(libnm_tests_libnm_vpn_plugin_utils_test_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(libnm_tests_libnm_vpn_plugin_utils_test_la_OBJECTS): $(src_libnm_core_public_mkenums_h) libnm_libnm_la_CPPFLAGS = \ - $(libnm_lib_cppflags) \ + -I$(builddir)/libnm \ + -I$(srcdir)/libnm \ + -I$(srcdir)/src \ + $(dflt_cppflags_libnm_core) \ + -DG_LOG_DOMAIN=\""libnm"\" \ $(LIBUDEV_CFLAGS) \ $(SANITIZER_LIB_CFLAGS) \ $(NULL) @@ -1670,10 +1695,10 @@ libnm_NM_1_0_gir_CFLAGS = \ $(NULL) libnm_NM_1_0_gir_LIBS = libnm/libnm.la libnm_NM_1_0_gir_FILES = \ - $(libnm_core_lib_h_pub_mkenums) \ - $(libnm_core_lib_h_pub_real) \ - $(libnm_core_lib_c_mkenums) \ - $(libnm_core_lib_c_real) \ + $(src_libnm_core_public_mkenums_h) \ + $(src_libnm_core_impl_lib_h_pub_real) \ + $(src_libnm_core_public_mkenums_c) \ + $(src_libnm_core_impl_lib_c_real) \ $(libnm_lib_h_pub_mkenums) \ $(libnm_lib_h_pub_real) \ $(libnm_lib_c_mkenums) \ @@ -1681,7 +1706,7 @@ libnm_NM_1_0_gir_FILES = \ libnm_NM_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=NM --symbol-prefix=nm libnm/libnm.typelib: libnm/libnm.gir - $(INTROSPECTION_COMPILER) --includedir=$(srcdir)/libnm-core --includedir=$(builddir)/libnm-core --includedir=$(srcdir)/libnm --includedir=$(builddir)/libnm $< -o $@ + $(INTROSPECTION_COMPILER) --includedir=$(srcdir)/src/libnm-core-public --includedir=$(builddir)/src/libnm-core-public --includedir=$(srcdir)/libnm --includedir=$(builddir)/libnm $< -o $@ INTROSPECTION_GIRS += libnm/NM-1.0.gir @@ -1713,7 +1738,7 @@ clients/cli/generate-docs-nm-settings-nmcli.xml: clients/cli/generate-docs-nm-se check-local-generate-docs-nm-settings-nmcli: endif -libnm_docs_sources = $(libnm_core_lib_c_settings_real) +libnm_docs_sources = $(src_libnm_core_impl_lib_c_settings_real) libnm/nm-property-infos-%.xml: tools/generate-docs-nm-property-infos.pl $(libnm_docs_sources) $(AM_V_GEN) $(srcdir)/tools/generate-docs-nm-property-infos.pl $(patsubst nm-property-infos-%.xml,%,$(notdir $@)) $@ $(filter-out $<,$^) @@ -1815,10 +1840,10 @@ libnm_tests_test_nm_client_LDFLAGS = $(libnm_tests_ldflags) libnm_tests_test_remote_settings_client_LDFLAGS = $(libnm_tests_ldflags) libnm_tests_test_secret_agent_LDFLAGS = $(libnm_tests_ldflags) -$(libnm_tests_test_libnm_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_tests_test_nm_client_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_tests_test_remote_settings_client_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(libnm_tests_test_secret_agent_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(libnm_tests_test_libnm_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(libnm_tests_test_nm_client_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(libnm_tests_test_remote_settings_client_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(libnm_tests_test_secret_agent_OBJECTS): $(src_libnm_core_public_mkenums_h) # tools/test-networkmanager-service.py uses libnm's typelib. Ensure it # is built first. @@ -1841,8 +1866,8 @@ libnm_tests_libnm_vpn_plugin_utils_test_la_CFLAGS = \ $(dflt_cppflags) \ -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ -I$(srcdir)/libnm \ -I$(builddir)/libnm \ $(GLIB_CFLAGS) \ @@ -2092,8 +2117,9 @@ shared_systemd_libnm_systemd_shared_la_LIBADD = \ src_core_libnm_systemd_core_la_cppflags = \ $(libsystemd_cppflags) \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ + -I$(srcdir)/src \ -I$(srcdir)/src/core \ -I$(srcdir)/src/core/systemd/sd-adapt-core \ -I$(srcdir)/src/core/systemd/src/systemd \ @@ -2181,7 +2207,7 @@ src_core_libnm_systemd_core_la_LIBADD = \ $(GLIB_LIBS) \ $(CODE_COVERAGE_LDFLAGS) \ $(NULL) -$(src_core_libnm_systemd_core_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_libnm_systemd_core_la_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/systemd/meson.build @@ -2270,7 +2296,7 @@ src_core_libNetworkManagerBase_la_LIBADD = \ $(LIBUDEV_LIBS) \ $(NULL) -$(src_core_libNetworkManagerBase_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_libNetworkManagerBase_la_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/platform/linux/nl802154.h @@ -2460,10 +2486,10 @@ src_core_libNetworkManager_la_SOURCES = \ src_core_libNetworkManager_la_LIBADD = \ src/core/libNetworkManagerBase.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/libnm-core.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-impl/libnm-core-impl.la \ $(libnm_crypto_lib) \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-platform/libnm-platform.la \ shared/nm-base/libnm-base.la \ shared/nm-log-core/libnm-log-core.la \ @@ -2488,7 +2514,7 @@ src_core_libNetworkManager_la_LIBADD = \ $(LIBCURL_LIBS) \ $(NULL) -$(src_core_libNetworkManager_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_libNetworkManager_la_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -2515,7 +2541,7 @@ src_core_libNetworkManagerTest_la_LIBADD = \ $(LIBUDEV_LIBS) \ $(NULL) -$(src_core_libNetworkManagerTest_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_libNetworkManagerTest_la_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -2536,7 +2562,7 @@ src_core_NetworkManager_all_sym_LDFLAGS = \ $(SANITIZER_EXEC_LDFLAGS) \ $(NULL) -$(src_core_NetworkManager_all_sym_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_NetworkManager_all_sym_OBJECTS): $(src_libnm_core_public_mkenums_h) src/core/NetworkManager.ver: src/core/NetworkManager-all-sym $(core_plugins) $(AM_V_GEN) NM="$(NM)" "$(srcdir)/tools/create-exports-NetworkManager.sh" --called-from-build "$(srcdir)" @@ -2562,7 +2588,7 @@ src_core_NetworkManager_LDFLAGS = \ $(SANITIZER_EXEC_LDFLAGS) \ $(NULL) -$(src_core_NetworkManager_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_NetworkManager_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -2573,10 +2599,10 @@ src_core_nm_iface_helper_SOURCES = \ src_core_nm_iface_helper_LDADD = \ src/core/libNetworkManagerBase.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/libnm-core.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-impl/libnm-core-impl.la \ $(libnm_crypto_lib) \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-platform/libnm-platform.la \ shared/nm-base/libnm-base.la \ shared/nm-log-core/libnm-log-core.la \ @@ -2600,7 +2626,7 @@ src_core_nm_iface_helper_LDFLAGS = \ -Wl,--version-script="$(srcdir)/linker-script-binary.ver" \ $(SANITIZER_EXEC_LDFLAGS) -$(src_core_nm_iface_helper_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_nm_iface_helper_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -2627,10 +2653,10 @@ src_core_initrd_nm_initrd_generator_SOURCES = \ src_core_initrd_nm_initrd_generator_LDADD = \ src/core/initrd/libnmi-core.la \ src/core/libNetworkManagerBase.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/libnm-core.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-impl/libnm-core-impl.la \ $(libnm_crypto_lib) \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-platform/libnm-platform.la \ shared/nm-base/libnm-base.la \ shared/nm-log-core/libnm-log-core.la \ @@ -2925,11 +2951,11 @@ src_core_initrd_tests_test_cmdline_reader_LDADD = \ $(GLIB_LIBS) \ $(NULL) -$(src_core_initrd_libnmi_core_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_initrd_nm_initrd_generator_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_initrd_tests_test_cmdline_reader_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_initrd_tests_test_ibft_reader_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_initrd_tests_test_dt_reader_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_initrd_libnmi_core_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_initrd_nm_initrd_generator_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_initrd_tests_test_cmdline_reader_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_initrd_tests_test_ibft_reader_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_initrd_tests_test_dt_reader_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -2987,8 +3013,8 @@ src_core_dhcp_tests_test_dhcp_utils_LDADD = $(src_core_dhcp_tests_ldadd) src_core_dhcp_tests_test_dhcp_dhclient_LDFLAGS = $(src_core_tests_ldflags) src_core_dhcp_tests_test_dhcp_utils_LDFLAGS = $(src_core_tests_ldflags) -$(src_core_dhcp_tests_test_dhcp_dhclient_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_dhcp_tests_test_dhcp_utils_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_dhcp_tests_test_dhcp_dhclient_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_dhcp_tests_test_dhcp_utils_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/dhcp/tests/test-dhclient-duid.leases \ @@ -3009,7 +3035,8 @@ src_core_ppp_nm_pppd_plugin_la_CPPFLAGS = \ $(dflt_cppflags) \ -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ -DG_LOG_DOMAIN=\""nm-pppd-plugin"\" \ $(GLIB_CFLAGS) @@ -3026,7 +3053,7 @@ src_core_ppp_nm_pppd_plugin_la_LIBADD = \ $(DL_LIBS) \ $(NULL) -$(src_core_ppp_nm_pppd_plugin_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_ppp_nm_pppd_plugin_la_OBJECTS): $(src_libnm_core_public_mkenums_h) src_core_ppp_libnm_ppp_plugin_la_SOURCES = \ src/core/ppp/nm-pppd-plugin.h \ @@ -3051,7 +3078,7 @@ src_core_ppp_libnm_ppp_plugin_la_LIBADD = \ $(GLIB_LIBS) \ $(NULL) -$(src_core_ppp_libnm_ppp_plugin_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_ppp_libnm_ppp_plugin_la_OBJECTS): $(src_libnm_core_public_mkenums_h) endif @@ -3074,7 +3101,7 @@ src_core_settings_plugins_keyfile_tests_test_keyfile_settings_LDFLAGS = \ src_core_settings_plugins_keyfile_tests_test_keyfile_settings_LDADD = \ src/core/libNetworkManagerTest.la -$(src_core_settings_plugins_keyfile_tests_test_keyfile_settings_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_settings_plugins_keyfile_tests_test_keyfile_settings_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection \ @@ -3170,7 +3197,7 @@ src_core_settings_plugins_ifcfg_rh_libnms_ifcfg_rh_core_la_SOURCES = \ src_core_settings_plugins_ifcfg_rh_libnms_ifcfg_rh_core_la_CPPFLAGS = $(src_core_cppflags_base) -$(src_core_settings_plugins_ifcfg_rh_libnms_ifcfg_rh_core_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_settings_plugins_ifcfg_rh_libnms_ifcfg_rh_core_la_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -3192,7 +3219,7 @@ src_core_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_LIBADD = \ src/core/settings/plugins/ifcfg-rh/libnms-ifcfg-rh-core.la $(src_core_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_OBJECTS): src/core/settings/plugins/ifcfg-rh/nmdbus-ifcfg-rh.h -$(src_core_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_OBJECTS): $(src_libnm_core_public_mkenums_h) check-local-symbols-settings-ifcfg-rh: src/core/settings/plugins/ifcfg-rh/libnm-settings-plugin-ifcfg-rh.la $(call check_so_symbols,$(builddir)/src/core/settings/plugins/ifcfg-rh/.libs/libnm-settings-plugin-ifcfg-rh.so) @@ -3219,7 +3246,7 @@ src_core_settings_plugins_ifcfg_rh_tests_test_ifcfg_rh_LDADD = \ src/core/settings/plugins/ifcfg-rh/libnms-ifcfg-rh-core.la \ src/core/libNetworkManagerTest.la -$(src_core_settings_plugins_ifcfg_rh_tests_test_ifcfg_rh_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_settings_plugins_ifcfg_rh_tests_test_ifcfg_rh_OBJECTS): $(src_libnm_core_public_mkenums_h) dist_libexec_SCRIPTS += \ src/core/settings/plugins/ifcfg-rh/nm-ifup \ @@ -3512,8 +3539,8 @@ src_core_settings_plugins_ifupdown_libnm_settings_plugin_ifupdown_la_LIBADD = \ $(LIBUDEV_LIBS) \ $(NULL) -$(src_core_settings_plugins_ifupdown_libnm_settings_plugin_ifupdown_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_settings_plugins_ifupdown_libnms_ifupdown_core_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_settings_plugins_ifupdown_libnm_settings_plugin_ifupdown_la_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_settings_plugins_ifupdown_libnms_ifupdown_core_la_OBJECTS): $(src_libnm_core_public_mkenums_h) check-local-symbols-settings-ifupdown: src/core/settings/plugins/ifupdown/libnm-settings-plugin-ifupdown.la $(call check_so_symbols,$(builddir)/src/core/settings/plugins/ifupdown/.libs/libnm-settings-plugin-ifupdown.so) @@ -3536,7 +3563,7 @@ src_core_settings_plugins_ifupdown_tests_test_ifupdown_LDADD = \ $(GLIB_LIBS) \ $(NULL) -$(src_core_settings_plugins_ifupdown_tests_test_ifupdown_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_settings_plugins_ifupdown_tests_test_ifupdown_OBJECTS): $(src_libnm_core_public_mkenums_h) endif @@ -3645,7 +3672,7 @@ src_core_devices_wwan_libnm_wwan_la_LIBADD = \ $(LIBSYSTEMD_LIBS) \ $(MM_GLIB_LIBS) -$(src_core_devices_wwan_libnm_wwan_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_devices_wwan_libnm_wwan_la_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_src_core_devices_wwan_libnm_wwan_la_DEPENDENCIES = \ src/core/devices/wwan/libnm-wwan.ver @@ -3697,7 +3724,7 @@ src_core_devices_wwan_tests_test_service_providers_LDADD = \ check_programs += src/core/devices/wwan/tests/test-service-providers -$(src_core_devices_wwan_tests_test_service_providers_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_devices_wwan_tests_test_service_providers_OBJECTS): $(src_libnm_core_public_mkenums_h) endif @@ -3739,7 +3766,7 @@ src_core_devices_bluetooth_libnm_bluetooth_utils_la_CPPFLAGS += $(BLUEZ5_CFLAGS) src_core_devices_bluetooth_libnm_bluetooth_utils_la_LIBADD += $(BLUEZ5_LIBS) endif -$(src_core_devices_bluetooth_libnm_bluetooth_utils_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_devices_bluetooth_libnm_bluetooth_utils_la_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -3783,7 +3810,7 @@ src_core_devices_bluetooth_tests_nm_bt_test_LDADD = \ $(GLIB_LIBS) \ $(NULL) -$(src_core_devices_bluetooth_tests_nm_bt_test_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_devices_bluetooth_tests_nm_bt_test_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -3838,7 +3865,7 @@ src_core_devices_wifi_libnm_wifi_base_la_CPPFLAGS = $(src_core_cppflags_device_p src_core_devices_wifi_libnm_wifi_base_la_LIBADD = \ $(GLIB_LIBS) -$(src_core_devices_wifi_libnm_wifi_base_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_devices_wifi_libnm_wifi_base_la_OBJECTS): $(src_libnm_core_public_mkenums_h) core_plugins += src/core/devices/wifi/libnm-device-plugin-wifi.la @@ -3878,7 +3905,7 @@ src_core_devices_wifi_tests_test_devices_wifi_LDADD = \ src_core_devices_wifi_tests_test_devices_wifi_LDFLAGS = $(SANITIZER_EXEC_LDFLAGS) -$(src_core_devices_wifi_tests_test_devices_wifi_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_devices_wifi_tests_test_devices_wifi_OBJECTS): $(src_libnm_core_public_mkenums_h) endif @@ -3995,7 +4022,7 @@ src_core_dnsmasq_tests_test_dnsmasq_utils_LDADD = \ src_core_dnsmasq_tests_test_dnsmasq_utils_LDFLAGS = \ $(SANITIZER_EXEC_LDFLAGS) -$(src_core_dnsmasq_tests_test_dnsmasq_utils_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_dnsmasq_tests_test_dnsmasq_utils_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/dnsmasq/tests/meson.build @@ -4094,19 +4121,19 @@ src_core_platform_tests_test_tc_linux_LDFLAGS = $(src_core_platform_tests_ldflag src_core_platform_tests_test_tc_linux_LDADD = $(src_core_platform_tests_libadd) -$(src_core_platform_tests_monitor_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_address_fake_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_address_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_cleanup_fake_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_cleanup_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_link_fake_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_link_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_nmp_object_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_platform_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_route_fake_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_route_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_tc_fake_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_platform_tests_test_tc_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_platform_tests_monitor_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_address_fake_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_address_linux_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_cleanup_fake_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_cleanup_linux_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_link_fake_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_link_linux_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_nmp_object_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_platform_general_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_route_fake_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_route_linux_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_tc_fake_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_platform_tests_test_tc_linux_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/platform/tests/meson.build \ @@ -4134,8 +4161,8 @@ src_core_devices_tests_test_acd_LDFLAGS = $(src_core_devices_tests_ldflags) src_core_devices_tests_test_acd_LDADD = \ src/core/libNetworkManagerTest.la -$(src_core_devices_tests_test_lldp_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_devices_tests_test_acd_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_devices_tests_test_lldp_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_devices_tests_test_acd_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/devices/tests/meson.build @@ -4163,8 +4190,8 @@ src_core_ndisc_tests_test_ndisc_fake_CPPFLAGS = $(src_core_cppflags_test) src_core_ndisc_tests_test_ndisc_fake_LDFLAGS = $(src_core_ndisc_tests_ldflags) src_core_ndisc_tests_test_ndisc_fake_LDADD = $(src_core_ndisc_tests_ldadd) -$(src_core_ndisc_tests_test_ndisc_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_ndisc_tests_test_ndisc_fake_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_ndisc_tests_test_ndisc_linux_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_ndisc_tests_test_ndisc_fake_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/ndisc/tests/meson.build @@ -4183,7 +4210,7 @@ src_core_supplicant_tests_test_supplicant_config_LDADD = \ src_core_supplicant_tests_test_supplicant_config_LDFLAGS = \ $(SANITIZER_EXEC_LDFLAGS) -$(src_core_supplicant_tests_test_supplicant_config_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_supplicant_tests_test_supplicant_config_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/supplicant/tests/certs/test-ca-cert.pem \ @@ -4209,7 +4236,7 @@ src_core_tests_config_test_config_LDADD = \ src_core_tests_config_test_config_LDFLAGS = \ $(SANITIZER_EXEC_LDFLAGS) -$(src_core_tests_config_test_config_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_tests_config_test_config_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/tests/config/NetworkManager.conf \ @@ -4278,14 +4305,14 @@ src_core_tests_test_l3cfg_CPPFLAGS = $(src_core_cppflags_test) src_core_tests_test_l3cfg_LDFLAGS = $(src_core_devices_tests_ldflags) src_core_tests_test_l3cfg_LDADD = $(src_core_tests_ldadd) -$(src_core_tests_test_core_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_tests_test_core_with_expect_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_tests_test_dcb_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_tests_test_ip4_config_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_tests_test_ip6_config_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_tests_test_l3cfg_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_tests_test_utils_OBJECTS): $(libnm_core_lib_h_pub_mkenums) -$(src_core_tests_test_wired_defname_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_tests_test_core_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_tests_test_core_with_expect_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_tests_test_dcb_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_tests_test_ip4_config_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_tests_test_ip6_config_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_tests_test_l3cfg_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_tests_test_utils_OBJECTS): $(src_libnm_core_public_mkenums_h) +$(src_core_tests_test_wired_defname_OBJECTS): $(src_libnm_core_public_mkenums_h) src_core_tests_test_systemd_CPPFLAGS = \ $(src_core_libnm_systemd_core_la_cppflags) \ @@ -4303,7 +4330,7 @@ src_core_tests_test_systemd_LDADD = \ $(CODE_COVERAGE_LDFLAGS) \ $(NULL) -$(src_core_tests_test_systemd_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(src_core_tests_test_systemd_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ src/core/tests/test-secret-agent.py \ @@ -4339,14 +4366,15 @@ noinst_LTLIBRARIES += \ dispatcher_cppflags = \ $(dflt_cppflags) \ - -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ - -I$(srcdir)/libnm \ - -I$(builddir)/libnm \ - -I$(srcdir)/dispatcher \ + -I$(srcdir)/shared \ -I$(builddir)/dispatcher \ + -I$(srcdir)/dispatcher \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ + -I$(builddir)/libnm \ + -I$(srcdir)/libnm \ + -I$(srcdir)/src \ $(GLIB_CFLAGS) \ -DG_LOG_DOMAIN=\""nm-dispatcher"\" \ $(NULL) @@ -4421,14 +4449,15 @@ check_programs += dispatcher/tests/test-dispatcher-envp dispatcher_tests_test_dispatcher_envp_CPPFLAGS = \ $(dflt_cppflags) \ - -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ - -I$(srcdir)/libnm \ - -I$(builddir)/libnm \ + -I$(srcdir)/shared \ -I$(srcdir)/dispatcher \ -I$(builddir)/dispatcher \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ + -I$(srcdir)/libnm \ + -I$(builddir)/libnm \ + -I$(srcdir)/src \ -DG_LOG_DOMAIN=\""NetworkManager"\" \ $(GLIB_CFLAGS) \ $(SANITIZER_EXEC_CFLAGS) \ @@ -4456,7 +4485,7 @@ dispatcher_tests_test_dispatcher_envp_LDADD = \ $(GLIB_LIBS) \ $(NULL) -$(dispatcher_tests_test_dispatcher_envp_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(dispatcher_tests_test_dispatcher_envp_OBJECTS): $(src_libnm_core_public_mkenums_h) EXTRA_DIST += \ dispatcher/tests/dispatcher-connectivity-full \ @@ -4479,8 +4508,8 @@ clients_nm_online_CPPFLAGS = \ $(dflt_cppflags) \ -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ -I$(srcdir)/libnm \ -I$(builddir)/libnm \ $(GLIB_CFLAGS) \ @@ -4501,7 +4530,7 @@ clients_nm_online_LDADD = \ $(GLIB_LIBS) \ $(NULL) -$(clients_nm_online_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_nm_online_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_nm_online_OBJECTS): $(libnm_lib_h_pub_mkenums) EXTRA_DIST += \ @@ -4515,11 +4544,13 @@ clients_cppflags = \ $(dflt_cppflags) \ -I$(srcdir)/shared \ -I$(builddir)/shared \ - -I$(srcdir)/libnm-core \ - -I$(builddir)/libnm-core \ - -I$(srcdir)/libnm \ - -I$(builddir)/libnm \ + -I$(builddir)/clients/common \ -I$(srcdir)/clients/common \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ + -I$(builddir)/libnm \ + -I$(srcdir)/libnm \ + -I$(srcdir)/src \ $(GLIB_CFLAGS) \ $(SANITIZER_EXEC_CFLAGS) \ $(NULL) @@ -4551,7 +4582,7 @@ clients_common_libnmc_base_la_LIBADD = \ $(GLIB_LIBS) \ $(NULL) -$(clients_common_libnmc_base_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_common_libnmc_base_la_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_common_libnmc_base_la_OBJECTS): $(libnm_lib_h_pub_mkenums) $(clients_common_libnmc_base_la_OBJECTS): clients/common/.dirstamp @@ -4591,7 +4622,6 @@ clients_common_libnmc_la_SOURCES = \ clients_common_libnmc_la_CPPFLAGS = \ $(clients_cppflags) \ - -I$(builddir)/clients/common \ -DG_LOG_DOMAIN=\""libnmc"\" \ $(NULL) @@ -4600,7 +4630,7 @@ clients_common_libnmc_la_LIBADD = \ $(GLIB_LIBS) \ $(NULL) -$(clients_common_libnmc_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_common_libnmc_la_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_common_libnmc_la_OBJECTS): $(clients_common_settings_doc_h) $(clients_common_libnmc_la_OBJECTS): clients/common/.dirstamp @@ -4624,8 +4654,8 @@ clients_common_tests_test_clients_common_LDFLAGS = \ clients_common_tests_test_clients_common_LDADD = \ clients/common/libnmc.la \ clients/common/libnmc-base.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-base/libnm-base.la \ shared/nm-glib-aux/libnm-glib-aux.la \ shared/nm-std-aux/libnm-std-aux.la \ @@ -4633,7 +4663,7 @@ clients_common_tests_test_clients_common_LDADD = \ libnm/libnm.la \ $(GLIB_LIBS) -$(clients_common_tests_test_clients_common_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_common_tests_test_clients_common_OBJECTS): $(src_libnm_core_public_mkenums_h) ############################################################################### @@ -4652,10 +4682,11 @@ clients_common_tests_test_libnm_core_aux_CPPFLAGS = \ $(dflt_cppflags) \ -I$(builddir)/shared \ -I$(srcdir)/shared \ - -I$(builddir)/libnm-core \ - -I$(srcdir)/libnm-core \ + -I$(builddir)/src/libnm-core-public \ + -I$(srcdir)/src/libnm-core-public \ -I$(builddir)/libnm \ -I$(srcdir)/libnm \ + -I$(srcdir)/src \ -DG_LOG_DOMAIN=\""test"\" \ $(CODE_COVERAGE_CFLAGS) \ $(GLIB_CFLAGS) \ @@ -4668,7 +4699,8 @@ clients_common_tests_test_libnm_core_aux_LDFLAGS = \ $(NULL) clients_common_tests_test_libnm_core_aux_LDADD = \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-glib-aux/libnm-glib-aux.la \ shared/nm-std-aux/libnm-std-aux.la \ shared/libcsiphash.la \ @@ -4676,7 +4708,7 @@ clients_common_tests_test_libnm_core_aux_LDADD = \ $(GLIB_LIBS) \ $(NULL) -$(clients_common_tests_test_libnm_core_aux_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_common_tests_test_libnm_core_aux_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_common_tests_test_libnm_core_aux_OBJECTS): $(libnm_lib_h_pub_mkenums) ############################################################################### @@ -4715,8 +4747,8 @@ clients_cli_nmcli_CPPFLAGS = \ clients_cli_nmcli_LDADD = \ clients/common/libnmc.la \ clients/common/libnmc-base.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-base/libnm-base.la \ shared/nm-glib-aux/libnm-glib-aux.la \ shared/nm-std-aux/libnm-std-aux.la \ @@ -4730,7 +4762,7 @@ clients_cli_nmcli_LDFLAGS = \ -Wl,--version-script="$(srcdir)/linker-script-binary.ver" \ $(SANITIZER_EXEC_LDFLAGS) -$(clients_cli_nmcli_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_cli_nmcli_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_cli_nmcli_OBJECTS): $(libnm_lib_h_pub_mkenums) install-data-hook-nmcli: @@ -4764,8 +4796,8 @@ clients_cli_generate_docs_nm_settings_nmcli_LDADD = \ clients/common/libnmc.la \ clients/common/libnmc-base.la \ libnm/nm-libnm-aux/libnm-libnm-aux.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-base/libnm-base.la \ libnm/libnm.la \ shared/nm-glib-aux/libnm-glib-aux.la \ @@ -4779,7 +4811,7 @@ clients_cli_generate_docs_nm_settings_nmcli_LDFLAGS = \ $(SANITIZER_EXEC_LDFLAGS) \ $(NULL) -$(clients_cli_generate_docs_nm_settings_nmcli_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_cli_generate_docs_nm_settings_nmcli_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_cli_generate_docs_nm_settings_nmcli_OBJECTS): $(libnm_lib_h_pub_mkenums) ############################################################################### @@ -4850,7 +4882,7 @@ clients_tui_newt_libnmt_newt_a_CPPFLAGS = \ $(NEWT_CFLAGS) \ $(NULL) -$(clients_tui_newt_libnmt_newt_a_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_tui_newt_libnmt_newt_a_OBJECTS): $(src_libnm_core_public_mkenums_h) bin_PROGRAMS += clients/tui/nmtui @@ -4955,8 +4987,8 @@ clients_tui_nmtui_LDADD = \ clients/common/libnmc.la \ clients/common/libnmc-base.la \ libnm/nm-libnm-aux/libnm-libnm-aux.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-base/libnm-base.la \ shared/nm-glib-aux/libnm-glib-aux.la \ shared/nm-std-aux/libnm-std-aux.la \ @@ -4966,7 +4998,7 @@ clients_tui_nmtui_LDADD = \ $(NEWT_LIBS) \ $(NULL) -$(clients_tui_nmtui_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_tui_nmtui_OBJECTS): $(src_libnm_core_public_mkenums_h) nmtui_links = nmtui-edit nmtui-connect nmtui-hostname @@ -5019,7 +5051,7 @@ clients_cloud_setup_libnm_cloud_setup_core_a_CPPFLAGS = \ $(LIBCURL_CFLAGS) \ $(NULL) -$(clients_cloud_setup_libnm_cloud_setup_core_a_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_cloud_setup_libnm_cloud_setup_core_a_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_cloud_setup_libnm_cloud_setup_core_a_OBJECTS): $(libnm_lib_h_pub_mkenums) libexec_PROGRAMS += clients/cloud-setup/nm-cloud-setup @@ -5042,8 +5074,8 @@ clients_cloud_setup_nm_cloud_setup_LDFLAGS = \ clients_cloud_setup_nm_cloud_setup_LDADD = \ clients/cloud-setup/libnm-cloud-setup-core.a \ libnm/nm-libnm-aux/libnm-libnm-aux.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-base/libnm-base.la \ shared/nm-glib-aux/libnm-glib-aux.la \ shared/nm-std-aux/libnm-std-aux.la \ @@ -5053,7 +5085,7 @@ clients_cloud_setup_nm_cloud_setup_LDADD = \ $(LIBCURL_LIBS) \ $(NULL) -$(clients_cloud_setup_nm_cloud_setup_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_cloud_setup_nm_cloud_setup_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_cloud_setup_nm_cloud_setup_OBJECTS): $(libnm_lib_h_pub_mkenums) if HAVE_SYSTEMD @@ -5108,8 +5140,8 @@ clients_cloud_setup_tests_test_cloud_setup_general_LDFLAGS = \ clients_cloud_setup_tests_test_cloud_setup_general_LDADD = \ clients/cloud-setup/libnm-cloud-setup-core.a \ libnm/nm-libnm-aux/libnm-libnm-aux.la \ - libnm-core/nm-libnm-core-aux/libnm-libnm-core-aux.la \ - libnm-core/nm-libnm-core-intern/libnm-libnm-core-intern.la \ + src/libnm-core-aux-extern/libnm-core-aux-extern.la \ + src/libnm-core-aux-intern/libnm-core-aux-intern.la \ shared/nm-base/libnm-base.la \ shared/nm-glib-aux/libnm-glib-aux.la \ shared/nm-std-aux/libnm-std-aux.la \ @@ -5119,7 +5151,7 @@ clients_cloud_setup_tests_test_cloud_setup_general_LDADD = \ $(LIBCURL_LIBS) \ $(NULL) -$(clients_cloud_setup_tests_test_cloud_setup_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums) +$(clients_cloud_setup_tests_test_cloud_setup_general_OBJECTS): $(src_libnm_core_public_mkenums_h) $(clients_cloud_setup_tests_test_cloud_setup_general_OBJECTS): $(libnm_lib_h_pub_mkenums) endif @@ -5447,7 +5479,9 @@ EXTRA_DIST += \ shared/nm-utils/nm-vpn-plugin-utils.h \ shared/meson.build \ \ - libnm-core/nm-version-macros.h.in \ + src/meson.build \ + \ + src/libnm-core-public/nm-version-macros.h.in \ \ tools/check-config-options.sh \ tools/check-docs.sh \ @@ -5526,7 +5560,7 @@ uninstall-hook: $(uninstall_hook) ############################################################################### cscope: - cscope -b -q -R -sshared -ssrc -slibnm-core -slibnm -sclients; + cscope -b -q -R -sshared -ssrc -slibnm -sclients; ############################################################################### diff --git a/Makefile.examples b/Makefile.examples index 3cb46293bb..7690baf252 100644 --- a/Makefile.examples +++ b/Makefile.examples @@ -3,12 +3,10 @@ ############################################################################### examples_C_glib_cppflags = \ - -I$(top_srcdir)/shared \ - -I$(top_builddir)/shared \ - -I$(top_srcdir)/libnm-core \ - -I$(top_builddir)/libnm-core \ - -I$(top_srcdir)/libnm \ + -I$(top_builddir)/src/libnm-core-public \ + -I$(top_srcdir)/src/libnm-core-public \ -I$(top_builddir)/libnm \ + -I$(top_srcdir)/libnm \ $(GLIB_CFLAGS) examples_C_glib_cppflags_gdbus = $(examples_C_glib_cppflags) @@ -75,8 +73,10 @@ EXTRA_DIST += \ if WITH_QT examples_C_qt_cppflags = \ - -I$(top_srcdir)/libnm-core \ - -I$(top_builddir)/libnm-core \ + -I$(top_builddir)/src/libnm-core-public \ + -I$(top_srcdir)/src/libnm-core-public \ + -I$(top_builddir)/libnm \ + -I$(top_srcdir)/libnm \ -I$(builddir)/examples/C/qt \ $(DBUS_CFLAGS) \ $(QT_CFLAGS) diff --git a/clients/cli/general.c b/clients/cli/general.c index 1dae57e116..8094ad7c71 100644 --- a/clients/cli/general.c +++ b/clients/cli/general.c @@ -7,7 +7,7 @@ #include -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-client-utils.h" diff --git a/clients/cli/meson.build b/clients/cli/meson.build index f8e6a8236d..7bb75d34a5 100644 --- a/clients/cli/meson.build +++ b/clients/cli/meson.build @@ -24,8 +24,12 @@ executable( dependencies: [ libnmc_base_dep, libnmc_dep, - readline_dep, libnm_libnm_aux_dep, + libnm_core_aux_extern_dep_link, + libnm_core_aux_intern_dep_link, + libnm_base_dep_link, + libnm_glib_aux_dep_link, + readline_dep, ], c_args: [ '-DG_LOG_DOMAIN="nmcli"', @@ -46,6 +50,10 @@ generate_docs_nm_settings_nmcli = executable( libnmc_base_dep, libnmc_dep, libnm_libnm_aux_dep, + libnm_core_aux_extern_dep_link, + libnm_core_aux_intern_dep_link, + libnm_base_dep_link, + libnm_glib_aux_dep_link, ], c_args: [ '-DG_LOG_DOMAIN="nmcli"', diff --git a/clients/cli/settings.c b/clients/cli/settings.c index 2c1037f222..4de1a37ebf 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -10,7 +10,7 @@ #include #include -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-client-utils.h" #include "nm-vpn-helpers.h" diff --git a/clients/cloud-setup/main.c b/clients/cloud-setup/main.c index 065901760a..7cee355d75 100644 --- a/clients/cloud-setup/main.c +++ b/clients/cloud-setup/main.c @@ -8,7 +8,7 @@ #include "nmcs-provider-ec2.h" #include "nmcs-provider-gcp.h" #include "nmcs-provider-azure.h" -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" /*****************************************************************************/ diff --git a/clients/cloud-setup/meson.build b/clients/cloud-setup/meson.build index 581dde6a18..debe19f02c 100644 --- a/clients/cloud-setup/meson.build +++ b/clients/cloud-setup/meson.build @@ -53,11 +53,13 @@ executable( 'main.c', ), dependencies: [ + libnm_cloud_setup_core_dep, libnmc_base_dep, libnmc_dep, + libnm_core_aux_intern_dep_link, + libnm_core_aux_extern_dep_link, + libnm_glib_aux_dep_link, libcurl_dep, - libnm_libnm_aux_dep, - libnm_cloud_setup_core_dep, ], c_args: [ '-DG_LOG_DOMAIN="nm-cloud-setup"', diff --git a/clients/cloud-setup/tests/meson.build b/clients/cloud-setup/tests/meson.build index 1c5e6ec667..976437af9a 100644 --- a/clients/cloud-setup/tests/meson.build +++ b/clients/cloud-setup/tests/meson.build @@ -4,9 +4,10 @@ exe = executable( 'test-cloud-setup-general', 'test-cloud-setup-general.c', dependencies: [ + libnm_cloud_setup_core_dep, libnmc_base_dep, libnmc_dep, - libnm_cloud_setup_core_dep, + libnm_glib_aux_dep_link, ], c_args: [ '-DG_LOG_DOMAIN="test"', diff --git a/clients/cloud-setup/tests/test-cloud-setup-general.c b/clients/cloud-setup/tests/test-cloud-setup-general.c index 63f3c13d59..e7d898e0e4 100644 --- a/clients/cloud-setup/tests/test-cloud-setup-general.c +++ b/clients/cloud-setup/tests/test-cloud-setup-general.c @@ -3,7 +3,7 @@ #include "libnm/nm-default-client.h" #include "nm-cloud-setup-utils.h" -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nm-utils/nm-test-utils.h" diff --git a/clients/common/meson.build b/clients/common/meson.build index 6b91f36ff0..260df35b68 100644 --- a/clients/common/meson.build +++ b/clients/common/meson.build @@ -76,7 +76,7 @@ libnmc = static_library( dependencies: [ libnm_dep, libnm_nm_default_dep, - libnm_libnm_core_aux_dep, + libnm_core_aux_extern_dep, ], c_args: [ '-DG_LOG_DOMAIN="libnmc"', diff --git a/clients/common/nm-client-utils.h b/clients/common/nm-client-utils.h index d6f163434a..0fd25c305d 100644 --- a/clients/common/nm-client-utils.h +++ b/clients/common/nm-client-utils.h @@ -9,7 +9,7 @@ #include "nm-meta-setting-desc.h" #include "nm-active-connection.h" #include "nm-device.h" -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" const NMObject **nmc_objects_sort_by_path(const NMObject *const *objs, gssize len); diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index b6e3d671fa..c0d086e433 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -12,11 +12,11 @@ #include #include -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-glib-aux/nm-enum-utils.h" #include "nm-glib-aux/nm-secret-utils.h" -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" -#include "nm-libnm-core-aux/nm-libnm-core-aux.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "libnm-core-aux-extern/nm-libnm-core-aux.h" #include "nm-vpn-helpers.h" #include "nm-client-utils.h" diff --git a/clients/common/nm-polkit-listener.c b/clients/common/nm-polkit-listener.c index 357e1efb8b..c83aa128bb 100644 --- a/clients/common/nm-polkit-listener.c +++ b/clients/common/nm-polkit-listener.c @@ -30,7 +30,7 @@ #include "nm-glib-aux/nm-str-buf.h" #include "nm-glib-aux/nm-secret-utils.h" #include "nm-glib-aux/nm-io-utils.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "c-list/src/c-list.h" #define LOGIND_BUS_NAME "org.freedesktop.login1" diff --git a/clients/common/tests/meson.build b/clients/common/tests/meson.build index 28b27ae9e0..0c2c727a46 100644 --- a/clients/common/tests/meson.build +++ b/clients/common/tests/meson.build @@ -6,6 +6,10 @@ exe = executable( dependencies: [ libnmc_base_dep, libnmc_dep, + libnm_core_aux_intern_dep_link, + libnm_core_aux_extern_dep_link, + libnm_glib_aux_dep_link, + libnm_base_dep_link, ], c_args: [ '-DG_LOG_DOMAIN="test"', @@ -23,8 +27,9 @@ exe = executable( 'test-libnm-core-aux.c', dependencies: [ libnm_dep, - libnm_libnm_core_aux_dep, + libnm_core_aux_extern_dep_link, libnm_nm_default_dep, + libnm_glib_aux_dep_link, ], c_args: [ '-DG_LOG_DOMAIN="test"', diff --git a/clients/common/tests/test-libnm-core-aux.c b/clients/common/tests/test-libnm-core-aux.c index bf639878c0..a0bfea25d2 100644 --- a/clients/common/tests/test-libnm-core-aux.c +++ b/clients/common/tests/test-libnm-core-aux.c @@ -5,8 +5,8 @@ #include "libnm/nm-default-client.h" -#include "nm-libnm-core-aux/nm-libnm-core-aux.h" -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" +#include "libnm-core-aux-extern/nm-libnm-core-aux.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nm-utils/nm-test-utils.h" diff --git a/clients/meson.build b/clients/meson.build index 2c92e29098..3e34c705cc 100644 --- a/clients/meson.build +++ b/clients/meson.build @@ -7,6 +7,7 @@ executable( libnm_dep, libnm_nm_default_dep, libnm_libnm_aux_dep, + libnm_glib_aux_dep_link, ], c_args: [ '-DG_LOG_DOMAIN="nm-online"', diff --git a/clients/tui/meson.build b/clients/tui/meson.build index 89f842e643..379200dbb0 100644 --- a/clients/tui/meson.build +++ b/clients/tui/meson.build @@ -51,6 +51,10 @@ executable( libnmc_dep, libnmt_newt_dep, libnm_libnm_aux_dep, + libnm_core_aux_extern_dep_link, + libnm_core_aux_intern_dep_link, + libnm_base_dep_link, + libnm_glib_aux_dep_link, ], c_args: [ '-DG_LOG_DOMAIN="nmtui"', diff --git a/clients/tui/nmt-mac-entry.c b/clients/tui/nmt-mac-entry.c index 2768eaab35..1f4cab9384 100644 --- a/clients/tui/nmt-mac-entry.c +++ b/clients/tui/nmt-mac-entry.c @@ -20,7 +20,7 @@ #include #include -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" G_DEFINE_TYPE(NmtMacEntry, nmt_mac_entry, NMT_TYPE_NEWT_ENTRY) diff --git a/clients/tui/nmt-page-bond.c b/clients/tui/nmt-page-bond.c index 9c86a49860..8dfc38f861 100644 --- a/clients/tui/nmt-page-bond.c +++ b/clients/tui/nmt-page-bond.c @@ -19,7 +19,7 @@ #include #include -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-mac-entry.h" #include "nmt-address-list.h" #include "nmt-slave-list.h" diff --git a/configure.ac b/configure.ac index 86ab9c6a5c..ba64a95835 100644 --- a/configure.ac +++ b/configure.ac @@ -1305,7 +1305,6 @@ AC_SUBST(AM_CFLAGS) AC_CONFIG_FILES([ Makefile -libnm-core/nm-version-macros.h libnm/libnm.pc po/Makefile.in data/org.freedesktop.NetworkManager.policy.in @@ -1314,6 +1313,7 @@ docs/api/version.xml docs/libnm/Makefile docs/libnm/version.xml NetworkManager.pc +src/libnm-core-public/nm-version-macros.h ]) AC_OUTPUT diff --git a/dispatcher/meson.build b/dispatcher/meson.build index d12e47145f..c0fe5f7187 100644 --- a/dispatcher/meson.build +++ b/dispatcher/meson.build @@ -40,7 +40,8 @@ executable( dependencies: [ libnm_dep, libnm_nm_default_dep, - libnm_libnm_aux_dep, + libnm_core_aux_extern_dep_link, + libnm_glib_aux_dep_link, ], c_args: [ '-DG_LOG_DOMAIN="nm-dispatcher"', diff --git a/dispatcher/nm-dispatcher-utils.c b/dispatcher/nm-dispatcher-utils.c index f1ec979f27..78885712f2 100644 --- a/dispatcher/nm-dispatcher-utils.c +++ b/dispatcher/nm-dispatcher-utils.c @@ -13,7 +13,7 @@ #include "nm-setting-ip6-config.h" #include "nm-setting-connection.h" -#include "nm-libnm-core-aux/nm-dispatcher-api.h" +#include "libnm-core-aux-extern/nm-dispatcher-api.h" #include "nm-utils.h" /*****************************************************************************/ diff --git a/dispatcher/nm-dispatcher.c b/dispatcher/nm-dispatcher.c index 9891bf3d15..06744ff3ab 100644 --- a/dispatcher/nm-dispatcher.c +++ b/dispatcher/nm-dispatcher.c @@ -16,7 +16,7 @@ #include #include -#include "nm-libnm-core-aux/nm-dispatcher-api.h" +#include "libnm-core-aux-extern/nm-dispatcher-api.h" #include "nm-dispatcher-utils.h" /*****************************************************************************/ diff --git a/dispatcher/tests/meson.build b/dispatcher/tests/meson.build index 84b4b61c66..9a86d098d2 100644 --- a/dispatcher/tests/meson.build +++ b/dispatcher/tests/meson.build @@ -9,7 +9,7 @@ exe = executable( include_directories: dispatcher_inc, dependencies: [ libnm_nm_default_dep, - libnm_glib_aux_dep, + libnm_glib_aux_dep_link, ], c_args: [ '-DG_LOG_DOMAIN="test"', diff --git a/dispatcher/tests/test-dispatcher-envp.c b/dispatcher/tests/test-dispatcher-envp.c index 4c37dd6c07..20097b56e6 100644 --- a/dispatcher/tests/test-dispatcher-envp.c +++ b/dispatcher/tests/test-dispatcher-envp.c @@ -9,7 +9,7 @@ #include #include "nm-dispatcher-utils.h" -#include "nm-libnm-core-aux/nm-dispatcher-api.h" +#include "libnm-core-aux-extern/nm-dispatcher-api.h" #include "nm-utils/nm-test-utils.h" diff --git a/docs/api/Makefile.am b/docs/api/Makefile.am index 65eed1a534..a5b71ad3fe 100644 --- a/docs/api/Makefile.am +++ b/docs/api/Makefile.am @@ -79,8 +79,8 @@ content_files = \ dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ dbus-org.freedesktop.NetworkManager.xml \ - $(top_builddir)/libnm-core/nm-dbus-types.xml \ - $(top_builddir)/libnm-core/nm-vpn-dbus-types.xml \ + $(top_builddir)/src/libnm-core-public/nm-dbus-types.xml \ + $(top_builddir)/src/libnm-core-public/nm-vpn-dbus-types.xml \ $(top_builddir)/man/nmcli.xml \ $(top_builddir)/man/nmtui.xml \ $(top_builddir)/man/nm-online.xml \ diff --git a/docs/api/network-manager-docs.xml b/docs/api/network-manager-docs.xml index 7a57582caa..f921b08604 100644 --- a/docs/api/network-manager-docs.xml +++ b/docs/api/network-manager-docs.xml @@ -265,7 +265,7 @@ Types - + @@ -289,7 +289,7 @@ Types - + diff --git a/docs/libnm/Makefile.am b/docs/libnm/Makefile.am index ae61d85af0..c868fff790 100644 --- a/docs/libnm/Makefile.am +++ b/docs/libnm/Makefile.am @@ -13,8 +13,10 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml # gtk-doc will search all .c & .h files beneath here for inline comments # documenting functions and macros. DOC_SOURCE_DIR= \ - $(top_srcdir)/libnm-core \ - $(top_builddir)/libnm-core \ + $(top_builddir)/src/libnm-core-public \ + $(top_srcdir)/src/libnm-core-public \ + $(top_builddir)/src/libnm-core-impl \ + $(top_srcdir)/src/libnm-core-impl \ $(top_srcdir)/libnm \ $(top_builddir)/libnm @@ -28,8 +30,8 @@ MKDB_OPTIONS=--sgml-mode --output-format=xml FIXXREF_OPTIONS= # Used for dependencies. -HFILE_GLOB=$(top_srcdir)/libnm-core/*.h $(top_srcdir)/libnm/*.h -CFILE_GLOB=$(top_srcdir)/libnm-core/*.c $(top_srcdir)/libnm/*.c +HFILE_GLOB=$(top_srcdir)/src/libnm-core-public/*.h $(top_srcdir)/libnm/*.h +CFILE_GLOB=$(top_srcdir)/src/libnm-core-impl/*.c $(top_srcdir)/libnm/*.c # Header files to ignore when scanning. IGNORE_HFILES= \ @@ -84,10 +86,10 @@ extra_files = libnm.png # CFLAGS and LDFLAGS for compiling scan program. Only needed # if $(DOC_MODULE).types is non-empty. GTKDOC_CFLAGS = \ - -I$(top_srcdir)/libnm-core \ - -I$(top_builddir)/libnm-core \ - -I$(top_srcdir)/libnm \ + -I$(top_builddir)/src/libnm-core-public \ + -I$(top_srcdir)/src/libnm-core-public \ -I$(top_builddir)/libnm \ + -I$(top_srcdir)/libnm \ -DNM_VERSION_MIN_REQUIRED=NM_VERSION_0_9_8 \ $(GLIB_CFLAGS) \ $(SANITIZER_EXEC_CFLAGS) diff --git a/docs/libnm/meson.build b/docs/libnm/meson.build index 102009899d..7cb5c646ee 100644 --- a/docs/libnm/meson.build +++ b/docs/libnm/meson.build @@ -1,10 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -src_dirs = [ - libnm_core_inc, - libnm_inc, -] - private_headers = [ 'common.h', 'nm-core-internal.h', @@ -57,7 +52,10 @@ version_xml = configure_file( gnome.gtkdoc( libnm_name, main_xml: libnm_name + '-docs.xml', - src_dir: src_dirs, + src_dir: [ + libnm_core_public_inc, + libnm_inc, + ], dependencies: libnm_dep, scan_args: scan_args, scanobjs_args: '--type-init-func="g_type_init();"', diff --git a/examples/C/qt/meson.build b/examples/C/qt/meson.build index 7e4e127419..8b905bd61d 100644 --- a/examples/C/qt/meson.build +++ b/examples/C/qt/meson.build @@ -6,13 +6,6 @@ examples = [ ['change-ipv4-addresses', []], ] -deps = [ - dbus_dep, - qt_core_dep, - qt_dbus_dep, - qt_network_dep, -] - moc = find_program('moc-qt4', required: false) if not moc.found() moc = qt_core_dep.get_pkgconfig_variable('moc_location') @@ -34,8 +27,13 @@ foreach example: examples executable( example[0], example[0] + '.cpp', - include_directories: libnm_core_inc, - dependencies: deps, + include_directories: libnm_core_public_inc, + dependencies: [ + dbus_dep, + qt_core_dep, + qt_dbus_dep, + qt_network_dep, + ], link_depends: example[1], ) endforeach diff --git a/libnm-core/meson.build b/libnm-core/meson.build deleted file mode 100644 index ec9fb8ce52..0000000000 --- a/libnm-core/meson.build +++ /dev/null @@ -1,280 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later - -libnm_core_inc = include_directories('.') - -nm_version_macro_header = configure_file( - input: 'nm-version-macros.h.in', - output: '@BASENAME@', - configuration: data_conf, -) - -libnm_core_nm_default_dep = declare_dependency( - sources: nm_version_macro_header, - include_directories: libnm_core_inc, - dependencies: glib_nm_default_dep, -) - -libnm_core_headers = files( - 'nm-connection.h', - 'nm-core-types.h', - 'nm-dbus-interface.h', - 'nm-errors.h', - 'nm-keyfile.h', - 'nm-setting-6lowpan.h', - 'nm-setting-8021x.h', - 'nm-setting-adsl.h', - 'nm-setting-bluetooth.h', - 'nm-setting-bond.h', - 'nm-setting-bridge-port.h', - 'nm-setting-bridge.h', - 'nm-setting-cdma.h', - 'nm-setting-connection.h', - 'nm-setting-dcb.h', - 'nm-setting-dummy.h', - 'nm-setting-ethtool.h', - 'nm-setting-generic.h', - 'nm-setting-gsm.h', - 'nm-setting-hostname.h', - 'nm-setting-infiniband.h', - 'nm-setting-ip-config.h', - 'nm-setting-ip-tunnel.h', - 'nm-setting-ip4-config.h', - 'nm-setting-ip6-config.h', - 'nm-setting-macsec.h', - 'nm-setting-macvlan.h', - 'nm-setting-match.h', - 'nm-setting-olpc-mesh.h', - 'nm-setting-ovs-bridge.h', - 'nm-setting-ovs-dpdk.h', - 'nm-setting-ovs-external-ids.h', - 'nm-setting-ovs-interface.h', - 'nm-setting-ovs-patch.h', - 'nm-setting-ovs-port.h', - 'nm-setting-ppp.h', - 'nm-setting-pppoe.h', - 'nm-setting-proxy.h', - 'nm-setting-serial.h', - 'nm-setting-sriov.h', - 'nm-setting-tc-config.h', - 'nm-setting-team-port.h', - 'nm-setting-team.h', - 'nm-setting-tun.h', - 'nm-setting-user.h', - 'nm-setting-veth.h', - 'nm-setting-vlan.h', - 'nm-setting-vpn.h', - 'nm-setting-vrf.h', - 'nm-setting-vxlan.h', - 'nm-setting-wifi-p2p.h', - 'nm-setting-wimax.h', - 'nm-setting-wired.h', - 'nm-setting-wireguard.h', - 'nm-setting-wireless-security.h', - 'nm-setting-wireless.h', - 'nm-setting-wpan.h', - 'nm-setting.h', - 'nm-simple-connection.h', - 'nm-utils.h', - 'nm-version.h', - 'nm-vpn-dbus-interface.h', - 'nm-vpn-editor-plugin.h', - 'nm-vpn-plugin-info.h', -) - -libnm_core_enum_sources = gnome.mkenums_simple( - 'nm-core-enum-types', - sources: libnm_core_headers + [nm_version_macro_header], - identifier_prefix: nm_id_prefix, - body_prefix: '#include "libnm-core/nm-default-libnm-core.h"', - install_header: true, - install_dir: libnm_pkgincludedir, -) - -libnm_libnm_core_intern = static_library( - 'nm-libnm-core-intern', - sources: files( - 'nm-libnm-core-intern/nm-auth-subject.c', - 'nm-libnm-core-intern/nm-libnm-core-utils.c', - ) + [libnm_core_enum_sources[1]], - dependencies: [ - libnm_core_nm_default_dep, - libnm_base_dep, - ], - c_args: [ - '-DG_LOG_DOMAIN="libnm"', - ], -) - -libnm_libnm_core_intern_dep = declare_dependency( - sources: [libnm_core_enum_sources[1], nm_version_macro_header], - include_directories: [libnm_core_inc, shared_inc], - dependencies: [ - libnm_glib_aux_dep, - libnm_base_dep, - ], - link_with: libnm_libnm_core_intern, -) - -libnm_crypto = static_library( - 'nm-crypto', - sources: 'nm-crypto-@0@.c'.format(crypto), - dependencies: [ - crypto_dep, - libnm_glib_aux_dep, - ], - c_args: [ - '-DG_LOG_DOMAIN="libnm"', - ], -) - -libnm_core_settings_sources = files( - 'nm-setting-6lowpan.c', - 'nm-setting-8021x.c', - 'nm-setting-adsl.c', - 'nm-setting-bluetooth.c', - 'nm-setting-bond.c', - 'nm-setting-bridge-port.c', - 'nm-setting-bridge.c', - 'nm-setting-cdma.c', - 'nm-setting-connection.c', - 'nm-setting-dcb.c', - 'nm-setting-dummy.c', - 'nm-setting-ethtool.c', - 'nm-setting-generic.c', - 'nm-setting-gsm.c', - 'nm-setting-hostname.c', - 'nm-setting-infiniband.c', - 'nm-setting-ip-config.c', - 'nm-setting-ip-tunnel.c', - 'nm-setting-ip4-config.c', - 'nm-setting-ip6-config.c', - 'nm-setting-macsec.c', - 'nm-setting-macvlan.c', - 'nm-setting-match.c', - 'nm-setting-olpc-mesh.c', - 'nm-setting-ovs-bridge.c', - 'nm-setting-ovs-dpdk.c', - 'nm-setting-ovs-external-ids.c', - 'nm-setting-ovs-interface.c', - 'nm-setting-ovs-patch.c', - 'nm-setting-ovs-port.c', - 'nm-setting-ppp.c', - 'nm-setting-pppoe.c', - 'nm-setting-proxy.c', - 'nm-setting-serial.c', - 'nm-setting-sriov.c', - 'nm-setting-tc-config.c', - 'nm-setting-team-port.c', - 'nm-setting-team.c', - 'nm-setting-tun.c', - 'nm-setting-user.c', - 'nm-setting-veth.c', - 'nm-setting-vlan.c', - 'nm-setting-vpn.c', - 'nm-setting-vrf.c', - 'nm-setting-vxlan.c', - 'nm-setting-wifi-p2p.c', - 'nm-setting-wimax.c', - 'nm-setting-wired.c', - 'nm-setting-wireguard.c', - 'nm-setting-wireless-security.c', - 'nm-setting-wireless.c', - 'nm-setting-wpan.c', -) - -libnm_core_sources = libnm_core_settings_sources + files( - 'nm-connection.c', - 'nm-crypto.c', - 'nm-dbus-utils.c', - 'nm-errors.c', - 'nm-keyfile-utils.c', - 'nm-keyfile.c', - 'nm-meta-setting-base-impl.c', - 'nm-property-compare.c', - 'nm-setting.c', - 'nm-simple-connection.c', - 'nm-team-utils.c', - 'nm-utils.c', - 'nm-vpn-editor-plugin.c', - 'nm-vpn-plugin-info.c', -) - -libnm_core = static_library( - 'nm-core', - sources: libnm_core_sources + libnm_core_enum_sources + [nm_version_macro_header], - include_directories: top_inc, - dependencies: [ - dl_dep, - libnm_systemd_shared_dep, - libnm_glib_aux_dep, - uuid_dep, - ], - c_args: [ - '-DG_LOG_DOMAIN="libnm"', - ], - link_with: [ - libnm_crypto, - libnm_libnm_core_intern, - ], -) - -libnm_core_dep = declare_dependency( - sources: [libnm_core_enum_sources[1], nm_version_macro_header], - include_directories: [libnm_core_inc, shared_inc], - dependencies: glib_dep, - link_with: libnm_core, -) - -libnm_libnm_core_aux = static_library( - 'nm-libnm-core-aux', - sources: files( - 'nm-libnm-core-aux/nm-libnm-core-aux.c', - ) + [libnm_core_enum_sources[1]], - dependencies: libnm_glib_aux_dep, - c_args: [ - '-DG_LOG_DOMAIN="libnm"', - ], - link_with: [ - libnm_libnm_core_intern, - libnm_base, - ], -) - -libnm_libnm_core_aux_dep = declare_dependency( - sources: [libnm_core_enum_sources[1], nm_version_macro_header], - include_directories: [libnm_core_inc, shared_inc], - dependencies: glib_dep, - link_with: libnm_libnm_core_aux, -) - -docbooks = [ - ['nm-dbus-types', 'nm-dbus-interface.h', 'NetworkManager D-Bus API Types'], - ['nm-vpn-dbus-types', 'nm-vpn-dbus-interface.h', 'VPN Plugin D-Bus API Types'], -] - -foreach docbook: docbooks - output = docbook[0] + '.xml' - - xml = custom_target( - output, - input: docbook[1], - output: output, - capture: true, - command: [ - perl, - join_paths(source_root, 'tools', 'enums-to-docbook.pl'), - docbook[0], - docbook[2], - '@INPUT@', - ], - # FIXME: gtkdoc does not depend directly on this. - # https://github.com/mesonbuild/meson/pull/2806 - build_by_default: true, - ) - - content_files += xml.full_path() -endforeach - -if enable_tests - subdir('tests') -endif diff --git a/libnm-core/nm-connection-private.h b/libnm-core/nm-connection-private.h deleted file mode 100644 index 532b17637b..0000000000 --- a/libnm-core/nm-connection-private.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 Red Hat, Inc. - */ - -#ifndef __NM_CONNECTION_PRIVATE_H__ -#define __NM_CONNECTION_PRIVATE_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) - #error Cannot use this header. -#endif - -#include "nm-setting.h" -#include "nm-connection.h" - -NMSetting *_nm_connection_find_base_type_setting(NMConnection *connection); - -const char *_nm_connection_detect_slave_type(NMConnection *connection, NMSetting **out_s_port); - -gboolean _nm_connection_detect_slave_type_full(NMSettingConnection *s_con, - NMConnection * connection, - const char ** out_slave_type, - const char ** out_normerr_slave_setting_type, - const char ** out_normerr_missing_slave_type, - const char **out_normerr_missing_slave_type_port, - GError ** error); - -const char *_nm_connection_detect_bluetooth_type(NMConnection *self); - -gboolean _nm_connection_verify_required_interface_name(NMConnection *connection, GError **error); - -int _nm_setting_ovs_interface_verify_interface_type(NMSettingOvsInterface *self, - const char * type, - NMConnection * connection, - gboolean normalize, - gboolean * out_modified, - const char ** out_normalized_type, - GError ** error); - -#endif /* __NM_CONNECTION_PRIVATE_H__ */ diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c deleted file mode 100644 index b39c41d7bd..0000000000 --- a/libnm-core/nm-connection.c +++ /dev/null @@ -1,3391 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2018 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-connection.h" - -#include - -#include "nm-connection-private.h" -#include "nm-utils.h" -#include "nm-setting-private.h" -#include "nm-core-internal.h" - -/** - * SECTION:nm-connection - * @short_description: Describes a connection to specific network or provider - * - * An #NMConnection describes all the settings and configuration values that - * are necessary to configure network devices for operation on a specific - * network. Connections are the fundamental operating object for - * NetworkManager; no device is connected without a #NMConnection, or - * disconnected without having been connected with a #NMConnection. - * - * Each #NMConnection contains a list of #NMSetting objects usually referenced - * by name (using nm_connection_get_setting_by_name()) or by type (with - * nm_connection_get_setting()). The settings describe the actual parameters - * with which the network devices are configured, including device-specific - * parameters (MTU, SSID, APN, channel, rate, etc) and IP-level parameters - * (addresses, routes, addressing methods, etc). - * - */ - -/*****************************************************************************/ - -enum { SECRETS_UPDATED, SECRETS_CLEARED, CHANGED, LAST_SIGNAL }; - -static guint signals[LAST_SIGNAL] = {0}; - -typedef struct { - NMConnection *self; - - GHashTable *settings; - - /* D-Bus path of the connection, if any */ - char *path; -} NMConnectionPrivate; - -G_DEFINE_INTERFACE(NMConnection, nm_connection, G_TYPE_OBJECT) - -static NMConnectionPrivate *nm_connection_get_private(NMConnection *connection); -#define NM_CONNECTION_GET_PRIVATE(o) (nm_connection_get_private((NMConnection *) o)) - -/*****************************************************************************/ - -static gpointer -_gtype_to_hash_key(GType gtype) -{ -#if NM_MORE_ASSERTS - _nm_unused const gsize *const test_gtype_typedef = >ype; - - nm_assert((GType)(GPOINTER_TO_SIZE(GSIZE_TO_POINTER(gtype))) == gtype); - G_STATIC_ASSERT_EXPR(sizeof(gpointer) >= sizeof(gsize)); - G_STATIC_ASSERT_EXPR(sizeof(gsize) == sizeof(GType)); -#endif - - return GSIZE_TO_POINTER(gtype); -} - -/*****************************************************************************/ - -static void -setting_changed_cb(NMSetting *setting, GParamSpec *pspec, NMConnection *self) -{ - g_signal_emit(self, signals[CHANGED], 0); -} - -static void -_setting_release(NMConnection *connection, NMSetting *setting) -{ - g_signal_handlers_disconnect_by_func(setting, setting_changed_cb, connection); -} - -static gboolean -_setting_release_hfr(gpointer key, gpointer value, gpointer user_data) -{ - _setting_release(user_data, value); - return TRUE; -} - -static void -_nm_connection_add_setting(NMConnection *connection, NMSetting *setting) -{ - NMConnectionPrivate *priv; - GType setting_type; - NMSetting * s_old; - - nm_assert(NM_IS_CONNECTION(connection)); - nm_assert(NM_IS_SETTING(setting)); - - priv = NM_CONNECTION_GET_PRIVATE(connection); - setting_type = G_OBJECT_TYPE(setting); - - if ((s_old = g_hash_table_lookup(priv->settings, _gtype_to_hash_key(setting_type)))) - _setting_release(connection, s_old); - - g_hash_table_insert(priv->settings, _gtype_to_hash_key(setting_type), setting); - - g_signal_connect(setting, "notify", (GCallback) setting_changed_cb, connection); -} - -/** - * nm_connection_add_setting: - * @connection: a #NMConnection - * @setting: (transfer full): the #NMSetting to add to the connection object - * - * Adds a #NMSetting to the connection, replacing any previous #NMSetting of the - * same name which has previously been added to the #NMConnection. The - * connection takes ownership of the #NMSetting object and does not increase - * the setting object's reference count. - **/ -void -nm_connection_add_setting(NMConnection *connection, NMSetting *setting) -{ - g_return_if_fail(NM_IS_CONNECTION(connection)); - g_return_if_fail(NM_IS_SETTING(setting)); - - _nm_connection_add_setting(connection, setting); - g_signal_emit(connection, signals[CHANGED], 0); -} - -gboolean -_nm_connection_remove_setting(NMConnection *connection, GType setting_type) -{ - NMConnectionPrivate *priv; - NMSetting * setting; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); - g_return_val_if_fail(g_type_is_a(setting_type, NM_TYPE_SETTING), FALSE); - - priv = NM_CONNECTION_GET_PRIVATE(connection); - setting = g_hash_table_lookup(priv->settings, _gtype_to_hash_key(setting_type)); - if (setting) { - g_signal_handlers_disconnect_by_func(setting, setting_changed_cb, connection); - g_hash_table_remove(priv->settings, _gtype_to_hash_key(setting_type)); - g_signal_emit(connection, signals[CHANGED], 0); - return TRUE; - } - return FALSE; -} - -/** - * nm_connection_remove_setting: - * @connection: a #NMConnection - * @setting_type: the #GType of the setting object to remove - * - * Removes the #NMSetting with the given #GType from the #NMConnection. This - * operation dereferences the #NMSetting object. - **/ -void -nm_connection_remove_setting(NMConnection *connection, GType setting_type) -{ - _nm_connection_remove_setting(connection, setting_type); -} - -static gpointer -_connection_get_setting(NMConnection *connection, GType setting_type) -{ - NMSetting *setting; - - nm_assert(NM_IS_CONNECTION(connection)); - nm_assert(g_type_is_a(setting_type, NM_TYPE_SETTING)); - - setting = g_hash_table_lookup(NM_CONNECTION_GET_PRIVATE(connection)->settings, - _gtype_to_hash_key(setting_type)); - nm_assert(!setting || G_TYPE_CHECK_INSTANCE_TYPE(setting, setting_type)); - return setting; -} - -static gpointer -_connection_get_setting_check(NMConnection *connection, GType setting_type) -{ - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - - return _connection_get_setting(connection, setting_type); -} - -/** - * nm_connection_get_setting: - * @connection: a #NMConnection - * @setting_type: the #GType of the setting object to return - * - * Gets the #NMSetting with the given #GType, if one has been previously added - * to the #NMConnection. - * - * Returns: (transfer none): the #NMSetting, or %NULL if no setting of that type was previously - * added to the #NMConnection - **/ -NMSetting * -nm_connection_get_setting(NMConnection *connection, GType setting_type) -{ - g_return_val_if_fail(g_type_is_a(setting_type, NM_TYPE_SETTING), NULL); - - return _connection_get_setting_check(connection, setting_type); -} - -NMSettingIPConfig * -nm_connection_get_setting_ip_config(NMConnection *connection, int addr_family) -{ - nm_assert_addr_family(addr_family); - - return NM_SETTING_IP_CONFIG(_connection_get_setting( - connection, - (addr_family == AF_INET) ? NM_TYPE_SETTING_IP4_CONFIG : NM_TYPE_SETTING_IP6_CONFIG)); -} - -/** - * nm_connection_get_setting_by_name: - * @connection: a #NMConnection - * @name: a setting name - * - * Gets the #NMSetting with the given name, if one has been previously added - * the #NMConnection. - * - * Returns: (transfer none): the #NMSetting, or %NULL if no setting with that name was previously - * added to the #NMConnection - **/ -NMSetting * -nm_connection_get_setting_by_name(NMConnection *connection, const char *name) -{ - GType type; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - - type = nm_setting_lookup_type(name); - return type ? _connection_get_setting(connection, type) : NULL; -} - -/*****************************************************************************/ - -gpointer /* (NMSetting *) */ -_nm_connection_check_main_setting(NMConnection *connection, - const char * setting_name, - GError ** error) -{ - NMSetting *setting; - - nm_assert(NM_IS_CONNECTION(connection)); - nm_assert(setting_name); - - if (!nm_connection_is_type(connection, setting_name)) { - nm_utils_error_set(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, - "connection type is not \"%s\"", - setting_name); - return NULL; - } - - setting = nm_connection_get_setting_by_name(connection, setting_name); - if (!setting) { - nm_utils_error_set(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, - "connection misses \"%s\" settings", - setting_name); - return NULL; - } - - return setting; -} - -/*****************************************************************************/ - -static gboolean -validate_permissions_type(GVariant *variant, GError **error) -{ - GVariant *s_con; - GVariant *permissions; - gboolean valid = TRUE; - - /* Ensure the connection::permissions item (if present) is the correct - * type, otherwise the g_object_set() will throw a warning and ignore the - * error, leaving us with no permissions. - */ - s_con = g_variant_lookup_value(variant, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - if (!s_con) - return TRUE; - - permissions = g_variant_lookup_value(s_con, NM_SETTING_CONNECTION_PERMISSIONS, NULL); - if (permissions) { - if (!g_variant_is_of_type(permissions, G_VARIANT_TYPE_STRING_ARRAY)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("wrong type; should be a list of strings.")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_PERMISSIONS); - valid = FALSE; - } - g_variant_unref(permissions); - } - - g_variant_unref(s_con); - return valid; -} - -/** - * _nm_connection_replace_settings: - * @connection: a #NMConnection - * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings - * @parse_flags: flags. - * @error: location to store error, or %NULL - * - * Replaces @connection's settings with @new_settings (which must be - * syntactically valid, and describe a known type of connection, but does not - * need to result in a connection that passes nm_connection_verify()). - * - * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not - * be deserialized (in which case @connection will be unchanged). - * Only exception is the NM_SETTING_PARSE_FLAGS_NORMALIZE flag: if normalization - * fails, the input @connection is already modified and the original settings - * are lost. - **/ -gboolean -_nm_connection_replace_settings(NMConnection * connection, - GVariant * new_settings, - NMSettingParseFlags parse_flags, - GError ** error) -{ - NMConnectionPrivate *priv; - GVariantIter iter; - const char * setting_name; - GVariant * setting_dict; - GSList * settings = NULL, *s; - gboolean changed, success; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); - g_return_val_if_fail(g_variant_is_of_type(new_settings, NM_VARIANT_TYPE_CONNECTION), FALSE); - g_return_val_if_fail(error == NULL || *error == NULL, FALSE); - - nm_assert(!NM_FLAGS_ANY(parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL)); - nm_assert(!NM_FLAGS_ALL(parse_flags, - NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT)); - - priv = NM_CONNECTION_GET_PRIVATE(connection); - - if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT) - && !validate_permissions_type(new_settings, error)) - return FALSE; - - g_variant_iter_init(&iter, new_settings); - while (g_variant_iter_next(&iter, "{&s@a{sv}}", &setting_name, &setting_dict)) { - gs_unref_variant GVariant *setting_dict_free = NULL; - GError * local = NULL; - NMSetting * setting; - GType type; - - setting_dict_free = setting_dict; - - type = nm_setting_lookup_type(setting_name); - if (type == G_TYPE_INVALID) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) - continue; - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("unknown setting name")); - g_prefix_error(error, "%s: ", setting_name); - g_slist_free_full(settings, g_object_unref); - return FALSE; - } - - for (s = settings; s; s = s->next) { - if (G_OBJECT_TYPE(s->data) == type) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("duplicate setting name")); - g_prefix_error(error, "%s: ", setting_name); - g_slist_free_full(settings, g_object_unref); - return FALSE; - } - /* last wins. */ - g_object_unref(s->data); - settings = g_slist_delete_link(settings, s); - break; - } - } - - setting = _nm_setting_new_from_dbus(type, setting_dict, new_settings, parse_flags, &local); - - if (!setting) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) - continue; - g_propagate_error(error, local); - g_slist_free_full(settings, g_object_unref); - return FALSE; - } - - settings = g_slist_prepend(settings, setting); - } - - if (g_hash_table_size(priv->settings) > 0) { - g_hash_table_foreach_remove(priv->settings, _setting_release_hfr, connection); - changed = TRUE; - } else - changed = (settings != NULL); - - /* Note: @settings might be empty in which case the connection - * has no NMSetting instances... which is fine, just something - * to be aware of. */ - for (s = settings; s; s = s->next) - _nm_connection_add_setting(connection, s->data); - - g_slist_free(settings); - - /* If verification/normalization fails, the original connection - * is already lost. From an API point of view, it would be nicer - * not to touch the input argument if we fail at the end. - * However, that would require creating a temporary connection - * to validate it first. As none of the caller cares about the - * state of the @connection when normalization fails, just do it - * this way. */ - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_NORMALIZE)) - success = nm_connection_normalize(connection, NULL, NULL, error); - else - success = TRUE; - - if (changed) - g_signal_emit(connection, signals[CHANGED], 0); - return success; -} - -/** - * nm_connection_replace_settings: - * @connection: a #NMConnection - * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings - * @error: location to store error, or %NULL - * - * Replaces @connection's settings with @new_settings (which must be - * syntactically valid, and describe a known type of connection, but does not - * need to result in a connection that passes nm_connection_verify()). - * - * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not - * be deserialized (in which case @connection will be unchanged). - **/ -gboolean -nm_connection_replace_settings(NMConnection *connection, GVariant *new_settings, GError **error) -{ - return _nm_connection_replace_settings(connection, - new_settings, - NM_SETTING_PARSE_FLAGS_NONE, - error); -} - -/** - * nm_connection_replace_settings_from_connection: - * @connection: a #NMConnection - * @new_connection: a #NMConnection to replace the settings of @connection with - * - * Deep-copies the settings of @new_connection and replaces the settings of @connection - * with the copied settings. - **/ -void -nm_connection_replace_settings_from_connection(NMConnection *connection, - NMConnection *new_connection) -{ - NMConnectionPrivate *priv, *new_priv; - GHashTableIter iter; - NMSetting * setting; - gboolean changed; - - g_return_if_fail(NM_IS_CONNECTION(connection)); - g_return_if_fail(NM_IS_CONNECTION(new_connection)); - - /* When 'connection' and 'new_connection' are the same object simply return - * in order not to destroy 'connection'. - */ - if (connection == new_connection) - return; - - /* No need to validate permissions like nm_connection_replace_settings() - * since we're dealing with an NMConnection which has already done that. - */ - - priv = NM_CONNECTION_GET_PRIVATE(connection); - new_priv = NM_CONNECTION_GET_PRIVATE(new_connection); - - if ((changed = g_hash_table_size(priv->settings) > 0)) - g_hash_table_foreach_remove(priv->settings, _setting_release_hfr, connection); - - if (g_hash_table_size(new_priv->settings)) { - g_hash_table_iter_init(&iter, new_priv->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) - _nm_connection_add_setting(connection, nm_setting_duplicate(setting)); - changed = TRUE; - } - - if (changed) - g_signal_emit(connection, signals[CHANGED], 0); -} - -/** - * nm_connection_clear_settings: - * @connection: a #NMConnection - * - * Deletes all of @connection's settings. - **/ -void -nm_connection_clear_settings(NMConnection *connection) -{ - NMConnectionPrivate *priv; - - g_return_if_fail(NM_IS_CONNECTION(connection)); - - priv = NM_CONNECTION_GET_PRIVATE(connection); - - if (g_hash_table_size(priv->settings) > 0) { - g_hash_table_foreach_remove(priv->settings, _setting_release_hfr, connection); - g_signal_emit(connection, signals[CHANGED], 0); - } -} - -/** - * nm_connection_compare: - * @a: a #NMConnection - * @b: a second #NMConnection to compare with the first - * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT - * - * Compares two #NMConnection objects for similarity, with comparison behavior - * modified by a set of flags. See nm_setting_compare() for a description of - * each flag's behavior. - * - * Returns: %TRUE if the comparison succeeds, %FALSE if it does not - **/ -gboolean -nm_connection_compare(NMConnection *a, NMConnection *b, NMSettingCompareFlags flags) -{ - GHashTableIter iter; - NMSetting * src; - - if (a == b) - return TRUE; - if (!a || !b) - return FALSE; - - /* B / A: ensure settings in B that are not in A make the comparison fail */ - if (g_hash_table_size(NM_CONNECTION_GET_PRIVATE(a)->settings) - != g_hash_table_size(NM_CONNECTION_GET_PRIVATE(b)->settings)) - return FALSE; - - /* A / B: ensure all settings in A match corresponding ones in B */ - g_hash_table_iter_init(&iter, NM_CONNECTION_GET_PRIVATE(a)->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer) &src)) { - NMSetting *cmp = nm_connection_get_setting(b, G_OBJECT_TYPE(src)); - - if (!cmp || !_nm_setting_compare(a, src, b, cmp, flags)) - return FALSE; - } - - return TRUE; -} - -static gboolean -diff_one_connection(NMConnection * a, - NMConnection * b, - NMSettingCompareFlags flags, - gboolean invert_results, - GHashTable * diffs) -{ - NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE(a); - GHashTableIter iter; - NMSetting * a_setting = NULL; - gboolean diff_found = FALSE; - - g_hash_table_iter_init(&iter, priv->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer) &a_setting)) { - NMSetting * b_setting = NULL; - const char *setting_name = nm_setting_get_name(a_setting); - GHashTable *results; - gboolean new_results = TRUE; - - if (b) - b_setting = nm_connection_get_setting(b, G_OBJECT_TYPE(a_setting)); - - results = g_hash_table_lookup(diffs, setting_name); - if (results) - new_results = FALSE; - - if (!_nm_setting_diff(a, a_setting, b, b_setting, flags, invert_results, &results)) - diff_found = TRUE; - - if (new_results && results) - g_hash_table_insert(diffs, g_strdup(setting_name), results); - } - - return diff_found; -} - -/** - * nm_connection_diff: - * @a: a #NMConnection - * @b: a second #NMConnection to compare with the first - * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT - * @out_settings: (element-type utf8 GLib.HashTable): if the - * connections differ, on return a hash table mapping setting names to - * second-level GHashTable (utf8 to guint32), which contains the key names that - * differ mapped to one or more of %NMSettingDiffResult as a bitfield - * - * Compares two #NMConnection objects for similarity, with comparison behavior - * modified by a set of flags. See nm_setting_compare() for a description of - * each flag's behavior. If the connections differ, settings and keys within - * each setting that differ are added to the returned @out_settings hash table. - * No values are returned, only key names. - * - * Returns: %TRUE if the connections contain the same values, %FALSE if they do - * not - **/ -gboolean -nm_connection_diff(NMConnection * a, - NMConnection * b, - NMSettingCompareFlags flags, - GHashTable ** out_settings) -{ - GHashTable *diffs; - gboolean diff_found = FALSE; - - g_return_val_if_fail(NM_IS_CONNECTION(a), FALSE); - g_return_val_if_fail(!out_settings || !*out_settings, FALSE); - g_return_val_if_fail(!b || NM_IS_CONNECTION(b), FALSE); - - if (a == b) - return TRUE; - - diffs = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_hash_table_destroy); - - /* Diff A to B, then B to A to capture keys in B that aren't in A */ - if (diff_one_connection(a, b, flags, FALSE, diffs)) - diff_found = TRUE; - if (b && diff_one_connection(b, a, flags, TRUE, diffs)) - diff_found = TRUE; - - nm_assert(diff_found == (g_hash_table_size(diffs) != 0)); - - if (g_hash_table_size(diffs) == 0) { - g_hash_table_destroy(diffs); - diffs = NULL; - } - - NM_SET_OUT(out_settings, diffs); - - return !diff_found; -} - -NMSetting * -_nm_connection_find_base_type_setting(NMConnection *connection) -{ - NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE(connection); - GHashTableIter iter; - NMSetting * setting = NULL; - NMSetting * s_iter; - NMSettingPriority setting_prio = NM_SETTING_PRIORITY_USER; - NMSettingPriority s_iter_prio; - - g_hash_table_iter_init(&iter, priv->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &s_iter)) { - s_iter_prio = _nm_setting_get_base_type_priority(s_iter); - if (s_iter_prio == NM_SETTING_PRIORITY_INVALID) - continue; - - if (setting) { - if (s_iter_prio > setting_prio) { - continue; - } else if (s_iter_prio == setting_prio) { - NMSettingConnection *s_con = nm_connection_get_setting_connection(connection); - const char * type; - - if (s_con) { - type = nm_setting_connection_get_connection_type(s_con); - if (type) - return nm_connection_get_setting_by_name(connection, type); - } - return NULL; - } - } - setting = s_iter; - setting_prio = s_iter_prio; - } - return setting; -} - -static gboolean -_normalize_connection_uuid(NMConnection *self) -{ - NMSettingConnection *s_con = nm_connection_get_setting_connection(self); - char uuid[37]; - - nm_assert(s_con); - - if (nm_setting_connection_get_uuid(s_con)) - return FALSE; - - g_object_set(s_con, NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf(uuid), NULL); - return TRUE; -} - -static gboolean -_normalize_connection_type(NMConnection *self) -{ - NMSettingConnection *s_con = nm_connection_get_setting_connection(self); - NMSetting * s_base = NULL; - const char * type; - - type = nm_setting_connection_get_connection_type(s_con); - - if (type) { - s_base = nm_connection_get_setting_by_name(self, type); - - if (!s_base) { - GType base_type = nm_setting_lookup_type(type); - - g_return_val_if_fail(base_type, FALSE); - nm_connection_add_setting(self, g_object_new(base_type, NULL)); - return TRUE; - } - } else { - s_base = _nm_connection_find_base_type_setting(self); - g_return_val_if_fail(s_base, FALSE); - - type = nm_setting_get_name(s_base); - g_object_set(s_con, NM_SETTING_CONNECTION_TYPE, type, NULL); - return TRUE; - } - - return FALSE; -} - -const char * -_nm_connection_detect_bluetooth_type(NMConnection *self) -{ - NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth(self); - - if (s_bt && nm_setting_bluetooth_get_connection_type(s_bt)) { - if (nm_connection_get_setting_gsm(self) || nm_connection_get_setting_cdma(self)) - return NM_SETTING_BLUETOOTH_TYPE_DUN; - if (nm_connection_get_setting_bridge(self)) - return NM_SETTING_BLUETOOTH_TYPE_NAP; - return NM_SETTING_BLUETOOTH_TYPE_PANU; - } - - /* NULL means the connection is not a bluetooth type, or it needs - * no normalization, as the type is set explicitly. */ - return NULL; -} - -const char * -_nm_connection_detect_slave_type(NMConnection *connection, NMSetting **out_s_port) -{ - NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE(connection); - GHashTableIter iter; - const char * slave_type = NULL; - NMSetting * s_port = NULL, *s_iter; - - g_hash_table_iter_init(&iter, priv->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &s_iter)) { - const char *name = nm_setting_get_name(s_iter); - const char *i_slave_type = NULL; - - if (!strcmp(name, NM_SETTING_BRIDGE_PORT_SETTING_NAME)) - i_slave_type = NM_SETTING_BRIDGE_SETTING_NAME; - else if (!strcmp(name, NM_SETTING_TEAM_PORT_SETTING_NAME)) - i_slave_type = NM_SETTING_TEAM_SETTING_NAME; - else if (!strcmp(name, NM_SETTING_OVS_PORT_SETTING_NAME)) - i_slave_type = NM_SETTING_OVS_BRIDGE_SETTING_NAME; - else if (!strcmp(name, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) - i_slave_type = NM_SETTING_OVS_PORT_SETTING_NAME; - else - continue; - - if (slave_type) { - /* there are more then one matching port types, cannot detect the slave type. */ - slave_type = NULL; - s_port = NULL; - break; - } - slave_type = i_slave_type; - s_port = s_iter; - } - - if (out_s_port) - *out_s_port = s_port; - return slave_type; -} - -static gboolean -_normalize_connection_slave_type(NMConnection *self) -{ - NMSettingConnection *s_con = nm_connection_get_setting_connection(self); - const char * slave_type, *port_type; - - if (!s_con) - return FALSE; - if (!nm_setting_connection_get_master(s_con)) - return FALSE; - - slave_type = nm_setting_connection_get_slave_type(s_con); - if (slave_type) { - if (_nm_setting_slave_type_is_valid(slave_type, &port_type) && port_type) { - NMSetting *s_port; - - s_port = nm_connection_get_setting_by_name(self, port_type); - if (!s_port) { - GType p_type = nm_setting_lookup_type(port_type); - - g_return_val_if_fail(p_type, FALSE); - nm_connection_add_setting(self, g_object_new(p_type, NULL)); - return TRUE; - } - } - } else { - if ((slave_type = _nm_connection_detect_slave_type(self, NULL))) { - g_object_set(s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, NULL); - return TRUE; - } - } - return FALSE; -} - -static gboolean -_normalize_ethernet_link_neg(NMConnection *self) -{ - NMSettingWired *s_wired = nm_connection_get_setting_wired(self); - - if (s_wired) { - guint32 speed = nm_setting_wired_get_speed(s_wired); - const char *duplex = nm_setting_wired_get_duplex(s_wired); - - if ((speed && !duplex) || (!speed && duplex)) { - speed = 0; - duplex = NULL; - g_object_set(s_wired, - NM_SETTING_WIRED_SPEED, - (guint) speed, - NM_SETTING_WIRED_DUPLEX, - duplex, - NULL); - return TRUE; - } - } - - return FALSE; -} - -/** - * _supports_addr_family: - * @self: a #NMConnection - * @family: AF_* - * - * Check whether the connection supports certain L3 address family, - * in order to be able to tell whether is should have the corresponding - * setting ("ipv4" for AF_INET and "ipv6" for AF_INET6). - * - * If AF_UNSPEC is given, then the function checks whether the connection - * supports any L3 configuration at all. - * - * Returns: %TRUE if the AF is supported, %FALSE otherwise - **/ -static gboolean -_supports_addr_family(NMConnection *self, int family) -{ - const char * connection_type = nm_connection_get_connection_type(self); - NMSettingConnection *s_con; - - g_return_val_if_fail(connection_type, TRUE); - if (strcmp(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) - return TRUE; - if (strcmp(connection_type, NM_SETTING_WPAN_SETTING_NAME) == 0) - return FALSE; - if (strcmp(connection_type, NM_SETTING_6LOWPAN_SETTING_NAME) == 0) - return family == AF_INET6 || family == AF_UNSPEC; - if ((s_con = nm_connection_get_setting_connection(self)) - && (nm_streq0(nm_setting_connection_get_slave_type(s_con), NM_SETTING_VRF_SETTING_NAME))) - return TRUE; - - return !nm_setting_connection_get_master(nm_connection_get_setting_connection(self)); -} - -static gboolean -_normalize_ip_config(NMConnection *self, GHashTable *parameters) -{ - NMSettingIPConfig *s_ip4, *s_ip6; - NMSettingProxy * s_proxy; - NMSetting * setting; - gboolean changed = FALSE; - guint num, i; - - s_ip4 = nm_connection_get_setting_ip4_config(self); - s_ip6 = nm_connection_get_setting_ip6_config(self); - s_proxy = nm_connection_get_setting_proxy(self); - - if (_supports_addr_family(self, AF_INET)) { - if (!s_ip4) { - const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; - - if (nm_connection_is_type(self, NM_SETTING_WIREGUARD_SETTING_NAME)) - default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - - /* But if no IP4 setting was specified, assume the caller was just - * being lazy and use the default method. - */ - setting = nm_setting_ip4_config_new(); - - g_object_set(setting, NM_SETTING_IP_CONFIG_METHOD, default_ip4_method, NULL); - nm_connection_add_setting(self, setting); - changed = TRUE; - } else { - if (nm_setting_ip_config_get_gateway(s_ip4) - && nm_setting_ip_config_get_never_default(s_ip4)) { - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, NULL, NULL); - changed = TRUE; - } - - if (nm_streq0(nm_setting_ip_config_get_method(s_ip4), - NM_SETTING_IP4_CONFIG_METHOD_DISABLED) - && !nm_setting_ip_config_get_may_fail(s_ip4)) { - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - changed = TRUE; - } - - num = nm_setting_ip_config_get_num_addresses(s_ip4); - if (num > 1 - && nm_streq0(nm_setting_ip_config_get_method(s_ip4), - NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { - for (i = num - 1; i > 0; i--) - nm_setting_ip_config_remove_address(s_ip4, i); - changed = TRUE; - } - } - } else { - if (s_ip4) { - nm_connection_remove_setting(self, NM_TYPE_SETTING_IP4_CONFIG); - changed = TRUE; - } - } - - if (_supports_addr_family(self, AF_INET6)) { - if (!s_ip6) { - const char *default_ip6_method = NULL; - - if (parameters) - default_ip6_method = - g_hash_table_lookup(parameters, - NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD); - if (!default_ip6_method) { - if (nm_connection_is_type(self, NM_SETTING_WIREGUARD_SETTING_NAME)) - default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - else - default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; - } - - /* If no IP6 setting was specified, then assume that means IP6 config is - * allowed to fail. - */ - setting = nm_setting_ip6_config_new(); - - g_object_set(setting, - NM_SETTING_IP_CONFIG_METHOD, - default_ip6_method, - NM_SETTING_IP_CONFIG_MAY_FAIL, - TRUE, - NULL); - nm_connection_add_setting(self, setting); - changed = TRUE; - } else { - const char *token; - - token = nm_setting_ip6_config_get_token((NMSettingIP6Config *) s_ip6); - if (token - && nm_setting_ip6_config_get_addr_gen_mode((NMSettingIP6Config *) s_ip6) - == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { - struct in6_addr i6_token; - char normalized[NM_UTILS_INET_ADDRSTRLEN]; - - if (inet_pton(AF_INET6, token, &i6_token) == 1 - && _nm_utils_inet6_is_token(&i6_token)) { - _nm_utils_inet6_ntop(&i6_token, normalized); - if (g_strcmp0(token, normalized)) { - g_object_set(s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, normalized, NULL); - changed = TRUE; - } - } - } - - if (nm_setting_ip_config_get_gateway(s_ip6) - && nm_setting_ip_config_get_never_default(s_ip6)) { - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, NULL, NULL); - changed = TRUE; - } - - if (NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip6), - NM_SETTING_IP6_CONFIG_METHOD_IGNORE, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED) - && !nm_setting_ip_config_get_may_fail(s_ip6)) { - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - changed = TRUE; - } - } - } else { - if (s_ip6) { - nm_connection_remove_setting(self, NM_TYPE_SETTING_IP6_CONFIG); - changed = TRUE; - } - } - - if (_supports_addr_family(self, AF_UNSPEC)) { - if (!s_proxy) { - setting = nm_setting_proxy_new(); - nm_connection_add_setting(self, setting); - changed = TRUE; - } - } else { - if (s_proxy) { - nm_connection_remove_setting(self, NM_TYPE_SETTING_PROXY); - changed = TRUE; - } - } - - return changed; -} - -static gboolean -_normalize_infiniband_mtu(NMConnection *self) -{ - NMSettingInfiniband *s_infini = nm_connection_get_setting_infiniband(self); - - if (!s_infini || nm_setting_infiniband_get_mtu(s_infini) <= NM_INFINIBAND_MAX_MTU - || !NM_IN_STRSET(nm_setting_infiniband_get_transport_mode(s_infini), - "datagram", - "connected")) - return FALSE; - - g_object_set(s_infini, NM_SETTING_INFINIBAND_MTU, (guint) NM_INFINIBAND_MAX_MTU, NULL); - return TRUE; -} - -static gboolean -_normalize_bond_mode(NMConnection *self) -{ - NMSettingBond *s_bond = nm_connection_get_setting_bond(self); - - /* Convert mode from numeric to string notation */ - if (s_bond) { - const char *mode = nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_MODE); - int mode_int = nm_utils_bond_mode_string_to_int(mode); - - if (mode_int != -1) { - const char *mode_new = nm_utils_bond_mode_int_to_string(mode_int); - - if (!nm_streq0(mode_new, mode)) { - nm_setting_bond_add_option(s_bond, NM_SETTING_BOND_OPTION_MODE, mode_new); - return TRUE; - } - } - } - return FALSE; -} - -static gboolean -_normalize_bond_options(NMConnection *self) -{ - NMSettingBond *s_bond = nm_connection_get_setting_bond(self); - gboolean changed = FALSE; - const char * name, *mode_str; - NMBondMode mode; - guint32 num, i; - - /* Strip away unsupported options for current mode */ - if (s_bond) { - mode_str = nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_MODE); - mode = _nm_setting_bond_mode_from_string(mode_str); - if (mode == NM_BOND_MODE_UNKNOWN) - return FALSE; -again: - num = nm_setting_bond_get_num_options(s_bond); - for (i = 0; i < num; i++) { - if (nm_setting_bond_get_option(s_bond, i, &name, NULL) - && !_nm_setting_bond_option_supported(name, mode)) { - nm_setting_bond_remove_option(s_bond, name); - changed = TRUE; - goto again; - } - } - } - - return changed; -} - -static gboolean -_normalize_wireless_mac_address_randomization(NMConnection *self) -{ - NMSettingWireless * s_wifi = nm_connection_get_setting_wireless(self); - const char * cloned_mac_address; - NMSettingMacRandomization mac_address_randomization; - - if (!s_wifi) - return FALSE; - - mac_address_randomization = nm_setting_wireless_get_mac_address_randomization(s_wifi); - if (!NM_IN_SET(mac_address_randomization, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, - NM_SETTING_MAC_RANDOMIZATION_NEVER, - NM_SETTING_MAC_RANDOMIZATION_ALWAYS)) - return FALSE; - - cloned_mac_address = nm_setting_wireless_get_cloned_mac_address(s_wifi); - if (cloned_mac_address) { - if (nm_streq(cloned_mac_address, "random")) { - if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS) - return FALSE; - mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_ALWAYS; - } else if (nm_streq(cloned_mac_address, "permanent")) { - if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_NEVER) - return FALSE; - mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER; - } else { - if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) - return FALSE; - mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_DEFAULT; - } - g_object_set(s_wifi, - NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, - mac_address_randomization, - NULL); - return TRUE; - } - if (mac_address_randomization != NM_SETTING_MAC_RANDOMIZATION_DEFAULT) { - g_object_set(s_wifi, - NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, - mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS ? "random" - : "permanent", - NULL); - return TRUE; - } - return FALSE; -} - -static gboolean -_normalize_macsec(NMConnection *self) -{ - NMSettingMacsec *s_macsec = nm_connection_get_setting_macsec(self); - gboolean changed = FALSE; - - if (!s_macsec) - return FALSE; - - if (nm_setting_macsec_get_mode(s_macsec) != NM_SETTING_MACSEC_MODE_PSK) { - if (nm_setting_macsec_get_mka_cak(s_macsec)) { - g_object_set(s_macsec, NM_SETTING_MACSEC_MKA_CAK, NULL, NULL); - changed = TRUE; - } - if (nm_setting_macsec_get_mka_ckn(s_macsec)) { - g_object_set(s_macsec, NM_SETTING_MACSEC_MKA_CKN, NULL, NULL); - changed = TRUE; - } - } - - return changed; -} - -static gboolean -_normalize_team_config(NMConnection *self) -{ - NMSettingTeam *s_team = nm_connection_get_setting_team(self); - - if (s_team) { - const char *config = nm_setting_team_get_config(s_team); - - if (config && !*config) { - g_object_set(s_team, NM_SETTING_TEAM_CONFIG, NULL, NULL); - return TRUE; - } - } - return FALSE; -} - -static gboolean -_normalize_team_port_config(NMConnection *self) -{ - NMSettingTeamPort *s_team_port = nm_connection_get_setting_team_port(self); - - if (s_team_port) { - const char *config = nm_setting_team_port_get_config(s_team_port); - - if (config && !*config) { - g_object_set(s_team_port, NM_SETTING_TEAM_PORT_CONFIG, NULL, NULL); - return TRUE; - } - } - return FALSE; -} - -static gboolean -_normalize_bluetooth_type(NMConnection *self) -{ - const char *type = _nm_connection_detect_bluetooth_type(self); - - if (type) { - g_object_set(nm_connection_get_setting_bluetooth(self), - NM_SETTING_BLUETOOTH_TYPE, - type, - NULL); - return TRUE; - } - return FALSE; -} - -static gboolean -_normalize_ovs_interface_type(NMConnection *self) -{ - NMSettingOvsInterface *s_ovs_interface = nm_connection_get_setting_ovs_interface(self); - gboolean modified; - int v; - - if (!s_ovs_interface) - return FALSE; - - v = _nm_setting_ovs_interface_verify_interface_type( - s_ovs_interface, - nm_setting_ovs_interface_get_interface_type(s_ovs_interface), - self, - TRUE, - &modified, - NULL, - NULL); - if (v != TRUE) - g_return_val_if_reached(modified); - - return modified; -} - -static gboolean -_normalize_ip_tunnel_wired_setting(NMConnection *self) -{ - NMSettingIPTunnel *s_ip_tunnel; - - s_ip_tunnel = nm_connection_get_setting_ip_tunnel(self); - if (!s_ip_tunnel) - return FALSE; - - if (nm_connection_get_setting_wired(self) - && !NM_IN_SET(nm_setting_ip_tunnel_get_mode(s_ip_tunnel), - NM_IP_TUNNEL_MODE_GRETAP, - NM_IP_TUNNEL_MODE_IP6GRETAP)) { - nm_connection_remove_setting(self, NM_TYPE_SETTING_WIRED); - return TRUE; - } - - return FALSE; -} - -static gboolean -_normalize_sriov_vf_order(NMConnection *self) -{ - NMSettingSriov *s_sriov; - - s_sriov = NM_SETTING_SRIOV(nm_connection_get_setting(self, NM_TYPE_SETTING_SRIOV)); - if (!s_sriov) - return FALSE; - - return _nm_setting_sriov_sort_vfs(s_sriov); -} - -static gboolean -_normalize_bridge_vlan_order(NMConnection *self) -{ - NMSettingBridge *s_bridge; - - s_bridge = nm_connection_get_setting_bridge(self); - if (!s_bridge) - return FALSE; - - return _nm_setting_bridge_sort_vlans(s_bridge); -} - -static gboolean -_normalize_bridge_port_vlan_order(NMConnection *self) -{ - NMSettingBridgePort *s_port; - - s_port = nm_connection_get_setting_bridge_port(self); - if (!s_port) - return FALSE; - - return _nm_setting_bridge_port_sort_vlans(s_port); -} - -static gboolean -_normalize_gsm_auto_config(NMConnection *self) -{ - NMSettingGsm *s_gsm; - - s_gsm = nm_connection_get_setting_gsm(self); - if (!s_gsm) - return FALSE; - - if (!nm_setting_gsm_get_auto_config(s_gsm)) - return FALSE; - - if (!nm_setting_gsm_get_apn(s_gsm) && !nm_setting_gsm_get_username(s_gsm) - && !nm_setting_gsm_get_password(s_gsm)) - return FALSE; - - g_object_set(s_gsm, NM_SETTING_GSM_AUTO_CONFIG, FALSE, NULL); - return TRUE; -} - -static gboolean -_normalize_required_settings(NMConnection *self) -{ - NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth(self); - NMSetting * s_bridge; - gboolean changed = FALSE; - - if (nm_connection_get_setting_vlan(self)) { - if (!nm_connection_get_setting_wired(self)) { - nm_connection_add_setting(self, nm_setting_wired_new()); - changed = TRUE; - } - } - if (s_bt - && nm_streq0(nm_setting_bluetooth_get_connection_type(s_bt), - NM_SETTING_BLUETOOTH_TYPE_NAP)) { - if (!nm_connection_get_setting_bridge(self)) { - s_bridge = nm_setting_bridge_new(); - g_object_set(s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL); - nm_connection_add_setting(self, s_bridge); - changed = TRUE; - } - } - return changed; -} - -static gboolean -_normalize_invalid_slave_port_settings(NMConnection *self) -{ - NMSettingConnection *s_con = nm_connection_get_setting_connection(self); - const char * slave_type; - gboolean changed = FALSE; - - slave_type = nm_setting_connection_get_slave_type(s_con); - - if (!nm_streq0(slave_type, NM_SETTING_BRIDGE_SETTING_NAME) - && _nm_connection_remove_setting(self, NM_TYPE_SETTING_BRIDGE_PORT)) - changed = TRUE; - - if (!nm_streq0(slave_type, NM_SETTING_TEAM_SETTING_NAME) - && _nm_connection_remove_setting(self, NM_TYPE_SETTING_TEAM_PORT)) - changed = TRUE; - - return changed; -} - -/** - * nm_connection_verify: - * @connection: the #NMConnection to verify - * @error: location to store error, or %NULL - * - * Validates the connection and all its settings. Each setting's properties - * have allowed values, and some values are dependent on other values. For - * example, if a Wi-Fi connection is security enabled, the #NMSettingWireless - * setting object's 'security' property must contain the setting name of the - * #NMSettingWirelessSecurity object, which must also be present in the - * connection for the connection to be valid. As another example, the - * #NMSettingWired object's 'mac-address' property must be a validly formatted - * MAC address. The returned #GError contains information about which - * setting and which property failed validation, and how it failed validation. - * - * Returns: %TRUE if the connection is valid, %FALSE if it is not - **/ -gboolean -nm_connection_verify(NMConnection *connection, GError **error) -{ - NMSettingVerifyResult result; - - result = _nm_connection_verify(connection, error); - - /* we treat normalizable connections as valid. */ - if (result == NM_SETTING_VERIFY_NORMALIZABLE) - g_clear_error(error); - - return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE; -} - -NMSettingVerifyResult -_nm_connection_verify(NMConnection *connection, GError **error) -{ - NMSettingIPConfig *s_ip4, *s_ip6; - NMSettingProxy * s_proxy; - gs_free NMSetting **settings = NULL; - gs_free_error GError *normalizable_error = NULL; - NMSettingVerifyResult normalizable_error_type = NM_SETTING_VERIFY_SUCCESS; - guint i; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), NM_SETTING_VERIFY_ERROR); - g_return_val_if_fail(!error || !*error, NM_SETTING_VERIFY_ERROR); - - settings = nm_connection_get_settings(connection, NULL); - if (!settings || !NM_IS_SETTING_CONNECTION(settings[0])) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("setting not found")); - g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); - return NM_SETTING_VERIFY_ERROR; - } - - for (i = 0; settings[i]; i++) { - GError * verify_error = NULL; - NMSettingVerifyResult verify_result; - - nm_assert(NM_IS_SETTING(settings[i])); - nm_assert(NM_IS_SETTING_CONNECTION(settings[i]) == (i == 0)); - - /* verify all settings. We stop if we find the first non-normalizable - * @NM_SETTING_VERIFY_ERROR. If we find normalizable errors we continue - * but remember the error to return it to the user. - * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR has a higher priority then - * @NM_SETTING_VERIFY_NORMALIZABLE, so, if we encounter such an error type, - * we remember it instead (to return it as output). - **/ - verify_result = _nm_setting_verify(settings[i], connection, &verify_error); - if (verify_result == NM_SETTING_VERIFY_NORMALIZABLE - || verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR) { - if (verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR - && normalizable_error_type == NM_SETTING_VERIFY_NORMALIZABLE) { - /* NORMALIZABLE_ERROR has higher priority. */ - g_clear_error(&normalizable_error); - } - if (!normalizable_error) { - g_propagate_error(&normalizable_error, verify_error); - verify_error = NULL; - normalizable_error_type = verify_result; - } - } else if (verify_result != NM_SETTING_VERIFY_SUCCESS) { - g_propagate_error(error, verify_error); - g_return_val_if_fail(verify_result == NM_SETTING_VERIFY_ERROR, NM_SETTING_VERIFY_ERROR); - return NM_SETTING_VERIFY_ERROR; - } - g_clear_error(&verify_error); - } - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - s_proxy = nm_connection_get_setting_proxy(connection); - - nm_assert(normalizable_error_type != NM_SETTING_VERIFY_ERROR); - if (NM_IN_SET(normalizable_error_type, - NM_SETTING_VERIFY_SUCCESS, - NM_SETTING_VERIFY_NORMALIZABLE)) { - if (_supports_addr_family(connection, AF_INET)) { - if (!s_ip4 && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { - g_set_error_literal(&normalizable_error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("setting is required for non-slave connections")); - g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME); - - /* having a master without IP config was not a verify() error, accept - * it for backward compatibility. */ - normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; - } - } else { - if (s_ip4) { - g_clear_error(&normalizable_error); - g_set_error_literal(&normalizable_error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("setting not allowed in slave connection")); - g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME); - /* having a slave with IP config *was* and is a verify() error. */ - normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - } - - if (_supports_addr_family(connection, AF_INET6)) { - if (!s_ip6 && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { - g_set_error_literal(&normalizable_error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("setting is required for non-slave connections")); - g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME); - - /* having a master without IP config was not a verify() error, accept - * it for backward compatibility. */ - normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; - } - } else { - if (s_ip6) { - g_clear_error(&normalizable_error); - g_set_error_literal(&normalizable_error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("setting not allowed in slave connection")); - g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME); - /* having a slave with IP config *was* and is a verify() error. */ - normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - } - - if (_supports_addr_family(connection, AF_UNSPEC)) { - if (!s_proxy && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { - g_set_error_literal(&normalizable_error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("setting is required for non-slave connections")); - g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_PROXY_SETTING_NAME); - - /* having a master without proxy config was not a verify() error, accept - * it for backward compatibility. */ - normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; - } - } else { - if (s_proxy) { - g_clear_error(&normalizable_error); - g_set_error_literal(&normalizable_error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("setting not allowed in slave connection")); - g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_PROXY_SETTING_NAME); - /* having a slave with proxy config *was* and is a verify() error. */ - normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - } - } - - if (normalizable_error_type != NM_SETTING_VERIFY_SUCCESS) { - g_propagate_error(error, normalizable_error); - normalizable_error = NULL; - return normalizable_error_type; - } - - return NM_SETTING_VERIFY_SUCCESS; -} - -/** - * nm_connection_verify_secrets: - * @connection: the #NMConnection to verify in - * @error: location to store error, or %NULL - * - * Verifies the secrets in the connection. - * - * Returns: %TRUE if the secrets are valid, %FALSE if they are not - * - * Since: 1.2 - **/ -gboolean -nm_connection_verify_secrets(NMConnection *connection, GError **error) -{ - GHashTableIter iter; - NMSetting * setting; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - g_hash_table_iter_init(&iter, NM_CONNECTION_GET_PRIVATE(connection)->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) { - if (!nm_setting_verify_secrets(setting, connection, error)) - return FALSE; - } - return TRUE; -} - -static gboolean -_connection_normalize(NMConnection *connection, - GHashTable * parameters, - gboolean * modified, - GError ** error) -{ - NMSettingVerifyResult success; - gboolean was_modified; - -#if NM_MORE_ASSERTS > 10 - /* only call this _nm_connection_verify() confirms that the connection - * requires normalization and is normalizable. */ - nm_assert(NM_IN_SET(_nm_connection_verify(connection, NULL), - NM_SETTING_VERIFY_NORMALIZABLE, - NM_SETTING_VERIFY_NORMALIZABLE_ERROR)); -#endif - - /* Try to perform all kind of normalizations on the settings to fix it. - * We only do this, after verifying that the connection contains no un-normalizable - * errors, because in that case we rather fail without touching the settings. */ - - was_modified = FALSE; - - was_modified |= _normalize_connection_uuid(connection); - was_modified |= _normalize_connection_type(connection); - was_modified |= _normalize_connection_slave_type(connection); - was_modified |= _normalize_required_settings(connection); - was_modified |= _normalize_invalid_slave_port_settings(connection); - was_modified |= _normalize_ip_config(connection, parameters); - was_modified |= _normalize_ethernet_link_neg(connection); - was_modified |= _normalize_infiniband_mtu(connection); - was_modified |= _normalize_bond_mode(connection); - was_modified |= _normalize_bond_options(connection); - was_modified |= _normalize_wireless_mac_address_randomization(connection); - was_modified |= _normalize_macsec(connection); - was_modified |= _normalize_team_config(connection); - was_modified |= _normalize_team_port_config(connection); - was_modified |= _normalize_bluetooth_type(connection); - was_modified |= _normalize_ovs_interface_type(connection); - was_modified |= _normalize_ip_tunnel_wired_setting(connection); - was_modified |= _normalize_sriov_vf_order(connection); - was_modified |= _normalize_bridge_vlan_order(connection); - was_modified |= _normalize_bridge_port_vlan_order(connection); - was_modified |= _normalize_gsm_auto_config(connection); - - was_modified = !!was_modified; - - /* Verify anew */ - success = _nm_connection_verify(connection, error); - - NM_SET_OUT(modified, was_modified); - - if (success != NM_SETTING_VERIFY_SUCCESS) { - /* we would expect, that after normalization, the connection can be verified. - * Also treat NM_SETTING_VERIFY_NORMALIZABLE as failure, because there is something - * odd going on. */ - if (error && !*error) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Unexpected failure to normalize the connection")); - } - g_warning("connection did not verify after normalization: %s", - error ? (*error)->message : "??"); - g_return_val_if_reached(FALSE); - } - - /* we would expect, that the connection was modified during normalization. */ - g_return_val_if_fail(was_modified, TRUE); - - return TRUE; -} - -/** - * nm_connection_normalize: - * @connection: the #NMConnection to normalize - * @parameters: (allow-none) (element-type utf8 gpointer): a #GHashTable with - * normalization parameters to allow customization of the normalization by providing - * specific arguments. Unknown arguments will be ignored and the default will be - * used. The keys must be strings compared with g_str_equal() function. - * The values are opaque and depend on the parameter name. - * @modified: (out) (allow-none): outputs whether any settings were modified. - * @error: location to store error, or %NULL. Contains the reason, - * why the connection is invalid, if the function returns an error. - * - * Does some basic normalization and fixup of well known inconsistencies - * and deprecated fields. If the connection was modified in any way, - * the output parameter @modified is set %TRUE. - * - * Finally the connection will be verified and %TRUE returns if the connection - * is valid. As this function only performs some specific normalization steps - * it cannot repair all connections. If the connection has errors that - * cannot be normalized, the connection will not be modified. - * - * Returns: %TRUE if the connection is valid, %FALSE if it is not - **/ -gboolean -nm_connection_normalize(NMConnection *connection, - GHashTable * parameters, - gboolean * modified, - GError ** error) -{ - NMSettingVerifyResult success; - gs_free_error GError *normalizable_error = NULL; - - success = _nm_connection_verify(connection, &normalizable_error); - - if (!NM_IN_SET(success, NM_SETTING_VERIFY_NORMALIZABLE, NM_SETTING_VERIFY_NORMALIZABLE_ERROR)) { - if (normalizable_error) { - nm_assert(success == NM_SETTING_VERIFY_ERROR); - g_propagate_error(error, g_steal_pointer(&normalizable_error)); - } else - nm_assert(success == NM_SETTING_VERIFY_SUCCESS); - - NM_SET_OUT(modified, FALSE); - - if (success != NM_SETTING_VERIFY_SUCCESS) { - if (error && !*error) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Unexpected failure to verify the connection")); - return FALSE; - } - return FALSE; - } - - if (error && *error) - return FALSE; - return TRUE; - } - - return _connection_normalize(connection, parameters, modified, error); -} - -gboolean -_nm_connection_ensure_normalized(NMConnection * connection, - gboolean allow_modify, - const char * expected_uuid, - gboolean coerce_uuid, - NMConnection **out_connection_clone, - GError ** error) -{ - gs_unref_object NMConnection *connection_clone = NULL; - gs_free_error GError *local = NULL; - NMSettingVerifyResult vresult; - - nm_assert(NM_IS_CONNECTION(connection)); - nm_assert(!out_connection_clone || !*out_connection_clone); - nm_assert(!expected_uuid || nm_utils_is_uuid(expected_uuid)); - - if (expected_uuid) { - if (nm_streq0(expected_uuid, nm_connection_get_uuid(connection))) - expected_uuid = NULL; - else if (!coerce_uuid || (!allow_modify && !out_connection_clone)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("unexpected uuid %s instead of %s"), - nm_connection_get_uuid(connection), - expected_uuid); - return FALSE; - } - } - - vresult = _nm_connection_verify(connection, &local); - if (vresult != NM_SETTING_VERIFY_SUCCESS) { - if (!NM_IN_SET(vresult, - NM_SETTING_VERIFY_NORMALIZABLE, - NM_SETTING_VERIFY_NORMALIZABLE_ERROR)) { - g_propagate_error(error, g_steal_pointer(&local)); - return FALSE; - } - if (!allow_modify) { - if (!out_connection_clone) { - /* even NM_SETTING_VERIFY_NORMALIZABLE is treated as an error. We could normalize, - * but are not allowed to (and no out argument is provided for cloning). */ - g_propagate_error(error, g_steal_pointer(&local)); - return FALSE; - } - connection_clone = nm_simple_connection_new_clone(connection); - connection = connection_clone; - } - if (!_connection_normalize(connection, NULL, NULL, error)) - g_return_val_if_reached(FALSE); - } - - if (expected_uuid) { - NMSettingConnection *s_con; - - if (!allow_modify && !connection_clone) { - nm_assert(out_connection_clone); - connection_clone = nm_simple_connection_new_clone(connection); - connection = connection_clone; - } - s_con = nm_connection_get_setting_connection(connection); - g_object_set(s_con, NM_SETTING_CONNECTION_UUID, expected_uuid, NULL); - } - - NM_SET_OUT(out_connection_clone, g_steal_pointer(&connection_clone)); - return TRUE; -} - -/*****************************************************************************/ - -#if NM_MORE_ASSERTS -static void -_nmtst_connection_unchanging_changed_cb(NMConnection *connection, gpointer user_data) -{ - nm_assert_not_reached(); -} - -static void -_nmtst_connection_unchanging_secrets_updated_cb(NMConnection *connection, - const char * setting_name, - gpointer user_data) -{ - nm_assert_not_reached(); -} - -const char _nmtst_connection_unchanging_user_data = 0; - -void -nmtst_connection_assert_unchanging(NMConnection *connection) -{ - if (!connection) - return; - - nm_assert(NM_IS_CONNECTION(connection)); - - if (g_signal_handler_find(connection, - G_SIGNAL_MATCH_DATA, - 0, - 0, - NULL, - NULL, - (gpointer) &_nmtst_connection_unchanging_user_data) - != 0) { - /* avoid connecting the assertion handler multiple times. */ - return; - } - - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - G_CALLBACK(_nmtst_connection_unchanging_changed_cb), - (gpointer) &_nmtst_connection_unchanging_user_data); - g_signal_connect(connection, - NM_CONNECTION_SECRETS_CLEARED, - G_CALLBACK(_nmtst_connection_unchanging_changed_cb), - (gpointer) &_nmtst_connection_unchanging_user_data); - g_signal_connect(connection, - NM_CONNECTION_SECRETS_UPDATED, - G_CALLBACK(_nmtst_connection_unchanging_secrets_updated_cb), - (gpointer) &_nmtst_connection_unchanging_user_data); -} -#endif - -/*****************************************************************************/ - -/** - * nm_connection_update_secrets: - * @connection: the #NMConnection - * @setting_name: the setting object name to which the secrets apply - * @secrets: a #GVariant of secrets, of type %NM_VARIANT_TYPE_CONNECTION - * or %NM_VARIANT_TYPE_SETTING - * @error: location to store error, or %NULL - * - * Update the specified setting's secrets, given a dictionary of secrets - * intended for that setting (deserialized from D-Bus for example). Will also - * extract the given setting's secrets hash if given a connection dictionary. - * If @setting_name is %NULL, expects a fully serialized #NMConnection as - * returned by nm_connection_to_dbus() and will update all secrets from all - * settings contained in @secrets. - * - * Returns: %TRUE if the secrets were successfully updated, %FALSE if the update - * failed (tried to update secrets for a setting that doesn't exist, etc) - **/ -gboolean -nm_connection_update_secrets(NMConnection *connection, - const char * setting_name, - GVariant * secrets, - GError ** error) -{ - NMSetting * setting; - gboolean success = TRUE; - gboolean updated = FALSE; - GVariant * setting_dict = NULL; - GVariantIter iter; - const char * key; - gboolean full_connection; - int success_detail; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); - - full_connection = g_variant_is_of_type(secrets, NM_VARIANT_TYPE_CONNECTION); - - g_return_val_if_fail(full_connection || g_variant_is_of_type(secrets, NM_VARIANT_TYPE_SETTING), - FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - g_return_val_if_fail(setting_name || full_connection, FALSE); - - /* Empty @secrets means success */ - if (g_variant_n_children(secrets) == 0) - return TRUE; - - if (setting_name) { - /* Update just one setting's secrets */ - setting = nm_connection_get_setting_by_name(connection, setting_name); - if (!setting) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_SETTING_NOT_FOUND, - setting_name); - return FALSE; - } - - if (full_connection) { - setting_dict = g_variant_lookup_value(secrets, setting_name, NM_VARIANT_TYPE_SETTING); - if (!setting_dict) { - /* The connection dictionary didn't contain any secrets for - * @setting_name; just return success. - */ - return TRUE; - } - } - - g_signal_handlers_block_by_func(setting, (GCallback) setting_changed_cb, connection); - success_detail = _nm_setting_update_secrets(setting, setting_dict ?: secrets, error); - g_signal_handlers_unblock_by_func(setting, (GCallback) setting_changed_cb, connection); - - nm_clear_pointer(&setting_dict, g_variant_unref); - - if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) { - nm_assert(!error || *error); - return FALSE; - } - if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) - updated = TRUE; - } else { - /* check first, whether all the settings exist... */ - g_variant_iter_init(&iter, secrets); - while (g_variant_iter_next(&iter, "{&s@a{sv}}", &key, NULL)) { - setting = nm_connection_get_setting_by_name(connection, key); - if (!setting) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_SETTING_NOT_FOUND, - key); - return FALSE; - } - } - - /* Update each setting with any secrets from the connection dictionary */ - g_variant_iter_init(&iter, secrets); - while (g_variant_iter_next(&iter, "{&s@a{sv}}", &key, &setting_dict)) { - gs_free_error GError *local = NULL; - - /* Update the secrets for this setting */ - setting = nm_connection_get_setting_by_name(connection, key); - - g_signal_handlers_block_by_func(setting, (GCallback) setting_changed_cb, connection); - success_detail = - _nm_setting_update_secrets(setting, setting_dict, error ? &local : NULL); - g_signal_handlers_unblock_by_func(setting, (GCallback) setting_changed_cb, connection); - - g_variant_unref(setting_dict); - - if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) { - if (success) { - if (error) { - nm_assert(local); - g_propagate_error(error, g_steal_pointer(&local)); - error = NULL; - } else - nm_assert(!local); - success = FALSE; - } - break; - } - if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) - updated = TRUE; - } - } - - if (updated) - g_signal_emit(connection, signals[SECRETS_UPDATED], 0, setting_name); - - return success; -} - -/** - * nm_connection_need_secrets: - * @connection: the #NMConnection - * @hints: (out) (element-type utf8) (allow-none) (transfer container): - * the address of a pointer to a #GPtrArray, initialized to %NULL, which on - * return points to an allocated #GPtrArray containing the property names of - * secrets of the #NMSetting which may be required; the caller owns the array - * and must free the array itself with g_ptr_array_free(), but not free its - * elements - * - * Returns the name of the first setting object in the connection which would - * need secrets to make a successful connection. The returned hints are only - * intended as a guide to what secrets may be required, because in some - * circumstances, there is no way to conclusively determine exactly which - * secrets are needed. - * - * Returns: the setting name of the #NMSetting object which has invalid or - * missing secrets - **/ -const char * -nm_connection_need_secrets(NMConnection *connection, GPtrArray **hints) -{ - NMConnectionPrivate *priv; - GHashTableIter hiter; - GSList * settings = NULL; - GSList * iter; - const char * name = NULL; - NMSetting * setting; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - if (hints) - g_return_val_if_fail(*hints == NULL, NULL); - - priv = NM_CONNECTION_GET_PRIVATE(connection); - - /* Get list of settings in priority order */ - g_hash_table_iter_init(&hiter, priv->settings); - while (g_hash_table_iter_next(&hiter, NULL, (gpointer) &setting)) - settings = g_slist_insert_sorted(settings, setting, _nm_setting_compare_priority); - - for (iter = settings; iter; iter = g_slist_next(iter)) { - GPtrArray *secrets; - - setting = NM_SETTING(iter->data); - secrets = _nm_setting_need_secrets(setting); - if (secrets) { - if (hints) - *hints = secrets; - else - g_ptr_array_free(secrets, TRUE); - - name = nm_setting_get_name(setting); - break; - } - } - - g_slist_free(settings); - return name; -} - -/** - * nm_connection_clear_secrets: - * @connection: the #NMConnection - * - * Clears and frees any secrets that may be stored in the connection, to avoid - * keeping secret data in memory when not needed. - **/ -void -nm_connection_clear_secrets(NMConnection *connection) -{ - return nm_connection_clear_secrets_with_flags(connection, NULL, NULL); -} - -/** - * nm_connection_clear_secrets_with_flags: - * @connection: the #NMConnection - * @func: (scope call) (allow-none): function to be called to determine whether a - * specific secret should be cleared or not. If %NULL, all secrets are cleared. - * @user_data: caller-supplied data passed to @func - * - * Clears and frees secrets determined by @func. - **/ -void -nm_connection_clear_secrets_with_flags(NMConnection * connection, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data) -{ - GHashTableIter iter; - NMSetting * setting; - - g_return_if_fail(NM_IS_CONNECTION(connection)); - - g_hash_table_iter_init(&iter, NM_CONNECTION_GET_PRIVATE(connection)->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) { - g_signal_handlers_block_by_func(setting, (GCallback) setting_changed_cb, connection); - _nm_setting_clear_secrets(setting, func, user_data); - g_signal_handlers_unblock_by_func(setting, (GCallback) setting_changed_cb, connection); - } - - g_signal_emit(connection, signals[SECRETS_CLEARED], 0); -} - -static gboolean -_clear_secrets_by_secret_flags_cb(NMSetting * setting, - const char * secret, - NMSettingSecretFlags flags, - gpointer user_data) -{ - NMSettingSecretFlags filter_flags = GPOINTER_TO_UINT(user_data); - gboolean remove_secret; - - if (filter_flags == NM_SETTING_SECRET_FLAG_NONE) { - /* Can't use bitops with SECRET_FLAG_NONE so handle that specifically */ - remove_secret = (flags != NM_SETTING_SECRET_FLAG_NONE); - } else { - /* Otherwise, if the secret has at least one of the desired flags keep it */ - remove_secret = !NM_FLAGS_ANY(flags, filter_flags); - } - - return remove_secret; -} - -/** - * _nm_connection_clear_secrets_by_secret_flags: - * @self: the #NMConnection to filter (will be modified) - * @filter_flags: the secret flags to control whether to drop/remove - * a secret or to keep it. The meaning of the filter flags is to - * preserve the secrets. The secrets that have matching (see below) - * flags are kept, the others are dropped. - * - * Removes/drops secrets from @self according to @filter_flags. - * If @filter_flags is %NM_SETTING_SECRET_NONE, then only secrets that - * have %NM_SETTING_SECRET_NONE flags are kept. - * Otherwise, only secrets with secret flags are kept that have at least - * one of the filter flags. - */ -void -_nm_connection_clear_secrets_by_secret_flags(NMConnection *self, NMSettingSecretFlags filter_flags) -{ - nm_connection_clear_secrets_with_flags(self, - _clear_secrets_by_secret_flags_cb, - GUINT_TO_POINTER(filter_flags)); -} - -/*****************************************************************************/ - -/*****************************************************************************/ - -/* Returns always a non-NULL, floating variant that must - * be unrefed by the caller. */ -GVariant * -_nm_connection_for_each_secret(NMConnection * self, - GVariant * secrets, - gboolean remove_non_secrets, - _NMConnectionForEachSecretFunc callback, - gpointer callback_data) -{ - GVariantBuilder secrets_builder; - GVariantBuilder setting_builder; - GVariantIter secrets_iter; - GVariantIter * setting_iter; - const char * setting_name; - - /* This function, given a dict of dicts representing new secrets of - * an NMConnection, walks through each toplevel dict (which represents a - * NMSetting), and for each setting, walks through that setting dict's - * properties. For each property that's a secret, it will check that - * secret's flags in the backing NMConnection object, and call a supplied - * callback. - * - * The one complexity is that the VPN setting's 'secrets' property is - * *also* a dict (since the key/value pairs are arbitrary and known - * only to the VPN plugin itself). That means we have three levels of - * dicts that we potentially have to traverse here. The differences - * are handled by the virtual for_each_secret() function. - */ - - g_return_val_if_fail(callback, NULL); - - g_variant_iter_init(&secrets_iter, secrets); - g_variant_builder_init(&secrets_builder, NM_VARIANT_TYPE_CONNECTION); - while (g_variant_iter_next(&secrets_iter, "{&sa{sv}}", &setting_name, &setting_iter)) { - _nm_unused nm_auto_free_variant_iter GVariantIter *setting_iter_free = setting_iter; - NMSetting * setting; - const char * secret_name; - GVariant * val; - - setting = nm_connection_get_setting_by_name(self, setting_name); - if (!setting) - continue; - - g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); - while (g_variant_iter_next(setting_iter, "{&sv}", &secret_name, &val)) { - _nm_unused gs_unref_variant GVariant *val_free = val; - - NM_SETTING_GET_CLASS(setting)->for_each_secret(setting, - secret_name, - val, - remove_non_secrets, - callback, - callback_data, - &setting_builder); - } - - g_variant_builder_add(&secrets_builder, "{sa{sv}}", setting_name, &setting_builder); - } - - return g_variant_builder_end(&secrets_builder); -} - -/*****************************************************************************/ - -typedef struct { - NMConnectionFindSecretFunc find_func; - gpointer find_func_data; - gboolean found; -} FindSecretData; - -static gboolean -find_secret_for_each_func(NMSettingSecretFlags flags, gpointer user_data) -{ - FindSecretData *data = user_data; - - if (!data->found) - data->found = data->find_func(flags, data->find_func_data); - return FALSE; -} - -gboolean -_nm_connection_find_secret(NMConnection * self, - GVariant * secrets, - NMConnectionFindSecretFunc callback, - gpointer callback_data) -{ - gs_unref_variant GVariant *dummy = NULL; - FindSecretData data = { - .find_func = callback, - .find_func_data = callback_data, - .found = FALSE, - }; - - dummy = _nm_connection_for_each_secret(self, secrets, FALSE, find_secret_for_each_func, &data); - return data.found; -} - -/*****************************************************************************/ - -/** - * nm_connection_to_dbus: - * @connection: the #NMConnection - * @flags: serialization flags, e.g. %NM_CONNECTION_SERIALIZE_ALL - * - * Converts the #NMConnection into a #GVariant of type - * %NM_VARIANT_TYPE_CONNECTION describing the connection, suitable for - * marshalling over D-Bus or otherwise serializing. - * - * Returns: (transfer none): a new floating #GVariant describing the connection, - * its settings, and each setting's properties. - **/ -GVariant * -nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags) -{ - return nm_connection_to_dbus_full(connection, flags, NULL); -} - -GVariant * -nm_connection_to_dbus_full(NMConnection * connection, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - GVariantBuilder builder; - gboolean any = FALSE; - gs_free NMSetting **settings = NULL; - guint settings_len = 0; - guint i; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - - settings = nm_connection_get_settings(connection, &settings_len); - for (i = 0; i < settings_len; i++) { - NMSetting *setting = settings[i]; - GVariant * setting_dict; - - setting_dict = _nm_setting_to_dbus(setting, connection, flags, options); - if (!setting_dict) - continue; - if (!any) { - any = TRUE; - g_variant_builder_init(&builder, NM_VARIANT_TYPE_CONNECTION); - } - g_variant_builder_add(&builder, "{s@a{sv}}", nm_setting_get_name(setting), setting_dict); - } - - if (!any) - return NULL; - - return g_variant_builder_end(&builder); -} - -/** - * nm_connection_is_type: - * @connection: the #NMConnection - * @type: a setting name to check the connection's type against (like - * %NM_SETTING_WIRELESS_SETTING_NAME or %NM_SETTING_WIRED_SETTING_NAME) - * - * A convenience function to check if the given @connection is a particular - * type (ie wired, Wi-Fi, ppp, etc). Checks the #NMSettingConnection:type - * property of the connection and matches that against @type. - * - * Returns: %TRUE if the connection is of the given @type, %FALSE if not - **/ -gboolean -nm_connection_is_type(NMConnection *connection, const char *type) -{ - g_return_val_if_fail(type, FALSE); - - return nm_streq0(type, nm_connection_get_connection_type(connection)); -} - -static int -_get_settings_sort(gconstpointer p_a, gconstpointer p_b, gpointer unused) -{ - NMSetting *a = *((NMSetting **) p_a); - NMSetting *b = *((NMSetting **) p_b); - - nm_assert(NM_IS_SETTING(a)); - nm_assert(NM_IS_SETTING(b)); - nm_assert(a != b); - nm_assert(G_OBJECT_TYPE(a) != G_OBJECT_TYPE(b)); - - NM_CMP_RETURN(_nm_setting_compare_priority(a, b)); - NM_CMP_DIRECT_STRCMP(nm_setting_get_name(a), nm_setting_get_name(b)); - - nm_assert_not_reached(); - return 0; -} - -/** - * nm_connection_get_settings: - * @connection: the #NMConnection instance - * @out_length: (allow-none) (out): the length of the returned array - * - * Retrieves the settings in @connection. - * - * The returned array is %NULL-terminated. - * - * Returns: (array length=out_length) (transfer container): a - * %NULL-terminated array containing every setting of - * @connection. - * If the connection has no settings, %NULL is returned. - * - * Since: 1.10 - */ -NMSetting ** -nm_connection_get_settings(NMConnection *connection, guint *out_length) -{ - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - - return (NMSetting **) nm_utils_hash_values_to_array( - NM_CONNECTION_GET_PRIVATE(connection)->settings, - _get_settings_sort, - NULL, - out_length); -} - -/** - * nm_connection_for_each_setting_value: - * @connection: the #NMConnection - * @func: (scope call): user-supplied function called for each setting's property - * @user_data: user data passed to @func at each invocation - * - * Iterates over the properties of each #NMSetting object in the #NMConnection, - * calling the supplied user function for each property. - **/ -void -nm_connection_for_each_setting_value(NMConnection * connection, - NMSettingValueIterFn func, - gpointer user_data) -{ - gs_free NMSetting **settings = NULL; - guint i, length = 0; - - g_return_if_fail(NM_IS_CONNECTION(connection)); - g_return_if_fail(func); - - settings = nm_connection_get_settings(connection, &length); - for (i = 0; i < length; i++) - nm_setting_enumerate_values(settings[i], func, user_data); -} - -/** - * _nm_connection_aggregate: - * @connection: the #NMConnection for which values are to be aggregated. - * @type: one of the supported aggregate types. - * @arg: the input/output argument that depends on @type. - * - * For example, with %NM_CONNECTION_AGGREGATE_ANY_SECRETS and - * %NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS @arg is a boolean - * output argument. It is either %NULL or a pointer to an gboolean - * out-argument. The function will always set @arg if given. - * Also, the return value of the function is likewise the result - * that is set to @arg. - * - * Returns: a boolean result with the meaning depending on the aggregation - * type @type. - */ -gboolean -_nm_connection_aggregate(NMConnection *connection, NMConnectionAggregateType type, gpointer arg) -{ - NMConnectionPrivate *priv; - GHashTableIter iter; - NMSetting * setting; - gboolean arg_boolean; - gboolean completed_early; - gpointer my_arg; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); - - switch (type) { - case NM_CONNECTION_AGGREGATE_ANY_SECRETS: - arg_boolean = FALSE; - my_arg = &arg_boolean; - goto good; - case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: - arg_boolean = FALSE; - my_arg = &arg_boolean; - goto good; - } - g_return_val_if_reached(FALSE); - -good: - priv = NM_CONNECTION_GET_PRIVATE(connection); - - completed_early = FALSE; - g_hash_table_iter_init(&iter, priv->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) { - if (_nm_setting_aggregate(setting, type, my_arg)) { - completed_early = TRUE; - break; - } - nm_assert(my_arg != &arg_boolean || !arg_boolean); - } - - if (my_arg == &arg_boolean) { - nm_assert(completed_early == arg_boolean); - if (arg) - *((gboolean *) arg) = arg_boolean; - return arg_boolean; - } - - nm_assert_not_reached(); - return FALSE; -} - -/** - * nm_connection_dump: - * @connection: the #NMConnection - * - * Print the connection (including secrets!) to stdout. For debugging - * purposes ONLY, should NOT be used for serialization of the setting, - * or machine-parsed in any way. The output format is not guaranteed to - * be stable and may change at any time. - **/ -void -nm_connection_dump(NMConnection *connection) -{ - GHashTableIter iter; - NMSetting * setting; - char * str; - - if (!connection) - return; - - g_hash_table_iter_init(&iter, NM_CONNECTION_GET_PRIVATE(connection)->settings); - while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) { - str = nm_setting_to_string(setting); - g_print("%s\n", str); - g_free(str); - } -} - -/** - * nm_connection_set_path: - * @connection: the #NMConnection - * @path: the D-Bus path of the connection as given by the settings service - * which provides the connection - * - * Sets the D-Bus path of the connection. This property is not serialized, and - * is only for the reference of the caller. Sets the #NMConnection:path - * property. - **/ -void -nm_connection_set_path(NMConnection *connection, const char *path) -{ - NMConnectionPrivate *priv; - - g_return_if_fail(NM_IS_CONNECTION(connection)); - - priv = NM_CONNECTION_GET_PRIVATE(connection); - - g_free(priv->path); - priv->path = g_strdup(path); -} - -/** - * nm_connection_get_path: - * @connection: the #NMConnection - * - * Returns the connection's D-Bus path. - * - * Returns: the D-Bus path of the connection, previously set by a call to - * nm_connection_set_path(). - **/ -const char * -nm_connection_get_path(NMConnection *connection) -{ - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - - return NM_CONNECTION_GET_PRIVATE(connection)->path; -} - -/** - * nm_connection_get_interface_name: - * @connection: The #NMConnection - * - * Returns the interface name as stored in NMSettingConnection:interface_name. - * If the connection contains no NMSettingConnection, it will return %NULL. - * - * For hardware devices and software devices created outside of NetworkManager, - * this name is used to match the device. for software devices created by - * NetworkManager, this is the name of the created interface. - * - * Returns: Name of the kernel interface or %NULL - */ -const char * -nm_connection_get_interface_name(NMConnection *connection) -{ - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection(connection); - return s_con ? nm_setting_connection_get_interface_name(s_con) : NULL; -} - -NMConnectionMultiConnect -_nm_connection_get_multi_connect(NMConnection *connection) -{ - NMSettingConnection * s_con; - NMConnectionMultiConnect multi_connect; - const NMConnectionMultiConnect DEFAULT = NM_CONNECTION_MULTI_CONNECT_SINGLE; - - /* connection.multi_connect property cannot be specified via regular - * connection defaults in NetworkManager.conf, because those are per-device, - * and we need to determine the multi_connect independent of a particular - * device. - * - * There is however still a default-value, so theoretically, the default - * value could be specified in NetworkManager.conf. Just not as [connection*] - * and indepdented of a device. */ - - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) - return DEFAULT; - - multi_connect = nm_setting_connection_get_multi_connect(s_con); - return multi_connect == NM_CONNECTION_MULTI_CONNECT_DEFAULT ? DEFAULT : multi_connect; -} - -gboolean -_nm_connection_verify_required_interface_name(NMConnection *connection, GError **error) -{ - const char *interface_name; - - if (!connection) - return TRUE; - - interface_name = nm_connection_get_interface_name(connection); - if (interface_name) - return TRUE; - - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_INTERFACE_NAME); - return FALSE; -} - -/** - * nm_connection_get_uuid: - * @connection: the #NMConnection - * - * A shortcut to return the UUID from the connection's #NMSettingConnection. - * - * Returns: the UUID from the connection's 'connection' setting - **/ -const char * -nm_connection_get_uuid(NMConnection *connection) -{ - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection(connection); - return s_con ? nm_setting_connection_get_uuid(s_con) : NULL; -} - -/** - * nm_connection_get_id: - * @connection: the #NMConnection - * - * A shortcut to return the ID from the connection's #NMSettingConnection. - * - * Returns: the ID from the connection's 'connection' setting - **/ -const char * -nm_connection_get_id(NMConnection *connection) -{ - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection(connection); - return s_con ? nm_setting_connection_get_id(s_con) : NULL; -} - -/** - * nm_connection_get_connection_type: - * @connection: the #NMConnection - * - * A shortcut to return the type from the connection's #NMSettingConnection. - * - * Returns: the type from the connection's 'connection' setting - **/ -const char * -nm_connection_get_connection_type(NMConnection *connection) -{ - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection(connection); - return s_con ? nm_setting_connection_get_connection_type(s_con) : NULL; -} - -/** - * nm_connection_is_virtual: - * @connection: an #NMConnection - * - * Checks if @connection refers to a virtual device (and thus can potentially be - * activated even if the device it refers to doesn't exist). - * - * Returns: whether @connection refers to a virtual device - */ -gboolean -nm_connection_is_virtual(NMConnection *connection) -{ - const char *type; - - type = nm_connection_get_connection_type(connection); - if (!type) - return FALSE; - - if (NM_IN_STRSET(type, - NM_SETTING_6LOWPAN_SETTING_NAME, - NM_SETTING_BOND_SETTING_NAME, - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_DUMMY_SETTING_NAME, - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_MACSEC_SETTING_NAME, - NM_SETTING_MACVLAN_SETTING_NAME, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_TUN_SETTING_NAME, - NM_SETTING_VETH_SETTING_NAME, - NM_SETTING_VLAN_SETTING_NAME, - NM_SETTING_VRF_SETTING_NAME, - NM_SETTING_VXLAN_SETTING_NAME, - NM_SETTING_WIREGUARD_SETTING_NAME)) - return TRUE; - - if (nm_streq(type, NM_SETTING_INFINIBAND_SETTING_NAME)) { - NMSettingInfiniband *s_ib; - - s_ib = nm_connection_get_setting_infiniband(connection); - return s_ib && nm_setting_infiniband_get_virtual_interface_name(s_ib); - } - - if (nm_streq(type, NM_SETTING_BLUETOOTH_SETTING_NAME)) - return !!_nm_connection_get_setting_bluetooth_for_nap(connection); - - if (nm_streq(type, NM_SETTING_PPPOE_SETTING_NAME)) { - NMSettingPppoe *s_pppoe; - - s_pppoe = nm_connection_get_setting_pppoe(connection); - return !!nm_setting_pppoe_get_parent(s_pppoe); - } - - return FALSE; -} - -/** - * nm_connection_get_virtual_device_description: - * @connection: an #NMConnection for a virtual device type - * - * Returns the name that nm_device_disambiguate_names() would - * return for the virtual device that would be created for @connection. - * Eg, "VLAN (eth1.1)". - * - * Returns: (transfer full): the name of @connection's device, - * or %NULL if @connection is not a virtual connection type - */ -char * -nm_connection_get_virtual_device_description(NMConnection *connection) -{ - const char *type; - const char *iface = NULL, *display_type = NULL; - - type = nm_connection_get_connection_type(connection); - if (!type) - return NULL; - - iface = nm_connection_get_interface_name(connection); - - if (!strcmp(type, NM_SETTING_BOND_SETTING_NAME)) - display_type = _("Bond"); - else if (!strcmp(type, NM_SETTING_TEAM_SETTING_NAME)) - display_type = _("Team"); - else if (!strcmp(type, NM_SETTING_BRIDGE_SETTING_NAME)) - display_type = _("Bridge"); - else if (!strcmp(type, NM_SETTING_VLAN_SETTING_NAME)) - display_type = _("VLAN"); - else if (!strcmp(type, NM_SETTING_INFINIBAND_SETTING_NAME)) { - display_type = _("InfiniBand"); - iface = nm_setting_infiniband_get_virtual_interface_name( - nm_connection_get_setting_infiniband(connection)); - } else if (!strcmp(type, NM_SETTING_IP_TUNNEL_SETTING_NAME)) - display_type = _("IP Tunnel"); - - if (!iface || !display_type) - return NULL; - - return g_strdup_printf("%s (%s)", display_type, iface); -} - -/*****************************************************************************/ - -/** - * nm_connection_get_setting_802_1x: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSetting8021x the connection might contain. - * - * Returns: (transfer none): an #NMSetting8021x if the connection contains one, otherwise %NULL - **/ -NMSetting8021x * -nm_connection_get_setting_802_1x(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_802_1X); -} - -/** - * nm_connection_get_setting_bluetooth: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingBluetooth the connection might contain. - * - * Returns: (transfer none): an #NMSettingBluetooth if the connection contains one, otherwise %NULL - **/ -NMSettingBluetooth * -nm_connection_get_setting_bluetooth(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_BLUETOOTH); -} - -/** - * nm_connection_get_setting_bond: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingBond the connection might contain. - * - * Returns: (transfer none): an #NMSettingBond if the connection contains one, otherwise %NULL - **/ -NMSettingBond * -nm_connection_get_setting_bond(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_BOND); -} - -/** - * nm_connection_get_setting_team: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingTeam the connection might contain. - * - * Returns: (transfer none): an #NMSettingTeam if the connection contains one, otherwise %NULL - **/ -NMSettingTeam * -nm_connection_get_setting_team(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_TEAM); -} - -/** - * nm_connection_get_setting_team_port: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingTeamPort the connection might contain. - * - * Returns: (transfer none): an #NMSettingTeamPort if the connection contains one, otherwise %NULL - **/ -NMSettingTeamPort * -nm_connection_get_setting_team_port(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_TEAM_PORT); -} - -/** - * nm_connection_get_setting_bridge: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingBridge the connection might contain. - * - * Returns: (transfer none): an #NMSettingBridge if the connection contains one, otherwise %NULL - **/ -NMSettingBridge * -nm_connection_get_setting_bridge(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_BRIDGE); -} - -/** - * nm_connection_get_setting_cdma: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingCdma the connection might contain. - * - * Returns: (transfer none): an #NMSettingCdma if the connection contains one, otherwise %NULL - **/ -NMSettingCdma * -nm_connection_get_setting_cdma(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_CDMA); -} - -/** - * nm_connection_get_setting_connection: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingConnection the connection might contain. - * - * Returns: (transfer none): an #NMSettingConnection if the connection contains one, otherwise %NULL - **/ -NMSettingConnection * -nm_connection_get_setting_connection(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_CONNECTION); -} - -/** - * nm_connection_get_setting_dcb: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingDcb the connection might contain. - * - * Returns: (transfer none): an #NMSettingDcb if the connection contains one, otherwise NULL - **/ -NMSettingDcb * -nm_connection_get_setting_dcb(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_DCB); -} - -/** - * nm_connection_get_setting_dummy: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingDummy the connection might contain. - * - * Returns: (transfer none): an #NMSettingDummy if the connection contains one, otherwise %NULL - * - * Since: 1.8 - **/ -NMSettingDummy * -nm_connection_get_setting_dummy(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_DUMMY); -} - -/** - * nm_connection_get_setting_generic: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingGeneric the connection might contain. - * - * Returns: (transfer none): an #NMSettingGeneric if the connection contains one, otherwise NULL - **/ -NMSettingGeneric * -nm_connection_get_setting_generic(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_GENERIC); -} - -/** - * nm_connection_get_setting_gsm: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingGsm the connection might contain. - * - * Returns: (transfer none): an #NMSettingGsm if the connection contains one, otherwise %NULL - **/ -NMSettingGsm * -nm_connection_get_setting_gsm(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_GSM); -} - -/** - * nm_connection_get_setting_infiniband: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingInfiniband the connection might contain. - * - * Returns: (transfer none): an #NMSettingInfiniband if the connection contains one, otherwise %NULL - **/ -NMSettingInfiniband * -nm_connection_get_setting_infiniband(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_INFINIBAND); -} - -/** - * nm_connection_get_setting_ip4_config: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingIP4Config the connection might contain. - * - * Note that it returns the value as type #NMSettingIPConfig, since the vast - * majority of IPv4-setting-related methods are on that type, not - * #NMSettingIP4Config. - * - * Returns: (type NMSettingIP4Config) (transfer none): an #NMSettingIP4Config if the - * connection contains one, otherwise %NULL - **/ -NMSettingIPConfig * -nm_connection_get_setting_ip4_config(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_IP4_CONFIG); -} - -/** - * nm_connection_get_setting_ip_tunnel: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingIPTunnel the connection might contain. - * - * Returns: (transfer none): an #NMSettingIPTunnel if the connection contains one, otherwise %NULL - * - * Since: 1.2 - **/ -NMSettingIPTunnel * -nm_connection_get_setting_ip_tunnel(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_IP_TUNNEL); -} - -/** - * nm_connection_get_setting_ip6_config: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingIP6Config the connection might contain. - * - * Note that it returns the value as type #NMSettingIPConfig, since the vast - * majority of IPv6-setting-related methods are on that type, not - * #NMSettingIP6Config. - * - * Returns: (type NMSettingIP6Config) (transfer none): an #NMSettingIP6Config if the - * connection contains one, otherwise %NULL - **/ -NMSettingIPConfig * -nm_connection_get_setting_ip6_config(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_IP6_CONFIG); -} - -/** - * nm_connection_get_setting_macsec: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingMacsec the connection might contain. - * - * Returns: (transfer none): an #NMSettingMacsec if the connection contains one, otherwise %NULL - * - * Since: 1.6 - **/ -NMSettingMacsec * -nm_connection_get_setting_macsec(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_MACSEC); -} - -/** - * nm_connection_get_setting_macvlan: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingMacvlan the connection might contain. - * - * Returns: (transfer none): an #NMSettingMacvlan if the connection contains one, otherwise %NULL - * - * Since: 1.2 - **/ -NMSettingMacvlan * -nm_connection_get_setting_macvlan(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_MACVLAN); -} - -/** - * nm_connection_get_setting_olpc_mesh: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingOlpcMesh the connection might contain. - * - * Returns: (transfer none): an #NMSettingOlpcMesh if the connection contains one, otherwise %NULL - **/ -NMSettingOlpcMesh * -nm_connection_get_setting_olpc_mesh(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_OLPC_MESH); -} - -/** - * nm_connection_get_setting_ovs_bridge: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingOvsBridge the connection might contain. - * - * Returns: (transfer none): an #NMSettingOvsBridge if the connection contains one, otherwise %NULL - * - * Since: 1.10 - **/ -NMSettingOvsBridge * -nm_connection_get_setting_ovs_bridge(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_OVS_BRIDGE); -} - -/** - * nm_connection_get_setting_ovs_interface: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingOvsInterface the connection might contain. - * - * Returns: (transfer none): an #NMSettingOvsInterface if the connection contains one, otherwise %NULL - * - * Since: 1.10 - **/ -NMSettingOvsInterface * -nm_connection_get_setting_ovs_interface(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_OVS_INTERFACE); -} - -/** - * nm_connection_get_setting_ovs_patch: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingOvsPatch the connection might contain. - * - * Returns: (transfer none): an #NMSettingOvsPatch if the connection contains one, otherwise %NULL - * - * Since: 1.10 - **/ -NMSettingOvsPatch * -nm_connection_get_setting_ovs_patch(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_OVS_PATCH); -} - -/** - * nm_connection_get_setting_ovs_port: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingOvsPort the connection might contain. - * - * Returns: (transfer none): an #NMSettingOvsPort if the connection contains one, otherwise %NULL - * - * Since: 1.10 - **/ -NMSettingOvsPort * -nm_connection_get_setting_ovs_port(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_OVS_PORT); -} - -/** - * nm_connection_get_setting_ppp: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingPpp the connection might contain. - * - * Returns: (transfer none): an #NMSettingPpp if the connection contains one, otherwise %NULL - **/ -NMSettingPpp * -nm_connection_get_setting_ppp(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_PPP); -} - -/** - * nm_connection_get_setting_pppoe: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingPppoe the connection might contain. - * - * Returns: (transfer none): an #NMSettingPppoe if the connection contains one, otherwise %NULL - **/ -NMSettingPppoe * -nm_connection_get_setting_pppoe(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_PPPOE); -} - -/** - * nm_connection_get_setting_proxy: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingProxy the connection might contain. - * - * Returns: (transfer none): an #NMSettingProxy if the connection contains one, otherwise %NULL - * - * Since: 1.6 - **/ -NMSettingProxy * -nm_connection_get_setting_proxy(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_PROXY); -} - -/** - * nm_connection_get_setting_serial: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingSerial the connection might contain. - * - * Returns: (transfer none): an #NMSettingSerial if the connection contains one, otherwise %NULL - **/ -NMSettingSerial * -nm_connection_get_setting_serial(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_SERIAL); -} - -/** - * nm_connection_get_setting_tc_config: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingTCConfig the connection might contain. - * - * Returns: (transfer none): an #NMSettingTCConfig if the connection contains one, otherwise %NULL - * - * Since: 1.12 - **/ -NMSettingTCConfig * -nm_connection_get_setting_tc_config(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_TC_CONFIG); -} - -/** - * nm_connection_get_setting_tun: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingTun the connection might contain. - * - * Returns: (transfer none): an #NMSettingTun if the connection contains one, otherwise %NULL - * - * Since: 1.2 - **/ -NMSettingTun * -nm_connection_get_setting_tun(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_TUN); -} - -/** - * nm_connection_get_setting_vpn: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingVpn the connection might contain. - * - * Returns: (transfer none): an #NMSettingVpn if the connection contains one, otherwise %NULL - **/ -NMSettingVpn * -nm_connection_get_setting_vpn(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_VPN); -} - -/** - * nm_connection_get_setting_vxlan: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingVxlan the connection might contain. - * - * Returns: (transfer none): an #NMSettingVxlan if the connection contains one, otherwise %NULL - * - * Since: 1.2 - **/ -NMSettingVxlan * -nm_connection_get_setting_vxlan(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_VXLAN); -} - -/** - * nm_connection_get_setting_wimax: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingWimax the connection might contain. - * - * Returns: (transfer none): an #NMSettingWimax if the connection contains one, otherwise %NULL - **/ -NMSettingWimax * -nm_connection_get_setting_wimax(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_WIMAX); -} - -/** - * nm_connection_get_setting_wired: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingWired the connection might contain. - * - * Returns: (transfer none): an #NMSettingWired if the connection contains one, otherwise %NULL - **/ -NMSettingWired * -nm_connection_get_setting_wired(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_WIRED); -} - -/** - * nm_connection_get_setting_adsl: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingAdsl the connection might contain. - * - * Returns: (transfer none): an #NMSettingAdsl if the connection contains one, otherwise %NULL - **/ -NMSettingAdsl * -nm_connection_get_setting_adsl(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_ADSL); -} - -/** - * nm_connection_get_setting_wireless: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingWireless the connection might contain. - * - * Returns: (transfer none): an #NMSettingWireless if the connection contains one, otherwise %NULL - **/ -NMSettingWireless * -nm_connection_get_setting_wireless(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_WIRELESS); -} - -/** - * nm_connection_get_setting_wireless_security: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingWirelessSecurity the connection might contain. - * - * Returns: (transfer none): an #NMSettingWirelessSecurity if the connection contains one, otherwise %NULL - **/ -NMSettingWirelessSecurity * -nm_connection_get_setting_wireless_security(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); -} - -/** - * nm_connection_get_setting_bridge_port: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingBridgePort the connection might contain. - * - * Returns: (transfer none): an #NMSettingBridgePort if the connection contains one, otherwise %NULL - **/ -NMSettingBridgePort * -nm_connection_get_setting_bridge_port(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_BRIDGE_PORT); -} - -/** - * nm_connection_get_setting_vlan: - * @connection: the #NMConnection - * - * A shortcut to return any #NMSettingVlan the connection might contain. - * - * Returns: (transfer none): an #NMSettingVlan if the connection contains one, otherwise %NULL - **/ -NMSettingVlan * -nm_connection_get_setting_vlan(NMConnection *connection) -{ - return _connection_get_setting_check(connection, NM_TYPE_SETTING_VLAN); -} - -NMSettingBluetooth * -_nm_connection_get_setting_bluetooth_for_nap(NMConnection *connection) -{ - NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth(connection); - - if (s_bt - && nm_streq0(nm_setting_bluetooth_get_connection_type(s_bt), NM_SETTING_BLUETOOTH_TYPE_NAP)) - return s_bt; - return NULL; -} - -/*****************************************************************************/ - -static void -nm_connection_private_free(NMConnectionPrivate *priv) -{ - NMConnection *self = priv->self; - - g_hash_table_foreach_remove(priv->settings, _setting_release_hfr, self); - g_hash_table_destroy(priv->settings); - g_free(priv->path); - - g_slice_free(NMConnectionPrivate, priv); -} - -static NMConnectionPrivate * -nm_connection_get_private(NMConnection *connection) -{ - GQuark key; - NMConnectionPrivate *priv; - - nm_assert(NM_IS_CONNECTION(connection)); - - key = NM_CACHED_QUARK("NMConnectionPrivate"); - - priv = g_object_get_qdata((GObject *) connection, key); - if (G_UNLIKELY(!priv)) { - priv = g_slice_new0(NMConnectionPrivate); - g_object_set_qdata_full((GObject *) connection, - key, - priv, - (GDestroyNotify) nm_connection_private_free); - - priv->self = connection; - priv->settings = g_hash_table_new_full(nm_direct_hash, NULL, NULL, g_object_unref); - } - - return priv; -} - -static void -nm_connection_default_init(NMConnectionInterface *iface) -{ - /** - * NMConnection::secrets-updated: - * @connection: the object on which the signal is emitted - * @setting_name: the setting name of the #NMSetting for which secrets were - * updated - * - * The ::secrets-updated signal is emitted when the secrets of a setting - * have been changed. - */ - signals[SECRETS_UPDATED] = g_signal_new(NM_CONNECTION_SECRETS_UPDATED, - NM_TYPE_CONNECTION, - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(NMConnectionInterface, secrets_updated), - NULL, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, - 1, - G_TYPE_STRING); - - /** - * NMConnection::secrets-cleared: - * @connection: the object on which the signal is emitted - * - * The ::secrets-cleared signal is emitted when the secrets of a connection - * are cleared. - */ - signals[SECRETS_CLEARED] = g_signal_new(NM_CONNECTION_SECRETS_CLEARED, - NM_TYPE_CONNECTION, - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(NMConnectionInterface, secrets_cleared), - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); - - /** - * NMConnection::changed: - * @connection: the object on which the signal is emitted - * - * The ::changed signal is emitted when any property of any property - * (including secrets) of any setting of the connection is modified, - * or when settings are added or removed. - */ - signals[CHANGED] = g_signal_new(NM_CONNECTION_CHANGED, - NM_TYPE_CONNECTION, - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(NMConnectionInterface, changed), - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); -} diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h deleted file mode 100644 index 19034e790a..0000000000 --- a/libnm-core/nm-connection.h +++ /dev/null @@ -1,224 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2018 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_CONNECTION_H__ -#define __NM_CONNECTION_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-core-types.h" -#include "nm-setting.h" -#include "nm-errors.h" - -G_BEGIN_DECLS - -#define NM_TYPE_CONNECTION (nm_connection_get_type()) -#define NM_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_CONNECTION, NMConnection)) -#define NM_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_CONNECTION)) -#define NM_CONNECTION_GET_INTERFACE(obj) \ - (G_TYPE_INSTANCE_GET_INTERFACE((obj), NM_TYPE_CONNECTION, NMConnectionClass)) - -/* Signals */ -#define NM_CONNECTION_SECRETS_UPDATED "secrets-updated" -#define NM_CONNECTION_SECRETS_CLEARED "secrets-cleared" -#define NM_CONNECTION_CHANGED "changed" - -/* - * NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD: overwrite the ip6 method - * when normalizing ip6 configuration. If omitted, this defaults to - * @NM_SETTING_IP6_CONFIG_METHOD_AUTO. - */ -#define NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD "ip6-config-method" - -/** - * NMConnection: - * - * NMConnection is the interface implemented by #NMRemoteConnection on the - * client side, and #NMSettingsConnection on the daemon side. - */ - -/** - * NMConnectionInterface: - * @parent: the parent interface struct - * @secrets_updated: emitted when the connection's secrets are updated - * @secrets_cleared: emitted when the connection's secrets are cleared - * @changed: emitted when any change to the connection's settings occurs - */ -typedef struct { - GTypeInterface parent; - - /* Signals */ - void (*secrets_updated)(NMConnection *connection, const char *setting); - void (*secrets_cleared)(NMConnection *connection); - void (*changed)(NMConnection *connection); - -} NMConnectionInterface; - -GType nm_connection_get_type(void); - -void nm_connection_add_setting(NMConnection *connection, NMSetting *setting); - -void nm_connection_remove_setting(NMConnection *connection, GType setting_type); - -NMSetting *nm_connection_get_setting(NMConnection *connection, GType setting_type); - -NMSetting *nm_connection_get_setting_by_name(NMConnection *connection, const char *name); - -/** - * NM_VARIANT_TYPE_CONNECTION: - * - * #GVariantType for a dictionary mapping from setting names to - * %NM_VARIANT_TYPE_SETTING variants. This is used to represent an - * #NMConnection, and is the type taken by nm_simple_connection_new_from_dbus() - * and returned from nm_connection_to_dbus(). - */ -#define NM_VARIANT_TYPE_CONNECTION (G_VARIANT_TYPE("a{sa{sv}}")) - -/** - * NM_VARIANT_TYPE_SETTING: - * - * #GVariantType for a dictionary mapping from property names to values. This is - * an alias for %G_VARIANT_TYPE_VARDICT, and is the type of each element of - * an %NM_VARIANT_TYPE_CONNECTION dictionary. - */ -#define NM_VARIANT_TYPE_SETTING G_VARIANT_TYPE_VARDICT - -/** - * NMConnectionSerializationFlags: - * @NM_CONNECTION_SERIALIZE_ALL: serialize all properties (including secrets) - * @NM_CONNECTION_SERIALIZE_NO_SECRETS: do not include secrets - * @NM_CONNECTION_SERIALIZE_ONLY_SECRETS: only serialize secrets - * @NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED: if set, only secrets that - * are agent owned will be serialized. Since: 1.20. - * - * These flags determine which properties are serialized when calling when - * calling nm_connection_to_dbus(). - **/ -typedef enum { /*< flags >*/ - NM_CONNECTION_SERIALIZE_ALL = 0x00000000, - NM_CONNECTION_SERIALIZE_NO_SECRETS = 0x00000001, - NM_CONNECTION_SERIALIZE_ONLY_SECRETS = 0x00000002, - NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED = 0x00000004, -} NMConnectionSerializationFlags; - -GVariant *nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags); - -gboolean -nm_connection_replace_settings(NMConnection *connection, GVariant *new_settings, GError **error); - -void nm_connection_replace_settings_from_connection(NMConnection *connection, - NMConnection *new_connection); - -void nm_connection_clear_settings(NMConnection *connection); - -gboolean nm_connection_compare(NMConnection *a, NMConnection *b, NMSettingCompareFlags flags); - -gboolean nm_connection_diff(NMConnection * a, - NMConnection * b, - NMSettingCompareFlags flags, - GHashTable ** out_settings); - -gboolean nm_connection_verify(NMConnection *connection, GError **error); -NM_AVAILABLE_IN_1_2 -gboolean nm_connection_verify_secrets(NMConnection *connection, GError **error); -gboolean nm_connection_normalize(NMConnection *connection, - GHashTable * parameters, - gboolean * modified, - GError ** error); - -const char *nm_connection_need_secrets(NMConnection *connection, GPtrArray **hints); - -void nm_connection_clear_secrets(NMConnection *connection); - -void nm_connection_clear_secrets_with_flags(NMConnection * connection, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data); - -gboolean nm_connection_update_secrets(NMConnection *connection, - const char * setting_name, - GVariant * secrets, - GError ** error); - -void nm_connection_set_path(NMConnection *connection, const char *path); - -const char *nm_connection_get_path(NMConnection *connection); - -const char *nm_connection_get_interface_name(NMConnection *connection); - -gboolean nm_connection_is_type(NMConnection *connection, const char *type); - -void nm_connection_for_each_setting_value(NMConnection * connection, - NMSettingValueIterFn func, - gpointer user_data); - -NM_AVAILABLE_IN_1_10 -NMSetting **nm_connection_get_settings(NMConnection *connection, guint *out_length); - -void nm_connection_dump(NMConnection *connection); - -/* Helpers */ -const char *nm_connection_get_uuid(NMConnection *connection); -const char *nm_connection_get_id(NMConnection *connection); -const char *nm_connection_get_connection_type(NMConnection *connection); - -gboolean nm_connection_is_virtual(NMConnection *connection); -char * nm_connection_get_virtual_device_description(NMConnection *connection); - -NMSetting8021x * nm_connection_get_setting_802_1x(NMConnection *connection); -NMSettingBluetooth * nm_connection_get_setting_bluetooth(NMConnection *connection); -NMSettingBond * nm_connection_get_setting_bond(NMConnection *connection); -NMSettingTeam * nm_connection_get_setting_team(NMConnection *connection); -NMSettingTeamPort * nm_connection_get_setting_team_port(NMConnection *connection); -NMSettingBridge * nm_connection_get_setting_bridge(NMConnection *connection); -NMSettingBridgePort *nm_connection_get_setting_bridge_port(NMConnection *connection); -NMSettingCdma * nm_connection_get_setting_cdma(NMConnection *connection); -NMSettingConnection *nm_connection_get_setting_connection(NMConnection *connection); -NMSettingDcb * nm_connection_get_setting_dcb(NMConnection *connection); -NM_AVAILABLE_IN_1_8 -NMSettingDummy * nm_connection_get_setting_dummy(NMConnection *connection); -NMSettingGeneric * nm_connection_get_setting_generic(NMConnection *connection); -NMSettingGsm * nm_connection_get_setting_gsm(NMConnection *connection); -NMSettingInfiniband *nm_connection_get_setting_infiniband(NMConnection *connection); -NM_AVAILABLE_IN_1_2 -NMSettingIPTunnel *nm_connection_get_setting_ip_tunnel(NMConnection *connection); -NMSettingIPConfig *nm_connection_get_setting_ip4_config(NMConnection *connection); -NMSettingIPConfig *nm_connection_get_setting_ip6_config(NMConnection *connection); -NM_AVAILABLE_IN_1_6 -NMSettingMacsec *nm_connection_get_setting_macsec(NMConnection *connection); -NM_AVAILABLE_IN_1_2 -NMSettingMacvlan * nm_connection_get_setting_macvlan(NMConnection *connection); -NMSettingOlpcMesh *nm_connection_get_setting_olpc_mesh(NMConnection *connection); -NM_AVAILABLE_IN_1_10 -NMSettingOvsBridge *nm_connection_get_setting_ovs_bridge(NMConnection *connection); -NM_AVAILABLE_IN_1_10 -NMSettingOvsInterface *nm_connection_get_setting_ovs_interface(NMConnection *connection); -NMSettingOvsPatch * nm_connection_get_setting_ovs_patch(NMConnection *connection); -NM_AVAILABLE_IN_1_10 -NMSettingOvsPort *nm_connection_get_setting_ovs_port(NMConnection *connection); -NMSettingPpp * nm_connection_get_setting_ppp(NMConnection *connection); -NMSettingPppoe * nm_connection_get_setting_pppoe(NMConnection *connection); -NM_AVAILABLE_IN_1_6 -NMSettingProxy * nm_connection_get_setting_proxy(NMConnection *connection); -NMSettingSerial *nm_connection_get_setting_serial(NMConnection *connection); -NM_AVAILABLE_IN_1_12 -NMSettingTCConfig *nm_connection_get_setting_tc_config(NMConnection *connection); -NM_AVAILABLE_IN_1_2 -NMSettingTun * nm_connection_get_setting_tun(NMConnection *connection); -NMSettingVpn * nm_connection_get_setting_vpn(NMConnection *connection); -NMSettingWimax * nm_connection_get_setting_wimax(NMConnection *connection); -NMSettingAdsl * nm_connection_get_setting_adsl(NMConnection *connection); -NMSettingWired * nm_connection_get_setting_wired(NMConnection *connection); -NMSettingWireless * nm_connection_get_setting_wireless(NMConnection *connection); -NMSettingWirelessSecurity *nm_connection_get_setting_wireless_security(NMConnection *connection); -NMSettingVlan * nm_connection_get_setting_vlan(NMConnection *connection); -NM_AVAILABLE_IN_1_2 -NMSettingVxlan *nm_connection_get_setting_vxlan(NMConnection *connection); - -G_END_DECLS - -#endif /* __NM_CONNECTION_H__ */ diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h deleted file mode 100644 index d9374fe5a7..0000000000 --- a/libnm-core/nm-core-internal.h +++ /dev/null @@ -1,930 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 - 2018 Red Hat, Inc. - */ - -#ifndef NM_CORE_NM_INTERNAL_H -#define NM_CORE_NM_INTERNAL_H - -/* This header file contain functions that are provided as private API - * by libnm-core. It will contain functions to give privileged access to - * libnm-core. This can be useful for NetworkManager and libnm.so - * which both are special users of libnm-core. - * It also exposes some utility functions for reuse. - * - * These functions are not exported and are only available to components that link - * statically against libnm-core. This basically means libnm-core, libnm, NetworkManager - * and some test programs. - **/ -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) - #error Cannot use this header. -#endif - -#include "nm-base/nm-base.h" -#include "nm-connection.h" -#include "nm-core-enum-types.h" -#include "nm-core-types-internal.h" -#include "nm-meta-setting-base.h" -#include "nm-setting-6lowpan.h" -#include "nm-setting-8021x.h" -#include "nm-setting-adsl.h" -#include "nm-setting-bluetooth.h" -#include "nm-setting-bond.h" -#include "nm-setting-bridge-port.h" -#include "nm-setting-bridge.h" -#include "nm-setting-cdma.h" -#include "nm-setting-connection.h" -#include "nm-setting-dcb.h" -#include "nm-setting-dummy.h" -#include "nm-setting-generic.h" -#include "nm-setting-gsm.h" -#include "nm-setting-hostname.h" -#include "nm-setting-infiniband.h" -#include "nm-setting-ip-tunnel.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-setting-macsec.h" -#include "nm-setting-macvlan.h" -#include "nm-setting-match.h" -#include "nm-setting-olpc-mesh.h" -#include "nm-setting-ovs-bridge.h" -#include "nm-setting-ovs-interface.h" -#include "nm-setting-ovs-dpdk.h" -#include "nm-setting-ovs-patch.h" -#include "nm-setting-ovs-port.h" -#include "nm-setting-ppp.h" -#include "nm-setting-pppoe.h" -#include "nm-setting-proxy.h" -#include "nm-setting-serial.h" -#include "nm-setting-sriov.h" -#include "nm-setting-tc-config.h" -#include "nm-setting-team-port.h" -#include "nm-setting-team.h" -#include "nm-setting-tun.h" -#include "nm-setting-veth.h" -#include "nm-setting-vlan.h" -#include "nm-setting-vpn.h" -#include "nm-setting-vrf.h" -#include "nm-setting-vxlan.h" -#include "nm-setting-wifi-p2p.h" -#include "nm-setting-wimax.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireguard.h" -#include "nm-setting-wireless-security.h" -#include "nm-setting-wireless.h" -#include "nm-setting-wpan.h" -#include "nm-setting.h" -#include "nm-simple-connection.h" -#include "nm-utils.h" -#include "nm-vpn-dbus-interface.h" -#include "nm-vpn-editor-plugin.h" -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" - -/* IEEE 802.1D-1998 timer values */ -#define NM_BRIDGE_HELLO_TIME_MIN 1u -#define NM_BRIDGE_HELLO_TIME_DEF 2u -#define NM_BRIDGE_HELLO_TIME_DEF_SYS (NM_BRIDGE_HELLO_TIME_DEF * 100u) -#define NM_BRIDGE_HELLO_TIME_MAX 10u - -#define NM_BRIDGE_FORWARD_DELAY_MIN 2u -#define NM_BRIDGE_FORWARD_DELAY_DEF 15u -#define NM_BRIDGE_FORWARD_DELAY_DEF_SYS (NM_BRIDGE_FORWARD_DELAY_DEF * 100u) -#define NM_BRIDGE_FORWARD_DELAY_MAX 30u - -#define NM_BRIDGE_MAX_AGE_MIN 6u -#define NM_BRIDGE_MAX_AGE_DEF 20u -#define NM_BRIDGE_MAX_AGE_DEF_SYS (NM_BRIDGE_MAX_AGE_DEF * 100u) -#define NM_BRIDGE_MAX_AGE_MAX 40u - -/* IEEE 802.1D-1998 Table 7.4 */ -#define NM_BRIDGE_AGEING_TIME_MIN 0u -#define NM_BRIDGE_AGEING_TIME_DEF 300u -#define NM_BRIDGE_AGEING_TIME_DEF_SYS (NM_BRIDGE_AGEING_TIME_DEF * 100u) -#define NM_BRIDGE_AGEING_TIME_MAX 1000000u - -#define NM_BRIDGE_PORT_PRIORITY_MIN 0u -#define NM_BRIDGE_PORT_PRIORITY_DEF 32u -#define NM_BRIDGE_PORT_PRIORITY_MAX 63u - -#define NM_BRIDGE_PORT_PATH_COST_MIN 0u -#define NM_BRIDGE_PORT_PATH_COST_DEF 100u -#define NM_BRIDGE_PORT_PATH_COST_MAX 65535u - -#define NM_BRIDGE_MULTICAST_HASH_MAX_MIN 1u -#define NM_BRIDGE_MULTICAST_HASH_MAX_DEF 4096u -#define NM_BRIDGE_MULTICAST_HASH_MAX_MAX ((guint) G_MAXUINT32) - -#define NM_BRIDGE_STP_DEF TRUE - -#define NM_BRIDGE_GROUP_ADDRESS_DEF_BIN 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 -#define NM_BRIDGE_GROUP_ADDRESS_DEF_STR "01:80:C2:00:00:00" - -#define NM_BRIDGE_PRIORITY_MIN 0u -#define NM_BRIDGE_PRIORITY_DEF 0x8000u -#define NM_BRIDGE_PRIORITY_MAX ((guint) G_MAXUINT16) - -#define NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MIN 0u -#define NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF 2u -#define NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MAX ((guint) G_MAXUINT32) - -#define NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MIN ((guint64) 0) -#define NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF ((guint64) 100) -#define NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MAX G_MAXUINT64 - -#define NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MIN ((guint64) 0) -#define NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF ((guint64) 26000) -#define NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MAX G_MAXUINT64 - -#define NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MIN ((guint64) 0) -#define NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF ((guint64) 25500) -#define NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MAX G_MAXUINT64 - -#define NM_BRIDGE_MULTICAST_QUERIER_DEF FALSE - -#define NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MIN ((guint64) 0) -#define NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF ((guint64) 12500) -#define NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MAX G_MAXUINT64 - -#define NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MIN ((guint64) 0) -#define NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF ((guint64) 1000) -#define NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MAX G_MAXUINT64 - -#define NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF FALSE - -#define NM_BRIDGE_MULTICAST_SNOOPING_DEF TRUE - -#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MIN 0u -#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF 2u -#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MAX ((guint) G_MAXUINT32) - -#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MIN ((guint64) 0) -#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF ((guint64) 3125) -#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MAX G_MAXUINT64 - -#define NM_BRIDGE_VLAN_STATS_ENABLED_DEF FALSE - -#define NM_BRIDGE_VLAN_DEFAULT_PVID_DEF 1u - -/* NM_SETTING_COMPARE_FLAG_INFERRABLE: check whether a device-generated - * connection can be replaced by a already-defined connection. This flag only - * takes into account properties marked with the %NM_SETTING_PARAM_INFERRABLE - * flag. - */ -#define NM_SETTING_COMPARE_FLAG_INFERRABLE ((NMSettingCompareFlags) 0x80000000) - -/* NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY: this flag is used for properties - * that automatically get re-applied on an active connection when the settings - * connection is modified. For most properties, the applied-connection is distinct - * from the setting-connection and changes don't propagate. Exceptions are the - * firewall-zone and the metered property. - */ -#define NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY ((NMSettingCompareFlags) 0x40000000) - -/* NM_SETTING_COMPARE_FLAG_NONE: for convenience, define a special flag NONE -- which - * equals to numeric zero (NM_SETTING_COMPARE_FLAG_EXACT). - */ -#define NM_SETTING_COMPARE_FLAG_NONE ((NMSettingCompareFlags) 0) - -/*****************************************************************************/ - -#define NM_SETTING_SECRET_FLAG_ALL \ - ((NMSettingSecretFlags)(NM_SETTING_SECRET_FLAG_NONE | NM_SETTING_SECRET_FLAG_AGENT_OWNED \ - | NM_SETTING_SECRET_FLAG_NOT_SAVED \ - | NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) - -static inline gboolean -_nm_setting_secret_flags_valid(NMSettingSecretFlags flags) -{ - return !NM_FLAGS_ANY(flags, ~NM_SETTING_SECRET_FLAG_ALL); -} - -/*****************************************************************************/ - -const char * -nm_bluetooth_capability_to_string(NMBluetoothCapabilities capabilities, char *buf, gsize len); - -/*****************************************************************************/ - -#define NM_DHCP_HOSTNAME_FLAGS_FQDN_MASK \ - (NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE \ - | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE | NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS) - -#define NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP4 \ - (NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) - -#define NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP6 NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE - -/*****************************************************************************/ - -static inline _NMSettingWiredWakeOnLan -_NM_SETTING_WIRED_WAKE_ON_LAN_CAST(NMSettingWiredWakeOnLan v) -{ - /* _NMSettingWiredWakeOnLan and NMSettingWiredWakeOnLan enums are really - * the same. - * - * The former is used by nm-platform (which should have no libnm-core dependency), - * the latter is used by libnm-core. A unit test ensures they are exactly the same, - * so we can just cast them. */ - return (_NMSettingWiredWakeOnLan) v; -} - -/*****************************************************************************/ - -static inline NMTernary -NM_TERNARY_FROM_OPTION_BOOL(NMOptionBool v) -{ - nm_assert(NM_IN_SET(v, NM_OPTION_BOOL_DEFAULT, NM_OPTION_BOOL_TRUE, NM_OPTION_BOOL_FALSE)); - - return (NMTernary) v; -} - -static inline NMOptionBool -NM_TERNARY_TO_OPTION_BOOL(NMTernary v) -{ - nm_assert(NM_IN_SET(v, NM_TERNARY_DEFAULT, NM_TERNARY_TRUE, NM_TERNARY_FALSE)); - - return (NMOptionBool) v; -} - -/*****************************************************************************/ - -typedef enum { /*< skip >*/ - NM_SETTING_PARSE_FLAGS_NONE = 0, - NM_SETTING_PARSE_FLAGS_STRICT = 1LL << 0, - NM_SETTING_PARSE_FLAGS_BEST_EFFORT = 1LL << 1, - NM_SETTING_PARSE_FLAGS_NORMALIZE = 1LL << 2, - - _NM_SETTING_PARSE_FLAGS_LAST, - NM_SETTING_PARSE_FLAGS_ALL = ((_NM_SETTING_PARSE_FLAGS_LAST - 1) << 1) - 1, -} NMSettingParseFlags; - -gboolean _nm_connection_replace_settings(NMConnection * connection, - GVariant * new_settings, - NMSettingParseFlags parse_flags, - GError ** error); - -gpointer _nm_connection_check_main_setting(NMConnection *connection, - const char * setting_name, - GError ** error); - -typedef struct { - struct { - guint64 val; - bool has; - } timestamp; - - const char **seen_bssids; - -} NMConnectionSerializationOptions; - -GVariant *nm_connection_to_dbus_full(NMConnection * connection, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options); - -typedef enum { - /* whether the connection has any secrets. - * - * @arg may be %NULL or a pointer to a gboolean for the result. The return - * value of _nm_connection_aggregate() is likewise the boolean result. */ - NM_CONNECTION_AGGREGATE_ANY_SECRETS, - - /* whether the connection has any secret with flags NM_SETTING_SECRET_FLAG_NONE. - * Note that this only cares about the flags, not whether the secret is actually - * present. - * - * @arg may be %NULL or a pointer to a gboolean for the result. The return - * value of _nm_connection_aggregate() is likewise the boolean result. */ - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, -} NMConnectionAggregateType; - -gboolean -_nm_connection_aggregate(NMConnection *connection, NMConnectionAggregateType type, gpointer arg); - -/** - * NMSettingVerifyResult: - * @NM_SETTING_VERIFY_SUCCESS: the setting verifies successfully - * @NM_SETTING_VERIFY_ERROR: the setting has a serious misconfiguration - * @NM_SETTING_VERIFY_NORMALIZABLE: the setting is valid but has properties - * that should be normalized - * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR: the setting is invalid but the - * errors can be fixed by nm_connection_normalize(). - */ -typedef enum { - NM_SETTING_VERIFY_SUCCESS = TRUE, - NM_SETTING_VERIFY_ERROR = FALSE, - NM_SETTING_VERIFY_NORMALIZABLE = 2, - NM_SETTING_VERIFY_NORMALIZABLE_ERROR = 3, -} NMSettingVerifyResult; - -NMSettingVerifyResult _nm_connection_verify(NMConnection *connection, GError **error); - -gboolean _nm_connection_ensure_normalized(NMConnection * connection, - gboolean allow_modify, - const char * expected_uuid, - gboolean coerce_uuid, - NMConnection **out_connection_clone, - GError ** error); - -gboolean _nm_connection_remove_setting(NMConnection *connection, GType setting_type); - -#if NM_MORE_ASSERTS -extern const char _nmtst_connection_unchanging_user_data; -void nmtst_connection_assert_unchanging(NMConnection *connection); -#else -static inline void -nmtst_connection_assert_unchanging(NMConnection *connection) -{} -#endif - -NMConnection *_nm_simple_connection_new_from_dbus(GVariant * dict, - NMSettingParseFlags parse_flags, - GError ** error); - -NMSettingPriority _nm_setting_get_setting_priority(NMSetting *setting); - -gboolean _nm_setting_get_property(NMSetting *setting, const char *name, GValue *value); - -/*****************************************************************************/ - -GHashTable *_nm_setting_option_hash(NMSetting *setting, gboolean create_if_necessary); - -void _nm_setting_option_notify(NMSetting *setting, gboolean keys_changed); - -guint _nm_setting_option_get_all(NMSetting * setting, - const char *const **out_names, - GVariant *const ** out_values); - -gboolean _nm_setting_option_clear(NMSetting *setting, const char *optname); - -/*****************************************************************************/ - -guint nm_setting_ethtool_init_features( - NMSettingEthtool *setting, - NMOptionBool * requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */); - -/*****************************************************************************/ - -#define NM_UTILS_HWADDR_LEN_MAX_STR (NM_UTILS_HWADDR_LEN_MAX * 3) - -gboolean nm_utils_is_valid_iface_name_utf8safe(const char *utf8safe_name); - -GSList *_nm_utils_hash_values_to_slist(GHashTable *hash); - -GHashTable *_nm_utils_copy_strdict(GHashTable *strdict); - -typedef gpointer (*NMUtilsCopyFunc)(gpointer); - -const char ** -_nm_ip_address_get_attribute_names(const NMIPAddress *addr, gboolean sorted, guint *out_length); - -void _nm_setting_wired_clear_s390_options(NMSettingWired *setting); - -gboolean _nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error); -const char ** -_nm_ip_route_get_attribute_names(const NMIPRoute *route, gboolean sorted, guint *out_length); -GHashTable *_nm_ip_route_get_attributes(NMIPRoute *route); - -NMSriovVF *_nm_utils_sriov_vf_from_strparts(const char *index, - const char *detail, - gboolean ignore_unknown, - GError ** error); -gboolean _nm_sriov_vf_attribute_validate_all(const NMSriovVF *vf, GError **error); - -GPtrArray * -_nm_utils_copy_array(const GPtrArray *array, NMUtilsCopyFunc copy_func, GDestroyNotify free_func); -GPtrArray *_nm_utils_copy_object_array(const GPtrArray *array); - -gssize _nm_utils_ptrarray_find_first(gconstpointer *list, gssize len, gconstpointer needle); - -GSList *_nm_utils_strv_to_slist(char **strv, gboolean deep_copy); -char ** _nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy); - -GPtrArray *_nm_utils_strv_to_ptrarray(char **strv); -char ** _nm_utils_ptrarray_to_strv(const GPtrArray *ptrarray); - -gboolean _nm_utils_check_file(const char * filename, - gint64 check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - struct stat * out_st, - GError ** error); - -gboolean _nm_utils_check_module_file(const char * name, - int check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - GError ** error); - -/*****************************************************************************/ - -typedef struct _NMUuid { - guchar uuid[16]; -} NMUuid; - -NMUuid *_nm_utils_uuid_parse(const char *str, NMUuid *uuid); -char * _nm_utils_uuid_unparse(const NMUuid *uuid, char *out_str /*[37]*/); -NMUuid *_nm_utils_uuid_generate_random(NMUuid *out_uuid); - -gboolean nm_utils_uuid_is_null(const NMUuid *uuid); - -#define NM_UTILS_UUID_TYPE_LEGACY 0 -#define NM_UTILS_UUID_TYPE_VERSION3 3 -#define NM_UTILS_UUID_TYPE_VERSION5 5 - -NMUuid *nm_utils_uuid_generate_from_string_bin(NMUuid * uuid, - const char *s, - gssize slen, - int uuid_type, - gpointer type_args); - -char * -nm_utils_uuid_generate_from_string(const char *s, gssize slen, int uuid_type, gpointer type_args); - -/* arbitrarily chosen namespace UUID for _nm_utils_uuid_generate_from_strings() */ -#define NM_UTILS_UUID_NS "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905" - -char *_nm_utils_uuid_generate_from_strings(const char *string1, ...) G_GNUC_NULL_TERMINATED; - -char *nm_utils_uuid_generate_buf_(char *buf); -#define nm_utils_uuid_generate_buf(buf) \ - ({ \ - G_STATIC_ASSERT(sizeof(buf) == G_N_ELEMENTS(buf) && sizeof(buf) >= 37); \ - nm_utils_uuid_generate_buf_(buf); \ - }) -#define nm_utils_uuid_generate_a() (nm_utils_uuid_generate_buf_(g_alloca(37))) - -void _nm_dbus_errors_init(void); - -extern gboolean _nm_utils_is_manager_process; - -gboolean -_nm_dbus_typecheck_response(GVariant *response, const GVariantType *reply_type, GError **error); - -gulong _nm_dbus_signal_connect_data(GDBusProxy * proxy, - const char * signal_name, - const GVariantType *signature, - GCallback c_handler, - gpointer data, - GClosureNotify destroy_data, - GConnectFlags connect_flags); -#define _nm_dbus_signal_connect(proxy, name, signature, handler, data) \ - _nm_dbus_signal_connect_data(proxy, name, signature, handler, data, NULL, (GConnectFlags) 0) - -GVariant *_nm_dbus_proxy_call_finish(GDBusProxy * proxy, - GAsyncResult * res, - const GVariantType *reply_type, - GError ** error); - -GVariant *_nm_dbus_connection_call_finish(GDBusConnection * dbus_connection, - GAsyncResult * result, - const GVariantType *reply_type, - GError ** error); - -gboolean _nm_dbus_error_has_name(GError *error, const char *dbus_error_name); - -/*****************************************************************************/ - -char * _nm_utils_ssid_to_string_arr(const guint8 *ssid, gsize len); -char * _nm_utils_ssid_to_string(GBytes *ssid); -char * _nm_utils_ssid_to_utf8(GBytes *ssid); -gboolean _nm_utils_is_empty_ssid(GBytes *ssid); - -/*****************************************************************************/ - -gboolean _nm_vpn_plugin_info_check_file(const char * filename, - gboolean check_absolute, - gboolean do_validate_filename, - gint64 check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - GError ** error); - -const char *_nm_vpn_plugin_info_get_default_dir_etc(void); -const char *_nm_vpn_plugin_info_get_default_dir_lib(void); -const char *_nm_vpn_plugin_info_get_default_dir_user(void); - -GSList *_nm_vpn_plugin_info_list_load_dir(const char * dirname, - gboolean do_validate_filename, - gint64 check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data); - -/*****************************************************************************/ - -GHashTable *_nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *self); - -/*****************************************************************************/ - -typedef struct { - const char *name; - gboolean numeric; - gboolean ipv6_only; -} NMUtilsDNSOptionDesc; - -extern const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[]; - -gboolean _nm_utils_dns_option_validate(const char * option, - char ** out_name, - long * out_value, - gboolean ipv6, - const NMUtilsDNSOptionDesc *option_descs); -gssize _nm_utils_dns_option_find_idx(GPtrArray *array, const char *option); - -int nm_setting_ip_config_next_valid_dns_option(NMSettingIPConfig *setting, guint idx); - -/*****************************************************************************/ - -typedef struct _NMUtilsStrStrDictKey NMUtilsStrStrDictKey; -guint _nm_utils_strstrdictkey_hash(gconstpointer a); -gboolean _nm_utils_strstrdictkey_equal(gconstpointer a, gconstpointer b); -NMUtilsStrStrDictKey *_nm_utils_strstrdictkey_create(const char *v1, const char *v2); - -#define _nm_utils_strstrdictkey_static(v1, v2) ((NMUtilsStrStrDictKey *) ("\03" v1 "\0" v2 "")) - -/*****************************************************************************/ - -gboolean _nm_setting_vlan_set_priorities(NMSettingVlan * setting, - NMVlanPriorityMap map, - const NMVlanQosMapping *qos_map, - guint n_qos_map); -void _nm_setting_vlan_get_priorities(NMSettingVlan * setting, - NMVlanPriorityMap map, - NMVlanQosMapping **out_qos_map, - guint * out_n_qos_map); - -/*****************************************************************************/ - -struct ether_addr; - -gboolean _nm_utils_generate_mac_address_mask_parse(const char * value, - struct ether_addr * out_mask, - struct ether_addr **out_ouis, - gsize * out_ouis_len, - GError ** error); - -/*****************************************************************************/ - -static inline gpointer -_nm_connection_get_setting(NMConnection *connection, GType type) -{ - return (gpointer) nm_connection_get_setting(connection, type); -} - -NMSettingIPConfig *nm_connection_get_setting_ip_config(NMConnection *connection, int addr_family); - -/*****************************************************************************/ - -typedef enum { - NM_BOND_OPTION_TYPE_INT, - NM_BOND_OPTION_TYPE_BOTH, - NM_BOND_OPTION_TYPE_IP, - NM_BOND_OPTION_TYPE_MAC, - NM_BOND_OPTION_TYPE_IFNAME, -} NMBondOptionType; - -NMBondOptionType _nm_setting_bond_get_option_type(NMSettingBond *setting, const char *name); - -const char *nm_setting_bond_get_option_or_default(NMSettingBond *self, const char *option); - -/*****************************************************************************/ - -/* nm_connection_get_uuid() asserts against NULL, which is the right thing to - * do in order to catch bugs. However, sometimes that behavior is inconvenient. - * Just try or return NULL. */ - -static inline const char * -_nm_connection_get_id(NMConnection *connection) -{ - return connection ? nm_connection_get_id(connection) : NULL; -} - -static inline const char * -_nm_connection_get_uuid(NMConnection *connection) -{ - return connection ? nm_connection_get_uuid(connection) : NULL; -} - -NMConnectionMultiConnect _nm_connection_get_multi_connect(NMConnection *connection); - -/*****************************************************************************/ - -gboolean _nm_setting_bond_option_supported(const char *option, NMBondMode mode); - -/*****************************************************************************/ - -NMSettingBluetooth *_nm_connection_get_setting_bluetooth_for_nap(NMConnection *connection); - -gboolean _nm_utils_inet6_is_token(const struct in6_addr *in6addr); - -/*****************************************************************************/ - -NMTeamLinkWatcher *_nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher); - -int nm_team_link_watcher_cmp(const NMTeamLinkWatcher *watcher, const NMTeamLinkWatcher *other); - -int nm_team_link_watchers_cmp(const NMTeamLinkWatcher *const *a, - const NMTeamLinkWatcher *const *b, - gsize len, - gboolean ignore_order); - -gboolean nm_team_link_watchers_equal(const GPtrArray *a, const GPtrArray *b, gboolean ignore_order); - -/*****************************************************************************/ - -guint32 _nm_utils_parse_tc_handle(const char *str, GError **error); -void _nm_utils_string_append_tc_parent(GString *string, const char *prefix, guint32 parent); -void _nm_utils_string_append_tc_qdisc_rest(GString *string, NMTCQdisc *qdisc); -gboolean -_nm_utils_string_append_tc_tfilter_rest(GString *string, NMTCTfilter *tfilter, GError **error); - -GHashTable *_nm_tc_qdisc_get_attributes(NMTCQdisc *qdisc); -GHashTable *_nm_tc_action_get_attributes(NMTCAction *action); - -/*****************************************************************************/ - -static inline gboolean -_nm_connection_type_is_master(const char *type) -{ - return (NM_IN_STRSET(type, - NM_SETTING_BOND_SETTING_NAME, - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_TEAM_SETTING_NAME, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME)); -} - -/*****************************************************************************/ - -gboolean _nm_utils_dhcp_duid_valid(const char *duid, GBytes **out_duid_bin); - -/*****************************************************************************/ - -gboolean _nm_setting_sriov_sort_vfs(NMSettingSriov *setting); -gboolean _nm_setting_bridge_port_sort_vlans(NMSettingBridgePort *setting); -gboolean _nm_setting_bridge_sort_vlans(NMSettingBridge *setting); - -/*****************************************************************************/ - -typedef struct _NMSockAddrEndpoint NMSockAddrEndpoint; - -NMSockAddrEndpoint *nm_sock_addr_endpoint_new(const char *endpoint); - -NMSockAddrEndpoint *nm_sock_addr_endpoint_ref(NMSockAddrEndpoint *self); -void nm_sock_addr_endpoint_unref(NMSockAddrEndpoint *self); - -const char *nm_sock_addr_endpoint_get_endpoint(NMSockAddrEndpoint *self); -const char *nm_sock_addr_endpoint_get_host(NMSockAddrEndpoint *self); -gint32 nm_sock_addr_endpoint_get_port(NMSockAddrEndpoint *self); - -gboolean nm_sock_addr_endpoint_get_fixed_sockaddr(NMSockAddrEndpoint *self, gpointer sockaddr); - -#define nm_auto_unref_sockaddrendpoint nm_auto(_nm_auto_unref_sockaddrendpoint) -NM_AUTO_DEFINE_FCN0(NMSockAddrEndpoint *, - _nm_auto_unref_sockaddrendpoint, - nm_sock_addr_endpoint_unref); - -/*****************************************************************************/ - -NMSockAddrEndpoint *_nm_wireguard_peer_get_endpoint(const NMWireGuardPeer *self); -void _nm_wireguard_peer_set_endpoint(NMWireGuardPeer *self, NMSockAddrEndpoint *endpoint); - -void -_nm_wireguard_peer_set_public_key_bin(NMWireGuardPeer *self, - const guint8 public_key[static NM_WIREGUARD_PUBLIC_KEY_LEN]); - -/*****************************************************************************/ - -const NMIPAddr *nm_ip_routing_rule_get_from_bin(const NMIPRoutingRule *self); -void nm_ip_routing_rule_set_from_bin(NMIPRoutingRule *self, gconstpointer from, guint8 len); - -const NMIPAddr *nm_ip_routing_rule_get_to_bin(const NMIPRoutingRule *self); -void nm_ip_routing_rule_set_to_bin(NMIPRoutingRule *self, gconstpointer to, guint8 len); - -gboolean nm_ip_routing_rule_get_xifname_bin(const NMIPRoutingRule *self, - gboolean iif /* or else oif */, - char out_xifname[static 16]); - -#define NM_IP_ROUTING_RULE_ATTR_ACTION "action" -#define NM_IP_ROUTING_RULE_ATTR_DPORT_END "dport-end" -#define NM_IP_ROUTING_RULE_ATTR_DPORT_START "dport-start" -#define NM_IP_ROUTING_RULE_ATTR_FAMILY "family" -#define NM_IP_ROUTING_RULE_ATTR_FROM "from" -#define NM_IP_ROUTING_RULE_ATTR_FROM_LEN "from-len" -#define NM_IP_ROUTING_RULE_ATTR_FWMARK "fwmark" -#define NM_IP_ROUTING_RULE_ATTR_FWMASK "fwmask" -#define NM_IP_ROUTING_RULE_ATTR_IIFNAME "iifname" -#define NM_IP_ROUTING_RULE_ATTR_INVERT "invert" -#define NM_IP_ROUTING_RULE_ATTR_IPPROTO "ipproto" -#define NM_IP_ROUTING_RULE_ATTR_OIFNAME "oifname" -#define NM_IP_ROUTING_RULE_ATTR_PRIORITY "priority" -#define NM_IP_ROUTING_RULE_ATTR_SPORT_END "sport-end" -#define NM_IP_ROUTING_RULE_ATTR_SPORT_START "sport-start" -#define NM_IP_ROUTING_RULE_ATTR_SUPPRESS_PREFIXLENGTH "suppress-prefixlength" -#define NM_IP_ROUTING_RULE_ATTR_TABLE "table" -#define NM_IP_ROUTING_RULE_ATTR_TO "to" -#define NM_IP_ROUTING_RULE_ATTR_TOS "tos" -#define NM_IP_ROUTING_RULE_ATTR_TO_LEN "to-len" - -NMIPRoutingRule *nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error); -GVariant * nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self); - -/*****************************************************************************/ - -typedef struct _NMSettInfoSetting NMSettInfoSetting; -typedef struct _NMSettInfoProperty NMSettInfoProperty; - -typedef GVariant *(*NMSettInfoPropToDBusFcn)(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options); -typedef gboolean (*NMSettInfoPropFromDBusFcn)(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error); -typedef gboolean (*NMSettInfoPropMissingFromDBusFcn)(NMSetting * setting, - GVariant * connection_dict, - const char * property, - NMSettingParseFlags parse_flags, - GError ** error); -typedef GVariant *(*NMSettInfoPropGPropToDBusFcn)(const GValue *from); -typedef void (*NMSettInfoPropGPropFromDBusFcn)(GVariant *from, GValue *to); - -const NMSettInfoSetting *nmtst_sett_info_settings(void); - -typedef struct { - const GVariantType *dbus_type; - - NMSettInfoPropToDBusFcn to_dbus_fcn; - NMSettInfoPropFromDBusFcn from_dbus_fcn; - NMSettInfoPropMissingFromDBusFcn missing_from_dbus_fcn; - - /* Simpler variants of @to_dbus_fcn/@from_dbus_fcn that operate solely - * on the GValue value of the GObject property. */ - NMSettInfoPropGPropToDBusFcn gprop_to_dbus_fcn; - NMSettInfoPropGPropFromDBusFcn gprop_from_dbus_fcn; -} NMSettInfoPropertType; - -struct _NMSettInfoProperty { - const char *name; - - GParamSpec *param_spec; - - const NMSettInfoPropertType *property_type; -}; - -typedef struct { - const GVariantType *(*get_variant_type)(const struct _NMSettInfoSetting *sett_info, - const char * name, - GError ** error); -} NMSettInfoSettGendata; - -typedef struct { - /* if set, then this setting class has no own fields. Instead, its - * data is entirely based on gendata. Meaning: it tracks all data - * as native GVariants. - * It might have some GObject properties, but these are merely accessors - * to the underlying gendata. - * - * Note, that at the moment there are few hooks, to customize the behavior - * of the setting further. They are currently unneeded. This is desired, - * but could be added when there is a good reason. - * - * However, a few hooks there are... see NMSettInfoSettGendata. */ - const NMSettInfoSettGendata *gendata_info; -} NMSettInfoSettDetail; - -struct _NMSettInfoSetting { - NMSettingClass *setting_class; - - /* the properties, sorted by property name. */ - const NMSettInfoProperty *property_infos; - - /* the @property_infos list is sorted by property name. For some uses we need - * a different sort order. If @property_infos_sorted is set, this is the order - * instead. It is used for: - * - * - nm_setting_enumerate_values() - * - keyfile writer adding keys to the group. - * - * Note that currently only NMSettingConnection implements here a sort order - * that differs from alphabetical sort of the property names. - */ - const NMSettInfoProperty *const *property_infos_sorted; - - guint property_infos_len; - NMSettInfoSettDetail detail; -}; - -static inline const NMSettInfoProperty * -_nm_sett_info_property_info_get_sorted(const NMSettInfoSetting *sett_info, guint idx) -{ - nm_assert(sett_info); - nm_assert(idx < sett_info->property_infos_len); - nm_assert(!sett_info->property_infos_sorted || sett_info->property_infos_sorted[idx]); - - return sett_info->property_infos_sorted ? sett_info->property_infos_sorted[idx] - : &sett_info->property_infos[idx]; -} - -const NMSettInfoProperty * -_nm_sett_info_setting_get_property_info(const NMSettInfoSetting *sett_info, - const char * property_name); - -const NMSettInfoSetting *_nm_setting_class_get_sett_info(NMSettingClass *setting_class); - -static inline const NMSettInfoProperty * -_nm_setting_class_get_property_info(NMSettingClass *setting_class, const char *property_name) -{ - return _nm_sett_info_setting_get_property_info(_nm_setting_class_get_sett_info(setting_class), - property_name); -} - -/*****************************************************************************/ - -gboolean _nm_setting_compare(NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags); - -gboolean _nm_setting_diff(NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags, - gboolean invert_results, - GHashTable ** results); - -NMSetting8021xCKScheme _nm_setting_802_1x_cert_get_scheme(GBytes *bytes, GError **error); - -GBytes *_nm_setting_802_1x_cert_value_to_bytes(NMSetting8021xCKScheme scheme, - const guint8 * val_bin, - gssize val_len, - GError ** error); - -/*****************************************************************************/ - -static inline gboolean -_nm_connection_serialize_secrets(NMConnectionSerializationFlags flags, - NMSettingSecretFlags secret_flags) -{ - if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_NO_SECRETS)) - return FALSE; - if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED) - && !NM_FLAGS_HAS(secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) - return FALSE; - return TRUE; -} - -void _nm_connection_clear_secrets_by_secret_flags(NMConnection * self, - NMSettingSecretFlags filter_flags); - -GVariant *_nm_connection_for_each_secret(NMConnection * self, - GVariant * secrets, - gboolean remove_non_secrets, - _NMConnectionForEachSecretFunc callback, - gpointer callback_data); - -typedef gboolean (*NMConnectionFindSecretFunc)(NMSettingSecretFlags flags, gpointer user_data); - -gboolean _nm_connection_find_secret(NMConnection * self, - GVariant * secrets, - NMConnectionFindSecretFunc callback, - gpointer callback_data); - -/*****************************************************************************/ - -gboolean nm_utils_base64secret_normalize(const char *base64_key, - gsize required_key_len, - char ** out_base64_key_norm); - -/*****************************************************************************/ - -gboolean nm_utils_connection_is_adhoc_wpa(NMConnection *connection); - -const char *nm_utils_wifi_freq_to_band(guint32 freq); - -gboolean _nm_utils_iaid_verify(const char *str, gint64 *out_value); - -gboolean -_nm_utils_validate_dhcp_hostname_flags(NMDhcpHostnameFlags flags, int addr_family, GError **error); - -/*****************************************************************************/ - -gboolean _nmtst_variant_attribute_spec_assert_sorted(const NMVariantAttributeSpec *const *array, - gsize len); - -const NMVariantAttributeSpec * -_nm_variant_attribute_spec_find_binary_search(const NMVariantAttributeSpec *const *array, - gsize len, - const char * name); - -/*****************************************************************************/ - -gboolean _nm_ip_tunnel_mode_is_layer2(NMIPTunnelMode mode); - -#endif diff --git a/libnm-core/nm-core-types-internal.h b/libnm-core/nm-core-types-internal.h deleted file mode 100644 index 346458d359..0000000000 --- a/libnm-core/nm-core-types-internal.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef NM_CORE_TYPES_INTERNAL_H -#define NM_CORE_TYPES_INTERNAL_H - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) - #error Cannot use this header. -#endif - -typedef struct { - guint32 from; - guint32 to; -} NMVlanQosMapping; - -#define _NM_IP_TUNNEL_FLAG_ALL_IP6TNL \ - (NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \ - | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL | NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV \ - | NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK) - -#endif /* NM_CORE_TYPES_INTERNAL_H */ diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h deleted file mode 100644 index bf0c2a9966..0000000000 --- a/libnm-core/nm-core-types.h +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 - 2018 Red Hat, Inc. - */ - -#ifndef __NM_CORE_TYPES_H__ -#define __NM_CORE_TYPES_H__ - -#include - -#include "nm-version.h" -#include "nm-dbus-interface.h" -#include "nm-core-enum-types.h" - -typedef struct _NMConnection NMConnection; -typedef struct _NMSetting NMSetting; -typedef struct _NMSetting6Lowpan NMSetting6Lowpan; -typedef struct _NMSetting8021x NMSetting8021x; -typedef struct _NMSettingAdsl NMSettingAdsl; -typedef struct _NMSettingBluetooth NMSettingBluetooth; -typedef struct _NMSettingBond NMSettingBond; -typedef struct _NMSettingBridge NMSettingBridge; -typedef struct _NMSettingBridgePort NMSettingBridgePort; -typedef struct _NMSettingCdma NMSettingCdma; -typedef struct _NMSettingConnection NMSettingConnection; -typedef struct _NMSettingDcb NMSettingDcb; -typedef struct _NMSettingDummy NMSettingDummy; -typedef struct _NMSettingEthtool NMSettingEthtool; -typedef struct _NMSettingGeneric NMSettingGeneric; -typedef struct _NMSettingGsm NMSettingGsm; -typedef struct _NMSettingHostname NMSettingHostname; -typedef struct _NMSettingIP4Config NMSettingIP4Config; -typedef struct _NMSettingIP6Config NMSettingIP6Config; -typedef struct _NMSettingIPConfig NMSettingIPConfig; -typedef struct _NMSettingIPTunnel NMSettingIPTunnel; -typedef struct _NMSettingInfiniband NMSettingInfiniband; -typedef struct _NMSettingMacsec NMSettingMacsec; -typedef struct _NMSettingMacvlan NMSettingMacvlan; -typedef struct _NMSettingMatch NMSettingMatch; -typedef struct _NMSettingOlpcMesh NMSettingOlpcMesh; -typedef struct _NMSettingOvsBridge NMSettingOvsBridge; -typedef struct _NMSettingOvsDpdk NMSettingOvsDpdk; -typedef struct _NMSettingOvsExternalIDs NMSettingOvsExternalIDs; -typedef struct _NMSettingOvsInterface NMSettingOvsInterface; -typedef struct _NMSettingOvsPatch NMSettingOvsPatch; -typedef struct _NMSettingOvsPort NMSettingOvsPort; -typedef struct _NMSettingPpp NMSettingPpp; -typedef struct _NMSettingPppoe NMSettingPppoe; -typedef struct _NMSettingProxy NMSettingProxy; -typedef struct _NMSettingSerial NMSettingSerial; -typedef struct _NMSettingSriov NMSettingSriov; -typedef struct _NMSettingTCConfig NMSettingTCConfig; -typedef struct _NMSettingTeam NMSettingTeam; -typedef struct _NMSettingTeamPort NMSettingTeamPort; -typedef struct _NMSettingTun NMSettingTun; -typedef struct _NMSettingUser NMSettingUser; -typedef struct _NMSettingVeth NMSettingVeth; -typedef struct _NMSettingVlan NMSettingVlan; -typedef struct _NMSettingVpn NMSettingVpn; -typedef struct _NMSettingVrf NMSettingVrf; -typedef struct _NMSettingVxlan NMSettingVxlan; -typedef struct _NMSettingWifiP2P NMSettingWifiP2P; -typedef struct _NMSettingWimax NMSettingWimax; -typedef struct _NMSettingWired NMSettingWired; -typedef struct _NMSettingWireGuard NMSettingWireGuard; -typedef struct _NMSettingWireless NMSettingWireless; -typedef struct _NMSettingWirelessSecurity NMSettingWirelessSecurity; -typedef struct _NMSettingWpan NMSettingWpan; -typedef struct _NMSimpleConnection NMSimpleConnection; - -typedef gboolean (*NMUtilsPredicateStr)(const char *str); - -#endif /* __NM_CORE_TYPES_H__ */ diff --git a/libnm-core/nm-crypto-gnutls.c b/libnm-core/nm-crypto-gnutls.c deleted file mode 100644 index 17c5d1dc6a..0000000000 --- a/libnm-core/nm-crypto-gnutls.c +++ /dev/null @@ -1,415 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Dan Williams - * Copyright (C) 2007 - 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-crypto-impl.h" - -#include -#include -#include -#include - -#include "nm-glib-aux/nm-secret-utils.h" -#include "nm-errors.h" - -/*****************************************************************************/ - -static gboolean -_get_cipher_info(NMCryptoCipherType cipher, int *out_cipher_mech, guint8 *out_real_iv_len) -{ - static const int cipher_mechs[] = { - [NM_CRYPTO_CIPHER_DES_EDE3_CBC] = GNUTLS_CIPHER_3DES_CBC, - [NM_CRYPTO_CIPHER_DES_CBC] = GNUTLS_CIPHER_DES_CBC, - [NM_CRYPTO_CIPHER_AES_128_CBC] = GNUTLS_CIPHER_AES_128_CBC, - [NM_CRYPTO_CIPHER_AES_192_CBC] = GNUTLS_CIPHER_AES_192_CBC, - [NM_CRYPTO_CIPHER_AES_256_CBC] = GNUTLS_CIPHER_AES_256_CBC, - }; - - g_return_val_if_fail(_NM_INT_NOT_NEGATIVE(cipher) - && (gsize) cipher < G_N_ELEMENTS(cipher_mechs), - FALSE); - - if (cipher_mechs[cipher] == 0) - return FALSE; - - NM_SET_OUT(out_cipher_mech, cipher_mechs[cipher]); - NM_SET_OUT(out_real_iv_len, nm_crypto_cipher_get_info(cipher)->real_iv_len); - return TRUE; -} - -/*****************************************************************************/ - -gboolean -_nm_crypto_init(GError **error) -{ - static gboolean initialized = FALSE; - - if (initialized) - return TRUE; - - if (gnutls_global_init() != 0) { - gnutls_global_deinit(); - g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, - _("Failed to initialize the crypto engine.")); - return FALSE; - } - - initialized = TRUE; - return TRUE; -} - -/*****************************************************************************/ - -guint8 * -_nmtst_crypto_decrypt(NMCryptoCipherType cipher, - const guint8 * data, - gsize data_len, - const guint8 * iv, - gsize iv_len, - const guint8 * key, - gsize key_len, - gsize * out_len, - GError ** error) -{ - gnutls_cipher_hd_t ctx; - gnutls_datum_t key_dt, iv_dt; - int err; - int cipher_mech; - nm_auto_clear_secret_ptr NMSecretPtr output = {0}; - guint8 pad_i, pad_len; - guint8 real_iv_len; - - if (!_get_cipher_info(cipher, &cipher_mech, &real_iv_len)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Unsupported key cipher for decryption")); - return NULL; - } - - if (!_nm_crypto_init(error)) - return NULL; - - if (iv_len < real_iv_len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Invalid IV length (must be at least %u)."), - (guint) real_iv_len); - return NULL; - } - - output.len = data_len; - output.bin = g_malloc(data_len); - - key_dt.data = (unsigned char *) key; - key_dt.size = key_len; - iv_dt.data = (unsigned char *) iv; - iv_dt.size = iv_len; - - err = gnutls_cipher_init(&ctx, cipher_mech, &key_dt, &iv_dt); - if (err < 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to initialize the decryption cipher context: %s (%s)"), - gnutls_strerror_name(err), - gnutls_strerror(err)); - return NULL; - } - - err = gnutls_cipher_decrypt2(ctx, data, data_len, output.bin, output.len); - - gnutls_cipher_deinit(ctx); - - if (err < 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to decrypt the private key: %s (%s)"), - gnutls_strerror_name(err), - gnutls_strerror(err)); - return NULL; - } - - pad_len = output.len > 0 ? output.bin[output.len - 1] : 0; - - /* Check if the padding at the end of the decrypted data is valid */ - if (pad_len == 0 || pad_len > real_iv_len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to decrypt the private key: unexpected padding length.")); - return NULL; - } - - /* Validate tail padding; last byte is the padding size, and all pad bytes - * should contain the padding size. - */ - for (pad_i = 1; pad_i <= pad_len; ++pad_i) { - if (output.bin[data_len - pad_i] != pad_len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to decrypt the private key.")); - return NULL; - } - } - - *out_len = output.len - pad_len; - return g_steal_pointer(&output.bin); -} - -guint8 * -_nmtst_crypto_encrypt(NMCryptoCipherType cipher, - const guint8 * data, - gsize data_len, - const guint8 * iv, - gsize iv_len, - const guint8 * key, - gsize key_len, - gsize * out_len, - GError ** error) -{ - gnutls_cipher_hd_t ctx; - gnutls_datum_t key_dt, iv_dt; - int err; - int cipher_mech; - nm_auto_clear_secret_ptr NMSecretPtr output = {0}; - nm_auto_clear_secret_ptr NMSecretPtr padded_buf = {0}; - gsize i, pad_len; - - nm_assert(iv_len); - - if (cipher == NM_CRYPTO_CIPHER_DES_CBC || !_get_cipher_info(cipher, &cipher_mech, NULL)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Unsupported key cipher for encryption")); - return NULL; - } - - if (!_nm_crypto_init(error)) - return NULL; - - key_dt.data = (unsigned char *) key; - key_dt.size = key_len; - iv_dt.data = (unsigned char *) iv; - iv_dt.size = iv_len; - - err = gnutls_cipher_init(&ctx, cipher_mech, &key_dt, &iv_dt); - if (err < 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, - _("Failed to initialize the encryption cipher context: %s (%s)"), - gnutls_strerror_name(err), - gnutls_strerror(err)); - return NULL; - } - - /* If data_len % ivlen == 0, then we add another complete block - * onto the end so that the decrypter knows there's padding. - */ - pad_len = iv_len - (data_len % iv_len); - - padded_buf.len = data_len + pad_len; - padded_buf.bin = g_malloc(padded_buf.len); - memcpy(padded_buf.bin, data, data_len); - for (i = 0; i < pad_len; i++) - padded_buf.bin[data_len + i] = (guint8)(pad_len & 0xFF); - - output.len = padded_buf.len; - output.bin = g_malloc(output.len); - - err = gnutls_cipher_encrypt2(ctx, padded_buf.bin, padded_buf.len, output.bin, output.len); - - gnutls_cipher_deinit(ctx); - - if (err < 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, - _("Failed to encrypt the data: %s (%s)"), - gnutls_strerror_name(err), - gnutls_strerror(err)); - return NULL; - } - - *out_len = output.len; - return g_steal_pointer(&output.bin); -} - -gboolean -_nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error) -{ - gnutls_x509_crt_t der; - gnutls_datum_t dt; - int err; - - if (!_nm_crypto_init(error)) - return FALSE; - - err = gnutls_x509_crt_init(&der); - if (err < 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Error initializing certificate data: %s"), - gnutls_strerror(err)); - return FALSE; - } - - /* Try DER first */ - dt.data = (unsigned char *) data; - dt.size = len; - err = gnutls_x509_crt_import(der, &dt, GNUTLS_X509_FMT_DER); - if (err == GNUTLS_E_SUCCESS) { - gnutls_x509_crt_deinit(der); - return TRUE; - } - - /* And PEM next */ - err = gnutls_x509_crt_import(der, &dt, GNUTLS_X509_FMT_PEM); - gnutls_x509_crt_deinit(der); - if (err == GNUTLS_E_SUCCESS) - return TRUE; - - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Couldn't decode certificate: %s"), - gnutls_strerror(err)); - return FALSE; -} - -gboolean -_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error) -{ - gnutls_pkcs12_t p12; - gnutls_datum_t dt; - int err; - - g_return_val_if_fail(data != NULL, FALSE); - - if (!_nm_crypto_init(error)) - return FALSE; - - dt.data = (unsigned char *) data; - dt.size = data_len; - - err = gnutls_pkcs12_init(&p12); - if (err < 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, - _("Couldn't initialize PKCS#12 decoder: %s"), - gnutls_strerror(err)); - return FALSE; - } - - /* DER first */ - err = gnutls_pkcs12_import(p12, &dt, GNUTLS_X509_FMT_DER, 0); - if (err < 0) { - /* PEM next */ - err = gnutls_pkcs12_import(p12, &dt, GNUTLS_X509_FMT_PEM, 0); - if (err < 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Couldn't decode PKCS#12 file: %s"), - gnutls_strerror(err)); - gnutls_pkcs12_deinit(p12); - return FALSE; - } - } - - err = gnutls_pkcs12_verify_mac(p12, password); - - gnutls_pkcs12_deinit(p12); - - if (err != GNUTLS_E_SUCCESS) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Couldn't verify PKCS#12 file: %s"), - gnutls_strerror(err)); - return FALSE; - } - - return TRUE; -} - -gboolean -_nm_crypto_verify_pkcs8(const guint8 *data, - gsize data_len, - gboolean is_encrypted, - const char * password, - GError ** error) -{ - gnutls_x509_privkey_t p8; - gnutls_datum_t dt; - int err; - - g_return_val_if_fail(data != NULL, FALSE); - - if (!_nm_crypto_init(error)) - return FALSE; - - err = gnutls_x509_privkey_init(&p8); - if (err < 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, - _("Couldn't initialize PKCS#8 decoder: %s"), - gnutls_strerror(err)); - return FALSE; - } - - dt.data = (unsigned char *) data; - dt.size = data_len; - - err = gnutls_x509_privkey_import_pkcs8(p8, - &dt, - GNUTLS_X509_FMT_DER, - is_encrypted ? password : NULL, - is_encrypted ? 0 : GNUTLS_PKCS_PLAIN); - - gnutls_x509_privkey_deinit(p8); - - if (err < 0) { - if (err == GNUTLS_E_UNKNOWN_CIPHER_TYPE) { - /* HACK: gnutls < 3.5.4 doesn't support all the cipher types that openssl - * can use with PKCS#8, so if we encounter one, we have to assume - * the given password works. gnutls needs to unsuckify, apparently. - * Specifically, by default openssl uses pbeWithMD5AndDES-CBC - * which gnutls does not support. - */ - } else { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Couldn't decode PKCS#8 file: %s"), - gnutls_strerror(err)); - return FALSE; - } - } - - return TRUE; -} - -gboolean -_nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error) -{ - if (!_nm_crypto_init(error)) - return FALSE; - - gnutls_rnd(GNUTLS_RND_RANDOM, buffer, buffer_len); - return TRUE; -} diff --git a/libnm-core/nm-crypto-impl.h b/libnm-core/nm-crypto-impl.h deleted file mode 100644 index 185f11da12..0000000000 --- a/libnm-core/nm-crypto-impl.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Dan Williams - * Copyright (C) 2007 - 2018 Red Hat, Inc. - */ - -#ifndef __NM_CRYPTO_IMPL_H__ -#define __NM_CRYPTO_IMPL_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) - #error Cannot use this header. -#endif - -#include "nm-crypto.h" - -gboolean _nm_crypto_init(GError **error); - -gboolean _nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error); - -gboolean _nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error); - -gboolean -_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error); - -gboolean _nm_crypto_verify_pkcs8(const guint8 *data, - gsize data_len, - gboolean is_encrypted, - const char * password, - GError ** error); - -/*****************************************************************************/ - -guint8 *_nmtst_crypto_encrypt(NMCryptoCipherType cipher, - const guint8 * data, - gsize data_len, - const guint8 * iv, - gsize iv_len, - const guint8 * key, - gsize key_len, - gsize * out_len, - GError ** error); - -guint8 *_nmtst_crypto_decrypt(NMCryptoCipherType cipher, - const guint8 * data, - gsize data_len, - const guint8 * iv, - gsize iv_len, - const guint8 * key, - gsize key_len, - gsize * out_len, - GError ** error); - -#endif /* __NM_CRYPTO_IMPL_H__ */ diff --git a/libnm-core/nm-crypto-nss.c b/libnm-core/nm-crypto-nss.c deleted file mode 100644 index 8cbb4daf67..0000000000 --- a/libnm-core/nm-crypto-nss.c +++ /dev/null @@ -1,548 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Dan Williams - * Copyright (C) 2007 - 2009 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-crypto-impl.h" - -NM_PRAGMA_WARNING_DISABLE("-Wstrict-prototypes") -#include -#include -#include -#include -#include -#include -#include -#include -#include -NM_PRAGMA_WARNING_REENABLE - -#include "nm-glib-aux/nm-secret-utils.h" -#include "nm-errors.h" - -/*****************************************************************************/ - -static gboolean -_get_cipher_info(NMCryptoCipherType cipher, - CK_MECHANISM_TYPE *out_cipher_mech, - guint8 * out_real_iv_len) -{ - static const CK_MECHANISM_TYPE cipher_mechs[] = { - [NM_CRYPTO_CIPHER_DES_EDE3_CBC] = CKM_DES3_CBC_PAD, - [NM_CRYPTO_CIPHER_DES_CBC] = CKM_DES_CBC_PAD, - [NM_CRYPTO_CIPHER_AES_128_CBC] = CKM_AES_CBC_PAD, - [NM_CRYPTO_CIPHER_AES_192_CBC] = CKM_AES_CBC_PAD, - [NM_CRYPTO_CIPHER_AES_256_CBC] = CKM_AES_CBC_PAD, - }; - - g_return_val_if_fail(_NM_INT_NOT_NEGATIVE(cipher) - && (gsize) cipher < G_N_ELEMENTS(cipher_mechs), - FALSE); - - if (!cipher_mechs[cipher]) - return FALSE; - - NM_SET_OUT(out_cipher_mech, cipher_mechs[cipher]); - NM_SET_OUT(out_real_iv_len, nm_crypto_cipher_get_info(cipher)->real_iv_len); - return TRUE; -} - -/*****************************************************************************/ - -gboolean -_nm_crypto_init(GError **error) -{ - static gboolean initialized = FALSE; - SECStatus ret; - - if (initialized) - return TRUE; - - PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1); - ret = NSS_NoDB_Init(NULL); - if (ret != SECSuccess) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, - _("Failed to initialize the crypto engine: %d."), - PR_GetError()); - PR_Cleanup(); - return FALSE; - } - - SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1); - SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1); - SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); - SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1); - SEC_PKCS12EnableCipher(PKCS12_DES_56, 1); - SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1); - SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1); - - initialized = TRUE; - return TRUE; -} - -guint8 * -_nmtst_crypto_decrypt(NMCryptoCipherType cipher, - const guint8 * data, - gsize data_len, - const guint8 * iv, - gsize iv_len, - const guint8 * key, - gsize key_len, - gsize * out_len, - GError ** error) -{ - CK_MECHANISM_TYPE cipher_mech; - PK11SlotInfo * slot = NULL; - SECItem key_item; - PK11SymKey * sym_key = NULL; - SECItem * sec_param = NULL; - PK11Context * ctx = NULL; - nm_auto_clear_secret_ptr NMSecretPtr output = {0}; - SECStatus s; - gboolean success = FALSE; - int decrypted_len = 0; - unsigned extra = 0; - unsigned pad_len = 0; - guint32 i; - guint8 real_iv_len; - - if (!_get_cipher_info(cipher, &cipher_mech, &real_iv_len)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Unsupported key cipher for decryption")); - return NULL; - } - - if (iv_len < real_iv_len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Invalid IV length (must be at least %u)."), - (guint) real_iv_len); - return NULL; - } - - if (!_nm_crypto_init(error)) - return NULL; - - slot = PK11_GetBestSlot(cipher_mech, NULL); - if (!slot) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, - _("Failed to initialize the decryption cipher slot.")); - goto out; - } - - key_item.data = (unsigned char *) key; - key_item.len = key_len; - sym_key = PK11_ImportSymKey(slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL); - if (!sym_key) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to set symmetric key for decryption.")); - goto out; - } - - key_item.data = (unsigned char *) iv; - key_item.len = real_iv_len; - sec_param = PK11_ParamFromIV(cipher_mech, &key_item); - if (!sec_param) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to set IV for decryption.")); - goto out; - } - - ctx = PK11_CreateContextBySymKey(cipher_mech, CKA_DECRYPT, sym_key, sec_param); - if (!ctx) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to initialize the decryption context.")); - goto out; - } - - output.len = data_len; - output.bin = g_malloc(data_len); - - s = PK11_CipherOp(ctx, - (unsigned char *) output.bin, - &decrypted_len, - output.len, - data, - data_len); - if (s != SECSuccess) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to decrypt the private key: %d."), - PORT_GetError()); - goto out; - } - - if (decrypted_len > data_len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to decrypt the private key: decrypted data too large.")); - goto out; - } - - s = PK11_DigestFinal(ctx, - (unsigned char *) &output.bin[decrypted_len], - &extra, - data_len - decrypted_len); - if (s != SECSuccess) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to finalize decryption of the private key: %d."), - PORT_GetError()); - goto out; - } - - decrypted_len += extra; - pad_len = data_len - decrypted_len; - - /* Check if the padding at the end of the decrypted data is valid */ - if (pad_len == 0 || pad_len > real_iv_len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to decrypt the private key: unexpected padding length.")); - goto out; - } - - /* Validate tail padding; last byte is the padding size, and all pad bytes - * should contain the padding size. - */ - for (i = pad_len; i > 0; i--) { - if (output.bin[data_len - i] != pad_len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Failed to decrypt the private key.")); - goto out; - } - } - - success = TRUE; - -out: - if (ctx) - PK11_DestroyContext(ctx, PR_TRUE); - if (sym_key) - PK11_FreeSymKey(sym_key); - if (sec_param) - SECITEM_FreeItem(sec_param, PR_TRUE); - if (slot) - PK11_FreeSlot(slot); - - if (!success) - return NULL; - - if (decrypted_len < output.len) - nm_explicit_bzero(&output.bin[decrypted_len], output.len - decrypted_len); - *out_len = decrypted_len; - return g_steal_pointer(&output.bin); -} - -guint8 * -_nmtst_crypto_encrypt(NMCryptoCipherType cipher, - const guint8 * data, - gsize data_len, - const guint8 * iv, - gsize iv_len, - const guint8 * key, - gsize key_len, - gsize * out_len, - GError ** error) -{ - SECStatus ret; - CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; - PK11SlotInfo * slot = NULL; - SECItem key_item = {.data = (unsigned char *) key, .len = key_len}; - SECItem iv_item = {.data = (unsigned char *) iv, .len = iv_len}; - PK11SymKey * sym_key = NULL; - SECItem * sec_param = NULL; - PK11Context * ctx = NULL; - nm_auto_clear_secret_ptr NMSecretPtr padded_buf = {0}; - nm_auto_clear_secret_ptr NMSecretPtr output = {0}; - int encrypted_len = 0, i; - gboolean success = FALSE; - gsize pad_len; - - if (cipher == NM_CRYPTO_CIPHER_DES_CBC || !_get_cipher_info(cipher, &cipher_mech, NULL)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Unsupported key cipher for encryption")); - return NULL; - } - - if (!_nm_crypto_init(error)) - return NULL; - - slot = PK11_GetBestSlot(cipher_mech, NULL); - if (!slot) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, - _("Failed to initialize the encryption cipher slot.")); - return NULL; - } - - sym_key = PK11_ImportSymKey(slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); - if (!sym_key) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, - _("Failed to set symmetric key for encryption.")); - goto out; - } - - sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); - if (!sec_param) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, - _("Failed to set IV for encryption.")); - goto out; - } - - ctx = PK11_CreateContextBySymKey(cipher_mech, CKA_ENCRYPT, sym_key, sec_param); - if (!ctx) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, - _("Failed to initialize the encryption context.")); - goto out; - } - - /* If data->len % ivlen == 0, then we add another complete block - * onto the end so that the decrypter knows there's padding. - */ - pad_len = iv_len - (data_len % iv_len); - - padded_buf.len = data_len + pad_len; - padded_buf.bin = g_malloc(padded_buf.len); - - memcpy(padded_buf.bin, data, data_len); - for (i = 0; i < pad_len; i++) - padded_buf.bin[data_len + i] = (guint8)(pad_len & 0xFF); - - output.len = padded_buf.len; - output.bin = g_malloc(output.len); - - ret = - PK11_CipherOp(ctx, output.bin, &encrypted_len, output.len, padded_buf.bin, padded_buf.len); - if (ret != SECSuccess) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, - _("Failed to encrypt: %d."), - PORT_GetError()); - goto out; - } - - if (encrypted_len != output.len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, - _("Unexpected amount of data after encrypting.")); - goto out; - } - - success = TRUE; - -out: - if (ctx) - PK11_DestroyContext(ctx, PR_TRUE); - if (sec_param) - SECITEM_FreeItem(sec_param, PR_TRUE); - if (sym_key) - PK11_FreeSymKey(sym_key); - if (slot) - PK11_FreeSlot(slot); - - if (!success) - return NULL; - - *out_len = output.len; - return g_steal_pointer(&output.bin); -} - -gboolean -_nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error) -{ - CERTCertificate *cert; - - if (!_nm_crypto_init(error)) - return FALSE; - - /* Try DER/PEM first */ - cert = CERT_DecodeCertFromPackage((char *) data, len); - if (!cert) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Couldn't decode certificate: %d"), - PORT_GetError()); - return FALSE; - } - - CERT_DestroyCertificate(cert); - return TRUE; -} - -gboolean -_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error) -{ - SEC_PKCS12DecoderContext *p12ctx = NULL; - SECItem pw = {0}; - PK11SlotInfo * slot = NULL; - SECStatus s; - gboolean success = FALSE; - - g_return_val_if_fail(!error || !*error, FALSE); - - if (!_nm_crypto_init(error)) - return FALSE; - - /* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do - * any conversions for us. - */ - if (password && *password) { - nm_auto_clear_secret_ptr NMSecretPtr ucs2_password = {0}; - - if (g_utf8_validate(password, -1, NULL)) { - long ucs2_chars; - - ucs2_password.bin = - (guint8 *) g_utf8_to_utf16(password, strlen(password), NULL, &ucs2_chars, NULL); - - /* cannot fail, because password is valid UTF-8*/ - nm_assert(ucs2_password.bin && ucs2_chars > 0); - - ucs2_password.len = ucs2_chars * 2; - } - - if (!ucs2_password.bin || ucs2_password.len == 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_PASSWORD, - _("Password must be UTF-8")); - return FALSE; - } - - pw.data = PORT_ZAlloc(ucs2_password.len + 2); - memcpy(pw.data, ucs2_password.bin, ucs2_password.len); - pw.len = ucs2_password.len + 2; - -#if __BYTE_ORDER == __LITTLE_ENDIAN - { - guint16 *p, *p_end; - - p_end = (guint16 *) &(((guint8 *) pw.data)[ucs2_password.len]); - for (p = (guint16 *) pw.data; p < p_end; p++) - *p = GUINT16_SWAP_LE_BE(*p); - } -#endif - } - - slot = PK11_GetInternalKeySlot(); - if (!slot) { - g_set_error(error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize slot")); - goto out; - } - - p12ctx = SEC_PKCS12DecoderStart(&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); - if (!p12ctx) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, - _("Couldn't initialize PKCS#12 decoder: %d"), - PORT_GetError()); - goto out; - } - - s = SEC_PKCS12DecoderUpdate(p12ctx, (guint8 *) data, data_len); - if (s != SECSuccess) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Couldn't decode PKCS#12 file: %d"), - PORT_GetError()); - goto out; - } - - s = SEC_PKCS12DecoderVerify(p12ctx); - if (s != SECSuccess) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - _("Couldn't verify PKCS#12 file: %d"), - PORT_GetError()); - goto out; - } - - success = TRUE; - -out: - if (p12ctx) - SEC_PKCS12DecoderFinish(p12ctx); - if (slot) - PK11_FreeSlot(slot); - - if (pw.data) - SECITEM_ZfreeItem(&pw, PR_FALSE); - - return success; -} - -gboolean -_nm_crypto_verify_pkcs8(const guint8 *data, - gsize data_len, - gboolean is_encrypted, - const char * password, - GError ** error) -{ - g_return_val_if_fail(data != NULL, FALSE); - - if (!_nm_crypto_init(error)) - return FALSE; - - /* NSS apparently doesn't do PKCS#8 natively, but you have to put the - * PKCS#8 key into a PKCS#12 file and import that?? So until we figure - * all that out, we can only assume the password is valid. - */ - return TRUE; -} - -gboolean -_nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error) -{ - SECStatus s; - - if (!_nm_crypto_init(error)) - return FALSE; - - s = PK11_GenerateRandom(buffer, buffer_len); - if (s != SECSuccess) { - g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_FAILED, - _("Could not generate random data.")); - return FALSE; - } - return TRUE; -} diff --git a/libnm-core/nm-crypto.c b/libnm-core/nm-crypto.c deleted file mode 100644 index 0eaeeb72f5..0000000000 --- a/libnm-core/nm-crypto.c +++ /dev/null @@ -1,1084 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Dan Williams - * Copyright (C) 2007 - 2018 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-crypto.h" - -#include -#include -#include - -#include "nm-glib-aux/nm-secret-utils.h" -#include "nm-glib-aux/nm-io-utils.h" - -#include "nm-crypto-impl.h" -#include "nm-utils.h" -#include "nm-errors.h" - -#define PEM_RSA_KEY_BEGIN "-----BEGIN RSA PRIVATE KEY-----" -#define PEM_RSA_KEY_END "-----END RSA PRIVATE KEY-----" - -#define PEM_DSA_KEY_BEGIN "-----BEGIN DSA PRIVATE KEY-----" -#define PEM_DSA_KEY_END "-----END DSA PRIVATE KEY-----" - -#define PEM_CERT_BEGIN "-----BEGIN CERTIFICATE-----" -#define PEM_CERT_END "-----END CERTIFICATE-----" - -#define PEM_PKCS8_ENC_KEY_BEGIN "-----BEGIN ENCRYPTED PRIVATE KEY-----" -#define PEM_PKCS8_ENC_KEY_END "-----END ENCRYPTED PRIVATE KEY-----" - -#define PEM_PKCS8_DEC_KEY_BEGIN "-----BEGIN PRIVATE KEY-----" -#define PEM_PKCS8_DEC_KEY_END "-----END PRIVATE KEY-----" - -#define PEM_TPM2_WRAPPED_KEY_BEGIN "-----BEGIN TSS2 PRIVATE KEY-----" -#define PEM_TPM2_WRAPPED_KEY_END "-----END TSS2 PRIVATE KEY-----" - -#define PEM_TPM2_OLD_WRAPPED_KEY_BEGIN "-----BEGIN TSS2 KEY BLOB-----" -#define PEM_TPM2_OLD_WRAPPED_KEY_END "-----END TSS2 KEY BLOB-----" - -/*****************************************************************************/ - -static const NMCryptoCipherInfo cipher_infos[] = { -#define _CI(_cipher, _name, _digest_len, _real_iv_len) \ - [(_cipher) -1] = {.cipher = _cipher, \ - .name = ""_name \ - "", \ - .digest_len = _digest_len, \ - .real_iv_len = _real_iv_len} - _CI(NM_CRYPTO_CIPHER_DES_EDE3_CBC, "DES-EDE3-CBC", 24, 8), - _CI(NM_CRYPTO_CIPHER_DES_CBC, "DES-CBC", 8, 8), - _CI(NM_CRYPTO_CIPHER_AES_128_CBC, "AES-128-CBC", 16, 16), - _CI(NM_CRYPTO_CIPHER_AES_192_CBC, "AES-192-CBC", 24, 16), - _CI(NM_CRYPTO_CIPHER_AES_256_CBC, "AES-256-CBC", 32, 16), -}; - -const NMCryptoCipherInfo * -nm_crypto_cipher_get_info(NMCryptoCipherType cipher) -{ - g_return_val_if_fail(cipher > NM_CRYPTO_CIPHER_UNKNOWN - && (gsize) cipher < G_N_ELEMENTS(cipher_infos) + 1, - NULL); - -#if NM_MORE_ASSERTS > 10 - { - int i, j; - - for (i = 0; i < (int) G_N_ELEMENTS(cipher_infos); i++) { - const NMCryptoCipherInfo *info = &cipher_infos[i]; - - nm_assert(info->cipher == (NMCryptoCipherType)(i + 1)); - nm_assert(info->name && info->name[0]); - for (j = 0; j < i; j++) - nm_assert(g_ascii_strcasecmp(info->name, cipher_infos[j].name) != 0); - } - } -#endif - - return &cipher_infos[cipher - 1]; -} - -const NMCryptoCipherInfo * -nm_crypto_cipher_get_info_by_name(const char *cipher_name, gssize p_len) -{ - int i; - - nm_assert(nm_crypto_cipher_get_info(NM_CRYPTO_CIPHER_DES_CBC)->cipher - == NM_CRYPTO_CIPHER_DES_CBC); - - if (p_len < 0) { - if (!cipher_name) - return FALSE; - p_len = strlen(cipher_name); - } - - for (i = 0; i < (int) G_N_ELEMENTS(cipher_infos); i++) { - const NMCryptoCipherInfo *info = &cipher_infos[i]; - - if ((gsize) p_len == strlen(info->name) - && g_ascii_strncasecmp(info->name, cipher_name, p_len) == 0) - return info; - } - return NULL; -} - -/*****************************************************************************/ - -static gboolean -find_tag(const char *tag, const guint8 *data, gsize data_len, gsize start_at, gsize *out_pos) -{ - const guint8 *p; - gsize taglen; - - nm_assert(out_pos); - nm_assert(start_at <= data_len); - - taglen = strlen(tag); - - p = memmem(&data[start_at], data_len - start_at, tag, taglen); - if (!p) - return FALSE; - - *out_pos = p - data; - - nm_assert(memcmp(&data[*out_pos], tag, taglen) == 0); - - return TRUE; -} - -#define DEK_INFO_TAG "DEK-Info: " -#define PROC_TYPE_TAG "Proc-Type: " - -static char * -_extract_line(const guint8 **p, const guint8 *p_end) -{ - const guint8 *x, *x0; - - nm_assert(p); - nm_assert(p_end); - nm_assert(*p); - nm_assert(*p < p_end); - - x = x0 = *p; - while (TRUE) { - if (x == p_end) { - *p = p_end; - break; - } - if (*x == '\0') { - /* the data contains embedded NUL. This is the end. */ - *p = p_end; - break; - } - if (*x == '\n') { - *p = x + 1; - break; - } - x++; - } - - if (x == x0) - return NULL; - return g_strndup((char *) x0, x - x0); -} - -static gboolean -parse_old_openssl_key_file(const guint8 * data, - gsize data_len, - NMSecretPtr * out_parsed, - NMCryptoKeyType * out_key_type, - NMCryptoCipherType *out_cipher, - char ** out_iv, - GError ** error) -{ - gsize start = 0, end = 0; - nm_auto_free_secret char * str = NULL; - char * str_p; - gsize str_len; - int enc_tags = 0; - NMCryptoKeyType key_type; - nm_auto_clear_secret_ptr NMSecretPtr parsed = {0}; - nm_auto_free_secret char * iv = NULL; - NMCryptoCipherType cipher = NM_CRYPTO_CIPHER_UNKNOWN; - const char * start_tag; - const char * end_tag; - const guint8 * data_start, *data_end; - - nm_assert(!out_parsed || (out_parsed->len == 0 && !out_parsed->bin)); - nm_assert(!out_iv || !*out_iv); - - NM_SET_OUT(out_key_type, NM_CRYPTO_KEY_TYPE_UNKNOWN); - NM_SET_OUT(out_cipher, NM_CRYPTO_CIPHER_UNKNOWN); - - if (find_tag(PEM_RSA_KEY_BEGIN, data, data_len, 0, &start)) { - key_type = NM_CRYPTO_KEY_TYPE_RSA; - start_tag = PEM_RSA_KEY_BEGIN; - end_tag = PEM_RSA_KEY_END; - } else if (find_tag(PEM_DSA_KEY_BEGIN, data, data_len, 0, &start)) { - key_type = NM_CRYPTO_KEY_TYPE_DSA; - start_tag = PEM_DSA_KEY_BEGIN; - end_tag = PEM_DSA_KEY_END; - } else { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("PEM key file had no start tag")); - return FALSE; - } - - start += strlen(start_tag); - if (!find_tag(end_tag, data, data_len, start, &end)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("PEM key file had no end tag '%s'."), - end_tag); - return FALSE; - } - - str_len = end - start + 1; - str = g_new(char, str_len); - str[0] = '\0'; - str_p = str; - - data_start = &data[start]; - data_end = &data[end]; - - while (data_start < data_end) { - nm_auto_free_secret char *line = NULL; - char * p; - - line = _extract_line(&data_start, data_end); - if (!line) - continue; - - p = nm_secret_strchomp(nm_str_skip_leading_spaces(line)); - - if (!strncmp(p, PROC_TYPE_TAG, strlen(PROC_TYPE_TAG))) { - if (enc_tags++ != 0 || str_p != str) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: Proc-Type was not first tag.")); - return FALSE; - } - - p += strlen(PROC_TYPE_TAG); - if (strcmp(p, "4,ENCRYPTED")) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: unknown Proc-Type tag '%s'."), - p); - return FALSE; - } - } else if (!strncmp(p, DEK_INFO_TAG, strlen(DEK_INFO_TAG))) { - const NMCryptoCipherInfo *cipher_info; - char * comma; - gsize p_len; - - if (enc_tags++ != 1 || str_p != str) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: DEK-Info was not the second tag.")); - return FALSE; - } - - p += strlen(DEK_INFO_TAG); - - /* Grab the IV first */ - comma = strchr(p, ','); - if (!comma || (*(comma + 1) == '\0')) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: no IV found in DEK-Info tag.")); - return FALSE; - } - p_len = comma - p; - comma++; - if (!g_ascii_isxdigit(*comma)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: invalid format of IV in DEK-Info tag.")); - return FALSE; - } - nm_free_secret(iv); - iv = g_strdup(comma); - - /* Get the private key cipher */ - cipher_info = nm_crypto_cipher_get_info_by_name(p, p_len); - if (!cipher_info) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: unknown private key cipher '%s'."), - p); - return FALSE; - } - cipher = cipher_info->cipher; - } else { - if (enc_tags == 1) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - "Malformed PEM file: both Proc-Type and DEK-Info tags are required."); - return FALSE; - } - nm_utils_strbuf_append_str(&str_p, &str_len, p); - nm_assert(str_len > 0); - } - } - - parsed.bin = (guint8 *) g_base64_decode(str, &parsed.len); - if (!parsed.bin || parsed.len == 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Could not decode private key.")); - nm_secret_ptr_clear(&parsed); - return FALSE; - } - - NM_SET_OUT(out_key_type, key_type); - NM_SET_OUT(out_iv, g_steal_pointer(&iv)); - NM_SET_OUT(out_cipher, cipher); - nm_secret_ptr_move(out_parsed, &parsed); - return TRUE; -} - -static gboolean -parse_pkcs8_key_file(const guint8 *data, - gsize data_len, - NMSecretPtr * parsed, - gboolean * out_encrypted, - GError ** error) -{ - gsize start = 0, end = 0; - const char * start_tag = NULL, *end_tag = NULL; - gboolean encrypted = FALSE; - nm_auto_free_secret char *der_base64 = NULL; - - nm_assert(parsed); - nm_assert(!parsed->bin); - nm_assert(parsed->len == 0); - nm_assert(out_encrypted); - - /* Try encrypted first, decrypted next */ - if (find_tag(PEM_PKCS8_ENC_KEY_BEGIN, data, data_len, 0, &start)) { - start_tag = PEM_PKCS8_ENC_KEY_BEGIN; - end_tag = PEM_PKCS8_ENC_KEY_END; - encrypted = TRUE; - } else if (find_tag(PEM_PKCS8_DEC_KEY_BEGIN, data, data_len, 0, &start)) { - start_tag = PEM_PKCS8_DEC_KEY_BEGIN; - end_tag = PEM_PKCS8_DEC_KEY_END; - encrypted = FALSE; - } else { - g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to find expected PKCS#8 start tag.")); - return FALSE; - } - - start += strlen(start_tag); - if (!find_tag(end_tag, data, data_len, start, &end)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to find expected PKCS#8 end tag '%s'."), - end_tag); - return FALSE; - } - - /* g_base64_decode() wants a NULL-terminated string */ - der_base64 = g_strndup((char *) &data[start], end - start); - - parsed->bin = (guint8 *) g_base64_decode(der_base64, &parsed->len); - if (!parsed->bin || parsed->len == 0) { - g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to decode PKCS#8 private key.")); - nm_secret_ptr_clear(parsed); - return FALSE; - } - - *out_encrypted = encrypted; - return TRUE; -} - -static gboolean -parse_tpm2_wrapped_key_file(const guint8 *data, - gsize data_len, - gboolean * out_encrypted, - GError ** error) -{ - gsize start = 0, end = 0; - const char *start_tag = NULL, *end_tag = NULL; - - nm_assert(out_encrypted); - - if (find_tag(PEM_TPM2_WRAPPED_KEY_BEGIN, data, data_len, 0, &start)) { - start_tag = PEM_TPM2_WRAPPED_KEY_BEGIN; - end_tag = PEM_TPM2_WRAPPED_KEY_END; - } else if (find_tag(PEM_TPM2_OLD_WRAPPED_KEY_BEGIN, data, data_len, 0, &start)) { - start_tag = PEM_TPM2_OLD_WRAPPED_KEY_BEGIN; - end_tag = PEM_TPM2_OLD_WRAPPED_KEY_END; - } else { - g_set_error_literal(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to find expected TSS start tag.")); - return FALSE; - } - - start += strlen(start_tag); - if (!find_tag(end_tag, data, data_len, start, &end)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to find expected TSS end tag '%s'."), - end_tag); - return FALSE; - } - - *out_encrypted = FALSE; - return TRUE; -} - -static gboolean -file_read_contents(const char *filename, NMSecretPtr *out_contents, GError **error) -{ - nm_assert(out_contents); - nm_assert(out_contents->len == 0); - nm_assert(!out_contents->str); - - return nm_utils_file_get_contents(-1, - filename, - 100 * 1024 * 1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, - &out_contents->str, - &out_contents->len, - NULL, - error); -} - -GBytes * -nm_crypto_read_file(const char *filename, GError **error) -{ - nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; - - g_return_val_if_fail(filename, NULL); - - if (!file_read_contents(filename, &contents, error)) - return NULL; - return nm_secret_copy_to_gbytes(contents.bin, contents.len); -} - -/* - * Convert a hex string into bytes. - */ -static guint8 * -_nmtst_convert_iv(const char *src, gsize *out_len, GError **error) -{ - gsize i, num; - gs_free guint8 *c = NULL; - int c0, c1; - - nm_assert(src); - - num = strlen(src); - if (num == 0 || (num % 2) != 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("IV must be an even number of bytes in length.")); - return NULL; - } - - num /= 2; - c = g_malloc(num + 1); - - /* defensively add trailing NUL. This function returns binary data, - * do not assume it's NUL terminated. */ - c[num] = '\0'; - - for (i = 0; i < num; i++) { - if (((c0 = nm_utils_hexchar_to_int(*(src++))) < 0) - || ((c1 = nm_utils_hexchar_to_int(*(src++))) < 0)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("IV contains non-hexadecimal digits.")); - nm_explicit_bzero(c, i); - return FALSE; - } - - c[i] = (c0 << 4) + c1; - } - *out_len = num; - return g_steal_pointer(&c); -} - -guint8 * -nmtst_crypto_make_des_aes_key(NMCryptoCipherType cipher, - const guint8 * salt, - gsize salt_len, - const char * password, - gsize * out_len, - GError ** error) -{ - guint8 * key; - const NMCryptoCipherInfo *cipher_info; - - g_return_val_if_fail(salt != NULL, NULL); - g_return_val_if_fail(salt_len >= 8, NULL); - g_return_val_if_fail(password != NULL, NULL); - g_return_val_if_fail(out_len != NULL, NULL); - - *out_len = 0; - - cipher_info = nm_crypto_cipher_get_info(cipher); - - g_return_val_if_fail(cipher_info, NULL); - - if (password[0] == '\0') - return NULL; - - key = g_malloc(cipher_info->digest_len); - - nm_crypto_md5_hash(salt, - 8, - (guint8 *) password, - strlen(password), - key, - cipher_info->digest_len); - - *out_len = cipher_info->digest_len; - return key; -} - -static gboolean -_nmtst_decrypt_key(NMCryptoCipherType cipher, - const guint8 * data, - gsize data_len, - const char * iv, - const char * password, - NMSecretPtr * parsed, - GError ** error) -{ - nm_auto_clear_secret_ptr NMSecretPtr bin_iv = {0}; - nm_auto_clear_secret_ptr NMSecretPtr key = {0}; - - nm_assert(password); - nm_assert(cipher != NM_CRYPTO_CIPHER_UNKNOWN); - nm_assert(iv); - nm_assert(parsed); - nm_assert(!parsed->bin); - nm_assert(parsed->len == 0); - - bin_iv.bin = _nmtst_convert_iv(iv, &bin_iv.len, error); - if (!bin_iv.bin) - return FALSE; - - if (bin_iv.len < 8) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("IV must contain at least 8 characters")); - return FALSE; - } - - /* Convert the password and IV into a DES or AES key */ - key.bin = - nmtst_crypto_make_des_aes_key(cipher, bin_iv.bin, bin_iv.len, password, &key.len, error); - if (!key.bin || !key.len) - return FALSE; - - parsed->bin = _nmtst_crypto_decrypt(cipher, - data, - data_len, - bin_iv.bin, - bin_iv.len, - key.bin, - key.len, - &parsed->len, - error); - if (!parsed->bin || parsed->len == 0) { - nm_secret_ptr_clear(parsed); - return FALSE; - } - - return TRUE; -} - -GBytes * -nmtst_crypto_decrypt_openssl_private_key_data(const guint8 * data, - gsize data_len, - const char * password, - NMCryptoKeyType *out_key_type, - GError ** error) -{ - NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - nm_auto_clear_secret_ptr NMSecretPtr parsed = {0}; - nm_auto_free_secret char * iv = NULL; - NMCryptoCipherType cipher = NM_CRYPTO_CIPHER_UNKNOWN; - - g_return_val_if_fail(data != NULL, NULL); - - NM_SET_OUT(out_key_type, NM_CRYPTO_KEY_TYPE_UNKNOWN); - - if (!_nm_crypto_init(error)) - return NULL; - - if (!parse_old_openssl_key_file(data, data_len, &parsed, &key_type, &cipher, &iv, NULL)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Unable to determine private key type.")); - return NULL; - } - - NM_SET_OUT(out_key_type, key_type); - - if (password) { - nm_auto_clear_secret_ptr NMSecretPtr parsed2 = {0}; - - if (cipher == NM_CRYPTO_CIPHER_UNKNOWN || !iv) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_PASSWORD, - _("Password provided, but key was not encrypted.")); - return NULL; - } - - if (!_nmtst_decrypt_key(cipher, parsed.bin, parsed.len, iv, password, &parsed2, error)) - return NULL; - - return nm_secret_copy_to_gbytes(parsed2.bin, parsed2.len); - } - - if (cipher != NM_CRYPTO_CIPHER_UNKNOWN || iv) - return NULL; - - return nm_secret_copy_to_gbytes(parsed.bin, parsed.len); -} - -GBytes * -nmtst_crypto_decrypt_openssl_private_key(const char * file, - const char * password, - NMCryptoKeyType *out_key_type, - GError ** error) -{ - nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; - - if (!_nm_crypto_init(error)) - return NULL; - - if (!file_read_contents(file, &contents, error)) - return NULL; - - return nmtst_crypto_decrypt_openssl_private_key_data(contents.bin, - contents.len, - password, - out_key_type, - error); -} - -static gboolean -extract_pem_cert_data(const guint8 *contents, - gsize contents_len, - NMSecretPtr * out_cert, - GError ** error) -{ - gsize start = 0; - gsize end = 0; - nm_auto_free_secret char *der_base64 = NULL; - - nm_assert(contents); - nm_assert(out_cert); - nm_assert(out_cert->len == 0); - nm_assert(!out_cert->ptr); - - if (!find_tag(PEM_CERT_BEGIN, contents, contents_len, 0, &start)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("PEM certificate had no start tag '%s'."), - PEM_CERT_BEGIN); - return FALSE; - } - - start += strlen(PEM_CERT_BEGIN); - if (!find_tag(PEM_CERT_END, contents, contents_len, start, &end)) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("PEM certificate had no end tag '%s'."), - PEM_CERT_END); - return FALSE; - } - - /* g_base64_decode() wants a NULL-terminated string */ - der_base64 = g_strndup((const char *) &contents[start], end - start); - - out_cert->bin = (guint8 *) g_base64_decode(der_base64, &out_cert->len); - if (!out_cert->bin || !out_cert->len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to decode certificate.")); - nm_secret_ptr_clear(out_cert); - return FALSE; - } - - return TRUE; -} - -gboolean -nm_crypto_load_and_verify_certificate(const char * file, - NMCryptoFileFormat *out_file_format, - GBytes ** out_certificate, - GError ** error) -{ - nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; - - g_return_val_if_fail(file, FALSE); - nm_assert(!error || !*error); - - if (!_nm_crypto_init(error)) - goto out; - - if (!file_read_contents(file, &contents, error)) - goto out; - - if (contents.len == 0) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Certificate file is empty")); - goto out; - } - - /* Check for PKCS#12 */ - if (nm_crypto_is_pkcs12_data(contents.bin, contents.len, NULL)) { - NM_SET_OUT(out_file_format, NM_CRYPTO_FILE_FORMAT_PKCS12); - NM_SET_OUT(out_certificate, nm_secret_copy_to_gbytes(contents.bin, contents.len)); - return TRUE; - } - - /* Check for plain DER format */ - if (contents.len > 2 && contents.bin[0] == 0x30 && contents.bin[1] == 0x82) { - if (_nm_crypto_verify_x509(contents.bin, contents.len, NULL)) { - NM_SET_OUT(out_file_format, NM_CRYPTO_FILE_FORMAT_X509); - NM_SET_OUT(out_certificate, nm_secret_copy_to_gbytes(contents.bin, contents.len)); - return TRUE; - } - } else { - nm_auto_clear_secret_ptr NMSecretPtr pem_cert = {0}; - - if (extract_pem_cert_data(contents.bin, contents.len, &pem_cert, NULL)) { - if (_nm_crypto_verify_x509(pem_cert.bin, pem_cert.len, NULL)) { - NM_SET_OUT(out_file_format, NM_CRYPTO_FILE_FORMAT_X509); - NM_SET_OUT(out_certificate, nm_secret_copy_to_gbytes(contents.bin, contents.len)); - return TRUE; - } - } - } - - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to recognize certificate")); - -out: - NM_SET_OUT(out_file_format, NM_CRYPTO_FILE_FORMAT_UNKNOWN); - NM_SET_OUT(out_certificate, NULL); - return FALSE; -} - -gboolean -nm_crypto_is_pkcs12_data(const guint8 *data, gsize data_len, GError **error) -{ - GError * local = NULL; - gboolean success; - - if (!data_len) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Certificate file is empty")); - return FALSE; - } - - g_return_val_if_fail(data != NULL, FALSE); - - if (!_nm_crypto_init(error)) - return FALSE; - - success = _nm_crypto_verify_pkcs12(data, data_len, NULL, &local); - if (success == FALSE) { - /* If the error was just a decryption error, then it's pkcs#12 */ - if (local) { - if (g_error_matches(local, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED)) { - success = TRUE; - g_error_free(local); - } else - g_propagate_error(error, local); - } - } - return success; -} - -gboolean -nm_crypto_is_pkcs12_file(const char *file, GError **error) -{ - nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; - - g_return_val_if_fail(file != NULL, FALSE); - - if (!_nm_crypto_init(error)) - return FALSE; - - if (!file_read_contents(file, &contents, error)) - return FALSE; - - return nm_crypto_is_pkcs12_data(contents.bin, contents.len, error); -} - -/* Verifies that a private key can be read, and if a password is given, that - * the private key can be decrypted with that password. - */ -NMCryptoFileFormat -nm_crypto_verify_private_key_data(const guint8 *data, - gsize data_len, - const char * password, - gboolean * out_is_encrypted, - GError ** error) -{ - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gboolean is_encrypted = FALSE; - - g_return_val_if_fail(data != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); - g_return_val_if_fail(out_is_encrypted == NULL || *out_is_encrypted == FALSE, - NM_CRYPTO_FILE_FORMAT_UNKNOWN); - - if (!_nm_crypto_init(error)) - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; - - /* Check for PKCS#12 first */ - if (nm_crypto_is_pkcs12_data(data, data_len, NULL)) { - is_encrypted = TRUE; - if (!password || _nm_crypto_verify_pkcs12(data, data_len, password, error)) - format = NM_CRYPTO_FILE_FORMAT_PKCS12; - } else { - nm_auto_clear_secret_ptr NMSecretPtr parsed = {0}; - - /* Maybe it's PKCS#8 */ - if (parse_pkcs8_key_file(data, data_len, &parsed, &is_encrypted, NULL)) { - if (!password - || _nm_crypto_verify_pkcs8(parsed.bin, parsed.len, is_encrypted, password, error)) - format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; - } else if (parse_tpm2_wrapped_key_file(data, data_len, &is_encrypted, NULL)) { - format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; - } else { - NMCryptoCipherType cipher; - nm_auto_free_secret char *iv = NULL; - - /* Or it's old-style OpenSSL */ - if (parse_old_openssl_key_file(data, data_len, NULL, NULL, &cipher, &iv, NULL)) { - format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; - is_encrypted = (cipher != NM_CRYPTO_CIPHER_UNKNOWN && iv); - } - } - } - - if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN && error && !*error) { - g_set_error(error, - NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("not a valid private key")); - } - - if (out_is_encrypted) - *out_is_encrypted = is_encrypted; - return format; -} - -NMCryptoFileFormat -nm_crypto_verify_private_key(const char *filename, - const char *password, - gboolean * out_is_encrypted, - GError ** error) -{ - nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; - - g_return_val_if_fail(filename != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); - - if (!_nm_crypto_init(error)) - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; - - if (!file_read_contents(filename, &contents, error)) - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; - - return nm_crypto_verify_private_key_data(contents.bin, - contents.len, - password, - out_is_encrypted, - error); -} - -void -nm_crypto_md5_hash(const guint8 *salt, - gsize salt_len, - const guint8 *password, - gsize password_len, - guint8 * buffer, - gsize buflen) -{ - nm_auto_free_checksum GChecksum * ctx = NULL; - nm_auto_clear_static_secret_ptr const NMSecretPtr digest = - NM_SECRET_PTR_STATIC(NM_UTILS_CHECKSUM_LENGTH_MD5); - gsize bufidx = 0; - int i; - - g_return_if_fail(password_len == 0 || password); - g_return_if_fail(buffer); - g_return_if_fail(buflen > 0); - g_return_if_fail(salt_len == 0 || salt); - - ctx = g_checksum_new(G_CHECKSUM_MD5); - - for (;;) { - if (password_len > 0) - g_checksum_update(ctx, (const guchar *) password, password_len); - if (salt_len > 0) - g_checksum_update(ctx, (const guchar *) salt, salt_len); - - nm_utils_checksum_get_digest_len(ctx, digest.bin, NM_UTILS_CHECKSUM_LENGTH_MD5); - - for (i = 0; i < NM_UTILS_CHECKSUM_LENGTH_MD5; i++) { - if (bufidx >= buflen) - return; - buffer[bufidx++] = digest.bin[i]; - } - - g_checksum_reset(ctx); - g_checksum_update(ctx, digest.ptr, NM_UTILS_CHECKSUM_LENGTH_MD5); - } -} - -gboolean -nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error) -{ - return _nm_crypto_randomize(buffer, buffer_len, error); -} - -/** - * nmtst_crypto_rsa_key_encrypt: - * @data: (array length=len): RSA private key data to be encrypted - * @len: length of @data - * @in_password: (allow-none): existing password to use, if any - * @out_password: (out) (allow-none): if @in_password was %NULL, a random - * password will be generated and returned in this argument - * @error: detailed error information on return, if an error occurred - * - * Encrypts the given RSA private key data with the given password (or generates - * a password if no password was given) and converts the data to PEM format - * suitable for writing to a file. It uses Triple DES cipher for the encryption. - * - * Returns: (transfer full): on success, PEM-formatted data suitable for writing - * to a PEM-formatted certificate/private key file. - **/ -GBytes * -nmtst_crypto_rsa_key_encrypt(const guint8 *data, - gsize len, - const char * in_password, - char ** out_password, - GError ** error) -{ - guint8 salt[8]; - nm_auto_clear_secret_ptr NMSecretPtr key = {0}; - nm_auto_clear_secret_ptr NMSecretPtr enc = {0}; - gs_unref_ptrarray GPtrArray *pem = NULL; - nm_auto_free_secret char * tmp_password = NULL; - nm_auto_free_secret char * enc_base64 = NULL; - gsize enc_base64_len; - const char * p; - gsize ret_len, ret_idx; - guint i; - NMSecretBuf * ret; - - g_return_val_if_fail(data, NULL); - g_return_val_if_fail(len > 0, NULL); - g_return_val_if_fail(!out_password || !*out_password, NULL); - - /* Make the password if needed */ - if (!in_password) { - nm_auto_clear_static_secret_ptr NMSecretPtr pw_buf = NM_SECRET_PTR_STATIC(32); - - if (!nm_crypto_randomize(pw_buf.bin, pw_buf.len, error)) - return NULL; - tmp_password = nm_utils_bin2hexstr(pw_buf.bin, pw_buf.len, -1); - in_password = tmp_password; - } - - if (!nm_crypto_randomize(salt, sizeof(salt), error)) - return NULL; - - key.bin = nmtst_crypto_make_des_aes_key(NM_CRYPTO_CIPHER_DES_EDE3_CBC, - salt, - sizeof(salt), - in_password, - &key.len, - NULL); - if (!key.bin) - g_return_val_if_reached(NULL); - - enc.bin = _nmtst_crypto_encrypt(NM_CRYPTO_CIPHER_DES_EDE3_CBC, - data, - len, - salt, - sizeof(salt), - key.bin, - key.len, - &enc.len, - error); - if (!enc.bin) - return NULL; - - /* What follows is not the most efficient way to construct the pem - * file line-by-line. At least, it makes sure, that the data will be cleared - * again and not left around in memory. - * - * If this would not be test code, we should improve the implementation - * to avoid some of the copying. */ - pem = g_ptr_array_new_with_free_func((GDestroyNotify) nm_free_secret); - - g_ptr_array_add(pem, g_strdup("-----BEGIN RSA PRIVATE KEY-----\n")); - g_ptr_array_add(pem, g_strdup("Proc-Type: 4,ENCRYPTED\n")); - - /* Convert the salt to a hex string */ - g_ptr_array_add( - pem, - g_strdup_printf("DEK-Info: %s,", - nm_crypto_cipher_get_info(NM_CRYPTO_CIPHER_DES_EDE3_CBC)->name)); - g_ptr_array_add(pem, nm_utils_bin2hexstr(salt, sizeof(salt), sizeof(salt) * 2)); - g_ptr_array_add(pem, g_strdup("\n\n")); - - /* Convert the encrypted key to a base64 string */ - enc_base64 = g_base64_encode((const guchar *) enc.bin, enc.len); - enc_base64_len = strlen(enc_base64); - for (p = enc_base64; (p - enc_base64) < (ptrdiff_t) enc_base64_len; p += 64) { - g_ptr_array_add(pem, g_strndup(p, 64)); - g_ptr_array_add(pem, g_strdup("\n")); - } - - g_ptr_array_add(pem, g_strdup("-----END RSA PRIVATE KEY-----\n")); - - ret_len = 0; - for (i = 0; i < pem->len; i++) - ret_len += strlen(pem->pdata[i]); - - ret = nm_secret_buf_new(ret_len + 1); - ret_idx = 0; - for (i = 0; i < pem->len; i++) { - const char *line = pem->pdata[i]; - gsize line_l = strlen(line); - - memcpy(&ret->bin[ret_idx], line, line_l); - ret_idx += line_l; - nm_assert(ret_idx <= ret_len); - } - nm_assert(ret_idx == ret_len); - ret->bin[ret_len] = '\0'; - - NM_SET_OUT(out_password, g_strdup(tmp_password)); - return nm_secret_buf_to_gbytes_take(ret, ret_len); -} diff --git a/libnm-core/nm-crypto.h b/libnm-core/nm-crypto.h deleted file mode 100644 index 97bd4628a7..0000000000 --- a/libnm-core/nm-crypto.h +++ /dev/null @@ -1,107 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Dan Williams - * Copyright (C) 2007 - 2014 Red Hat, Inc. - */ - -#ifndef __NM_CRYPTO_H__ -#define __NM_CRYPTO_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) - #error Cannot use this header. -#endif - -typedef enum { - NM_CRYPTO_CIPHER_UNKNOWN, - NM_CRYPTO_CIPHER_DES_EDE3_CBC, - NM_CRYPTO_CIPHER_DES_CBC, - NM_CRYPTO_CIPHER_AES_128_CBC, - NM_CRYPTO_CIPHER_AES_192_CBC, - NM_CRYPTO_CIPHER_AES_256_CBC, -} NMCryptoCipherType; - -typedef struct { - const char * name; - NMCryptoCipherType cipher; - guint8 digest_len; - guint8 real_iv_len; -} NMCryptoCipherInfo; - -const NMCryptoCipherInfo *nm_crypto_cipher_get_info(NMCryptoCipherType cipher); -const NMCryptoCipherInfo *nm_crypto_cipher_get_info_by_name(const char *cipher_name, gssize p_len); - -typedef enum { - NM_CRYPTO_KEY_TYPE_UNKNOWN = 0, - NM_CRYPTO_KEY_TYPE_RSA, - NM_CRYPTO_KEY_TYPE_DSA -} NMCryptoKeyType; - -typedef enum { - NM_CRYPTO_FILE_FORMAT_UNKNOWN = 0, - NM_CRYPTO_FILE_FORMAT_X509, - NM_CRYPTO_FILE_FORMAT_RAW_KEY, - NM_CRYPTO_FILE_FORMAT_PKCS12 -} NMCryptoFileFormat; - -/*****************************************************************************/ - -GBytes *nm_crypto_read_file(const char *filename, GError **error); - -gboolean nm_crypto_load_and_verify_certificate(const char * file, - NMCryptoFileFormat *out_file_format, - GBytes ** out_certificat, - GError ** error); - -gboolean nm_crypto_is_pkcs12_file(const char *file, GError **error); - -gboolean nm_crypto_is_pkcs12_data(const guint8 *data, gsize len, GError **error); - -NMCryptoFileFormat nm_crypto_verify_private_key_data(const guint8 *data, - gsize data_len, - const char * password, - gboolean * out_is_encrypted, - GError ** error); - -NMCryptoFileFormat nm_crypto_verify_private_key(const char *file, - const char *password, - gboolean * out_is_encrypted, - GError ** error); - -void nm_crypto_md5_hash(const guint8 *salt, - gsize salt_len, - const guint8 *password, - gsize password_len, - guint8 * buffer, - gsize buflen); - -gboolean nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error); - -/*****************************************************************************/ - -GBytes *nmtst_crypto_decrypt_openssl_private_key_data(const guint8 * data, - gsize data_len, - const char * password, - NMCryptoKeyType *out_key_type, - GError ** error); - -GBytes *nmtst_crypto_decrypt_openssl_private_key(const char * file, - const char * password, - NMCryptoKeyType *out_key_type, - GError ** error); - -GBytes *nmtst_crypto_rsa_key_encrypt(const guint8 *data, - gsize len, - const char * in_password, - char ** out_password, - GError ** error); - -guint8 *nmtst_crypto_make_des_aes_key(NMCryptoCipherType cipher, - const guint8 * salt, - gsize salt_len, - const char * password, - gsize * out_len, - GError ** error); - -/*****************************************************************************/ - -#endif /* __NM_CRYPTO_H__ */ diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h deleted file mode 100644 index 295a22a177..0000000000 --- a/libnm-core/nm-dbus-interface.h +++ /dev/null @@ -1,1284 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2004 - 2018 Red Hat, Inc. - */ - -/* Definitions related to NetworkManager's D-Bus interfaces. - * - * Note that although this header is installed as part of libnm, it is also - * used by some external code that does not link to libnm. - */ - -#ifndef __NM_DBUS_INTERFACE_H__ -#define __NM_DBUS_INTERFACE_H__ - -/* This header must not include glib or libnm. */ - -#ifndef NM_VERSION_H - #define NM_AVAILABLE_IN_1_2 - #define NM_AVAILABLE_IN_1_8 -#endif - -/* - * dbus services details - */ -#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager" - -#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" -#define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint" -#define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active" -#define NM_DBUS_INTERFACE_CHECKPOINT NM_DBUS_INTERFACE ".Checkpoint" -#define NM_DBUS_INTERFACE_DEVICE NM_DBUS_INTERFACE ".Device" -#define NM_DBUS_INTERFACE_DEVICE_6LOWPAN NM_DBUS_INTERFACE_DEVICE ".Lowpan" -#define NM_DBUS_INTERFACE_DEVICE_ADSL NM_DBUS_INTERFACE_DEVICE ".Adsl" -#define NM_DBUS_INTERFACE_DEVICE_BLUETOOTH NM_DBUS_INTERFACE_DEVICE ".Bluetooth" -#define NM_DBUS_INTERFACE_DEVICE_BOND NM_DBUS_INTERFACE_DEVICE ".Bond" -#define NM_DBUS_INTERFACE_DEVICE_BRIDGE NM_DBUS_INTERFACE_DEVICE ".Bridge" -#define NM_DBUS_INTERFACE_DEVICE_DUMMY NM_DBUS_INTERFACE_DEVICE ".Dummy" -#define NM_DBUS_INTERFACE_DEVICE_GENERIC NM_DBUS_INTERFACE_DEVICE ".Generic" -#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre" -#define NM_DBUS_INTERFACE_DEVICE_INFINIBAND NM_DBUS_INTERFACE_DEVICE ".Infiniband" -#define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel" -#define NM_DBUS_INTERFACE_DEVICE_MACSEC NM_DBUS_INTERFACE_DEVICE ".Macsec" -#define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan" -#define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem" -#define NM_DBUS_INTERFACE_DEVICE_OLPC_MESH NM_DBUS_INTERFACE_DEVICE ".OlpcMesh" -#define NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE NM_DBUS_INTERFACE_DEVICE ".OvsBridge" -#define NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE NM_DBUS_INTERFACE_DEVICE ".OvsInterface" -#define NM_DBUS_INTERFACE_DEVICE_OVS_PORT NM_DBUS_INTERFACE_DEVICE ".OvsPort" -#define NM_DBUS_INTERFACE_DEVICE_PPP NM_DBUS_INTERFACE_DEVICE ".Ppp" -#define NM_DBUS_INTERFACE_DEVICE_STATISTICS NM_DBUS_INTERFACE_DEVICE ".Statistics" -#define NM_DBUS_INTERFACE_DEVICE_TEAM NM_DBUS_INTERFACE_DEVICE ".Team" -#define NM_DBUS_INTERFACE_DEVICE_TUN NM_DBUS_INTERFACE_DEVICE ".Tun" -#define NM_DBUS_INTERFACE_DEVICE_VETH NM_DBUS_INTERFACE_DEVICE ".Veth" -#define NM_DBUS_INTERFACE_DEVICE_VLAN NM_DBUS_INTERFACE_DEVICE ".Vlan" -#define NM_DBUS_INTERFACE_DEVICE_VRF NM_DBUS_INTERFACE_DEVICE ".Vrf" -#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan" -#define NM_DBUS_INTERFACE_DEVICE_WIFI_P2P NM_DBUS_INTERFACE_DEVICE ".WifiP2P" -#define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax" -#define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired" -#define NM_DBUS_INTERFACE_DEVICE_WIREGUARD NM_DBUS_INTERFACE_DEVICE ".WireGuard" -#define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless" -#define NM_DBUS_INTERFACE_DEVICE_WPAN NM_DBUS_INTERFACE_DEVICE ".Wpan" -#define NM_DBUS_INTERFACE_DHCP4_CONFIG NM_DBUS_INTERFACE ".DHCP4Config" -#define NM_DBUS_INTERFACE_DHCP6_CONFIG NM_DBUS_INTERFACE ".DHCP6Config" -#define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config" -#define NM_DBUS_INTERFACE_IP6_CONFIG NM_DBUS_INTERFACE ".IP6Config" -#define NM_DBUS_INTERFACE_WIFI_P2P_PEER NM_DBUS_INTERFACE ".WifiP2PPeer" -#define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp" - -#define NM_DBUS_PATH "/org/freedesktop/NetworkManager" -#define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint" -#define NM_DBUS_PATH_WIFI_P2P_PEER NM_DBUS_PATH "/WifiP2PPeer" -#define NM_DBUS_PATH_WIMAX_NSP NM_DBUS_PATH "/Nsp" - -#define NM_DBUS_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings" -#define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings" - -#define NM_DBUS_INTERFACE_SETTINGS_CONNECTION "org.freedesktop.NetworkManager.Settings.Connection" -#define NM_DBUS_PATH_SETTINGS_CONNECTION "/org/freedesktop/NetworkManager/Settings/Connection" -#define NM_DBUS_INTERFACE_SETTINGS_CONNECTION_SECRETS \ - "org.freedesktop.NetworkManager.Settings.Connection.Secrets" - -#define NM_DBUS_INTERFACE_AGENT_MANAGER NM_DBUS_INTERFACE ".AgentManager" -#define NM_DBUS_PATH_AGENT_MANAGER "/org/freedesktop/NetworkManager/AgentManager" - -#define NM_DBUS_INTERFACE_SECRET_AGENT NM_DBUS_INTERFACE ".SecretAgent" -#define NM_DBUS_PATH_SECRET_AGENT "/org/freedesktop/NetworkManager/SecretAgent" - -#define NM_DBUS_INTERFACE_DNS_MANAGER "org.freedesktop.NetworkManager.DnsManager" -#define NM_DBUS_PATH_DNS_MANAGER "/org/freedesktop/NetworkManager/DnsManager" - -/** - * NMCapability: - * @NM_CAPABILITY_TEAM: Teams can be managed. This means the team device plugin - * is loaded. - * @NM_CAPABILITY_OVS: OpenVSwitch can be managed. This means the OVS device plugin - * is loaded. Since: 1.24. - * - * #NMCapability names the numbers in the Capabilities property. - * Capabilities are positive numbers. They are part of stable API - * and a certain capability number is guaranteed not to change. - * - * The range 0x7000 - 0x7FFF of capabilities is guaranteed not to be - * used by upstream NetworkManager. It could thus be used for downstream - * extensions. - */ -typedef enum { - NM_CAPABILITY_TEAM = 1, - NM_CAPABILITY_OVS = 2, -} NMCapability; - -/** - * NMState: - * @NM_STATE_UNKNOWN: Networking state is unknown. This indicates a daemon error - * that makes it unable to reasonably assess the state. In such event the - * applications are expected to assume Internet connectivity might be present - * and not disable controls that require network access. - * The graphical shells may hide the network accessibility indicator altogether - * since no meaningful status indication can be provided. - * @NM_STATE_ASLEEP: Networking is not enabled, the system is being suspended or - * resumed from suspend. - * @NM_STATE_DISCONNECTED: There is no active network connection. - * The graphical shell should indicate no network connectivity and the - * applications should not attempt to access the network. - * @NM_STATE_DISCONNECTING: Network connections are being cleaned up. - * The applications should tear down their network sessions. - * @NM_STATE_CONNECTING: A network connection is being started - * The graphical shell should indicate the network is being connected while - * the applications should still make no attempts to connect the network. - * @NM_STATE_CONNECTED_LOCAL: There is only local IPv4 and/or IPv6 connectivity, - * but no default route to access the Internet. The graphical shell should - * indicate no network connectivity. - * @NM_STATE_CONNECTED_SITE: There is only site-wide IPv4 and/or IPv6 connectivity. - * This means a default route is available, but the Internet connectivity check - * (see "Connectivity" property) did not succeed. The graphical shell should - * indicate limited network connectivity. - * @NM_STATE_CONNECTED_GLOBAL: There is global IPv4 and/or IPv6 Internet connectivity - * This means the Internet connectivity check succeeded, the graphical shell should - * indicate full network connectivity. - * - * #NMState values indicate the current overall networking state. - **/ -typedef enum { - NM_STATE_UNKNOWN = 0, - NM_STATE_ASLEEP = 10, - NM_STATE_DISCONNECTED = 20, - NM_STATE_DISCONNECTING = 30, - NM_STATE_CONNECTING = 40, - NM_STATE_CONNECTED_LOCAL = 50, - NM_STATE_CONNECTED_SITE = 60, - NM_STATE_CONNECTED_GLOBAL = 70, -} NMState; - -/** - * NMConnectivityState: - * @NM_CONNECTIVITY_UNKNOWN: Network connectivity is unknown. This means the - * connectivity checks are disabled (e.g. on server installations) or has - * not run yet. The graphical shell should assume the Internet connection - * might be available and not present a captive portal window. - * @NM_CONNECTIVITY_NONE: The host is not connected to any network. There's - * no active connection that contains a default route to the internet and - * thus it makes no sense to even attempt a connectivity check. The graphical - * shell should use this state to indicate the network connection is unavailable. - * @NM_CONNECTIVITY_PORTAL: The Internet connection is hijacked by a captive - * portal gateway. The graphical shell may open a sandboxed web browser window - * (because the captive portals typically attempt a man-in-the-middle attacks - * against the https connections) for the purpose of authenticating to a gateway - * and retrigger the connectivity check with CheckConnectivity() when the - * browser window is dismissed. - * @NM_CONNECTIVITY_LIMITED: The host is connected to a network, does not appear - * to be able to reach the full Internet, but a captive portal has not been - * detected. - * @NM_CONNECTIVITY_FULL: The host is connected to a network, and - * appears to be able to reach the full Internet. - */ -typedef enum { - NM_CONNECTIVITY_UNKNOWN = 0, - NM_CONNECTIVITY_NONE = 1, - NM_CONNECTIVITY_PORTAL = 2, - NM_CONNECTIVITY_LIMITED = 3, - NM_CONNECTIVITY_FULL = 4, -} NMConnectivityState; - -/** - * NMDeviceType: - * @NM_DEVICE_TYPE_UNKNOWN: unknown device - * @NM_DEVICE_TYPE_GENERIC: generic support for unrecognized device types - * @NM_DEVICE_TYPE_ETHERNET: a wired ethernet device - * @NM_DEVICE_TYPE_WIFI: an 802.11 Wi-Fi device - * @NM_DEVICE_TYPE_UNUSED1: not used - * @NM_DEVICE_TYPE_UNUSED2: not used - * @NM_DEVICE_TYPE_BT: a Bluetooth device supporting PAN or DUN access protocols - * @NM_DEVICE_TYPE_OLPC_MESH: an OLPC XO mesh networking device - * @NM_DEVICE_TYPE_WIMAX: an 802.16e Mobile WiMAX broadband device - * @NM_DEVICE_TYPE_MODEM: a modem supporting analog telephone, CDMA/EVDO, - * GSM/UMTS, or LTE network access protocols - * @NM_DEVICE_TYPE_INFINIBAND: an IP-over-InfiniBand device - * @NM_DEVICE_TYPE_BOND: a bond master interface - * @NM_DEVICE_TYPE_VLAN: an 802.1Q VLAN interface - * @NM_DEVICE_TYPE_ADSL: ADSL modem - * @NM_DEVICE_TYPE_BRIDGE: a bridge master interface - * @NM_DEVICE_TYPE_TEAM: a team master interface - * @NM_DEVICE_TYPE_TUN: a TUN or TAP interface - * @NM_DEVICE_TYPE_IP_TUNNEL: a IP tunnel interface - * @NM_DEVICE_TYPE_MACVLAN: a MACVLAN interface - * @NM_DEVICE_TYPE_VXLAN: a VXLAN interface - * @NM_DEVICE_TYPE_VETH: a VETH interface - * @NM_DEVICE_TYPE_MACSEC: a MACsec interface - * @NM_DEVICE_TYPE_DUMMY: a dummy interface - * @NM_DEVICE_TYPE_PPP: a PPP interface - * @NM_DEVICE_TYPE_OVS_INTERFACE: a Open vSwitch interface - * @NM_DEVICE_TYPE_OVS_PORT: a Open vSwitch port - * @NM_DEVICE_TYPE_OVS_BRIDGE: a Open vSwitch bridge - * @NM_DEVICE_TYPE_WPAN: a IEEE 802.15.4 (WPAN) MAC Layer Device - * @NM_DEVICE_TYPE_6LOWPAN: 6LoWPAN interface - * @NM_DEVICE_TYPE_WIREGUARD: a WireGuard interface - * @NM_DEVICE_TYPE_WIFI_P2P: an 802.11 Wi-Fi P2P device. Since: 1.16. - * @NM_DEVICE_TYPE_VRF: A VRF (Virtual Routing and Forwarding) interface. Since: 1.24. - * - * #NMDeviceType values indicate the type of hardware represented by a - * device object. - **/ -typedef enum { - NM_DEVICE_TYPE_UNKNOWN = 0, - NM_DEVICE_TYPE_ETHERNET = 1, - NM_DEVICE_TYPE_WIFI = 2, - NM_DEVICE_TYPE_UNUSED1 = 3, - NM_DEVICE_TYPE_UNUSED2 = 4, - NM_DEVICE_TYPE_BT = 5, /* Bluetooth */ - NM_DEVICE_TYPE_OLPC_MESH = 6, - NM_DEVICE_TYPE_WIMAX = 7, - NM_DEVICE_TYPE_MODEM = 8, - NM_DEVICE_TYPE_INFINIBAND = 9, - NM_DEVICE_TYPE_BOND = 10, - NM_DEVICE_TYPE_VLAN = 11, - NM_DEVICE_TYPE_ADSL = 12, - NM_DEVICE_TYPE_BRIDGE = 13, - NM_DEVICE_TYPE_GENERIC = 14, - NM_DEVICE_TYPE_TEAM = 15, - NM_DEVICE_TYPE_TUN = 16, - NM_DEVICE_TYPE_IP_TUNNEL = 17, - NM_DEVICE_TYPE_MACVLAN = 18, - NM_DEVICE_TYPE_VXLAN = 19, - NM_DEVICE_TYPE_VETH = 20, - NM_DEVICE_TYPE_MACSEC = 21, - NM_DEVICE_TYPE_DUMMY = 22, - NM_DEVICE_TYPE_PPP = 23, - NM_DEVICE_TYPE_OVS_INTERFACE = 24, - NM_DEVICE_TYPE_OVS_PORT = 25, - NM_DEVICE_TYPE_OVS_BRIDGE = 26, - NM_DEVICE_TYPE_WPAN = 27, - NM_DEVICE_TYPE_6LOWPAN = 28, - NM_DEVICE_TYPE_WIREGUARD = 29, - NM_DEVICE_TYPE_WIFI_P2P = 30, - NM_DEVICE_TYPE_VRF = 31, -} NMDeviceType; - -/** - * NMDeviceCapabilities: - * @NM_DEVICE_CAP_NONE: device has no special capabilities - * @NM_DEVICE_CAP_NM_SUPPORTED: NetworkManager supports this device - * @NM_DEVICE_CAP_CARRIER_DETECT: this device can indicate carrier status - * @NM_DEVICE_CAP_IS_SOFTWARE: this device is a software device - * @NM_DEVICE_CAP_SRIOV: this device supports single-root I/O virtualization - * - * General device capability flags. - **/ -typedef enum { /*< flags >*/ - NM_DEVICE_CAP_NONE = 0x00000000, - NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001, - NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002, - NM_DEVICE_CAP_IS_SOFTWARE = 0x00000004, - NM_DEVICE_CAP_SRIOV = 0x00000008, -} NMDeviceCapabilities; - -/** - * NMDeviceWifiCapabilities: - * @NM_WIFI_DEVICE_CAP_NONE: device has no encryption/authentication capabilities - * @NM_WIFI_DEVICE_CAP_CIPHER_WEP40: device supports 40/64-bit WEP encryption - * @NM_WIFI_DEVICE_CAP_CIPHER_WEP104: device supports 104/128-bit WEP encryption - * @NM_WIFI_DEVICE_CAP_CIPHER_TKIP: device supports TKIP encryption - * @NM_WIFI_DEVICE_CAP_CIPHER_CCMP: device supports AES/CCMP encryption - * @NM_WIFI_DEVICE_CAP_WPA: device supports WPA1 authentication - * @NM_WIFI_DEVICE_CAP_RSN: device supports WPA2/RSN authentication - * @NM_WIFI_DEVICE_CAP_AP: device supports Access Point mode - * @NM_WIFI_DEVICE_CAP_ADHOC: device supports Ad-Hoc mode - * @NM_WIFI_DEVICE_CAP_FREQ_VALID: device reports frequency capabilities - * @NM_WIFI_DEVICE_CAP_FREQ_2GHZ: device supports 2.4GHz frequencies - * @NM_WIFI_DEVICE_CAP_FREQ_5GHZ: device supports 5GHz frequencies - * @NM_WIFI_DEVICE_CAP_MESH: device supports acting as a mesh point. Since: 1.20. - * @NM_WIFI_DEVICE_CAP_IBSS_RSN: device supports WPA2/RSN in an IBSS network. Since: 1.22. - * - * 802.11 specific device encryption and authentication capabilities. - **/ -typedef enum { /*< flags >*/ - NM_WIFI_DEVICE_CAP_NONE = 0x00000000, - NM_WIFI_DEVICE_CAP_CIPHER_WEP40 = 0x00000001, - NM_WIFI_DEVICE_CAP_CIPHER_WEP104 = 0x00000002, - NM_WIFI_DEVICE_CAP_CIPHER_TKIP = 0x00000004, - NM_WIFI_DEVICE_CAP_CIPHER_CCMP = 0x00000008, - NM_WIFI_DEVICE_CAP_WPA = 0x00000010, - NM_WIFI_DEVICE_CAP_RSN = 0x00000020, - NM_WIFI_DEVICE_CAP_AP = 0x00000040, - NM_WIFI_DEVICE_CAP_ADHOC = 0x00000080, - NM_WIFI_DEVICE_CAP_FREQ_VALID = 0x00000100, - NM_WIFI_DEVICE_CAP_FREQ_2GHZ = 0x00000200, - NM_WIFI_DEVICE_CAP_FREQ_5GHZ = 0x00000400, - NM_WIFI_DEVICE_CAP_MESH = 0x00001000, - NM_WIFI_DEVICE_CAP_IBSS_RSN = 0x00002000, -} NMDeviceWifiCapabilities; - -/** - * NM80211ApFlags: - * @NM_802_11_AP_FLAGS_NONE: access point has no special capabilities - * @NM_802_11_AP_FLAGS_PRIVACY: access point requires authentication and - * encryption (usually means WEP) - * @NM_802_11_AP_FLAGS_WPS: access point supports some WPS method - * @NM_802_11_AP_FLAGS_WPS_PBC: access point supports push-button WPS - * @NM_802_11_AP_FLAGS_WPS_PIN: access point supports PIN-based WPS - * - * 802.11 access point flags. - **/ -typedef enum { /*< underscore_name=nm_802_11_ap_flags, flags >*/ - NM_802_11_AP_FLAGS_NONE = 0x00000000, - NM_802_11_AP_FLAGS_PRIVACY = 0x00000001, - NM_802_11_AP_FLAGS_WPS = 0x00000002, - NM_802_11_AP_FLAGS_WPS_PBC = 0x00000004, - NM_802_11_AP_FLAGS_WPS_PIN = 0x00000008, -} NM80211ApFlags; - -/** - * NM80211ApSecurityFlags: - * @NM_802_11_AP_SEC_NONE: the access point has no special security requirements - * @NM_802_11_AP_SEC_PAIR_WEP40: 40/64-bit WEP is supported for - * pairwise/unicast encryption - * @NM_802_11_AP_SEC_PAIR_WEP104: 104/128-bit WEP is supported for - * pairwise/unicast encryption - * @NM_802_11_AP_SEC_PAIR_TKIP: TKIP is supported for pairwise/unicast encryption - * @NM_802_11_AP_SEC_PAIR_CCMP: AES/CCMP is supported for pairwise/unicast encryption - * @NM_802_11_AP_SEC_GROUP_WEP40: 40/64-bit WEP is supported for group/broadcast - * encryption - * @NM_802_11_AP_SEC_GROUP_WEP104: 104/128-bit WEP is supported for - * group/broadcast encryption - * @NM_802_11_AP_SEC_GROUP_TKIP: TKIP is supported for group/broadcast encryption - * @NM_802_11_AP_SEC_GROUP_CCMP: AES/CCMP is supported for group/broadcast - * encryption - * @NM_802_11_AP_SEC_KEY_MGMT_PSK: WPA/RSN Pre-Shared Key encryption is - * supported - * @NM_802_11_AP_SEC_KEY_MGMT_802_1X: 802.1x authentication and key management - * is supported - * @NM_802_11_AP_SEC_KEY_MGMT_SAE: WPA/RSN Simultaneous Authentication of Equals is - * supported - * @NM_802_11_AP_SEC_KEY_MGMT_OWE: WPA/RSN Opportunistic Wireless Encryption is - * supported - * @NM_802_11_AP_SEC_KEY_MGMT_OWE_TM: WPA/RSN Opportunistic Wireless Encryption - * transition mode is supported. Since: 1.26. - * @NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192: WPA3 Enterprise Suite-B 192 bit mode - * is supported. Since: 1.30. - * - * 802.11 access point security and authentication flags. These flags describe - * the current security requirements of an access point as determined from the - * access point's beacon. - **/ -typedef enum { /*< underscore_name=nm_802_11_ap_security_flags, flags >*/ - NM_802_11_AP_SEC_NONE = 0x00000000, - NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001, - NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002, - NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004, - NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008, - NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010, - NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020, - NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040, - NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080, - NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100, - NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200, - NM_802_11_AP_SEC_KEY_MGMT_SAE = 0x00000400, - NM_802_11_AP_SEC_KEY_MGMT_OWE = 0x00000800, - NM_802_11_AP_SEC_KEY_MGMT_OWE_TM = 0x00001000, - NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 = 0x00002000, -} NM80211ApSecurityFlags; - -/** - * NM80211Mode: - * @NM_802_11_MODE_UNKNOWN: the device or access point mode is unknown - * @NM_802_11_MODE_ADHOC: for both devices and access point objects, indicates - * the object is part of an Ad-Hoc 802.11 network without a central - * coordinating access point. - * @NM_802_11_MODE_INFRA: the device or access point is in infrastructure mode. - * For devices, this indicates the device is an 802.11 client/station. For - * access point objects, this indicates the object is an access point that - * provides connectivity to clients. - * @NM_802_11_MODE_AP: the device is an access point/hotspot. Not valid for - * access point objects; used only for hotspot mode on the local machine. - * @NM_802_11_MODE_MESH: the device is a 802.11s mesh point. Since: 1.20. - * - * Indicates the 802.11 mode an access point or device is currently in. - **/ -typedef enum { /*< underscore_name=nm_802_11_mode >*/ - NM_802_11_MODE_UNKNOWN = 0, - NM_802_11_MODE_ADHOC = 1, - NM_802_11_MODE_INFRA = 2, - NM_802_11_MODE_AP = 3, - NM_802_11_MODE_MESH = 4, -} NM80211Mode; - -/** - * NMBluetoothCapabilities: - * @NM_BT_CAPABILITY_NONE: device has no usable capabilities - * @NM_BT_CAPABILITY_DUN: device provides Dial-Up Networking capability - * @NM_BT_CAPABILITY_NAP: device provides Network Access Point capability - * - * #NMBluetoothCapabilities values indicate the usable capabilities of a - * Bluetooth device. - **/ -typedef enum { /*< flags >*/ - NM_BT_CAPABILITY_NONE = 0x00000000, - NM_BT_CAPABILITY_DUN = 0x00000001, - NM_BT_CAPABILITY_NAP = 0x00000002, -} NMBluetoothCapabilities; - -/** - * NMDeviceModemCapabilities: - * @NM_DEVICE_MODEM_CAPABILITY_NONE: modem has no usable capabilities - * @NM_DEVICE_MODEM_CAPABILITY_POTS: modem uses the analog wired telephone - * network and is not a wireless/cellular device - * @NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO: modem supports at least one of CDMA - * 1xRTT, EVDO revision 0, EVDO revision A, or EVDO revision B - * @NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS: modem supports at least one of GSM, - * GPRS, EDGE, UMTS, HSDPA, HSUPA, or HSPA+ packet switched data capability - * @NM_DEVICE_MODEM_CAPABILITY_LTE: modem has LTE data capability - * - * #NMDeviceModemCapabilities values indicate the generic radio access - * technology families a modem device supports. For more information on the - * specific access technologies the device supports use the ModemManager D-Bus - * API. - **/ -typedef enum { /*< flags >*/ - NM_DEVICE_MODEM_CAPABILITY_NONE = 0x00000000, - NM_DEVICE_MODEM_CAPABILITY_POTS = 0x00000001, - NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO = 0x00000002, - NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS = 0x00000004, - NM_DEVICE_MODEM_CAPABILITY_LTE = 0x00000008, -} NMDeviceModemCapabilities; - -/** - * NMWimaxNspNetworkType: - * @NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN: unknown network type - * @NM_WIMAX_NSP_NETWORK_TYPE_HOME: home network - * @NM_WIMAX_NSP_NETWORK_TYPE_PARTNER: partner network - * @NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER: roaming partner network - * - * WiMAX network type. - */ -typedef enum { - NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN = 0, - NM_WIMAX_NSP_NETWORK_TYPE_HOME = 1, - NM_WIMAX_NSP_NETWORK_TYPE_PARTNER = 2, - NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER = 3, -} NMWimaxNspNetworkType; - -/** - * NMDeviceState: - * @NM_DEVICE_STATE_UNKNOWN: the device's state is unknown - * @NM_DEVICE_STATE_UNMANAGED: the device is recognized, but not managed by - * NetworkManager - * @NM_DEVICE_STATE_UNAVAILABLE: the device is managed by NetworkManager, but - * is not available for use. Reasons may include the wireless switched off, - * missing firmware, no ethernet carrier, missing supplicant or modem manager, - * etc. - * @NM_DEVICE_STATE_DISCONNECTED: the device can be activated, but is currently - * idle and not connected to a network. - * @NM_DEVICE_STATE_PREPARE: the device is preparing the connection to the - * network. This may include operations like changing the MAC address, - * setting physical link properties, and anything else required to connect - * to the requested network. - * @NM_DEVICE_STATE_CONFIG: the device is connecting to the requested network. - * This may include operations like associating with the Wi-Fi AP, dialing - * the modem, connecting to the remote Bluetooth device, etc. - * @NM_DEVICE_STATE_NEED_AUTH: the device requires more information to continue - * connecting to the requested network. This includes secrets like WiFi - * passphrases, login passwords, PIN codes, etc. - * @NM_DEVICE_STATE_IP_CONFIG: the device is requesting IPv4 and/or IPv6 - * addresses and routing information from the network. - * @NM_DEVICE_STATE_IP_CHECK: the device is checking whether further action is - * required for the requested network connection. This may include checking - * whether only local network access is available, whether a captive portal - * is blocking access to the Internet, etc. - * @NM_DEVICE_STATE_SECONDARIES: the device is waiting for a secondary - * connection (like a VPN) which must activated before the device can be - * activated - * @NM_DEVICE_STATE_ACTIVATED: the device has a network connection, either local - * or global. - * @NM_DEVICE_STATE_DEACTIVATING: a disconnection from the current network - * connection was requested, and the device is cleaning up resources used for - * that connection. The network connection may still be valid. - * @NM_DEVICE_STATE_FAILED: the device failed to connect to the requested - * network and is cleaning up the connection request - **/ -typedef enum { - NM_DEVICE_STATE_UNKNOWN = 0, - NM_DEVICE_STATE_UNMANAGED = 10, - NM_DEVICE_STATE_UNAVAILABLE = 20, - NM_DEVICE_STATE_DISCONNECTED = 30, - NM_DEVICE_STATE_PREPARE = 40, - NM_DEVICE_STATE_CONFIG = 50, - NM_DEVICE_STATE_NEED_AUTH = 60, - NM_DEVICE_STATE_IP_CONFIG = 70, - NM_DEVICE_STATE_IP_CHECK = 80, - NM_DEVICE_STATE_SECONDARIES = 90, - NM_DEVICE_STATE_ACTIVATED = 100, - NM_DEVICE_STATE_DEACTIVATING = 110, - NM_DEVICE_STATE_FAILED = 120, -} NMDeviceState; - -/** - * NMDeviceStateReason: - * @NM_DEVICE_STATE_REASON_NONE: No reason given - * @NM_DEVICE_STATE_REASON_UNKNOWN: Unknown error - * @NM_DEVICE_STATE_REASON_NOW_MANAGED: Device is now managed - * @NM_DEVICE_STATE_REASON_NOW_UNMANAGED: Device is now unmanaged - * @NM_DEVICE_STATE_REASON_CONFIG_FAILED: The device could not be readied for configuration - * @NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE: IP configuration could not be reserved (no available address, timeout, etc) - * @NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED: The IP config is no longer valid - * @NM_DEVICE_STATE_REASON_NO_SECRETS: Secrets were required, but not provided - * @NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT: 802.1x supplicant disconnected - * @NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED: 802.1x supplicant configuration failed - * @NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED: 802.1x supplicant failed - * @NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT: 802.1x supplicant took too long to authenticate - * @NM_DEVICE_STATE_REASON_PPP_START_FAILED: PPP service failed to start - * @NM_DEVICE_STATE_REASON_PPP_DISCONNECT: PPP service disconnected - * @NM_DEVICE_STATE_REASON_PPP_FAILED: PPP failed - * @NM_DEVICE_STATE_REASON_DHCP_START_FAILED: DHCP client failed to start - * @NM_DEVICE_STATE_REASON_DHCP_ERROR: DHCP client error - * @NM_DEVICE_STATE_REASON_DHCP_FAILED: DHCP client failed - * @NM_DEVICE_STATE_REASON_SHARED_START_FAILED: Shared connection service failed to start - * @NM_DEVICE_STATE_REASON_SHARED_FAILED: Shared connection service failed - * @NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED: AutoIP service failed to start - * @NM_DEVICE_STATE_REASON_AUTOIP_ERROR: AutoIP service error - * @NM_DEVICE_STATE_REASON_AUTOIP_FAILED: AutoIP service failed - * @NM_DEVICE_STATE_REASON_MODEM_BUSY: The line is busy - * @NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE: No dial tone - * @NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER: No carrier could be established - * @NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT: The dialing request timed out - * @NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED: The dialing attempt failed - * @NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: Modem initialization failed - * @NM_DEVICE_STATE_REASON_GSM_APN_FAILED: Failed to select the specified APN - * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: Not searching for networks - * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: Network registration denied - * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT: Network registration timed out - * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED: Failed to register with the requested network - * @NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED: PIN check failed - * @NM_DEVICE_STATE_REASON_FIRMWARE_MISSING: Necessary firmware for the device may be missing - * @NM_DEVICE_STATE_REASON_REMOVED: The device was removed - * @NM_DEVICE_STATE_REASON_SLEEPING: NetworkManager went to sleep - * @NM_DEVICE_STATE_REASON_CONNECTION_REMOVED: The device's active connection disappeared - * @NM_DEVICE_STATE_REASON_USER_REQUESTED: Device disconnected by user or client - * @NM_DEVICE_STATE_REASON_CARRIER: Carrier/link changed - * @NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED: The device's existing connection was assumed - * @NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: The supplicant is now available - * @NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND: The modem could not be found - * @NM_DEVICE_STATE_REASON_BT_FAILED: The Bluetooth connection failed or timed out - * @NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: GSM Modem's SIM Card not inserted - * @NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: GSM Modem's SIM Pin required - * @NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED: GSM Modem's SIM Puk required - * @NM_DEVICE_STATE_REASON_GSM_SIM_WRONG: GSM Modem's SIM wrong - * @NM_DEVICE_STATE_REASON_INFINIBAND_MODE: InfiniBand device does not support connected mode - * @NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: A dependency of the connection failed - * @NM_DEVICE_STATE_REASON_BR2684_FAILED: Problem with the RFC 2684 Ethernet over ADSL bridge - * @NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE: ModemManager not running - * @NM_DEVICE_STATE_REASON_SSID_NOT_FOUND: The Wi-Fi network could not be found - * @NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED: A secondary connection of the base connection failed - * @NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED: DCB or FCoE setup failed - * @NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED: teamd control failed - * @NM_DEVICE_STATE_REASON_MODEM_FAILED: Modem failed or no longer available - * @NM_DEVICE_STATE_REASON_MODEM_AVAILABLE: Modem now ready and available - * @NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT: SIM PIN was incorrect - * @NM_DEVICE_STATE_REASON_NEW_ACTIVATION: New connection activation was enqueued - * @NM_DEVICE_STATE_REASON_PARENT_CHANGED: the device's parent changed - * @NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED: the device parent's management changed - * @NM_DEVICE_STATE_REASON_OVSDB_FAILED: problem communicating with Open vSwitch database - * @NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE: a duplicate IP address was detected - * @NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED: The selected IP method is not supported - * @NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED: configuration of SR-IOV parameters failed - * @NM_DEVICE_STATE_REASON_PEER_NOT_FOUND: The Wi-Fi P2P peer could not be found - * - * Device state change reason codes - */ -typedef enum { - NM_DEVICE_STATE_REASON_NONE = 0, - NM_DEVICE_STATE_REASON_UNKNOWN = 1, - NM_DEVICE_STATE_REASON_NOW_MANAGED = 2, - NM_DEVICE_STATE_REASON_NOW_UNMANAGED = 3, - NM_DEVICE_STATE_REASON_CONFIG_FAILED = 4, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE = 5, - NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED = 6, - NM_DEVICE_STATE_REASON_NO_SECRETS = 7, - NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8, - NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED = 9, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED = 10, - NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT = 11, - NM_DEVICE_STATE_REASON_PPP_START_FAILED = 12, - NM_DEVICE_STATE_REASON_PPP_DISCONNECT = 13, - NM_DEVICE_STATE_REASON_PPP_FAILED = 14, - NM_DEVICE_STATE_REASON_DHCP_START_FAILED = 15, - NM_DEVICE_STATE_REASON_DHCP_ERROR = 16, - NM_DEVICE_STATE_REASON_DHCP_FAILED = 17, - NM_DEVICE_STATE_REASON_SHARED_START_FAILED = 18, - NM_DEVICE_STATE_REASON_SHARED_FAILED = 19, - NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED = 20, - NM_DEVICE_STATE_REASON_AUTOIP_ERROR = 21, - NM_DEVICE_STATE_REASON_AUTOIP_FAILED = 22, - NM_DEVICE_STATE_REASON_MODEM_BUSY = 23, - NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE = 24, - NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER = 25, - NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT = 26, - NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED = 27, - NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED = 28, - NM_DEVICE_STATE_REASON_GSM_APN_FAILED = 29, - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING = 30, - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED = 31, - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT = 32, - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED = 33, - NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED = 34, - NM_DEVICE_STATE_REASON_FIRMWARE_MISSING = 35, - NM_DEVICE_STATE_REASON_REMOVED = 36, - NM_DEVICE_STATE_REASON_SLEEPING = 37, - NM_DEVICE_STATE_REASON_CONNECTION_REMOVED = 38, - NM_DEVICE_STATE_REASON_USER_REQUESTED = 39, - NM_DEVICE_STATE_REASON_CARRIER = 40, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED = 41, - NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE = 42, - NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND = 43, - NM_DEVICE_STATE_REASON_BT_FAILED = 44, - NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED = 45, - NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED = 46, - NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED = 47, - NM_DEVICE_STATE_REASON_GSM_SIM_WRONG = 48, - NM_DEVICE_STATE_REASON_INFINIBAND_MODE = 49, - NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED = 50, - NM_DEVICE_STATE_REASON_BR2684_FAILED = 51, - NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE = 52, - NM_DEVICE_STATE_REASON_SSID_NOT_FOUND = 53, - NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED = 54, - NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED = 55, - NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED = 56, - NM_DEVICE_STATE_REASON_MODEM_FAILED = 57, - NM_DEVICE_STATE_REASON_MODEM_AVAILABLE = 58, - NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT = 59, - NM_DEVICE_STATE_REASON_NEW_ACTIVATION = 60, - NM_DEVICE_STATE_REASON_PARENT_CHANGED = 61, - NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED = 62, - NM_DEVICE_STATE_REASON_OVSDB_FAILED = 63, - NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE = 64, - NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED = 65, - NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED = 66, - NM_DEVICE_STATE_REASON_PEER_NOT_FOUND = 67, -} NMDeviceStateReason; - -/** - * NMMetered: - * @NM_METERED_UNKNOWN: The metered status is unknown - * @NM_METERED_YES: Metered, the value was explicitly configured - * @NM_METERED_NO: Not metered, the value was explicitly configured - * @NM_METERED_GUESS_YES: Metered, the value was guessed - * @NM_METERED_GUESS_NO: Not metered, the value was guessed - * - * The NMMetered enum has two different purposes: one is to configure - * "connection.metered" setting of a connection profile in #NMSettingConnection, and - * the other is to express the actual metered state of the #NMDevice at a given moment. - * - * For the connection profile only #NM_METERED_UNKNOWN, #NM_METERED_NO - * and #NM_METERED_YES are allowed. - * - * The device's metered state at runtime is determined by the profile - * which is currently active. If the profile explicitly specifies #NM_METERED_NO - * or #NM_METERED_YES, then the device's metered state is as such. - * If the connection profile leaves it undecided at #NM_METERED_UNKNOWN (the default), - * then NetworkManager tries to guess the metered state, for example based on the - * device type or on DHCP options (like Android devices exposing a "ANDROID_METERED" - * DHCP vendor option). This then leads to either #NM_METERED_GUESS_NO or #NM_METERED_GUESS_YES. - * - * Most applications probably should treat the runtime state #NM_METERED_GUESS_YES - * like #NM_METERED_YES, and all other states as not metered. - * - * Note that the per-device metered states are then combined to a global metered - * state. This is basically the metered state of the device with the best default - * route. However, that generalization of a global metered state may not be correct - * if the default routes for IPv4 and IPv6 are on different devices, or if policy - * routing is configured. In general, the global metered state tries to express whether - * the traffic is likely metered, but since that depends on the traffic itself, - * there is not one answer in all cases. Hence, an application may want to consider - * the per-device's metered states. - * - * Since: 1.2 - **/ -NM_AVAILABLE_IN_1_2 -typedef enum { - NM_METERED_UNKNOWN = 0, - NM_METERED_YES = 1, - NM_METERED_NO = 2, - NM_METERED_GUESS_YES = 3, - NM_METERED_GUESS_NO = 4, -} NMMetered; - -/** - * NMConnectionMultiConnect: - * @NM_CONNECTION_MULTI_CONNECT_DEFAULT: indicates that the per-connection - * setting is unspecified. In this case, it will fallback to the default - * value, which is %NM_CONNECTION_MULTI_CONNECT_SINGLE. - * @NM_CONNECTION_MULTI_CONNECT_SINGLE: the connection profile can only - * be active once at each moment. Activating a profile that is already active, - * will first deactivate it. - * @NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE: the profile can - * be manually activated multiple times on different devices. However, - * regarding autoconnect, the profile will autoconnect only if it is - * currently not connected otherwise. - * @NM_CONNECTION_MULTI_CONNECT_MULTIPLE: the profile can autoactivate - * and be manually activated multiple times together. - * - * Since: 1.14 - */ -typedef enum { - NM_CONNECTION_MULTI_CONNECT_DEFAULT = 0, - NM_CONNECTION_MULTI_CONNECT_SINGLE = 1, - NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE = 2, - NM_CONNECTION_MULTI_CONNECT_MULTIPLE = 3, -} NMConnectionMultiConnect; - -/** - * NMActiveConnectionState: - * @NM_ACTIVE_CONNECTION_STATE_UNKNOWN: the state of the connection is unknown - * @NM_ACTIVE_CONNECTION_STATE_ACTIVATING: a network connection is being prepared - * @NM_ACTIVE_CONNECTION_STATE_ACTIVATED: there is a connection to the network - * @NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: the network connection is being - * torn down and cleaned up - * @NM_ACTIVE_CONNECTION_STATE_DEACTIVATED: the network connection is disconnected - * and will be removed - * - * #NMActiveConnectionState values indicate the state of a connection to a - * specific network while it is starting, connected, or disconnecting from that - * network. - **/ -typedef enum { - NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0, - NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1, - NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATING = 3, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATED = 4, -} NMActiveConnectionState; - -/** - * NMActiveConnectionStateReason: - * @NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN: The reason for the active connection - * state change is unknown. - * @NM_ACTIVE_CONNECTION_STATE_REASON_NONE: No reason was given for the active - * connection state change. - * @NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED: The active connection changed - * state because the user disconnected it. - * @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED: The active connection - * changed state because the device it was using was disconnected. - * @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED: The service providing the - * VPN connection was stopped. - * @NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID: The IP config of the active - * connection was invalid. - * @NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT: The connection attempt to - * the VPN service timed out. - * @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT: A timeout occurred - * while starting the service providing the VPN connection. - * @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED: Starting the service - * providing the VPN connection failed. - * @NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS: Necessary secrets for the - * connection were not provided. - * @NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED: Authentication to the - * server failed. - * @NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED: The connection was - * deleted from settings. - * @NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED: Master connection of this - * connection failed to activate. - * @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED: Could not create the - * software device link. - * @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED: The device this connection - * depended on disappeared. - * - * Active connection state reasons. - * - * Since: 1.8 - */ -NM_AVAILABLE_IN_1_8 -typedef enum { - NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN = 0, - NM_ACTIVE_CONNECTION_STATE_REASON_NONE = 1, - NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED = 2, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED = 3, - NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED = 4, - NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID = 5, - NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT = 6, - NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT = 7, - NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED = 8, - NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS = 9, - NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED = 10, - NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED = 11, - NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED = 12, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED = 13, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED = 14, -} NMActiveConnectionStateReason; - -/** - * NMSecretAgentGetSecretsFlags: - * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE: no special behavior; by default no - * user interaction is allowed and requests for secrets are fulfilled from - * persistent storage, or if no secrets are available an error is returned. - * @NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION: allows the request to - * interact with the user, possibly prompting via UI for secrets if any are - * required, or if none are found in persistent storage. - * @NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW: explicitly prompt for new - * secrets from the user. This flag signals that NetworkManager thinks any - * existing secrets are invalid or wrong. This flag implies that interaction - * is allowed. - * @NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED: set if the request was - * initiated by user-requested action via the D-Bus interface, as opposed to - * automatically initiated by NetworkManager in response to (for example) scan - * results or carrier changes. - * @NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE: indicates that WPS enrollment - * is active with PBC method. The agent may suggest that the user pushes a button - * on the router instead of supplying a PSK. - * @NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM: Internal flag, not part of - * the D-Bus API. - * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS: Internal flag, not part of - * the D-Bus API. - * - * #NMSecretAgentGetSecretsFlags values modify the behavior of a GetSecrets request. - */ -typedef enum { /*< flags >*/ - NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE = 0x0, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1, - NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2, - NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4, - NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE = 0x8, - - /* Internal to NM; not part of the D-Bus API */ - NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM = 0x80000000, - NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS = 0x40000000, -} NMSecretAgentGetSecretsFlags; - -/** - * NMSecretAgentCapabilities: - * @NM_SECRET_AGENT_CAPABILITY_NONE: the agent supports no special capabilities - * @NM_SECRET_AGENT_CAPABILITY_VPN_HINTS: the agent supports passing hints to - * VPN plugin authentication dialogs. - * @NM_SECRET_AGENT_CAPABILITY_LAST: bounds checking value; should not be used. - * - * #NMSecretAgentCapabilities indicate various capabilities of the agent. - */ -typedef enum /*< flags >*/ { - NM_SECRET_AGENT_CAPABILITY_NONE = 0x0, - NM_SECRET_AGENT_CAPABILITY_VPN_HINTS = 0x1, - - /* boundary value */ - NM_SECRET_AGENT_CAPABILITY_LAST = NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, -} NMSecretAgentCapabilities; - -#ifndef NM_VERSION_H - #undef NM_AVAILABLE_IN_1_2 - #undef NM_AVAILABLE_IN_1_8 -#endif - -#define NM_LLDP_ATTR_RAW "raw" -#define NM_LLDP_ATTR_DESTINATION "destination" -#define NM_LLDP_ATTR_CHASSIS_ID_TYPE "chassis-id-type" -#define NM_LLDP_ATTR_CHASSIS_ID "chassis-id" -#define NM_LLDP_ATTR_PORT_ID_TYPE "port-id-type" -#define NM_LLDP_ATTR_PORT_ID "port-id" -#define NM_LLDP_ATTR_PORT_DESCRIPTION "port-description" -#define NM_LLDP_ATTR_SYSTEM_NAME "system-name" -#define NM_LLDP_ATTR_SYSTEM_DESCRIPTION "system-description" -#define NM_LLDP_ATTR_SYSTEM_CAPABILITIES "system-capabilities" -#define NM_LLDP_ATTR_MANAGEMENT_ADDRESSES "management-addresses" - -#define NM_LLDP_ATTR_IEEE_802_1_PVID "ieee-802-1-pvid" -#define NM_LLDP_ATTR_IEEE_802_1_VLANS "ieee-802-1-vlans" -#define NM_LLDP_ATTR_IEEE_802_1_PPVIDS "ieee-802-1-ppvids" - -#define NM_LLDP_ATTR_IEEE_802_3_MAC_PHY_CONF "ieee-802-3-mac-phy-conf" -#define NM_LLDP_ATTR_IEEE_802_3_POWER_VIA_MDI "ieee-802-3-power-via-mdi" -#define NM_LLDP_ATTR_IEEE_802_3_MAX_FRAME_SIZE "ieee-802-3-max-frame-size" - -#define NM_LLDP_ATTR_MUD_URL "mud-url" - -/* These are deprecated in favor of NM_LLDP_ATTR_IEEE_802_1_VLANS, - * which can report multiple VLANs */ -#define NM_LLDP_ATTR_IEEE_802_1_VID "ieee-802-1-vid" -#define NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME "ieee-802-1-vlan-name" - -/* These are deprecated in favor of NM_LLDP_ATTR_IEEE_802_1_PPVIDS, - * which can report multiple PPVIDs */ -#define NM_LLDP_ATTR_IEEE_802_1_PPVID "ieee-802-1-ppvid" -#define NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS "ieee-802-1-ppvid-flags" - -#define NM_LLDP_DEST_NEAREST_BRIDGE "nearest-bridge" -#define NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE "nearest-non-tpmr-bridge" -#define NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE "nearest-customer-bridge" - -/** - * NMIPTunnelMode: - * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode - * @NM_IP_TUNNEL_MODE_IPIP: IP in IP tunnel - * @NM_IP_TUNNEL_MODE_GRE: GRE tunnel - * @NM_IP_TUNNEL_MODE_SIT: SIT tunnel - * @NM_IP_TUNNEL_MODE_ISATAP: ISATAP tunnel - * @NM_IP_TUNNEL_MODE_VTI: VTI tunnel - * @NM_IP_TUNNEL_MODE_IP6IP6: IPv6 in IPv6 tunnel - * @NM_IP_TUNNEL_MODE_IPIP6: IPv4 in IPv6 tunnel - * @NM_IP_TUNNEL_MODE_IP6GRE: IPv6 GRE tunnel - * @NM_IP_TUNNEL_MODE_VTI6: IPv6 VTI tunnel - * @NM_IP_TUNNEL_MODE_GRETAP: GRETAP tunnel - * @NM_IP_TUNNEL_MODE_IP6GRETAP: IPv6 GRETAP tunnel - * - * The tunneling mode. - * - * Since: 1.2 - */ -typedef enum { - NM_IP_TUNNEL_MODE_UNKNOWN = 0, - NM_IP_TUNNEL_MODE_IPIP = 1, - NM_IP_TUNNEL_MODE_GRE = 2, - NM_IP_TUNNEL_MODE_SIT = 3, - NM_IP_TUNNEL_MODE_ISATAP = 4, - NM_IP_TUNNEL_MODE_VTI = 5, - NM_IP_TUNNEL_MODE_IP6IP6 = 6, - NM_IP_TUNNEL_MODE_IPIP6 = 7, - NM_IP_TUNNEL_MODE_IP6GRE = 8, - NM_IP_TUNNEL_MODE_VTI6 = 9, - NM_IP_TUNNEL_MODE_GRETAP = 10, - NM_IP_TUNNEL_MODE_IP6GRETAP = 11, -} NMIPTunnelMode; - -/** - * NMCheckpointCreateFlags: - * @NM_CHECKPOINT_CREATE_FLAG_NONE: no flags - * @NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL: when creating - * a new checkpoint, destroy all existing ones. - * @NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS: upon rollback, - * delete any new connection added after the checkpoint. Since: 1.6. - * @NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES: upon rollback, - * disconnect any new device appeared after the checkpoint. Since: 1.6. - * @NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING: by default, creating - * a checkpoint fails if there are already existing checkoints that - * reference the same devices. With this flag, creation of such - * checkpoints is allowed, however, if an older checkpoint - * that references overlapping devices gets rolled back, it will - * automatically destroy this checkpoint during rollback. This - * allows to create several overlapping checkpoints in parallel, - * and rollback to them at will. With the special case that - * rolling back to an older checkpoint will invalidate all - * overlapping younger checkpoints. This opts-in that the - * checkpoint can be automatically destroyed by the rollback - * of an older checkpoint. Since: 1.12. - * - * The flags for CheckpointCreate call - * - * Since: 1.4 (gi flags generated since 1.12) - */ -typedef enum { /*< flags >*/ - NM_CHECKPOINT_CREATE_FLAG_NONE = 0, - NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL = 0x01, - NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS = 0x02, - NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES = 0x04, - NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING = 0x08, -} NMCheckpointCreateFlags; - -/** - * NMRollbackResult: - * @NM_ROLLBACK_RESULT_OK: the rollback succeeded. - * @NM_ROLLBACK_RESULT_ERR_NO_DEVICE: the device no longer exists. - * @NM_ROLLBACK_RESULT_ERR_DEVICE_UNMANAGED: the device is now unmanaged. - * @NM_ROLLBACK_RESULT_ERR_FAILED: other errors during rollback. - * - * The result of a checkpoint Rollback() operation for a specific device. - * - * Since: 1.4 - **/ -typedef enum { /*< skip >*/ - NM_ROLLBACK_RESULT_OK = 0, - NM_ROLLBACK_RESULT_ERR_NO_DEVICE = 1, - NM_ROLLBACK_RESULT_ERR_DEVICE_UNMANAGED = 2, - NM_ROLLBACK_RESULT_ERR_FAILED = 3, -} NMRollbackResult; - -/** - * NMSettingsConnectionFlags: - * @NM_SETTINGS_CONNECTION_FLAG_NONE: an alias for numeric zero, no flags set. - * @NM_SETTINGS_CONNECTION_FLAG_UNSAVED: the connection is not saved to disk. - * That either means, that the connection is in-memory only and currently - * is not backed by a file. Or, that the connection is backed by a file, - * but has modifications in-memory that were not persisted to disk. - * @NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED: A connection is "nm-generated" if - * it was generated by NetworkManger. If the connection gets modified or saved - * by the user, the flag gets cleared. A nm-generated is also unsaved - * and has no backing file as it is in-memory only. - * @NM_SETTINGS_CONNECTION_FLAG_VOLATILE: The connection will be deleted - * when it disconnects. That is for in-memory connections (unsaved), which are - * currently active but deleted on disconnect. Volatile connections are - * always unsaved, but they are also no backing file on disk and are entirely - * in-memory only. - * @NM_SETTINGS_CONNECTION_FLAG_EXTERNAL: the profile was generated to represent - * an external configuration of a networking device. Since: 1.26. - * - * Flags describing the current activation state. - * - * Since: 1.12 - **/ -typedef enum { /*< flags >*/ - NM_SETTINGS_CONNECTION_FLAG_NONE = 0, - NM_SETTINGS_CONNECTION_FLAG_UNSAVED = 0x01, - NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED = 0x02, - NM_SETTINGS_CONNECTION_FLAG_VOLATILE = 0x04, - NM_SETTINGS_CONNECTION_FLAG_EXTERNAL = 0x08, -} NMSettingsConnectionFlags; - -/** - * NMActivationStateFlags: - * @NM_ACTIVATION_STATE_FLAG_NONE: an alias for numeric zero, no flags set. - * @NM_ACTIVATION_STATE_FLAG_IS_MASTER: the device is a master. - * @NM_ACTIVATION_STATE_FLAG_IS_SLAVE: the device is a slave. - * @NM_ACTIVATION_STATE_FLAG_LAYER2_READY: layer2 is activated and ready. - * @NM_ACTIVATION_STATE_FLAG_IP4_READY: IPv4 setting is completed. - * @NM_ACTIVATION_STATE_FLAG_IP6_READY: IPv6 setting is completed. - * @NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES: The master has any slave devices attached. - * This only makes sense if the device is a master. - * @NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY: the lifetime - * of the activation is bound to the visibility of the connection profile, - * which in turn depends on "connection.permissions" and whether a session - * for the user exists. Since: 1.16. - * @NM_ACTIVATION_STATE_FLAG_EXTERNAL: the active connection was generated to - * represent an external configuration of a networking device. Since: 1.26. - * - * Flags describing the current activation state. - * - * Since: 1.10 - **/ -typedef enum { /*< flags >*/ - NM_ACTIVATION_STATE_FLAG_NONE = 0, - - NM_ACTIVATION_STATE_FLAG_IS_MASTER = 0x1, - NM_ACTIVATION_STATE_FLAG_IS_SLAVE = 0x2, - NM_ACTIVATION_STATE_FLAG_LAYER2_READY = 0x4, - NM_ACTIVATION_STATE_FLAG_IP4_READY = 0x8, - NM_ACTIVATION_STATE_FLAG_IP6_READY = 0x10, - NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES = 0x20, - NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY = 0x40, - NM_ACTIVATION_STATE_FLAG_EXTERNAL = 0x80, -} NMActivationStateFlags; - -/** - * NMSettingsAddConnection2Flags: - * @NM_SETTINGS_ADD_CONNECTION2_FLAG_NONE: an alias for numeric zero, no flags set. - * @NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK: to persist the connection to disk. - * @NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY: to make the connection in-memory only. - * @NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT: usually, when the connection - * has autoconnect enabled and gets added, it becomes eligible to autoconnect - * right away. Setting this flag, disables autoconnect until the connection - * is manually activated. - * - * Numeric flags for the "flags" argument of AddConnection2() D-Bus API. - * - * Since: 1.20 - */ -typedef enum { /*< flags >*/ - NM_SETTINGS_ADD_CONNECTION2_FLAG_NONE = 0, - NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK = 0x1, - NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY = 0x2, - NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT = 0x20, -} NMSettingsAddConnection2Flags; - -/** - * NMSettingsUpdate2Flags: - * @NM_SETTINGS_UPDATE2_FLAG_NONE: an alias for numeric zero, no flags set. - * @NM_SETTINGS_UPDATE2_FLAG_TO_DISK: to persist the connection to disk. - * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY: makes the profile in-memory. - * Note that such profiles are stored in keyfile format under /run. - * If the file is already in-memory, the file in /run is updated in-place. - * Otherwise, the previous storage for the profile is left unchanged - * on disk, and the in-memory copy shadows it. - * Note that the original filename of the previous persistent storage (if any) - * is remembered. That means, when later persisting the profile again to disk, - * the file on disk will be overwritten again. - * Likewise, when finally deleting the profile, both the storage from /run - * and persistent storage are deleted (or if the persistent storage does not - * allow deletion, and nmmeta file is written to mark the UUID as deleted). - * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED: this is almost the same - * as %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, with one difference: when later deleting - * the profile, the original profile will not be deleted. Instead a nmmeta - * file is written to /run to indicate that the profile is gone. - * Note that if such a nmmeta tombstone file exists and hides a file in persistent - * storage, then when re-adding the profile with the same UUID, then the original - * storage is taken over again. - * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY: this is like %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, - * but if the connection has a corresponding file on persistent storage, the file - * will be deleted right away. If the profile is later again persisted to disk, - * a new, unused filename will be chosen. - * @NM_SETTINGS_UPDATE2_FLAG_VOLATILE: This can be specified with either - * %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED - * or %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY. - * After making the connection in-memory only, the connection is marked - * as volatile. That means, if the connection is currently not active - * it will be deleted right away. Otherwise, it is marked to for deletion - * once the connection deactivates. A volatile connection cannot autoactivate - * again (because it's about to be deleted), but a manual activation will - * clear the volatile flag. - * @NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT: usually, when the connection - * has autoconnect enabled and is modified, it becomes eligible to autoconnect - * right away. Setting this flag, disables autoconnect until the connection - * is manually activated. - * @NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY: when a profile gets modified that is - * currently active, then these changes don't take effect for the active - * device unless the profile gets reactivated or the configuration reapplied. - * There are two exceptions: by default "connection.zone" and "connection.metered" - * properties take effect immediately. Specify this flag to prevent these - * properties to take effect, so that the change is restricted to modify - * the profile. Since: 1.20. - * - * Since: 1.12 - */ -typedef enum { /*< flags >*/ - NM_SETTINGS_UPDATE2_FLAG_NONE = 0, - NM_SETTINGS_UPDATE2_FLAG_TO_DISK = 0x1, - NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY = 0x2, - NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED = 0x4, - NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY = 0x8, - NM_SETTINGS_UPDATE2_FLAG_VOLATILE = 0x10, - NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT = 0x20, - NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY = 0x40, -} NMSettingsUpdate2Flags; - -/** - * NMTernary: - * @NM_TERNARY_DEFAULT: use the globally-configured default value. - * @NM_TERNARY_FALSE: the option is disabled. - * @NM_TERNARY_TRUE: the option is enabled. - * - * An boolean value that can be overridden by a default. - * - * Since: 1.14 - **/ -typedef enum { - NM_TERNARY_DEFAULT = -1, - NM_TERNARY_FALSE = 0, - NM_TERNARY_TRUE = 1, -} NMTernary; - -/** - * NMManagerReloadFlags: - * @NM_MANAGER_RELOAD_FLAG_NONE: an alias for numeric zero, no flags set. This - * reloads everything that is supported and is identical to a SIGHUP. - * @NM_MANAGER_RELOAD_FLAG_CONF: reload the NetworkManager.conf configuration - * from disk. Note that this does not include connections, which can be - * reloaded via Setting's ReloadConnections(). - * @NM_MANAGER_RELOAD_FLAG_DNS_RC: update DNS configuration, which usually - * involves writing /etc/resolv.conf anew. - * @NM_MANAGER_RELOAD_FLAG_DNS_FULL: means to restart the DNS plugin. This - * is for example useful when using dnsmasq plugin, which uses additional - * configuration in /etc/NetworkManager/dnsmasq.d. If you edit those files, - * you can restart the DNS plugin. This action shortly interrupts name - * resolution. - * @NM_MANAGER_RELOAD_FLAG_ALL: all flags. - * - * Flags for the manager Reload() call. - * - * Since: 1.22 - */ -typedef enum { /*< flags >*/ - NM_MANAGER_RELOAD_FLAG_NONE = 0, /*< skip >*/ - NM_MANAGER_RELOAD_FLAG_CONF = 0x1, - NM_MANAGER_RELOAD_FLAG_DNS_RC = 0x2, - NM_MANAGER_RELOAD_FLAG_DNS_FULL = 0x4, - NM_MANAGER_RELOAD_FLAG_ALL = 0x7, /*< skip >*/ -} NMManagerReloadFlags; - -/** - * NMDeviceInterfaceFlags: - * @NM_DEVICE_INTERFACE_FLAG_NONE: an alias for numeric zero, no flags set. - * @NM_DEVICE_INTERFACE_FLAG_UP: the interface is enabled from the - * administrative point of view. Corresponds to kernel IFF_UP. - * @NM_DEVICE_INTERFACE_FLAG_LOWER_UP: the physical link is up. Corresponds - * to kernel IFF_LOWER_UP. - * @NM_DEVICE_INTERFACE_FLAG_CARRIER: the interface has carrier. In most - * cases this is equal to the value of @NM_DEVICE_INTERFACE_FLAG_LOWER_UP. - * However some devices have a non-standard carrier detection mechanism. - * - * Flags for a network interface. - * - * Since: 1.22 - */ -typedef enum { /*< flags >*/ - /* kernel flags */ - NM_DEVICE_INTERFACE_FLAG_NONE = 0, /*< skip >*/ - NM_DEVICE_INTERFACE_FLAG_UP = 0x1, - NM_DEVICE_INTERFACE_FLAG_LOWER_UP = 0x2, - /* NM-specific flags */ - NM_DEVICE_INTERFACE_FLAG_CARRIER = 0x10000, -} NMDeviceInterfaceFlags; - -/** - * NMClientPermission: - * @NM_CLIENT_PERMISSION_NONE: unknown or no permission - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK: controls whether networking - * can be globally enabled or disabled - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI: controls whether Wi-Fi can be - * globally enabled or disabled - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN: controls whether WWAN (3G) can be - * globally enabled or disabled - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX: controls whether WiMAX can be - * globally enabled or disabled - * @NM_CLIENT_PERMISSION_SLEEP_WAKE: controls whether the client can ask - * NetworkManager to sleep and wake - * @NM_CLIENT_PERMISSION_NETWORK_CONTROL: controls whether networking connections - * can be started, stopped, and changed - * @NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED: controls whether a password - * protected Wi-Fi hotspot can be created - * @NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN: controls whether an open Wi-Fi hotspot - * can be created - * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM: controls whether connections - * that are available to all users can be modified - * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN: controls whether connections - * owned by the current user can be modified - * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME: controls whether the - * persistent hostname can be changed - * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS: modify persistent global - * DNS configuration - * @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload. - * @NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK: permission to create checkpoints. - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS: controls whether device - * statistics can be globally enabled or disabled - * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK: controls whether - * connectivity check can be enabled or disabled - * @NM_CLIENT_PERMISSION_WIFI_SCAN: controls whether wifi scans can be performed - * @NM_CLIENT_PERMISSION_LAST: a reserved boundary value - * - * #NMClientPermission values indicate various permissions that NetworkManager - * clients can obtain to perform certain tasks on behalf of the current user. - **/ -typedef enum { - NM_CLIENT_PERMISSION_NONE = 0, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 4, - NM_CLIENT_PERMISSION_SLEEP_WAKE = 5, - NM_CLIENT_PERMISSION_NETWORK_CONTROL = 6, - NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED = 7, - NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 8, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM = 9, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12, - NM_CLIENT_PERMISSION_RELOAD = 13, - NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK = 16, - NM_CLIENT_PERMISSION_WIFI_SCAN = 17, - - NM_CLIENT_PERMISSION_LAST = 17, -} NMClientPermission; - -/** - * NMClientPermissionResult: - * @NM_CLIENT_PERMISSION_RESULT_UNKNOWN: unknown or no authorization - * @NM_CLIENT_PERMISSION_RESULT_YES: the permission is available - * @NM_CLIENT_PERMISSION_RESULT_AUTH: authorization is necessary before the - * permission is available - * @NM_CLIENT_PERMISSION_RESULT_NO: permission to perform the operation is - * denied by system policy - * - * #NMClientPermissionResult values indicate what authorizations and permissions - * the user requires to obtain a given #NMClientPermission - **/ -typedef enum { - NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0, - NM_CLIENT_PERMISSION_RESULT_YES, - NM_CLIENT_PERMISSION_RESULT_AUTH, - NM_CLIENT_PERMISSION_RESULT_NO -} NMClientPermissionResult; - -#endif /* __NM_DBUS_INTERFACE_H__ */ diff --git a/libnm-core/nm-dbus-utils.c b/libnm-core/nm-dbus-utils.c deleted file mode 100644 index cf679daf9c..0000000000 --- a/libnm-core/nm-dbus-utils.c +++ /dev/null @@ -1,259 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-core-internal.h" - -typedef struct { - char * signal_name; - const GVariantType *signature; -} NMDBusSignalData; - -static void -dbus_signal_data_free(gpointer data, GClosure *closure) -{ - NMDBusSignalData *sd = data; - - g_free(sd->signal_name); - g_slice_free(NMDBusSignalData, sd); -} - -static void -dbus_signal_meta_marshal(GClosure * closure, - GValue * return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - NMDBusSignalData *sd = marshal_data; - const char * signal_name; - GVariant * parameters, *param; - GValue * closure_params; - gsize n_params, i; - - g_return_if_fail(n_param_values == 4); - - signal_name = g_value_get_string(¶m_values[2]); - parameters = g_value_get_variant(¶m_values[3]); - - if (strcmp(signal_name, sd->signal_name) != 0) - return; - - if (sd->signature) { - if (!g_variant_is_of_type(parameters, sd->signature)) { - g_warning("%p: got signal '%s' but parameters were of type '%s', not '%s'", - g_value_get_object(¶m_values[0]), - signal_name, - g_variant_get_type_string(parameters), - g_variant_type_peek_string(sd->signature)); - return; - } - - n_params = g_variant_n_children(parameters) + 1; - } else - n_params = 1; - - closure_params = g_new0(GValue, n_params); - g_value_init(&closure_params[0], G_TYPE_OBJECT); - g_value_copy(¶m_values[0], &closure_params[0]); - - for (i = 1; i < n_params; i++) { - param = g_variant_get_child_value(parameters, i - 1); - if (g_variant_is_of_type(param, G_VARIANT_TYPE("ay")) - || g_variant_is_of_type(param, G_VARIANT_TYPE("aay"))) { - /* g_dbus_gvariant_to_gvalue() thinks 'ay' means "non-UTF-8 NUL-terminated string" */ - g_value_init(&closure_params[i], G_TYPE_VARIANT); - g_value_set_variant(&closure_params[i], param); - } else - g_dbus_gvariant_to_gvalue(param, &closure_params[i]); - g_variant_unref(param); - } - - g_cclosure_marshal_generic(closure, NULL, n_params, closure_params, invocation_hint, NULL); - - for (i = 0; i < n_params; i++) - g_value_unset(&closure_params[i]); - g_free(closure_params); -} - -/** - * _nm_dbus_signal_connect_data: - * @proxy: a #GDBusProxy - * @signal_name: the D-Bus signal to connect to - * @signature: (allow-none): the signal's type signature (must be a tuple) - * @c_handler: the signal handler function - * @data: (allow-none): data to pass to @c_handler - * @destroy_data: (allow-none): closure destroy notify for @data - * @connect_flags: connection flags - * - * Connects to the D-Bus signal @signal_name on @proxy. @c_handler must be a - * void function whose first argument is a #GDBusProxy, followed by arguments - * for each element of @signature, ending with a #gpointer argument for @data. - * - * The argument types in @c_handler correspond to the types output by - * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular: - * - both 16-bit and 32-bit integers are passed as #int/#guint - * - 'as' values are passed as #GStrv (char **) - * - all other array, tuple, and dict types are passed as #GVariant - * - * If @signature is %NULL, then the signal's parameters will be ignored, and - * @c_handler should take only the #GDBusProxy and #gpointer arguments. - * - * Returns: the signal handler ID, which can be used with - * g_signal_handler_remove(). Beware that because of the way the signal is - * connected, you will not be able to remove it with - * g_signal_handlers_disconnect_by_func(), although - * g_signal_handlers_disconnect_by_data() will work correctly. - */ -gulong -_nm_dbus_signal_connect_data(GDBusProxy * proxy, - const char * signal_name, - const GVariantType *signature, - GCallback c_handler, - gpointer data, - GClosureNotify destroy_data, - GConnectFlags connect_flags) -{ - NMDBusSignalData *sd; - GClosure * closure; - gboolean swapped = !!(connect_flags & G_CONNECT_SWAPPED); - gboolean after = !!(connect_flags & G_CONNECT_AFTER); - - g_return_val_if_fail(G_IS_DBUS_PROXY(proxy), 0); - g_return_val_if_fail(signal_name != NULL, 0); - g_return_val_if_fail(signature == NULL || g_variant_type_is_tuple(signature), 0); - g_return_val_if_fail(c_handler != NULL, 0); - - sd = g_slice_new(NMDBusSignalData); - sd->signal_name = g_strdup(signal_name); - sd->signature = signature; - - closure = (swapped ? g_cclosure_new_swap : g_cclosure_new)(c_handler, data, destroy_data); - g_closure_set_marshal(closure, g_cclosure_marshal_generic); - g_closure_set_meta_marshal(closure, sd, dbus_signal_meta_marshal); - g_closure_add_finalize_notifier(closure, sd, dbus_signal_data_free); - - return g_signal_connect_closure(proxy, "g-signal", closure, after); -} - -/** - * _nm_dbus_signal_connect: - * @proxy: a #GDBusProxy - * @signal_name: the D-Bus signal to connect to - * @signature: the signal's type signature (must be a tuple) - * @c_handler: the signal handler function - * @data: (allow-none): data to pass to @c_handler - * - * Simplified version of _nm_dbus_signal_connect_data() with fewer arguments. - * - * Returns: the signal handler ID, as with _nm_signal_connect_data(). - */ - -/** - * _nm_dbus_typecheck_response: - * @response: the #GVariant response to check. - * @reply_type: the expected reply type. It may be %NULL to perform no - * checking. - * @error: (allow-none): the error in case the @reply_type does not match. - * - * Returns: %TRUE, if @response is of the expected @reply_type. - */ -gboolean -_nm_dbus_typecheck_response(GVariant *response, const GVariantType *reply_type, GError **error) -{ - g_return_val_if_fail(response, FALSE); - - if (!reply_type) - return TRUE; - if (g_variant_is_of_type(response, reply_type)) - return TRUE; - - /* This is the same error code that g_dbus_connection_call() returns if - * @reply_type doesn't match. - */ - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_INVALID_ARGUMENT, - _("Method returned type '%s', but expected '%s'"), - g_variant_get_type_string(response), - g_variant_type_peek_string(reply_type)); - return FALSE; -} - -/** - * _nm_dbus_proxy_call_finish: - * @proxy: A #GDBusProxy. - * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to - * g_dbus_proxy_call(). - * @reply_type: (allow-none): the expected type of the reply, or %NULL - * @error: Return location for error or %NULL. - * - * Finishes an operation started with g_dbus_proxy_call(), as with - * g_dbus_proxy_call_finish(), except thatif @reply_type is non-%NULL, then it - * will also check that the response matches that type signature, and return - * an error if not. - * - * Returns: %NULL if @error is set. Otherwise, a #GVariant tuple with - * return values. Free with g_variant_unref(). - */ -GVariant * -_nm_dbus_proxy_call_finish(GDBusProxy * proxy, - GAsyncResult * res, - const GVariantType *reply_type, - GError ** error) -{ - GVariant *variant; - - variant = g_dbus_proxy_call_finish(proxy, res, error); - if (variant && !_nm_dbus_typecheck_response(variant, reply_type, error)) - nm_clear_pointer(&variant, g_variant_unref); - return variant; -} - -GVariant * -_nm_dbus_connection_call_finish(GDBusConnection * dbus_connection, - GAsyncResult * result, - const GVariantType *reply_type, - GError ** error) -{ - GVariant *variant; - - variant = g_dbus_connection_call_finish(dbus_connection, result, error); - if (variant && !_nm_dbus_typecheck_response(variant, reply_type, error)) - nm_clear_pointer(&variant, g_variant_unref); - return variant; -} - -/** - * _nm_dbus_error_has_name: - * @error: (allow-none): a #GError, or %NULL - * @dbus_error_name: a D-Bus error name - * - * Checks if @error is set and corresponds to the D-Bus error @dbus_error_name. - * - * This should only be used for "foreign" D-Bus errors (eg, errors - * from BlueZ or wpa_supplicant). All NetworkManager D-Bus errors - * should be properly mapped by gdbus to one of the domains/codes in - * nm-errors.h. - * - * Returns: %TRUE or %FALSE - */ -gboolean -_nm_dbus_error_has_name(GError *error, const char *dbus_error_name) -{ - gboolean has_name = FALSE; - - if (error && g_dbus_error_is_remote_error(error)) { - char *error_name; - - error_name = g_dbus_error_get_remote_error(error); - has_name = !g_strcmp0(error_name, dbus_error_name); - g_free(error_name); - } - - return has_name; -} diff --git a/libnm-core/nm-default-libnm-core.h b/libnm-core/nm-default-libnm-core.h deleted file mode 100644 index 6eb84b947a..0000000000 --- a/libnm-core/nm-default-libnm-core.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_DEFAULT_LIBNM_CORE_H__ -#define __NM_DEFAULT_LIBNM_CORE_H__ - -/*****************************************************************************/ - -#include "nm-glib-aux/nm-default-glib-i18n-lib.h" - -#undef NETWORKMANAGER_COMPILATION -#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE - -/*****************************************************************************/ - -#include "nm-version.h" - -/*****************************************************************************/ - -#endif /* __NM_DEFAULT_LIBNM_CORE_H__ */ diff --git a/libnm-core/nm-errors.c b/libnm-core/nm-errors.c deleted file mode 100644 index 023926630a..0000000000 --- a/libnm-core/nm-errors.c +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2004 - 2014 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-errors.h" - -#include "nm-vpn-dbus-interface.h" -#include "nm-core-internal.h" - -NM_CACHED_QUARK_FCN("nm-agent-manager-error-quark", nm_agent_manager_error_quark); -NM_CACHED_QUARK_FCN("nm-connection-error-quark", nm_connection_error_quark); -NM_CACHED_QUARK_FCN("nm-crypto-error-quark", nm_crypto_error_quark); -NM_CACHED_QUARK_FCN("nm-device-error-quark", nm_device_error_quark); -NM_CACHED_QUARK_FCN("nm-secret-agent-error-quark", nm_secret_agent_error_quark); -NM_CACHED_QUARK_FCN("nm-settings-error-quark", nm_settings_error_quark); -NM_CACHED_QUARK_FCN("nm-vpn-plugin-error-quark", nm_vpn_plugin_error_quark); - -static void -register_error_domain(GQuark domain, const char *interface, GType enum_type) -{ - nm_auto_unref_gtypeclass GEnumClass *enum_class = g_type_class_ref(enum_type); - guint i; - - for (i = 0; i < enum_class->n_values; i++) { - const GEnumValue *e = &enum_class->values[i]; - char error_name[200]; - - nm_assert(e && e->value_nick && !strchr(e->value_nick, '-')); - - nm_sprintf_buf(error_name, "%s.%s", interface, e->value_nick); - if (!g_dbus_error_register_error(domain, e->value, error_name)) - nm_assert_not_reached(); - } -} - -void -_nm_dbus_errors_init(void) -{ - register_error_domain(NM_AGENT_MANAGER_ERROR, - NM_DBUS_INTERFACE_AGENT_MANAGER, - NM_TYPE_AGENT_MANAGER_ERROR); - register_error_domain(NM_CONNECTION_ERROR, - NM_DBUS_INTERFACE_SETTINGS_CONNECTION, - NM_TYPE_CONNECTION_ERROR); - register_error_domain(NM_DEVICE_ERROR, NM_DBUS_INTERFACE_DEVICE, NM_TYPE_DEVICE_ERROR); - register_error_domain(NM_MANAGER_ERROR, NM_DBUS_INTERFACE, NM_TYPE_MANAGER_ERROR); - register_error_domain(NM_SECRET_AGENT_ERROR, - NM_DBUS_INTERFACE_SECRET_AGENT, - NM_TYPE_SECRET_AGENT_ERROR); - register_error_domain(NM_SETTINGS_ERROR, NM_DBUS_INTERFACE_SETTINGS, NM_TYPE_SETTINGS_ERROR); - register_error_domain(NM_VPN_PLUGIN_ERROR, NM_DBUS_VPN_ERROR_PREFIX, NM_TYPE_VPN_PLUGIN_ERROR); -} diff --git a/libnm-core/nm-errors.h b/libnm-core/nm-errors.h deleted file mode 100644 index 639c508e3e..0000000000 --- a/libnm-core/nm-errors.h +++ /dev/null @@ -1,319 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2004 - 2014 Red Hat, Inc. - */ - -#ifndef __NM_ERRORS_H__ -#define __NM_ERRORS_H__ - -/** - * NMAgentManagerError: - * @NM_AGENT_MANAGER_ERROR_FAILED: unknown or unspecified error - * @NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED: The caller does not have permission - * to register a secret agent, or is trying to register the same secret agent - * twice. - * @NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER: The identifier is not a valid - * secret agent identifier. - * @NM_AGENT_MANAGER_ERROR_NOT_REGISTERED: The caller tried to unregister an agent - * that was not registered. - * @NM_AGENT_MANAGER_ERROR_NO_SECRETS: No secret agent returned secrets for this - * request - * @NM_AGENT_MANAGER_ERROR_USER_CANCELED: The user canceled the secrets request. - * - * Errors returned from the secret-agent manager. - * - * These errors may be returned from operations that could cause secrets to be - * requested (such as nm_client_activate_connection()), and correspond to D-Bus - * errors in the "org.freedesktop.NetworkManager.AgentManager" namespace. - */ -typedef enum { - NM_AGENT_MANAGER_ERROR_FAILED = 0, /*< nick=Failed >*/ - NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/ - NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER, /*< nick=InvalidIdentifier >*/ - NM_AGENT_MANAGER_ERROR_NOT_REGISTERED, /*< nick=NotRegistered >*/ - NM_AGENT_MANAGER_ERROR_NO_SECRETS, /*< nick=NoSecrets >*/ - NM_AGENT_MANAGER_ERROR_USER_CANCELED, /*< nick=UserCanceled >*/ -} NMAgentManagerError; - -GQuark nm_agent_manager_error_quark(void); -#define NM_AGENT_MANAGER_ERROR (nm_agent_manager_error_quark()) - -/** - * NMConnectionError: - * @NM_CONNECTION_ERROR_FAILED: unknown or unclassified error - * @NM_CONNECTION_ERROR_SETTING_NOT_FOUND: the #NMConnection object - * did not contain the specified #NMSetting object - * @NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND: the #NMConnection did not contain the - * requested #NMSetting property - * @NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET: an operation which requires a secret - * was attempted on a non-secret property - * @NM_CONNECTION_ERROR_MISSING_SETTING: the #NMConnection object is missing an - * #NMSetting which is required for its configuration. The error message will - * always be prefixed with "<setting-name>: ", where "<setting-name>" is the - * name of the setting that is missing. - * @NM_CONNECTION_ERROR_INVALID_SETTING: the #NMConnection object contains an - * invalid or inappropriate #NMSetting. The error message will always be - * prefixed with "<setting-name>: ", where "<setting-name>" is the name of the - * setting that is invalid. - * @NM_CONNECTION_ERROR_MISSING_PROPERTY: the #NMConnection object is invalid - * because it is missing a required property. The error message will always be - * prefixed with "<setting-name>.<property-name>: ", where "<setting-name>" is - * the name of the setting with the missing property, and "<property-name>" is - * the property that is missing. - * @NM_CONNECTION_ERROR_INVALID_PROPERTY: the #NMConnection object is invalid - * because a property has an invalid value. The error message will always be - * prefixed with "<setting-name>.<property-name>: ", where "<setting-name>" is - * the name of the setting with the invalid property, and "<property-name>" is - * the property that is invalid. - * - * Describes errors that may result from operations involving a #NMConnection - * or its #NMSettings. - * - * These errors may be returned directly from #NMConnection and #NMSetting - * methods, or may be returned from D-Bus operations (eg on #NMClient or - * #NMDevice), where they correspond to errors in the - * "org.freedesktop.NetworkManager.Settings.Connection" namespace. - */ -typedef enum { - NM_CONNECTION_ERROR_FAILED = 0, /*< nick=Failed >*/ - NM_CONNECTION_ERROR_SETTING_NOT_FOUND, /*< nick=SettingNotFound >*/ - NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND, /*< nick=PropertyNotFound >*/ - NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, /*< nick=PropertyNotSecret >*/ - NM_CONNECTION_ERROR_MISSING_SETTING, /*< nick=MissingSetting >*/ - NM_CONNECTION_ERROR_INVALID_SETTING, /*< nick=InvalidSetting >*/ - NM_CONNECTION_ERROR_MISSING_PROPERTY, /*< nick=MissingProperty >*/ - NM_CONNECTION_ERROR_INVALID_PROPERTY, /*< nick=InvalidProperty >*/ -} NMConnectionError; - -#define NM_CONNECTION_ERROR nm_connection_error_quark() -GQuark nm_connection_error_quark(void); - -/** - * NMCryptoError: - * @NM_CRYPTO_ERROR_FAILED: generic failure - * @NM_CRYPTO_ERROR_INVALID_DATA: the certificate or key data provided - * was invalid - * @NM_CRYPTO_ERROR_INVALID_PASSWORD: the password was invalid - * @NM_CRYPTO_ERROR_UNKNOWN_CIPHER: the data uses an unknown cipher - * @NM_CRYPTO_ERROR_DECRYPTION_FAILED: decryption failed - * @NM_CRYPTO_ERROR_ENCRYPTION_FAILED: encryption failed - * - * Cryptography-related errors that can be returned from some nm-utils methods, - * and some #NMSetting8021x operations. - */ -typedef enum { - NM_CRYPTO_ERROR_FAILED = 0, - NM_CRYPTO_ERROR_INVALID_DATA, - NM_CRYPTO_ERROR_INVALID_PASSWORD, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - NM_CRYPTO_ERROR_DECRYPTION_FAILED, - NM_CRYPTO_ERROR_ENCRYPTION_FAILED, -} NMCryptoError; - -#define NM_CRYPTO_ERROR nm_crypto_error_quark() -GQuark nm_crypto_error_quark(void); - -/** - * NMDeviceError: - * @NM_DEVICE_ERROR_FAILED: unknown or unclassified error - * @NM_DEVICE_ERROR_CREATION_FAILED: NetworkManager failed to create the device - * @NM_DEVICE_ERROR_INVALID_CONNECTION: the specified connection is not valid - * @NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION: the specified connection is not - * compatible with this device. - * @NM_DEVICE_ERROR_NOT_ACTIVE: the device does not have an active connection - * @NM_DEVICE_ERROR_NOT_SOFTWARE: the requested operation is only valid on - * software devices. - * @NM_DEVICE_ERROR_NOT_ALLOWED: the requested operation is not allowed at - * this time. - * @NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND: the "specific object" in the - * activation request (eg, the #NMAccessPoint or #NMWimaxNsp) was not - * found. - * @NM_DEVICE_ERROR_VERSION_ID_MISMATCH: the version id did not match. - * @NM_DEVICE_ERROR_MISSING_DEPENDENCIES: the requested operation could not - * be completed due to missing dependencies. - * @NM_DEVICE_ERROR_INVALID_ARGUMENT: invalid argument. Since: 1.16. - * - * Device-related errors. - * - * These errors may be returned directly from #NMDevice methods, or may be - * returned from D-Bus operations (where they correspond to errors in the - * "org.freedesktop.NetworkManager.Device" namespace). - */ -typedef enum { - NM_DEVICE_ERROR_FAILED = 0, /*< nick=Failed >*/ - NM_DEVICE_ERROR_CREATION_FAILED, /*< nick=CreationFailed >*/ - NM_DEVICE_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/ - NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, /*< nick=IncompatibleConnection >*/ - NM_DEVICE_ERROR_NOT_ACTIVE, /*< nick=NotActive >*/ - NM_DEVICE_ERROR_NOT_SOFTWARE, /*< nick=NotSoftware >*/ - NM_DEVICE_ERROR_NOT_ALLOWED, /*< nick=NotAllowed >*/ - NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, /*< nick=SpecificObjectNotFound >*/ - NM_DEVICE_ERROR_VERSION_ID_MISMATCH, /*< nick=VersionIdMismatch >*/ - NM_DEVICE_ERROR_MISSING_DEPENDENCIES, /*< nick=MissingDependencies >*/ - NM_DEVICE_ERROR_INVALID_ARGUMENT, /*< nick=InvalidArgument >*/ -} NMDeviceError; - -#define NM_DEVICE_ERROR nm_device_error_quark() -GQuark nm_device_error_quark(void); - -/** - * NMManagerError: - * @NM_MANAGER_ERROR_FAILED: unknown or unclassified error - * @NM_MANAGER_ERROR_PERMISSION_DENIED: Permission denied. - * @NM_MANAGER_ERROR_UNKNOWN_CONNECTION: The requested connection is not known. - * @NM_MANAGER_ERROR_UNKNOWN_DEVICE: The requested device is not known. - * @NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE: The requested connection cannot be - * activated at this time. - * @NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE: The request could not be completed - * because a required connection is not active. - * @NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE: The connection to be activated was - * already active on another device. - * @NM_MANAGER_ERROR_DEPENDENCY_FAILED: An activation request failed due to a - * dependency being unavailable. - * @NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE: The manager is already in the requested - * sleep/wake state. - * @NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED: The network is already - * enabled/disabled. - * @NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL: Unknown log level in SetLogging - * @NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN: Unknown log domain in SetLogging - * @NM_MANAGER_ERROR_INVALID_ARGUMENTS: Invalid arguments for D-Bus request - * @NM_MANAGER_ERROR_MISSING_PLUGIN: A plug-in was needed to complete the - * activation but is not available. - * - * Errors related to the main "network management" interface of NetworkManager. - * These may be returned from #NMClient methods that invoke D-Bus operations on - * the "org.freedesktop.NetworkManager" interface, and correspond to D-Bus - * errors in that namespace. - */ -typedef enum { - NM_MANAGER_ERROR_FAILED = 0, /*< nick=Failed >*/ - NM_MANAGER_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/ - NM_MANAGER_ERROR_UNKNOWN_CONNECTION, /*< nick=UnknownConnection >*/ - NM_MANAGER_ERROR_UNKNOWN_DEVICE, /*< nick=UnknownDevice >*/ - NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE, /*< nick=ConnectionNotAvailable >*/ - NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, /*< nick=ConnectionNotActive >*/ - NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, /*< nick=ConnectionAlreadyActive >*/ - NM_MANAGER_ERROR_DEPENDENCY_FAILED, /*< nick=DependencyFailed >*/ - NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE, /*< nick=AlreadyAsleepOrAwake >*/ - NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, /*< nick=AlreadyEnabledOrDisabled >*/ - NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL, /*< nick=UnknownLogLevel >*/ - NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN, /*< nick=UnknownLogDomain >*/ - NM_MANAGER_ERROR_INVALID_ARGUMENTS, /*< nick=InvalidArguments >*/ - NM_MANAGER_ERROR_MISSING_PLUGIN, /*< nick=MissingPlugin >*/ -} NMManagerError; - -GQuark nm_manager_error_quark(void); -#define NM_MANAGER_ERROR (nm_manager_error_quark()) - -/** - * NMSecretAgentError: - * @NM_SECRET_AGENT_ERROR_FAILED: unknown or unclassified error - * @NM_SECRET_AGENT_ERROR_PERMISSION_DENIED: the caller (ie, NetworkManager) is - * not authorized to make this request - * @NM_SECRET_AGENT_ERROR_INVALID_CONNECTION: the connection for which secrets - * were requested is invalid - * @NM_SECRET_AGENT_ERROR_USER_CANCELED: the request was canceled by the user - * @NM_SECRET_AGENT_ERROR_AGENT_CANCELED: the agent canceled the request - * because it was requested to do so by NetworkManager - * @NM_SECRET_AGENT_ERROR_NO_SECRETS: the agent cannot find any secrets for this - * connection - * - * #NMSecretAgentError values are passed by secret agents back to NetworkManager - * when they encounter problems retrieving secrets on behalf of NM. They - * correspond to errors in the "org.freedesktop.NetworkManager.SecretManager" - * namespace. - * - * Client APIs such as nm_client_activate_connection() will not see these error - * codes; instead, the secret agent manager will translate them to the - * corresponding #NMAgentManagerError codes. - */ -typedef enum { - NM_SECRET_AGENT_ERROR_FAILED = 0, /*< nick=Failed >*/ - NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/ - NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/ - NM_SECRET_AGENT_ERROR_USER_CANCELED, /*< nick=UserCanceled >*/ - NM_SECRET_AGENT_ERROR_AGENT_CANCELED, /*< nick=AgentCanceled >*/ - NM_SECRET_AGENT_ERROR_NO_SECRETS, /*< nick=NoSecrets >*/ -} NMSecretAgentError; - -GQuark nm_secret_agent_error_quark(void); -#define NM_SECRET_AGENT_ERROR (nm_secret_agent_error_quark()) - -/** - * NMSettingsError: - * @NM_SETTINGS_ERROR_FAILED: unknown or unclassified error - * @NM_SETTINGS_ERROR_PERMISSION_DENIED: permission denied - * @NM_SETTINGS_ERROR_NOT_SUPPORTED: the requested operation is not supported by any - * active settings backend - * @NM_SETTINGS_ERROR_INVALID_CONNECTION: the connection was invalid - * @NM_SETTINGS_ERROR_READ_ONLY_CONNECTION: attempted to modify a read-only connection - * @NM_SETTINGS_ERROR_UUID_EXISTS: a connection with that UUID already exists - * @NM_SETTINGS_ERROR_INVALID_HOSTNAME: attempted to set an invalid hostname - * @NM_SETTINGS_ERROR_INVALID_ARGUMENTS: invalid arguments - * - * Errors related to the settings/persistent configuration interface of - * NetworkManager. - * - * These may be returned from #NMClient methods that invoke D-Bus operations on - * the "org.freedesktop.NetworkManager.Settings" interface, and correspond to - * D-Bus errors in that namespace. - */ -typedef enum { - NM_SETTINGS_ERROR_FAILED = 0, /*< nick=Failed >*/ - NM_SETTINGS_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/ - NM_SETTINGS_ERROR_NOT_SUPPORTED, /*< nick=NotSupported >*/ - NM_SETTINGS_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/ - NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, /*< nick=ReadOnlyConnection >*/ - NM_SETTINGS_ERROR_UUID_EXISTS, /*< nick=UuidExists >*/ - NM_SETTINGS_ERROR_INVALID_HOSTNAME, /*< nick=InvalidHostname >*/ - NM_SETTINGS_ERROR_INVALID_ARGUMENTS, /*< nick=InvalidArguments >*/ -} NMSettingsError; - -GQuark nm_settings_error_quark(void); -#define NM_SETTINGS_ERROR (nm_settings_error_quark()) - -/** - * NMVpnPluginError: - * @NM_VPN_PLUGIN_ERROR_FAILED: unknown or unclassified error - * @NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS: the plugin is already starting, - * and another connect request was received - * @NM_VPN_PLUGIN_ERROR_ALREADY_STARTED: the plugin is already connected, and - * another connect request was received - * @NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS: the plugin is already stopping, - * and another stop request was received - * @NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED: the plugin is already stopped, and - * another disconnect request was received - * @NM_VPN_PLUGIN_ERROR_WRONG_STATE: the operation could not be performed in - * this state - * @NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS: the operation could not be performed as - * the request contained malformed arguments, or arguments of unexpected type. - * Usually means that one of the VPN setting data items or secrets was not of - * the expected type (ie int, string, bool, etc). - * @NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED: a child process failed to launch - * @NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION: the operation could not be performed - * because the connection was invalid. Usually means that the connection's - * VPN setting was missing some required data item or secret. - * @NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED: the operation could not be - * performed as the plugin does not support interactive operations, such as - * ConnectInteractive() or NewSecrets() - * - * Returned by the VPN service plugin to indicate errors. These codes correspond - * to errors in the "org.freedesktop.NetworkManager.VPN.Error" namespace. - **/ -typedef enum { - NM_VPN_PLUGIN_ERROR_FAILED, /*< nick=Failed >*/ - NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, /*< nick=StartingInProgress >*/ - NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, /*< nick=AlreadyStarted >*/ - NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, /*< nick=StoppingInProgress >*/ - NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, /*< nick=AlreadyStopped >*/ - NM_VPN_PLUGIN_ERROR_WRONG_STATE, /*< nick=WrongState >*/ - NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, /*< nick=BadArguments >*/ - NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, /*< nick=LaunchFailed >*/ - NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/ - NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, /*< nick=InteractiveNotSupported >*/ -} NMVpnPluginError; - -#define NM_VPN_PLUGIN_ERROR (nm_vpn_plugin_error_quark()) -GQuark nm_vpn_plugin_error_quark(void); - -#endif /* __NM_ERRORS_H__ */ diff --git a/libnm-core/nm-keyfile-internal.h b/libnm-core/nm-keyfile-internal.h deleted file mode 100644 index bb89214c5e..0000000000 --- a/libnm-core/nm-keyfile-internal.h +++ /dev/null @@ -1,124 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_KEYFILE_INTERNAL_H__ -#define __NM_KEYFILE_INTERNAL_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) - #error Cannot use this header. -#endif - -#include - -#include "nm-keyfile.h" - -#include "nm-connection.h" -#include "nm-setting-8021x.h" - -#include "nm-core-internal.h" - -/*****************************************************************************/ - -#define NM_KEYFILE_CERT_SCHEME_PREFIX_PATH "file://" -#define NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11 "pkcs11:" -#define NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB "data:;base64," - -char *nm_keyfile_detect_unqualified_path_scheme(const char * base_dir, - gconstpointer pdata, - gsize data_len, - gboolean consider_exists, - gboolean * out_exists); - -gboolean nm_keyfile_read_ensure_id(NMConnection *connection, const char *fallback_id); - -gboolean nm_keyfile_read_ensure_uuid(NMConnection *connection, const char *fallback_uuid_seed); - -/*****************************************************************************/ - -/** - * NMKeyfileHandlerDataWarn: - * - * this struct is passed as @handler_data for the @NMKeyfileReadHandler of - * type %NM_KEYFILE_HANDLER_TYPE_WARN. - */ -typedef struct { - NMKeyfileWarnSeverity severity; - char * message; - const char * fmt; - va_list ap; -} NMKeyfileHandlerDataWarn; - -/** - * NMKeyfileHandlerDataWriteCert: - * - * this struct is passed as @handler_data for the @NMKeyfileWriteHandler of - * type %NM_KEYFILE_HANDLER_TYPE_WRITE_CERT. - */ -typedef struct { - const NMSetting8021xSchemeVtable *vtable; -} NMKeyfileHandlerDataWriteCert; - -struct _NMKeyfileHandlerData { - NMKeyfileHandlerType type; - - GError **p_error; - - const char *kf_group_name; - const char *kf_key; - - NMSetting * cur_setting; - const char *cur_property; - - union { - NMKeyfileHandlerDataWarn warn; - NMKeyfileHandlerDataWriteCert write_cert; - }; -}; - -/*****************************************************************************/ - -const char *_nm_keyfile_handler_data_warn_get_message(const NMKeyfileHandlerData *handler_data); - -/*****************************************************************************/ - -char * -nm_keyfile_plugin_kf_get_string(GKeyFile *kf, const char *group, const char *key, GError **error); -void nm_keyfile_plugin_kf_set_string(GKeyFile * kf, - const char *group, - const char *key, - const char *value); - -int nm_key_file_get_boolean(GKeyFile *kf, const char *group, const char *key, int default_value); - -void _nm_keyfile_copy(GKeyFile *dst, GKeyFile *src); -gboolean _nm_keyfile_a_contains_all_in_b(GKeyFile *kf_a, GKeyFile *kf_b); -gboolean _nm_keyfile_equals(GKeyFile *kf_a, GKeyFile *kf_b, gboolean consider_order); -gboolean _nm_keyfile_has_values(GKeyFile *keyfile); - -/*****************************************************************************/ - -#define NM_KEYFILE_GROUP_NMMETA ".nmmeta" -#define NM_KEYFILE_KEY_NMMETA_NM_GENERATED "nm-generated" -#define NM_KEYFILE_KEY_NMMETA_VOLATILE "volatile" -#define NM_KEYFILE_KEY_NMMETA_EXTERNAL "external" -#define NM_KEYFILE_KEY_NMMETA_SHADOWED_STORAGE "shadowed-storage" -#define NM_KEYFILE_KEY_NMMETA_SHADOWED_OWNED "shadowed-owned" - -#define NM_KEYFILE_PATH_NAME_LIB NMLIBDIR "/system-connections" -#define NM_KEYFILE_PATH_NAME_ETC_DEFAULT NMCONFDIR "/system-connections" -#define NM_KEYFILE_PATH_NAME_RUN NMRUNDIR "/system-connections" - -#define NM_KEYFILE_PATH_SUFFIX_NMCONNECTION ".nmconnection" - -#define NM_KEYFILE_PATH_SUFFIX_NMMETA ".nmmeta" - -#define NM_KEYFILE_PATH_NMMETA_SYMLINK_NULL "/dev/null" - -gboolean nm_keyfile_utils_ignore_filename(const char *filename, gboolean require_extension); - -char *nm_keyfile_utils_create_filename(const char *filename, gboolean with_extension); - -#endif /* __NM_KEYFILE_INTERNAL_H__ */ diff --git a/libnm-core/nm-keyfile-utils.c b/libnm-core/nm-keyfile-utils.c deleted file mode 100644 index 8de4b0d257..0000000000 --- a/libnm-core/nm-keyfile-utils.c +++ /dev/null @@ -1,684 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2010 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-keyfile-utils.h" - -#include - -#include "nm-glib-aux/nm-str-buf.h" - -#include "nm-keyfile.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireless.h" -#include "nm-setting-wireless-security.h" - -#include "nm-keyfile-internal.h" - -/*****************************************************************************/ - -/** - * nm_key_file_get_boolean: - * @kf: the #GKeyFile - * @group: the group - * @key: the key - * @default_value: the default value if the value is set or not parsable as a boolean. - * - * Replacement for g_key_file_get_boolean() (which uses g_key_file_parse_value_as_boolean()). - * g_key_file_get_boolean() seems odd to me, because it accepts trailing ASCII whitespace, - * but not leading. - * This uses _nm_utils_ascii_str_to_bool(), which accepts trailing and leading whitespace, - * case-insensitive words, and also strings like "on" and "off". - * _nm_utils_ascii_str_to_bool() is our way to parse booleans from string, and we should - * use that one consistently. - * - * Also, it doesn't have g_key_file_get_boolean()'s odd API to require an error argument - * to detect parsing failures. - * - * Returns: either %TRUE or %FALSE if the key exists and is parsable as a boolean. - * Otherwise, @default_value. Sets errno to ENODATA, EINVAL or 0, depending on whether - * the key exists, whether the value is invalid, or success. - */ -int -nm_key_file_get_boolean(GKeyFile *kf, const char *group, const char *key, int default_value) -{ - int v; - gs_free char *value = NULL; - - value = g_key_file_get_value(kf, group, key, NULL); - - if (!value) { - errno = ENODATA; - return default_value; - } - v = _nm_utils_ascii_str_to_bool(value, -1); - if (v != -1) { - errno = 0; - return v; - } - errno = EINVAL; - return default_value; -} - -/*****************************************************************************/ - -typedef struct { - const char *setting; - const char *alias; -} SettingAlias; - -static const SettingAlias alias_list[] = { - {NM_SETTING_WIRED_SETTING_NAME, "ethernet"}, - {NM_SETTING_WIRELESS_SETTING_NAME, "wifi"}, - {NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, "wifi-security"}, -}; - -const char * -nm_keyfile_plugin_get_alias_for_setting_name(const char *setting_name) -{ - guint i; - - g_return_val_if_fail(setting_name != NULL, NULL); - - for (i = 0; i < G_N_ELEMENTS(alias_list); i++) { - if (nm_streq(setting_name, alias_list[i].setting)) - return alias_list[i].alias; - } - return NULL; -} - -const char * -nm_keyfile_plugin_get_setting_name_for_alias(const char *alias) -{ - guint i; - - g_return_val_if_fail(alias != NULL, NULL); - - for (i = 0; i < G_N_ELEMENTS(alias_list); i++) { - if (nm_streq(alias, alias_list[i].alias)) - return alias_list[i].setting; - } - return NULL; -} - -/*****************************************************************************/ - -char ** -nm_keyfile_plugin_kf_get_string_list(GKeyFile * kf, - const char *group, - const char *key, - gsize * out_length, - GError ** error) -{ - char ** list; - const char *alias; - GError * local = NULL; - gsize l; - - list = g_key_file_get_string_list(kf, group, key, &l, &local); - if (nm_g_error_matches(local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { - alias = nm_keyfile_plugin_get_alias_for_setting_name(group); - if (alias) { - g_clear_error(&local); - list = g_key_file_get_string_list(kf, alias, key, &l, &local); - } - } - if (local) - g_propagate_error(error, local); - if (!list) - l = 0; - NM_SET_OUT(out_length, l); - return list; -} - -guint * -nm_keyfile_plugin_kf_get_integer_list_uint(GKeyFile * key_file, - const char *group_name, - const char *key, - gsize * out_length, - GError ** error) -{ - GError * key_file_error = NULL; - gs_strfreev char **values = NULL; - gs_free guint *int_values = NULL; - gsize i, num_ints; - - NM_SET_OUT(out_length, 0); - - g_return_val_if_fail(key_file != NULL, NULL); - g_return_val_if_fail(group_name != NULL, NULL); - g_return_val_if_fail(key != NULL, NULL); - - values = - nm_keyfile_plugin_kf_get_string_list(key_file, group_name, key, &num_ints, &key_file_error); - - if (key_file_error) - g_propagate_error(error, key_file_error); - if (!values) - return NULL; - - int_values = g_new(guint, num_ints); - - for (i = 0; i < num_ints; i++) { - gint64 v; - - G_STATIC_ASSERT_EXPR(sizeof(v) > sizeof(guint)); - v = _nm_utils_ascii_str_to_int64(values[i], 10, 0, G_MAXUINT, -1); - if (v == -1) { - g_set_error(error, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("Value cannot be interpreted as a list of numbers.")); - return NULL; - } - - int_values[i] = v; - } - - NM_SET_OUT(out_length, num_ints); - return g_steal_pointer(&int_values); -} - -void -nm_keyfile_plugin_kf_set_string_list(GKeyFile * kf, - const char * group, - const char * key, - const char *const *list, - gsize length) -{ - const char *alias; - - alias = nm_keyfile_plugin_get_alias_for_setting_name(group); - g_key_file_set_string_list(kf, alias ?: group, key, list, length); -} - -void -nm_keyfile_plugin_kf_set_integer_list_uint(GKeyFile * kf, - const char * group, - const char * key, - const guint *data, - gsize length) -{ - nm_auto_str_buf NMStrBuf strbuf = {}; - gsize i; - - g_return_if_fail(kf); - g_return_if_fail(!length || data); - g_return_if_fail(group && group[0]); - g_return_if_fail(key && key[0]); - - nm_str_buf_init(&strbuf, length * 4u + 2u, FALSE); - for (i = 0; i < length; i++) - nm_str_buf_append_printf(&strbuf, "%u;", data[i]); - nm_keyfile_plugin_kf_set_value(kf, group, key, nm_str_buf_get_str(&strbuf)); -} - -void -nm_keyfile_plugin_kf_set_integer_list_uint8(GKeyFile * kf, - const char * group, - const char * key, - const guint8 *data, - gsize length) -{ - nm_auto_str_buf NMStrBuf strbuf = {}; - gsize i; - - g_return_if_fail(kf); - g_return_if_fail(!length || data); - g_return_if_fail(group && group[0]); - g_return_if_fail(key && key[0]); - - nm_str_buf_init(&strbuf, length * 4u + 2u, FALSE); - for (i = 0; i < length; i++) - nm_str_buf_append_printf(&strbuf, "%u;", (guint) data[i]); - nm_keyfile_plugin_kf_set_value(kf, group, key, nm_str_buf_get_str(&strbuf)); -} - -#define DEFINE_KF_WRAPPER_GET(fcn_name, get_ctype, key_file_get_fcn) \ - get_ctype fcn_name(GKeyFile *kf, const char *group, const char *key, GError **error) \ - { \ - get_ctype val; \ - const char *alias; \ - GError * local = NULL; \ - \ - val = key_file_get_fcn(kf, group, key, &local); \ - if (nm_g_error_matches(local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \ - alias = nm_keyfile_plugin_get_alias_for_setting_name(group); \ - if (alias) { \ - g_clear_error(&local); \ - val = key_file_get_fcn(kf, alias, key, &local); \ - } \ - } \ - if (local) \ - g_propagate_error(error, local); \ - return val; \ - } - -DEFINE_KF_WRAPPER_GET(nm_keyfile_plugin_kf_get_string, char *, g_key_file_get_string); -DEFINE_KF_WRAPPER_GET(nm_keyfile_plugin_kf_get_boolean, gboolean, g_key_file_get_boolean); -DEFINE_KF_WRAPPER_GET(nm_keyfile_plugin_kf_get_value, char *, g_key_file_get_value); - -#define DEFINE_KF_WRAPPER_SET(fcn_name, set_ctype, key_file_set_fcn) \ - void fcn_name(GKeyFile *kf, const char *group, const char *key, set_ctype value) \ - { \ - const char *alias; \ - \ - alias = nm_keyfile_plugin_get_alias_for_setting_name(group); \ - key_file_set_fcn(kf, alias ?: group, key, value); \ - } - -DEFINE_KF_WRAPPER_SET(nm_keyfile_plugin_kf_set_string, const char *, g_key_file_set_string); -DEFINE_KF_WRAPPER_SET(nm_keyfile_plugin_kf_set_boolean, gboolean, g_key_file_set_boolean); -DEFINE_KF_WRAPPER_SET(nm_keyfile_plugin_kf_set_value, const char *, g_key_file_set_value); - -gint64 -nm_keyfile_plugin_kf_get_int64(GKeyFile * kf, - const char *group, - const char *key, - guint base, - gint64 min, - gint64 max, - gint64 fallback, - GError ** error) -{ - gs_free char *s = NULL; - int errsv; - gint64 v; - - s = nm_keyfile_plugin_kf_get_value(kf, group, key, error); - if (!s) { - errno = ENODATA; - return fallback; - } - - v = _nm_utils_ascii_str_to_int64(s, base, min, max, fallback); - errsv = errno; - if (errsv != 0 && error) { - g_set_error(error, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("value is not an integer in range [%lld, %lld]"), - (long long) min, - (long long) max); - errno = errsv; - } - return v; -} - -char ** -nm_keyfile_plugin_kf_get_keys(GKeyFile *kf, const char *group, gsize *out_length, GError **error) -{ - char ** keys; - const char *alias; - GError * local = NULL; - gsize l; - - keys = g_key_file_get_keys(kf, group, &l, &local); - if (nm_g_error_matches(local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { - alias = nm_keyfile_plugin_get_alias_for_setting_name(group); - if (alias) { - g_clear_error(&local); - keys = g_key_file_get_keys(kf, alias, &l, error ? &local : NULL); - } - } - nm_assert((!local) != (!keys)); - if (!keys) - l = 0; - nm_assert(l == NM_PTRARRAY_LEN(keys)); - NM_SET_OUT(out_length, l); - if (local) - g_propagate_error(error, local); - return keys; -} - -gboolean -nm_keyfile_plugin_kf_has_key(GKeyFile *kf, const char *group, const char *key, GError **error) -{ - gboolean has; - const char *alias; - GError * local = NULL; - - has = g_key_file_has_key(kf, group, key, &local); - if (nm_g_error_matches(local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { - alias = nm_keyfile_plugin_get_alias_for_setting_name(group); - if (alias) { - g_clear_error(&local); - has = g_key_file_has_key(kf, alias, key, &local); - } - } - if (local) - g_propagate_error(error, local); - return has; -} - -/*****************************************************************************/ - -void -_nm_keyfile_copy(GKeyFile *dst, GKeyFile *src) -{ - gs_strfreev char **groups = NULL; - guint g, k; - - groups = g_key_file_get_groups(src, NULL); - for (g = 0; groups && groups[g]; g++) { - const char * group = groups[g]; - gs_strfreev char **keys = NULL; - - keys = g_key_file_get_keys(src, group, NULL, NULL); - if (!keys) - continue; - - for (k = 0; keys[k]; k++) { - const char * key = keys[k]; - gs_free char *value = NULL; - - value = g_key_file_get_value(src, group, key, NULL); - if (value) - g_key_file_set_value(dst, group, key, value); - else - g_key_file_remove_key(dst, group, key, NULL); - } - } -} - -/*****************************************************************************/ - -gboolean -_nm_keyfile_a_contains_all_in_b(GKeyFile *kf_a, GKeyFile *kf_b) -{ - gs_strfreev char **groups = NULL; - guint i, j; - - if (kf_a == kf_b) - return TRUE; - if (!kf_a || !kf_b) - return FALSE; - - groups = g_key_file_get_groups(kf_a, NULL); - for (i = 0; groups && groups[i]; i++) { - gs_strfreev char **keys = NULL; - - keys = g_key_file_get_keys(kf_a, groups[i], NULL, NULL); - if (!keys) - continue; - - for (j = 0; keys[j]; j++) { - gs_free char *key_a = g_key_file_get_value(kf_a, groups[i], keys[j], NULL); - gs_free char *key_b = g_key_file_get_value(kf_b, groups[i], keys[j], NULL); - - if (g_strcmp0(key_a, key_b) != 0) - return FALSE; - } - } - return TRUE; -} - -static gboolean -_nm_keyfile_equals_ordered(GKeyFile *kf_a, GKeyFile *kf_b) -{ - gs_strfreev char **groups = NULL; - gs_strfreev char **groups_b = NULL; - guint i, j; - - if (kf_a == kf_b) - return TRUE; - if (!kf_a || !kf_b) - return FALSE; - - groups = g_key_file_get_groups(kf_a, NULL); - groups_b = g_key_file_get_groups(kf_b, NULL); - if (!groups && !groups_b) - return TRUE; - if (!groups || !groups_b) - return FALSE; - for (i = 0; groups[i] && groups_b[i] && !strcmp(groups[i], groups_b[i]); i++) - ; - if (groups[i] || groups_b[i]) - return FALSE; - - for (i = 0; groups[i]; i++) { - gs_strfreev char **keys = NULL; - gs_strfreev char **keys_b = NULL; - - keys = g_key_file_get_keys(kf_a, groups[i], NULL, NULL); - keys_b = g_key_file_get_keys(kf_b, groups[i], NULL, NULL); - - if ((!keys) != (!keys_b)) - return FALSE; - if (!keys) - continue; - - for (j = 0; keys[j] && keys_b[j] && !strcmp(keys[j], keys_b[j]); j++) - ; - if (keys[j] || keys_b[j]) - return FALSE; - - for (j = 0; keys[j]; j++) { - gs_free char *key_a = g_key_file_get_value(kf_a, groups[i], keys[j], NULL); - gs_free char *key_b = g_key_file_get_value(kf_b, groups[i], keys[j], NULL); - - if (g_strcmp0(key_a, key_b) != 0) - return FALSE; - } - } - return TRUE; -} - -gboolean -_nm_keyfile_equals(GKeyFile *kf_a, GKeyFile *kf_b, gboolean consider_order) -{ - if (!consider_order) { - return _nm_keyfile_a_contains_all_in_b(kf_a, kf_b) - && _nm_keyfile_a_contains_all_in_b(kf_b, kf_a); - } else { - return _nm_keyfile_equals_ordered(kf_a, kf_b); - } -} - -gboolean -_nm_keyfile_has_values(GKeyFile *keyfile) -{ - gs_strfreev char **groups = NULL; - - g_return_val_if_fail(keyfile, FALSE); - - groups = g_key_file_get_groups(keyfile, NULL); - return groups && groups[0]; -} - -/*****************************************************************************/ - -static const char * -_keyfile_key_encode(const char *name, char **out_to_free) -{ - NMStrBuf str; - gsize len; - gsize i; - - nm_assert(name); - nm_assert(out_to_free && !*out_to_free); - - /* See g_key_file_is_key_name(). - * - * GKeyFile allows all UTF-8 characters (even non-well formed sequences), - * except: - * - no empty keys - * - no leading/trailing ' ' - * - no '=', '[', ']' - * - * We do something more strict here. All non-ASCII characters, all non-printable - * characters, and all invalid characters are escaped with "\\XX". - * - * We don't escape \\, unless it is followed by two hex digits. - */ - - if (!name[0]) { - /* empty keys are backslash encoded. Note that usually - * \\00 is not a valid encode, the only exception is the empty - * word. */ - return "\\00"; - } - - /* find the first character that needs escaping. */ - i = 0; - if (name[0] != ' ') { - for (;; i++) { - const guchar ch = (guchar) name[i]; - - if (ch == '\0') - return name; - - if (ch < 0x20 || ch >= 127 || NM_IN_SET(ch, '=', '[', ']') - || (ch == '\\' && g_ascii_isxdigit(name[i + 1]) && g_ascii_isxdigit(name[i + 2])) - || (ch == ' ' && name[i + 1] == '\0')) - break; - } - } else if (name[1] == '\0') - return "\\20"; - - len = i + strlen(&name[i]); - nm_assert(len == strlen(name)); - - nm_str_buf_init(&str, len + 15u, FALSE); - - if (name[0] == ' ') { - nm_assert(i == 0); - nm_str_buf_append(&str, "\\20"); - i = 1; - } else - nm_str_buf_append_len(&str, name, i); - - for (;; i++) { - const guchar ch = (guchar) name[i]; - - if (ch == '\0') - break; - - if (ch < 0x20 || ch >= 127 || NM_IN_SET(ch, '=', '[', ']') - || (ch == '\\' && g_ascii_isxdigit(name[i + 1]) && g_ascii_isxdigit(name[i + 2])) - || (ch == ' ' && name[i + 1] == '\0')) { - nm_str_buf_append_c(&str, '\\'); - nm_str_buf_append_c_hex(&str, ch, TRUE); - } else - nm_str_buf_append_c(&str, (char) ch); - } - - return (*out_to_free = nm_str_buf_finalize(&str, NULL)); -} - -static const char * -_keyfile_key_decode(const char *key, char **out_to_free) -{ - char *out; - gsize len; - gsize i; - gsize j; - - nm_assert(key); - nm_assert(out_to_free && !*out_to_free); - - if (!key[0]) - return ""; - - for (i = 0; TRUE; i++) { - const char ch = key[i]; - - if (ch == '\0') - return key; - if (ch == '\\' && g_ascii_isxdigit(key[i + 1]) && g_ascii_isxdigit(key[i + 2])) - break; - } - - len = i + strlen(&key[i]); - - if (len == 3 && nm_streq(key, "\\00")) - return ""; - - nm_assert(len == strlen(key)); - - out = g_new(char, len + 1u); - - memcpy(out, key, sizeof(char) * i); - - j = i; - for (;;) { - const char ch = key[i]; - char ch1, ch2; - unsigned v; - - if (ch == '\0') - break; - - if (ch == '\\' && g_ascii_isxdigit((ch1 = key[i + 1])) - && g_ascii_isxdigit((ch2 = key[i + 2]))) { - v = (g_ascii_xdigit_value(ch1) << 4) + g_ascii_xdigit_value(ch2); - if (v != 0) { - out[j++] = (char) v; - i += 3; - continue; - } - } - out[j++] = ch; - i++; - } - - nm_assert(j <= len); - out[j] = '\0'; - return (*out_to_free = out); -} - -/*****************************************************************************/ - -const char * -nm_keyfile_key_encode(const char *name, char **out_to_free) -{ - const char *key; - - key = _keyfile_key_encode(name, out_to_free); -#if NM_MORE_ASSERTS > 5 - nm_assert(key); - nm_assert(!*out_to_free || key == *out_to_free); - nm_assert(!*out_to_free || !nm_streq0(name, key)); - { - gs_free char *to_free2 = NULL; - const char * name2; - - name2 = _keyfile_key_decode(key, &to_free2); - /* name2, the result of encode()+decode() is identical to name. - * That is because - * - encode() is a injective function. - * - decode() is a surjective function, however for output - * values of encode() is behaves injective too. */ - nm_assert(nm_streq0(name2, name)); - } -#endif - return key; -} - -const char * -nm_keyfile_key_decode(const char *key, char **out_to_free) -{ - const char *name; - - name = _keyfile_key_decode(key, out_to_free); -#if NM_MORE_ASSERTS > 5 - nm_assert(name); - nm_assert(!*out_to_free || name == *out_to_free); - { - gs_free char *to_free2 = NULL; - const char * key2; - - key2 = _keyfile_key_encode(name, &to_free2); - /* key2, the result of decode+encode may not be identical - * to the original key. That is, decode() is a surjective - * function mapping different keys to the same name. - * However, decode() behaves injective for input that - * are valid output of encode(). */ - nm_assert(key2); - } -#endif - return name; -} diff --git a/libnm-core/nm-keyfile-utils.h b/libnm-core/nm-keyfile-utils.h deleted file mode 100644 index 1555c11244..0000000000 --- a/libnm-core/nm-keyfile-utils.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2010 - 2015 Red Hat, Inc. - */ - -#ifndef __NM_KEYFILE_UTILS_H__ -#define __NM_KEYFILE_UTILS_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) - #error Cannot use this header. -#endif - -/*****************************************************************************/ - -#include "nm-glib-aux/nm-shared-utils.h" - -/*****************************************************************************/ - -#define NM_KEYFILE_GROUP_VPN_SECRETS "vpn-secrets" -#define NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER "wireguard-peer." - -#define nm_keyfile_error_is_not_found(error) \ - nm_g_error_matches(error, \ - G_KEY_FILE_ERROR, \ - G_KEY_FILE_ERROR_GROUP_NOT_FOUND, \ - G_KEY_FILE_ERROR_KEY_NOT_FOUND) - -const char *nm_keyfile_plugin_get_alias_for_setting_name(const char *setting_name); - -const char *nm_keyfile_plugin_get_setting_name_for_alias(const char *alias); - -/*****************************************************************************/ - -guint *nm_keyfile_plugin_kf_get_integer_list_uint(GKeyFile * kf, - const char *group, - const char *key, - gsize * out_length, - GError ** error); -char **nm_keyfile_plugin_kf_get_string_list(GKeyFile * kf, - const char *group, - const char *key, - gsize * out_length, - GError ** error); -char * -nm_keyfile_plugin_kf_get_string(GKeyFile *kf, const char *group, const char *key, GError **error); -gboolean -nm_keyfile_plugin_kf_get_boolean(GKeyFile *kf, const char *group, const char *key, GError **error); -char * -nm_keyfile_plugin_kf_get_value(GKeyFile *kf, const char *group, const char *key, GError **error); - -void nm_keyfile_plugin_kf_set_integer_list_uint8(GKeyFile * kf, - const char * group, - const char * key, - const guint8 *list, - gsize length); -void nm_keyfile_plugin_kf_set_integer_list_uint(GKeyFile * kf, - const char * group, - const char * key, - const guint *list, - gsize length); -void nm_keyfile_plugin_kf_set_string_list(GKeyFile * kf, - const char * group, - const char * key, - const char *const *list, - gsize length); - -void nm_keyfile_plugin_kf_set_string(GKeyFile * kf, - const char *group, - const char *key, - const char *value); -void -nm_keyfile_plugin_kf_set_boolean(GKeyFile *kf, const char *group, const char *key, gboolean value); -void -nm_keyfile_plugin_kf_set_value(GKeyFile *kf, const char *group, const char *key, const char *value); - -gint64 nm_keyfile_plugin_kf_get_int64(GKeyFile * kf, - const char *group, - const char *key, - guint base, - gint64 min, - gint64 max, - gint64 fallback, - GError ** error); - -char ** -nm_keyfile_plugin_kf_get_keys(GKeyFile *kf, const char *group, gsize *out_length, GError **error); - -gboolean -nm_keyfile_plugin_kf_has_key(GKeyFile *kf, const char *group, const char *key, GError **error); - -const char *nm_keyfile_key_encode(const char *name, char **out_to_free); - -const char *nm_keyfile_key_decode(const char *key, char **out_to_free); - -#endif /* __NM_KEYFILE_UTILS_H__ */ diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c deleted file mode 100644 index c9c8cf8966..0000000000 --- a/libnm-core/nm-keyfile.c +++ /dev/null @@ -1,4443 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2008 - 2009 Novell, Inc. - * Copyright (C) 2008 - 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-keyfile-internal.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-glib-aux/nm-str-buf.h" -#include "nm-glib-aux/nm-secret-utils.h" -#include "systemd/nm-sd-utils-shared.h" -#include "nm-libnm-core-intern/nm-common-macros.h" - -#include "nm-core-internal.h" -#include "nm-keyfile.h" -#include "nm-setting-user.h" -#include "nm-setting-ovs-external-ids.h" - -#include "nm-keyfile-utils.h" - -#define ETHERNET_S390_OPTIONS_GROUP_NAME "ethernet-s390-options" - -#define OVS_EXTERNAL_IDS_DATA_PREFIX "data." - -/*****************************************************************************/ - -typedef struct _ParseInfoProperty ParseInfoProperty; - -typedef struct { - NMConnection * connection; - GKeyFile * keyfile; - const char * base_dir; - NMKeyfileReadHandler read_handler; - void * user_data; - GError * error; - const char * group; - NMSetting * setting; -} KeyfileReaderInfo; - -typedef struct { - NMConnection * connection; - GKeyFile * keyfile; - GError * error; - NMKeyfileWriteHandler write_handler; - void * user_data; -} KeyfileWriterInfo; - -/*****************************************************************************/ - -static void -_key_file_handler_data_init(NMKeyfileHandlerData *handler_data, - NMKeyfileHandlerType handler_type, - const char * kf_group_name, - const char * kf_key, - NMSetting * cur_setting, - const char * cur_property, - GError ** p_error) -{ - nm_assert(handler_data); - nm_assert(p_error && !*p_error); - - handler_data->type = handler_type; - handler_data->p_error = p_error; - handler_data->kf_group_name = kf_group_name; - handler_data->kf_key = kf_key; - handler_data->cur_setting = cur_setting; - handler_data->cur_property = cur_property; -} - -static void -_key_file_handler_data_init_read(NMKeyfileHandlerData *handler_data, - NMKeyfileHandlerType handler_type, - KeyfileReaderInfo * info, - const char * kf_key, - const char * cur_property) -{ - _key_file_handler_data_init(handler_data, - handler_type, - info->group, - kf_key, - info->setting, - cur_property, - &info->error); -} - -static void -_key_file_handler_data_init_write(NMKeyfileHandlerData *handler_data, - NMKeyfileHandlerType handler_type, - KeyfileWriterInfo * info, - const char * kf_group, - const char * kf_key, - NMSetting * cur_setting, - const char * cur_property) -{ - _key_file_handler_data_init(handler_data, - handler_type, - kf_group, - kf_key, - cur_setting, - cur_property, - &info->error); -} - -_nm_printf(5, 6) static void _handle_warn(KeyfileReaderInfo * info, - const char * kf_key, - const char * cur_property, - NMKeyfileWarnSeverity severity, - const char * fmt, - ...) -{ - NMKeyfileHandlerData handler_data; - - _key_file_handler_data_init_read(&handler_data, - NM_KEYFILE_HANDLER_TYPE_WARN, - info, - kf_key, - cur_property); - handler_data.warn = (NMKeyfileHandlerDataWarn){ - .severity = severity, - .message = NULL, - .fmt = fmt, - }; - - va_start(handler_data.warn.ap, fmt); - - info->read_handler(info->keyfile, - info->connection, - NM_KEYFILE_HANDLER_TYPE_WARN, - &handler_data, - info->user_data); - - va_end(handler_data.warn.ap); - - g_free(handler_data.warn.message); -} - -#define handle_warn(arg_info, arg_kf_key, arg_property_name, arg_severity, ...) \ - ({ \ - KeyfileReaderInfo *_info = (arg_info); \ - \ - nm_assert(!_info->error); \ - \ - if (_info->read_handler) { \ - _handle_warn(_info, (arg_kf_key), (arg_property_name), (arg_severity), __VA_ARGS__); \ - } \ - _info->error == NULL; \ - }) - -/*****************************************************************************/ - -static gboolean -_secret_flags_persist_secret(NMSettingSecretFlags flags) -{ - return flags == NM_SETTING_SECRET_FLAG_NONE; -} - -/*****************************************************************************/ -/* Some setting properties also contain setting names, such as - * NMSettingConnection's 'type' property (which specifies the base type of the - * connection, e.g. ethernet or wifi) or 'slave-type' (specifies type of slave - * connection, e.g. bond or bridge). This function handles translating those - * properties' values to the real setting name if they are an alias. - */ -static void -setting_alias_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - const char * key_setting_name; - gs_free char *s = NULL; - - s = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); - if (!s) - return; - - key_setting_name = nm_keyfile_plugin_get_setting_name_for_alias(s); - g_object_set(G_OBJECT(setting), key, key_setting_name ?: s, NULL); -} - -static void -sriov_vfs_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - gs_unref_ptrarray GPtrArray *vfs = NULL; - gs_strfreev char ** keys = NULL; - gsize n_keys = 0; - int i; - - keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); - if (n_keys == 0) - return; - - vfs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_sriov_vf_unref); - - for (i = 0; i < n_keys; i++) { - gs_free char *value = NULL; - NMSriovVF * vf; - const char * rest; - - if (!g_str_has_prefix(keys[i], "vf.")) - continue; - - rest = &keys[i][3]; - - if (!NM_STRCHAR_ALL(rest, ch, g_ascii_isdigit(ch))) - continue; - - value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, keys[i], NULL); - - vf = _nm_utils_sriov_vf_from_strparts(rest, value, TRUE, NULL); - if (vf) - g_ptr_array_add(vfs, vf); - } - - g_object_set(G_OBJECT(setting), key, vfs, NULL); -} - -static void -read_array_of_uint(GKeyFile *file, NMSetting *setting, const char *key) -{ - gs_unref_array GArray *array = NULL; - gs_free_error GError *error = NULL; - gs_free guint *tmp = NULL; - gsize length; - - tmp = nm_keyfile_plugin_kf_get_integer_list_uint(file, - nm_setting_get_name(setting), - key, - &length, - &error); - if (error) - return; - - array = g_array_sized_new(FALSE, FALSE, sizeof(guint), length); - g_array_append_vals(array, tmp, length); - g_object_set(setting, key, array, NULL); -} - -static gboolean -get_one_int(KeyfileReaderInfo *info, - const char * kf_key, - const char * property_name, - const char * str, - guint32 max_val, - guint32 * out) -{ - gint64 tmp; - - nm_assert((!info) == (!property_name)); - nm_assert((!info) == (!kf_key)); - - if (!str || !str[0]) { - if (info) { - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring missing number")); - } - return FALSE; - } - - tmp = _nm_utils_ascii_str_to_int64(str, 10, 0, max_val, -1); - if (tmp == -1) { - if (info) { - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid number '%s'"), - str); - } - return FALSE; - } - - *out = (guint32) tmp; - return TRUE; -} - -static gpointer -build_address(KeyfileReaderInfo *info, - const char * kf_key, - const char * property_name, - int family, - const char * address_str, - guint32 plen) -{ - NMIPAddress *addr; - GError * error = NULL; - - g_return_val_if_fail(address_str, NULL); - - addr = nm_ip_address_new(family, address_str, plen, &error); - if (!addr) { - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid %s address: %s"), - family == AF_INET ? "IPv4" : "IPv6", - error->message); - g_error_free(error); - } - - return addr; -} - -static gpointer -build_route(KeyfileReaderInfo *info, - const char * kf_key, - const char * property_name, - int family, - const char * dest_str, - guint32 plen, - const char * gateway_str, - const char * metric_str) -{ - NMIPRoute *route; - guint32 u32; - gint64 metric = -1; - GError * error = NULL; - - g_return_val_if_fail(dest_str, NULL); - - /* Next hop */ - if (gateway_str && gateway_str[0]) { - if (!nm_utils_ipaddr_is_valid(family, gateway_str)) { - /* Try workaround for routes written by broken keyfile writer. - * Due to bug bgo#719851, an older version of writer would have - * written "a:b:c:d::/plen,metric" if the gateway was ::, instead - * of "a:b:c:d::/plen,,metric" or "a:b:c:d::/plen,::,metric" - * Try workaround by interpreting gateway_str as metric to accept such - * invalid routes. This broken syntax should not be not officially - * supported. - **/ - if (family == AF_INET6 && !metric_str - && get_one_int(NULL, NULL, NULL, gateway_str, G_MAXUINT32, &u32)) { - metric = u32; - gateway_str = NULL; - } else { - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid gateway '%s' for %s route"), - gateway_str, - family == AF_INET ? "IPv4" : "IPv6"); - return NULL; - } - } - } else - gateway_str = NULL; - - /* parse metric, default to -1 */ - if (metric_str) { - if (!get_one_int(info, kf_key, property_name, metric_str, G_MAXUINT32, &u32)) - return NULL; - metric = u32; - } - - route = nm_ip_route_new(family, dest_str, plen, gateway_str, metric, &error); - if (!route) { - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid %s route: %s"), - family == AF_INET ? "IPv4" : "IPv6", - error->message); - g_error_free(error); - } - - return route; -} - -/* On success, returns pointer to the zero-terminated field (original @current). - * The @current * pointer target is set to point to the rest of the input - * or %NULL if there is no more input. Sets error to %NULL for convenience. - * - * On failure, returns %NULL (unspecified). The @current pointer target is - * resets to its original value to allow skipping fields. The @error target - * is set to the character that breaks the parsing or %NULL if @current was %NULL. - * - * When @current target is %NULL, gracefully fail returning %NULL while - * leaving the @current target %NULL end setting @error to %NULL; - */ -static const char * -read_field(char **current, const char **out_err_str, const char *characters, const char *delimiters) -{ - const char *start; - - nm_assert(current); - nm_assert(out_err_str); - nm_assert(characters); - nm_assert(delimiters); - - *out_err_str = NULL; - - if (!*current) { - /* graceful failure, leave '*current' NULL */ - return NULL; - } - - /* fail on empty input */ - if (!**current) - return NULL; - - /* remember beginning of input */ - start = *current; - - while (**current && strchr(characters, **current)) - (*current)++; - if (**current) - if (strchr(delimiters, **current)) { - /* success, more data available */ - *(*current)++ = '\0'; - return start; - } else { - /* error, bad character */ - *out_err_str = *current; - *current = (char *) start; - return NULL; - } - else { - /* success, end of input */ - *current = NULL; - return start; - } -} - -/*****************************************************************************/ - -#define NM_DBUS_SERVICE_OPENCONNECT "org.freedesktop.NetworkManager.openconnect" -#define NM_OPENCONNECT_KEY_GATEWAY "gateway" -#define NM_OPENCONNECT_KEY_COOKIE "cookie" -#define NM_OPENCONNECT_KEY_GWCERT "gwcert" -#define NM_OPENCONNECT_KEY_XMLCONFIG "xmlconfig" -#define NM_OPENCONNECT_KEY_LASTHOST "lasthost" -#define NM_OPENCONNECT_KEY_AUTOCONNECT "autoconnect" -#define NM_OPENCONNECT_KEY_CERTSIGS "certsigs" - -static void -openconnect_fix_secret_flags(NMSetting *setting) -{ - NMSettingVpn * s_vpn; - NMSettingSecretFlags flags; - - /* Huge hack. There were some openconnect changes that needed to happen - * pretty late, too late to get into distros. Migration has already - * happened for many people, and their secret flags are wrong. But we - * don't want to require re-migration, so we have to fix it up here. Ugh. - */ - - if (!NM_IS_SETTING_VPN(setting)) - return; - - s_vpn = NM_SETTING_VPN(setting); - - if (!nm_streq0(nm_setting_vpn_get_service_type(s_vpn), NM_DBUS_SERVICE_OPENCONNECT)) - return; - - /* These are different for every login session, and should not be stored */ - flags = NM_SETTING_SECRET_FLAG_NOT_SAVED; - nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_GATEWAY, flags, NULL); - nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_COOKIE, flags, NULL); - nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_GWCERT, flags, NULL); - - /* These are purely internal data for the auth-dialog, and should be stored */ - flags = 0; - nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_XMLCONFIG, flags, NULL); - nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_LASTHOST, flags, NULL); - nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_AUTOCONNECT, flags, NULL); - nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_CERTSIGS, flags, NULL); -} - -/*****************************************************************************/ - -#define IP_ADDRESS_CHARS "0123456789abcdefABCDEF:.%" -#define DIGITS "0123456789" -#define DELIMITERS "/;," - -/* The following IPv4 and IPv6 address formats are supported: - * - * address (DEPRECATED) - * address/plen - * address/gateway (DEPRECATED) - * address/plen,gateway - * - * The following IPv4 and IPv6 route formats are supported: - * - * address/plen (NETWORK dev DEVICE) - * address/plen,gateway (NETWORK via GATEWAY dev DEVICE) - * address/plen,,metric (NETWORK dev DEVICE metric METRIC) - * address/plen,gateway,metric (NETWORK via GATEWAY dev DEVICE metric METRIC) - * - * For backward, forward and sideward compatibility, slash (/), - * semicolon (;) and comma (,) are interchangeable. The choice of - * separator in the above examples is therefore not significant. - * - * Leaving out the prefix length is discouraged and DEPRECATED. The - * default value of IPv6 prefix length was 64 and has not been - * changed. The default for IPv4 is now 24, which is the closest - * IPv4 equivalent. These defaults may just as well be changed to - * match the iproute2 defaults (32 for IPv4 and 128 for IPv6). - */ -static gpointer -read_one_ip_address_or_route(KeyfileReaderInfo *info, - const char * property_name, - const char * setting_name, - const char * kf_key, - gboolean ipv6, - gboolean route, - char ** out_gateway, - NMSetting * setting) -{ - guint plen; - gpointer result; - const char * address_str; - const char * plen_str; - const char * gateway_str; - const char * metric_str; - const char * err_str = NULL; - char * current; - gs_free char *value = NULL; - gs_free char *value_orig = NULL; - -#define VALUE_ORIG() \ - (value_orig \ - ?: (value_orig = \ - nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, kf_key, NULL))) - - value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, kf_key, NULL); - if (!value) - return NULL; - - current = value; - - /* get address field */ - address_str = read_field(¤t, &err_str, IP_ADDRESS_CHARS, DELIMITERS); - if (err_str) { - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("unexpected character '%c' for address %s: '%s' (position %td)"), - *err_str, - kf_key, - VALUE_ORIG(), - err_str - current); - return NULL; - } - /* get prefix length field (skippable) */ - plen_str = read_field(¤t, &err_str, DIGITS, DELIMITERS); - /* get gateway field */ - gateway_str = read_field(¤t, &err_str, IP_ADDRESS_CHARS, DELIMITERS); - if (err_str) { - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("unexpected character '%c' for %s: '%s' (position %td)"), - *err_str, - kf_key, - VALUE_ORIG(), - err_str - current); - return NULL; - } - /* for routes, get metric */ - if (route) { - metric_str = read_field(¤t, &err_str, DIGITS, DELIMITERS); - if (err_str) { - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("unexpected character '%c' in prefix length for %s: '%s' (position %td)"), - *err_str, - kf_key, - VALUE_ORIG(), - err_str - current); - return NULL; - } - } else - metric_str = NULL; - if (current) { - /* there is still some data */ - if (*current) { - /* another field follows */ - handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("garbage at the end of value %s: '%s'"), - kf_key, - VALUE_ORIG()); - return NULL; - } else { - /* semicolon at the end of input */ - if (!handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_INFO, - _("deprecated semicolon at the end of value %s: '%s'"), - kf_key, - VALUE_ORIG())) - return NULL; - } - } - -#define DEFAULT_PREFIX(for_route, for_ipv6) \ - ((for_route) ? ((for_ipv6) ? 128 : 24) : ((for_ipv6) ? 64 : 24)) - - /* parse plen, fallback to defaults */ - if (plen_str) { - if (!get_one_int(info, kf_key, property_name, plen_str, ipv6 ? 128 : 32, &plen)) { - plen = DEFAULT_PREFIX(route, ipv6); - if (info->error - || !handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid prefix length for %s '%s', defaulting to %d"), - kf_key, - VALUE_ORIG(), - plen)) - return NULL; - } - } else { - plen = DEFAULT_PREFIX(route, ipv6); - if (!handle_warn(info, - kf_key, - property_name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("missing prefix length for %s '%s', defaulting to %d"), - kf_key, - VALUE_ORIG(), - plen)) - return NULL; - } - - /* build the appropriate data structure for NetworkManager settings */ - if (route) { - result = build_route(info, - kf_key, - property_name, - ipv6 ? AF_INET6 : AF_INET, - address_str, - plen, - gateway_str, - metric_str); - } else { - result = build_address(info, - kf_key, - property_name, - ipv6 ? AF_INET6 : AF_INET, - address_str, - plen); - if (!result) - return NULL; - if (gateway_str) - NM_SET_OUT(out_gateway, g_strdup(gateway_str)); - } - -#undef VALUE_ORIG - - return result; -} - -static void -fill_route_attributes(GKeyFile * kf, - NMIPRoute * route, - const char *setting, - const char *key, - int family) -{ - gs_free char * value = NULL; - gs_unref_hashtable GHashTable *hash = NULL; - GHashTableIter iter; - char * name; - GVariant * variant; - - value = nm_keyfile_plugin_kf_get_string(kf, setting, key, NULL); - if (!value || !value[0]) - return; - - hash = nm_utils_parse_variant_attributes(value, - ',', - '=', - TRUE, - nm_ip_route_get_variant_attribute_spec(), - NULL); - if (hash) { - g_hash_table_iter_init(&iter, hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) { - if (nm_ip_route_attribute_validate(name, variant, family, NULL, NULL)) - nm_ip_route_set_attribute(route, name, g_variant_ref(variant)); - } - } -} - -typedef struct { - const char *s_key; - gint32 key_idx; - gint8 key_type; -} BuildListData; - -typedef enum { - BUILD_LIST_TYPE_ADDRESSES, - BUILD_LIST_TYPE_ROUTES, - BUILD_LIST_TYPE_ROUTING_RULES, -} BuildListType; - -static int -_build_list_data_cmp(gconstpointer p_a, gconstpointer p_b, gpointer user_data) -{ - const BuildListData *a = p_a; - const BuildListData *b = p_b; - - NM_CMP_FIELD(a, b, key_idx); - NM_CMP_FIELD(a, b, key_type); - NM_CMP_FIELD_STR(a, b, s_key); - return 0; -} - -static gboolean -_build_list_data_is_shadowed(const BuildListData *build_list, gsize build_list_len, gsize idx) -{ - /* the keyfile contains duplicate keys, which are both returned - * by g_key_file_get_keys() (WHY??). - * - * Skip the earlier one. */ - return idx + 1 < build_list_len && build_list[idx].key_idx == build_list[idx + 1].key_idx - && build_list[idx].key_type == build_list[idx + 1].key_type - && nm_streq(build_list[idx].s_key, build_list[idx + 1].s_key); -} - -static gboolean -_build_list_match_key_w_name_impl(const char *key, - const char *base_name, - gsize base_name_l, - gint32 * out_key_idx) -{ - gint64 v; - - /* some very strict parsing. */ - - /* the key must start with base_name. */ - if (strncmp(key, base_name, base_name_l) != 0) - return FALSE; - - key += base_name_l; - if (key[0] == '\0') { - /* if key is identical to base_name, that's good. */ - NM_SET_OUT(out_key_idx, -1); - return TRUE; - } - - /* if base_name is followed by a zero, then it must be - * only a zero, nothing else. */ - if (key[0] == '0') { - if (key[1] != '\0') - return FALSE; - NM_SET_OUT(out_key_idx, 0); - return TRUE; - } - - /* otherwise, it can only be followed by a non-zero decimal. */ - if (!(key[0] >= '1' && key[0] <= '9')) - return FALSE; - /* and all remaining chars must be decimals too. */ - if (!NM_STRCHAR_ALL(&key[1], ch, g_ascii_isdigit(ch))) - return FALSE; - - /* and it must be convertible to a (positive) int. */ - v = _nm_utils_ascii_str_to_int64(key, 10, 0, G_MAXINT32, -1); - if (v < 0) - return FALSE; - - /* good */ - NM_SET_OUT(out_key_idx, v); - return TRUE; -} - -#define _build_list_match_key_w_name(key, base_name, out_key_idx) \ - _build_list_match_key_w_name_impl(key, base_name, NM_STRLEN(base_name), out_key_idx) - -static BuildListData * -_build_list_create(GKeyFile * keyfile, - const char * group_name, - BuildListType build_list_type, - gsize * out_build_list_len, - char *** out_keys_strv) -{ - gs_strfreev char **keys = NULL; - gsize i_keys, n_keys; - gs_free BuildListData *build_list = NULL; - gsize build_list_len = 0; - - nm_assert(out_build_list_len && *out_build_list_len == 0); - nm_assert(out_keys_strv && !*out_keys_strv); - - keys = nm_keyfile_plugin_kf_get_keys(keyfile, group_name, &n_keys, NULL); - if (n_keys == 0) - return NULL; - - for (i_keys = 0; i_keys < n_keys; i_keys++) { - const char *s_key = keys[i_keys]; - gint32 key_idx; - gint8 key_type = 0; - - switch (build_list_type) { - case BUILD_LIST_TYPE_ROUTES: - if (_build_list_match_key_w_name(s_key, "route", &key_idx)) - key_type = 0; - else if (_build_list_match_key_w_name(s_key, "routes", &key_idx)) - key_type = 1; - else - continue; - break; - case BUILD_LIST_TYPE_ADDRESSES: - if (_build_list_match_key_w_name(s_key, "address", &key_idx)) - key_type = 0; - else if (_build_list_match_key_w_name(s_key, "addresses", &key_idx)) - key_type = 1; - else - continue; - break; - case BUILD_LIST_TYPE_ROUTING_RULES: - if (_build_list_match_key_w_name(s_key, "routing-rule", &key_idx)) - key_type = 0; - else - continue; - break; - default: - nm_assert_not_reached(); - break; - } - - if (G_UNLIKELY(!build_list)) - build_list = g_new(BuildListData, n_keys - i_keys); - - build_list[build_list_len++] = (BuildListData){ - .s_key = s_key, - .key_idx = key_idx, - .key_type = key_type, - }; - } - - if (build_list_len == 0) - return NULL; - - if (build_list_len > 1) { - g_qsort_with_data(build_list, - build_list_len, - sizeof(BuildListData), - _build_list_data_cmp, - NULL); - } - - *out_build_list_len = build_list_len; - *out_keys_strv = g_steal_pointer(&keys); - return g_steal_pointer(&build_list); -} - -static void -ip_address_or_route_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *setting_key) -{ - const char * setting_name = nm_setting_get_name(setting); - gboolean is_ipv6 = nm_streq(setting_name, "ipv6"); - gboolean is_routes = nm_streq(setting_key, "routes"); - gs_free char * gateway = NULL; - gs_unref_ptrarray GPtrArray *list = NULL; - gs_strfreev char ** keys = NULL; - gs_free BuildListData *build_list = NULL; - gsize i_build_list, build_list_len = 0; - - build_list = _build_list_create(info->keyfile, - setting_name, - is_routes ? BUILD_LIST_TYPE_ROUTES : BUILD_LIST_TYPE_ADDRESSES, - &build_list_len, - &keys); - if (!build_list) - return; - - list = g_ptr_array_new_with_free_func(is_routes ? (GDestroyNotify) nm_ip_route_unref - : (GDestroyNotify) nm_ip_address_unref); - - for (i_build_list = 0; i_build_list < build_list_len; i_build_list++) { - const char *s_key; - gpointer item; - - if (_build_list_data_is_shadowed(build_list, build_list_len, i_build_list)) - continue; - - s_key = build_list[i_build_list].s_key; - item = read_one_ip_address_or_route(info, - setting_key, - setting_name, - s_key, - is_ipv6, - is_routes, - gateway ? NULL : &gateway, - setting); - if (item && is_routes) { - char options_key[128]; - - nm_sprintf_buf(options_key, "%s_options", s_key); - fill_route_attributes(info->keyfile, - item, - setting_name, - options_key, - is_ipv6 ? AF_INET6 : AF_INET); - } - - if (info->error) - return; - - if (item) - g_ptr_array_add(list, item); - } - - if (list->len >= 1) - g_object_set(setting, setting_key, list, NULL); - - if (gateway) - g_object_set(setting, "gateway", gateway, NULL); -} - -static void -ip_routing_rule_parser_full(KeyfileReaderInfo * info, - const NMMetaSettingInfo * setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty * pip, - NMSetting * setting) -{ - const char * setting_name = nm_setting_get_name(setting); - gboolean is_ipv6 = nm_streq(setting_name, "ipv6"); - gs_strfreev char **keys = NULL; - gs_free BuildListData *build_list = NULL; - gsize i_build_list, build_list_len = 0; - - build_list = _build_list_create(info->keyfile, - setting_name, - BUILD_LIST_TYPE_ROUTING_RULES, - &build_list_len, - &keys); - if (!build_list) - return; - - for (i_build_list = 0; i_build_list < build_list_len; i_build_list++) { - nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL; - gs_free char * value = NULL; - gs_free_error GError *local = NULL; - - if (_build_list_data_is_shadowed(build_list, build_list_len, i_build_list)) - continue; - - value = nm_keyfile_plugin_kf_get_string(info->keyfile, - setting_name, - build_list[i_build_list].s_key, - NULL); - if (!value) - continue; - - rule = nm_ip_routing_rule_from_string( - value, - (NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE - | (is_ipv6 ? NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 - : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET)), - NULL, - &local); - if (!rule) { - if (!handle_warn(info, - build_list[i_build_list].s_key, - property_info->name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid value for \"%s\": %s"), - build_list[i_build_list].s_key, - local->message)) - return; - continue; - } - - nm_setting_ip_config_add_routing_rule(NM_SETTING_IP_CONFIG(setting), rule); - } -} - -static void -_parser_full_ovs_external_ids_data(KeyfileReaderInfo * info, - const NMMetaSettingInfo * setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty * pip, - NMSetting * setting) -{ - const char * setting_name = NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME; - gs_strfreev char **keys = NULL; - gsize n_keys; - gsize i; - - nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)); - nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)); - nm_assert(nm_streq(setting_name, setting_info->setting_name)); - nm_assert(nm_streq(setting_name, nm_setting_get_name(setting))); - - keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); - - for (i = 0; i < n_keys; i++) { - const char * key = keys[i]; - gs_free char *name_to_free = NULL; - gs_free char *value = NULL; - const char * name; - - if (!NM_STR_HAS_PREFIX(key, OVS_EXTERNAL_IDS_DATA_PREFIX)) - continue; - - value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); - if (!value) - continue; - - name = &key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)]; - name = nm_keyfile_key_decode(name, &name_to_free); - nm_setting_ovs_external_ids_set_data(NM_SETTING_OVS_EXTERNAL_IDS(setting), name, value); - } -} - -static void -ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - int addr_family; - gs_strfreev char **list = NULL; - gsize i, n, length; - - nm_assert(NM_IS_SETTING_IP4_CONFIG(setting) || NM_IS_SETTING_IP6_CONFIG(setting)); - - list = nm_keyfile_plugin_kf_get_string_list(info->keyfile, - nm_setting_get_name(setting), - key, - &length, - NULL); - nm_assert(length == NM_PTRARRAY_LEN(list)); - if (length == 0) - return; - - addr_family = NM_IS_SETTING_IP4_CONFIG(setting) ? AF_INET : AF_INET6; - - n = 0; - for (i = 0; i < length; i++) { - NMIPAddr addr; - - if (inet_pton(addr_family, list[i], &addr) <= 0) { - if (!handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid DNS server IPv%c address '%s'"), - nm_utils_addr_family_to_char(addr_family), - list[i])) { - do { - nm_clear_g_free(&list[i]); - } while (++i < length); - return; - } - nm_clear_g_free(&list[i]); - continue; - } - - if (n != i) - list[n] = g_steal_pointer(&list[i]); - n++; - } - - g_object_set(setting, key, list, NULL); -} - -static void -ip6_addr_gen_mode_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - NMSettingIP6ConfigAddrGenMode addr_gen_mode; - const char * setting_name = nm_setting_get_name(setting); - gs_free char * s = NULL; - - s = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); - if (s) { - if (!nm_utils_enum_from_str(nm_setting_ip6_config_addr_gen_mode_get_type(), - s, - (int *) &addr_gen_mode, - NULL)) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid option '%s', use one of [%s]"), - s, - "eui64,stable-privacy"); - return; - } - } else - addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64; - - g_object_set(G_OBJECT(setting), key, (int) addr_gen_mode, NULL); -} - -static void -mac_address_parser(KeyfileReaderInfo *info, - NMSetting * setting, - const char * key, - gsize addr_len, - gboolean cloned_mac_addr) -{ - const char * setting_name = nm_setting_get_name(setting); - char addr_str[NM_UTILS_HWADDR_LEN_MAX * 3]; - guint8 addr_bin[NM_UTILS_HWADDR_LEN_MAX]; - gs_free char *tmp_string = NULL; - gs_free guint *int_list = NULL; - const char * mac_str; - gsize int_list_len; - gsize i; - - nm_assert(addr_len > 0); - nm_assert(addr_len <= NM_UTILS_HWADDR_LEN_MAX); - - tmp_string = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); - - if (cloned_mac_addr && NM_CLONED_MAC_IS_SPECIAL(tmp_string)) { - mac_str = tmp_string; - goto out; - } - - if (tmp_string && nm_utils_hwaddr_aton(tmp_string, addr_bin, addr_len)) - goto good_addr_bin; - - /* Old format; list of ints */ - int_list = nm_keyfile_plugin_kf_get_integer_list_uint(info->keyfile, - setting_name, - key, - &int_list_len, - NULL); - if (int_list_len == addr_len) { - for (i = 0; i < addr_len; i++) { - const guint val = int_list[i]; - - if (val > 255) - break; - addr_bin[i] = (guint8) val; - } - if (i == addr_len) - goto good_addr_bin; - } - - handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid MAC address")); - return; - -good_addr_bin: - nm_utils_bin2hexstr_full(addr_bin, addr_len, ':', TRUE, addr_str); - mac_str = addr_str; - -out: - g_object_set(setting, key, mac_str, NULL); -} - -static void -mac_address_parser_ETHER(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - mac_address_parser(info, setting, key, ETH_ALEN, FALSE); -} - -static void -mac_address_parser_ETHER_cloned(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - mac_address_parser(info, setting, key, ETH_ALEN, TRUE); -} - -static void -mac_address_parser_INFINIBAND(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - mac_address_parser(info, setting, key, INFINIBAND_ALEN, FALSE); -} - -static void -read_hash_of_string(KeyfileReaderInfo *info, - GKeyFile * file, - NMSetting * setting, - const char * kf_group) -{ - gs_strfreev char **keys = NULL; - const char *const *iter; - const char * setting_name = nm_setting_get_name(setting); - gboolean is_vpn; - gsize n_keys; - - nm_assert((NM_IS_SETTING_VPN(setting) && nm_streq(kf_group, NM_SETTING_VPN_DATA)) - || (NM_IS_SETTING_VPN(setting) && nm_streq(kf_group, NM_SETTING_VPN_SECRETS)) - || (NM_IS_SETTING_BOND(setting) && nm_streq(kf_group, NM_SETTING_BOND_OPTIONS)) - || (NM_IS_SETTING_USER(setting) && nm_streq(kf_group, NM_SETTING_USER_DATA))); - - keys = nm_keyfile_plugin_kf_get_keys(file, setting_name, &n_keys, NULL); - if (n_keys == 0) - return; - - if ((is_vpn = NM_IS_SETTING_VPN(setting)) || NM_IS_SETTING_BOND(setting)) { - for (iter = (const char *const *) keys; *iter; iter++) { - const char * kf_key = *iter; - gs_free char *to_free = NULL; - gs_free char *value = NULL; - const char * name; - - value = nm_keyfile_plugin_kf_get_string(file, setting_name, kf_key, NULL); - if (!value) - continue; - - name = nm_keyfile_key_decode(kf_key, &to_free); - - if (is_vpn) { - /* Add any item that's not a class property to the data hash */ - if (!g_object_class_find_property(G_OBJECT_GET_CLASS(setting), name)) - nm_setting_vpn_add_data_item(NM_SETTING_VPN(setting), name, value); - } else { - if (!nm_streq(name, "interface-name")) { - gs_free_error GError *error = NULL; - - if (!_nm_setting_bond_validate_option(name, value, &error)) { - if (!handle_warn(info, - kf_key, - name, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid bond option %s%s%s = %s%s%s: %s"), - NM_PRINT_FMT_QUOTE_STRING(name), - NM_PRINT_FMT_QUOTE_STRING(value), - error->message)) - return; - } else - nm_setting_bond_add_option(NM_SETTING_BOND(setting), name, value); - } - } - } - openconnect_fix_secret_flags(setting); - return; - } - - if (NM_IS_SETTING_USER(setting)) { - gs_unref_hashtable GHashTable *data = NULL; - - data = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); - for (iter = (const char *const *) keys; *iter; iter++) { - gs_free char *to_free = NULL; - char * value = NULL; - const char * name; - - value = nm_keyfile_plugin_kf_get_string(file, setting_name, *iter, NULL); - if (!value) - continue; - name = nm_keyfile_key_decode(*iter, &to_free); - g_hash_table_insert(data, g_steal_pointer(&to_free) ?: g_strdup(name), value); - } - g_object_set(setting, NM_SETTING_USER_DATA, data, NULL); - return; - } - - nm_assert_not_reached(); -} - -static gsize -unescape_semicolons(char *str) -{ - gsize i, j; - - for (i = 0, j = 0; str[i];) { - if (str[i] == '\\' && str[i + 1] == ';') - i++; - str[j++] = str[i++]; - } - nm_explicit_bzero(&str[j], i - j); - return j; -} - -static GBytes * -get_bytes(KeyfileReaderInfo *info, - const char * setting_name, - const char * key, - gboolean zero_terminate, - gboolean unescape_semicolon) -{ - nm_auto_free_secret char *tmp_string = NULL; - gboolean may_be_int_list = TRUE; - gsize length; - GBytes * result; - - /* New format: just a string - * Old format: integer list; e.g. 11;25;38; - */ - tmp_string = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); - if (!tmp_string) - return NULL; - - /* if the string is empty, we return an empty GBytes array. - * Note that for NM_SETTING_802_1X_PASSWORD_RAW both %NULL and - * an empty GBytes are valid, and shall be destinguished. */ - if (!tmp_string[0]) { - /* note that even if @zero_terminate is TRUE, we return an empty - * byte-array. The reason is that zero_terminate is there to terminate - * *valid* strings. It's not there to terminated invalid (empty) strings. - */ - return g_bytes_new_static("", 0); - } - - for (length = 0; tmp_string[length]; length++) { - const char ch = tmp_string[length]; - - if (!g_ascii_isspace(ch) && !g_ascii_isdigit(ch) && ch != ';') { - may_be_int_list = FALSE; - length += strlen(&tmp_string[length]); - break; - } - } - - /* Try to parse the string as a integer list. */ - if (may_be_int_list && length > 0) { - nm_auto_free_secret_buf NMSecretBuf *bin = NULL; - const char *const s = tmp_string; - gsize i, d; - - bin = nm_secret_buf_new(length / 2 + 3); - -#define DIGIT(c) ((c) - '0') - i = 0; - d = 0; - while (TRUE) { - int n; - - /* leading whitespace */ - while (g_ascii_isspace(s[i])) - i++; - if (s[i] == '\0') - break; - /* then expect 1 to 3 digits */ - if (!g_ascii_isdigit(s[i])) { - d = 0; - break; - } - n = DIGIT(s[i]); - i++; - if (g_ascii_isdigit(s[i])) { - n = 10 * n + DIGIT(s[i]); - i++; - if (g_ascii_isdigit(s[i])) { - n = 10 * n + DIGIT(s[i]); - i++; - } - } - if (n > 255) { - d = 0; - break; - } - - nm_assert(d < bin->len); - bin->bin[d++] = n; - - /* allow whitespace after the digit. */ - while (g_ascii_isspace(s[i])) - i++; - /* need a semicolon as separator. */ - if (s[i] != ';') { - d = 0; - break; - } - i++; - } -#undef DIGIT - - /* Old format; list of ints. We already did a strict validation of the - * string format before. We expect that this conversion cannot fail. */ - if (d > 0) { - /* note that @zero_terminate does not add a terminating '\0' to - * binary data as an integer list. If the bytes are expressed as - * an integer list, all potential NUL characters are supposed to - * be included there explicitly. - * - * However, in the spirit of defensive programming, we do append a - * NUL character to the buffer, although this character is hidden - * and only a mitigation for bugs. */ - - if (d + 10 < bin->len) { - /* hm, too much unused memory. Copy the memory to a suitable - * sized buffer. */ - return nm_secret_copy_to_gbytes(bin->bin, d); - } - - nm_assert(d < bin->len); - bin->bin[d] = '\0'; - return nm_secret_buf_to_gbytes_take(g_steal_pointer(&bin), d); - } - } - - /* Handle as a simple string (ie, new format) */ - if (unescape_semicolon) - length = unescape_semicolons(tmp_string); - if (zero_terminate) - length++; - if (length == 0) - return NULL; - - result = - g_bytes_new_with_free_func(tmp_string, length, (GDestroyNotify) nm_free_secret, tmp_string); - tmp_string = NULL; - return result; -} - -static void -ssid_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - gs_unref_bytes GBytes *bytes = NULL; - - bytes = get_bytes(info, setting_name, key, FALSE, TRUE); - if (!bytes) { - handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid SSID")); - return; - } - g_object_set(setting, key, bytes, NULL); -} - -static void -password_raw_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - gs_unref_bytes GBytes *bytes = NULL; - - bytes = get_bytes(info, setting_name, key, FALSE, TRUE); - if (!bytes) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid raw password")); - return; - } - g_object_set(setting, key, bytes, NULL); -} - -static char * -get_cert_path(const char *base_dir, const guint8 *cert_path, gsize cert_path_len) -{ - const char *base; - char * p = NULL, *path, *tmp; - - g_return_val_if_fail(base_dir != NULL, NULL); - g_return_val_if_fail(cert_path != NULL, NULL); - - path = g_strndup((char *) cert_path, cert_path_len); - - if (path[0] == '/') - return path; - - base = path; - p = strrchr(path, '/'); - if (p) - base = p + 1; - - tmp = g_build_path("/", base_dir, base, NULL); - g_free(path); - return tmp; -} - -static const char *certext[] = {".pem", ".cert", ".crt", ".cer", ".p12", ".der", ".key"}; - -static gboolean -has_cert_ext(const char *path) -{ - int i; - - for (i = 0; i < G_N_ELEMENTS(certext); i++) { - if (g_str_has_suffix(path, certext[i])) - return TRUE; - } - return FALSE; -} - -char * -nm_keyfile_detect_unqualified_path_scheme(const char * base_dir, - gconstpointer pdata, - gsize data_len, - gboolean consider_exists, - gboolean * out_exists) -{ - const char * data = pdata; - gboolean exists = FALSE; - gsize validate_len; - gsize path_len, pathuri_len; - gs_free char *path = NULL; - gs_free char *pathuri = NULL; - - g_return_val_if_fail(base_dir && base_dir[0] == '/', NULL); - - if (!pdata) - return NULL; - if (data_len == -1) - data_len = strlen(data); - if (data_len > 500 || data_len < 1) - return NULL; - - /* If there's a trailing zero tell g_utf8_validate() to validate until the zero */ - if (data[data_len - 1] == '\0') { - /* setting it to -1, would mean we accept data to contain NUL characters before the - * end. Don't accept any NUL in [0 .. data_len-1[ . */ - validate_len = data_len - 1; - } else - validate_len = data_len; - if (validate_len == 0 || g_utf8_validate((const char *) data, validate_len, NULL) == FALSE) - return NULL; - - /* Might be a bare path without the file:// prefix; in that case - * if it's an absolute path, use that, otherwise treat it as a - * relative path to the current directory. - */ - - path = get_cert_path(base_dir, (const guint8 *) data, data_len); - - /* FIXME(keyfile-parse-in-memory): it is wrong that keyfile reader makes decisions based on - * the file systems content. The serialization/parsing should be entirely in-memory. */ - if (!memchr(data, '/', data_len) && !has_cert_ext(path)) { - if (!consider_exists) - return NULL; - exists = g_file_test(path, G_FILE_TEST_EXISTS); - if (!exists) - return NULL; - } else if (out_exists) - exists = g_file_test(path, G_FILE_TEST_EXISTS); - - /* Construct the proper value as required for the PATH scheme. - * - * When returning TRUE, we must also be sure that @data_len does not look like - * the deprecated format of list of integers. With this implementation that is the - * case, as long as @consider_exists is FALSE. */ - path_len = strlen(path); - pathuri_len = (NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + 1) + path_len; - pathuri = g_new(char, pathuri_len); - memcpy(pathuri, - NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, - NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)); - memcpy(&pathuri[NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)], path, path_len + 1); - if (nm_setting_802_1x_check_cert_scheme(pathuri, pathuri_len, NULL) - != NM_SETTING_802_1X_CK_SCHEME_PATH) - return NULL; - - NM_SET_OUT(out_exists, exists); - return g_steal_pointer(&pathuri); -} - -#define HAS_SCHEME_PREFIX(bin, bin_len, scheme) \ - ({ \ - const char *const _bin = (bin); \ - const gsize _bin_len = (bin_len); \ - \ - nm_assert(_bin &&_bin_len > 0); \ - \ - (_bin_len > NM_STRLEN(scheme) + 1 && _bin[_bin_len - 1] == '\0' \ - && memcmp(_bin, scheme, NM_STRLEN(scheme)) == 0); \ - }) - -static void -cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - gs_unref_bytes GBytes *bytes = NULL; - const char * bin = NULL; - gsize bin_len = 0; - char * path; - gboolean path_exists; - - bytes = get_bytes(info, setting_name, key, TRUE, FALSE); - if (bytes) - bin = g_bytes_get_data(bytes, &bin_len); - if (bin_len == 0) { - if (!info->error) { - handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid key/cert value")); - } - return; - } - - if (HAS_SCHEME_PREFIX(bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)) { - const char * path2 = &bin[NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)]; - gs_free char *path2_free = NULL; - - if (nm_setting_802_1x_check_cert_scheme(bin, bin_len, NULL) - != NM_SETTING_802_1X_CK_SCHEME_PATH) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value path \"%s\""), - bin); - return; - } - - g_object_set(setting, key, bytes, NULL); - - if (path2[0] != '/') { - /* we want to read absolute paths because we use keyfile as exchange - * between different processes which might not have the same cwd. */ - path2_free = get_cert_path(info->base_dir, - (const guint8 *) path2, - bin_len - NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) - 1); - path2 = path2_free; - } - - /* FIXME(keyfile-parse-in-memory): keyfile reader must not access the file system and - * (in a first step) only operate in memory-only. If the presence of files should be checked, - * then by invoking a callback (and possibly keyfile settings plugin would - * collect the file names to be checked and check them later). */ - if (!g_file_test(path2, G_FILE_TEST_EXISTS)) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, - _("certificate or key file '%s' does not exist"), - path2); - } - return; - } - - if (HAS_SCHEME_PREFIX(bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11)) { - if (nm_setting_802_1x_check_cert_scheme(bin, bin_len, NULL) - != NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid PKCS#11 URI \"%s\""), - bin); - return; - } - - g_object_set(setting, key, bytes, NULL); - return; - } - - if (HAS_SCHEME_PREFIX(bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)) { - const char *cdata = bin + NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB); - gsize cdata_len = bin_len - NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB) - 1; - gs_free guchar *bin_decoded = NULL; - gsize bin_decoded_len = 0; - gsize i; - gboolean valid_base64; - gs_unref_bytes GBytes *val = NULL; - - /* Let's be strict here. We expect valid base64, no funny stuff!! - * We didn't write such invalid data ourselfes and refuse to read it as blob. */ - if ((valid_base64 = (cdata_len % 4 == 0))) { - for (i = 0; i < cdata_len; i++) { - char c = cdata[i]; - - if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') - || (c == '+' || c == '/'))) { - if (c != '=' || i < cdata_len - 2) - valid_base64 = FALSE; - else { - for (; i < cdata_len; i++) { - if (cdata[i] != '=') - valid_base64 = FALSE; - } - } - break; - } - } - } - if (valid_base64) - bin_decoded = g_base64_decode(cdata, &bin_decoded_len); - - if (bin_decoded_len == 0) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value data:;base64, is not base64")); - return; - } - - if (nm_setting_802_1x_check_cert_scheme(bin_decoded, bin_decoded_len, NULL) - != NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* The blob probably starts with "file://". Setting the cert data will confuse NMSetting8021x. - * In fact this is a limitation of NMSetting8021x which does not support setting blobs that start - * with file://. Just warn and return TRUE to signal that we ~handled~ the setting. */ - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value data:;base64,file://")); - return; - } - - val = g_bytes_new_take(g_steal_pointer(&bin_decoded), bin_decoded_len); - g_object_set(setting, key, val, NULL); - return; - } - - /* If not, it might be a plain path */ - path = - nm_keyfile_detect_unqualified_path_scheme(info->base_dir, bin, bin_len, TRUE, &path_exists); - if (path) { - gs_unref_bytes GBytes *val = NULL; - - /* Construct the proper value as required for the PATH scheme */ - val = g_bytes_new_take(path, strlen(path) + 1); - g_object_set(setting, key, val, NULL); - - /* Warn if the certificate didn't exist */ - if (!path_exists) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, - _("certificate or key file '%s' does not exist"), - path); - } - return; - } - - if (nm_setting_802_1x_check_cert_scheme(bin, bin_len, NULL) - != NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* The blob probably starts with "file://" but contains invalid characters for a path. - * Setting the cert data will confuse NMSetting8021x. - * In fact, NMSetting8021x does not support setting such binary data, so just warn and - * continue. */ - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key/cert value is not a valid blob")); - return; - } - - g_object_set(setting, key, bytes, NULL); -} - -static int -_parity_from_char(int ch) -{ -#if NM_MORE_ASSERTS > 5 - { - static char check = 0; - - if (check == 0) { - nm_auto_unref_gtypeclass GEnumClass *klass = - g_type_class_ref(NM_TYPE_SETTING_SERIAL_PARITY); - guint i; - - check = 1; - - /* In older versions, parity was G_TYPE_CHAR/gint8, and the character - * value was stored as integer. - * For example parity=69 equals parity=E, meaning NM_SETTING_SERIAL_PARITY_EVEN. - * - * That means, certain values are reserved. Assert that these numbers - * are not reused when we extend NMSettingSerialParity enum. - * Actually, since NM_SETTING_SERIAL_PARITY is g_param_spec_enum(), - * we anyway cannot extend the enum without breaking API... - * - * [1] commit "a91e60902e libnm-core: make NMSettingSerial:parity an enum" - * [2] https://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=a91e60902eabae1de93d61323dae6ac894b5d40f - */ - g_assert(G_IS_ENUM_CLASS(klass)); - for (i = 0; i < klass->n_values; i++) { - const GEnumValue *v = &klass->values[i]; - int num = v->value; - - g_assert(_parity_from_char(num) == -1); - g_assert(!NM_IN_SET(num, 'e', 'E', 'o', 'O', 'n', 'N')); - } - } - } -#endif - - switch (ch) { - case 'E': - case 'e': - return NM_SETTING_SERIAL_PARITY_EVEN; - case 'O': - case 'o': - return NM_SETTING_SERIAL_PARITY_ODD; - case 'N': - case 'n': - return NM_SETTING_SERIAL_PARITY_NONE; - } - - return -1; -} - -static void -parity_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - gs_free_error GError *err = NULL; - int parity; - gs_free char * tmp_str = NULL; - gint64 i64; - - /* Keyfile traditionally stored this as the ASCII value for 'E', 'o', or 'n'. - * We now accept either that or the (case-insensitive) character itself (but - * still always write it the old way, for backward compatibility). - */ - tmp_str = nm_keyfile_plugin_kf_get_value(info->keyfile, setting_name, key, &err); - if (err) - goto out_err; - - if (tmp_str && tmp_str[0] != '\0' && tmp_str[1] == '\0') { - /* the ASCII characters like 'E' are taken directly... */ - parity = _parity_from_char(tmp_str[0]); - if (parity >= 0) - goto parity_good; - } - - i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT, G_MAXINT, G_MININT64); - if (i64 != G_MININT64 && errno == 0) { - if ((parity = _parity_from_char(i64)) >= 0) { - /* another oddity: the string is a valid number. However, if the numeric values - * is one of the supported ASCII codes, accept it (like 69 for 'E'). - */ - goto parity_good; - } - - /* Finally, take the numeric value as is. */ - parity = i64; - goto parity_good; - } - - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid parity value '%s'"), - tmp_str ?: ""); - return; - -parity_good: - nm_g_object_set_property_enum(G_OBJECT(setting), - key, - NM_TYPE_SETTING_SERIAL_PARITY, - parity, - &err); - -out_err: - if (!err) - return; - if (nm_keyfile_error_is_not_found(err)) { - /* ignore such errors. The key is not present. */ - return; - } - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid setting: %s"), - err->message); -} - -static void -team_config_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - gs_free char *conf = NULL; - gs_free_error GError *error = NULL; - - conf = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); - - g_object_set(G_OBJECT(setting), key, conf, NULL); - - if (conf && !nm_setting_verify(setting, NULL, &error)) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid team configuration: %s"), - error->message); - g_object_set(G_OBJECT(setting), key, NULL, NULL); - } -} - -static void -bridge_vlan_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - gs_unref_ptrarray GPtrArray *vlans = NULL; - gs_free char * value = NULL; - gs_free const char ** strv = NULL; - const char *const * iter; - GError * local = NULL; - NMBridgeVlan * vlan; - - value = nm_keyfile_plugin_kf_get_string(info->keyfile, nm_setting_get_name(setting), key, NULL); - if (!value || !value[0]) - return; - - vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); - - strv = nm_utils_escaped_tokens_split(value, ","); - if (strv) { - for (iter = strv; *iter; iter++) { - vlan = nm_bridge_vlan_from_str(*iter, &local); - if (!vlan) { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - "invalid bridge VLAN: %s", - local->message); - g_clear_error(&local); - continue; - } - g_ptr_array_add(vlans, vlan); - } - } - - if (vlans->len > 0) - g_object_set(setting, key, vlans, NULL); -} - -static void -qdisc_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - gs_unref_ptrarray GPtrArray *qdiscs = NULL; - gs_strfreev char ** keys = NULL; - gsize n_keys = 0; - int i; - - keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); - if (n_keys == 0) - return; - - qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref); - - for (i = 0; i < n_keys; i++) { - NMTCQdisc * qdisc; - const char * qdisc_parent; - gs_free char *qdisc_rest = NULL; - gs_free char *qdisc_str = NULL; - gs_free_error GError *err = NULL; - - if (!g_str_has_prefix(keys[i], "qdisc.")) - continue; - - qdisc_parent = keys[i] + sizeof("qdisc.") - 1; - qdisc_rest = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, keys[i], NULL); - qdisc_str = g_strdup_printf( - "%s%s %s", - _nm_utils_parse_tc_handle(qdisc_parent, NULL) != TC_H_UNSPEC ? "parent " : "", - qdisc_parent, - qdisc_rest); - - qdisc = nm_utils_tc_qdisc_from_str(qdisc_str, &err); - if (!qdisc) { - handle_warn(info, - keys[i], - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid qdisc: %s"), - err->message); - } else { - g_ptr_array_add(qdiscs, qdisc); - } - } - - if (qdiscs->len >= 1) - g_object_set(setting, key, qdiscs, NULL); -} - -static void -tfilter_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) -{ - const char * setting_name = nm_setting_get_name(setting); - gs_unref_ptrarray GPtrArray *tfilters = NULL; - gs_strfreev char ** keys = NULL; - gsize n_keys = 0; - int i; - - keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); - if (n_keys == 0) - return; - - tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref); - - for (i = 0; i < n_keys; i++) { - NMTCTfilter * tfilter; - const char * tfilter_parent; - gs_free char *tfilter_rest = NULL; - gs_free char *tfilter_str = NULL; - gs_free_error GError *err = NULL; - - if (!g_str_has_prefix(keys[i], "tfilter.")) - continue; - - tfilter_parent = keys[i] + sizeof("tfilter.") - 1; - tfilter_rest = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, keys[i], NULL); - tfilter_str = g_strdup_printf( - "%s%s %s", - _nm_utils_parse_tc_handle(tfilter_parent, NULL) != TC_H_UNSPEC ? "parent " : "", - tfilter_parent, - tfilter_rest); - - tfilter = nm_utils_tc_tfilter_from_str(tfilter_str, &err); - if (!tfilter) { - handle_warn(info, - keys[i], - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid tfilter: %s"), - err->message); - } else { - g_ptr_array_add(tfilters, tfilter); - } - } - - if (tfilters->len >= 1) - g_object_set(setting, key, tfilters, NULL); -} - -/*****************************************************************************/ - -/* Some setting properties also contain setting names, such as - * NMSettingConnection's 'type' property (which specifies the base type of the - * connection, eg ethernet or wifi) or the 802-11-wireless setting's - * 'security' property which specifies whether or not the AP requires - * encryption. This function handles translating those properties' values - * from the real setting name to the more-readable alias. - */ -static void -setting_alias_writer(KeyfileWriterInfo *info, - NMSetting * setting, - const char * key, - const GValue * value) -{ - const char *str, *alias; - - str = g_value_get_string(value); - alias = nm_keyfile_plugin_get_alias_for_setting_name(str); - nm_keyfile_plugin_kf_set_string(info->keyfile, nm_setting_get_name(setting), key, alias ?: str); -} - -static void -sriov_vfs_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) -{ - GPtrArray *vfs; - guint i; - - vfs = g_value_get_boxed(value); - if (!vfs) - return; - - for (i = 0; i < vfs->len; i++) { - const NMSriovVF *vf = vfs->pdata[i]; - gs_free char * kf_value = NULL; - char kf_key[32]; - - kf_value = nm_utils_sriov_vf_to_str(vf, TRUE, NULL); - if (!kf_value) - continue; - - nm_sprintf_buf(kf_key, "vf.%u", nm_sriov_vf_get_index(vf)); - - nm_keyfile_plugin_kf_set_string(info->keyfile, - nm_setting_get_name(setting), - kf_key, - kf_value); - } -} - -static void -write_array_of_uint(GKeyFile *file, NMSetting *setting, const char *key, const GValue *value) -{ - GArray *array; - - array = g_value_get_boxed(value); - - nm_assert(!array || g_array_get_element_size(array) == sizeof(guint)); - - if (!array || !array->len) - return; - - nm_keyfile_plugin_kf_set_integer_list_uint(file, - nm_setting_get_name(setting), - key, - (const guint *) array->data, - array->len); -} - -static void -dns_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) -{ - char **list; - - list = g_value_get_boxed(value); - if (list && list[0]) { - nm_keyfile_plugin_kf_set_string_list(info->keyfile, - nm_setting_get_name(setting), - key, - (const char **) list, - g_strv_length(list)); - } -} - -static void -ip6_addr_gen_mode_writer(KeyfileWriterInfo *info, - NMSetting * setting, - const char * key, - const GValue * value) -{ - NMSettingIP6ConfigAddrGenMode addr_gen_mode; - gs_free char * str = NULL; - - addr_gen_mode = (NMSettingIP6ConfigAddrGenMode) g_value_get_int(value); - str = nm_utils_enum_to_str(nm_setting_ip6_config_addr_gen_mode_get_type(), addr_gen_mode); - nm_keyfile_plugin_kf_set_string(info->keyfile, nm_setting_get_name(setting), key, str); -} - -static void -write_ip_values(GKeyFile * file, - const char *setting_name, - GPtrArray * array, - const char *gateway, - gboolean is_route) -{ - if (array->len > 0) { - nm_auto_str_buf NMStrBuf output = NM_STR_BUF_INIT(2 * INET_ADDRSTRLEN + 10, FALSE); - int addr_family; - guint i; - const char * addr; - const char * gw; - guint32 plen; - char key_name[64]; - char * key_name_idx; - - addr_family = - nm_streq(setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME) ? AF_INET : AF_INET6; - - strcpy(key_name, is_route ? "route" : "address"); - key_name_idx = key_name + strlen(key_name); - - for (i = 0; i < array->len; i++) { - gint64 metric = -1; - - if (is_route) { - NMIPRoute *route = array->pdata[i]; - - addr = nm_ip_route_get_dest(route); - plen = nm_ip_route_get_prefix(route); - gw = nm_ip_route_get_next_hop(route); - metric = nm_ip_route_get_metric(route); - } else { - NMIPAddress *address = array->pdata[i]; - - addr = nm_ip_address_get_address(address); - plen = nm_ip_address_get_prefix(address); - gw = (i == 0) ? gateway : NULL; - } - - nm_str_buf_set_size(&output, 0, FALSE, FALSE); - nm_str_buf_append_printf(&output, "%s/%u", addr, plen); - if (metric != -1 || gw) { - /* Older versions of the plugin do not support the form - * "a.b.c.d/plen,,metric", so, we always have to write the - * gateway, even if there isn't one. - * The current version supports reading of the above form. - */ - if (!gw) { - if (addr_family == AF_INET) - gw = "0.0.0.0"; - else - gw = "::"; - } - - nm_str_buf_append_c(&output, ','); - nm_str_buf_append(&output, gw); - if (is_route && metric != -1) - nm_str_buf_append_printf(&output, ",%lu", (unsigned long) metric); - } - - sprintf(key_name_idx, "%u", i + 1); - nm_keyfile_plugin_kf_set_string(file, - setting_name, - key_name, - nm_str_buf_get_str(&output)); - - if (is_route) { - gs_free char *attributes = NULL; - - attributes = - nm_utils_format_variant_attributes(_nm_ip_route_get_attributes(array->pdata[i]), - ',', - '='); - if (attributes) { - g_strlcat(key_name, "_options", sizeof(key_name)); - nm_keyfile_plugin_kf_set_string(file, setting_name, key_name, attributes); - } - } - } - } -} - -static void -addr_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) -{ - GPtrArray * array; - const char *setting_name = nm_setting_get_name(setting); - const char *gateway = nm_setting_ip_config_get_gateway(NM_SETTING_IP_CONFIG(setting)); - - array = (GPtrArray *) g_value_get_boxed(value); - if (array && array->len) - write_ip_values(info->keyfile, setting_name, array, gateway, FALSE); -} - -static void -route_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) -{ - GPtrArray * array; - const char *setting_name = nm_setting_get_name(setting); - - array = (GPtrArray *) g_value_get_boxed(value); - if (array && array->len) - write_ip_values(info->keyfile, setting_name, array, NULL, TRUE); -} - -static void -bridge_vlan_writer(KeyfileWriterInfo *info, - NMSetting * setting, - const char * key, - const GValue * value) -{ - GPtrArray *vlans; - - vlans = g_value_get_boxed(value); - if (vlans && vlans->len > 0) { - const guint string_initial_size = vlans->len * 10u; - nm_auto_str_buf NMStrBuf string = NM_STR_BUF_INIT(string_initial_size, FALSE); - guint i; - - for (i = 0; i < vlans->len; i++) { - gs_free char *vlan_str = NULL; - - vlan_str = nm_bridge_vlan_to_str(vlans->pdata[i], NULL); - if (i > 0) - nm_str_buf_append_c(&string, ','); - nm_utils_escaped_tokens_escape_strbuf_assert(vlan_str, ",", &string); - } - - nm_keyfile_plugin_kf_set_string(info->keyfile, - nm_setting_get_name(setting), - "vlans", - nm_str_buf_get_str(&string)); - } -} - -static void -wired_s390_options_parser_full(KeyfileReaderInfo * info, - const NMMetaSettingInfo * setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty * pip, - NMSetting * setting) -{ - NMSettingWired * s_wired = NM_SETTING_WIRED(setting); - gs_strfreev char **keys = NULL; - gsize n_keys; - gsize i; - - keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, - ETHERNET_S390_OPTIONS_GROUP_NAME, - &n_keys, - NULL); - for (i = 0; i < n_keys; i++) { - gs_free char *value = NULL; - gs_free char *key_to_free = NULL; - - value = nm_keyfile_plugin_kf_get_string(info->keyfile, - ETHERNET_S390_OPTIONS_GROUP_NAME, - keys[i], - NULL); - if (!value) - continue; - - nm_setting_wired_add_s390_option(s_wired, - nm_keyfile_key_decode(keys[i], &key_to_free), - value); - } -} - -static void -wired_s390_options_writer_full(KeyfileWriterInfo * info, - const NMMetaSettingInfo * setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty * pip, - NMSetting * setting) -{ - NMSettingWired *s_wired = NM_SETTING_WIRED(setting); - guint i, n; - - n = nm_setting_wired_get_num_s390_options(s_wired); - for (i = 0; i < n; i++) { - gs_free char *key_to_free = NULL; - const char * opt_key; - const char * opt_val; - - nm_setting_wired_get_s390_option(s_wired, i, &opt_key, &opt_val); - nm_keyfile_plugin_kf_set_string(info->keyfile, - ETHERNET_S390_OPTIONS_GROUP_NAME, - nm_keyfile_key_encode(opt_key, &key_to_free), - opt_val); - } -} - -static void -ip_routing_rule_writer_full(KeyfileWriterInfo * info, - const NMMetaSettingInfo * setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty * pip, - NMSetting * setting) -{ - const char * setting_name = nm_setting_get_name(setting); - NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG(setting); - guint i, j, n; - char key_name_full[100] = "routing-rule"; - char * key_name_num = &key_name_full[NM_STRLEN("routing-rule")]; - - n = nm_setting_ip_config_get_num_routing_rules(s_ip); - j = 0; - for (i = 0; i < n; i++) { - NMIPRoutingRule *rule = nm_setting_ip_config_get_routing_rule(s_ip, i); - gs_free char * str = NULL; - - str = - nm_ip_routing_rule_to_string(rule, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE, NULL, NULL); - if (!str) - continue; - - sprintf(key_name_num, "%u", ++j); - nm_keyfile_plugin_kf_set_string(info->keyfile, setting_name, key_name_full, str); - } -} - -static void -qdisc_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) -{ - nm_auto_free_gstring GString *key_name = NULL; - nm_auto_free_gstring GString *value_str = NULL; - GPtrArray * array; - guint i; - - array = g_value_get_boxed(value); - if (!array || !array->len) - return; - - for (i = 0; i < array->len; i++) { - NMTCQdisc *qdisc = array->pdata[i]; - - nm_gstring_prepare(&key_name); - nm_gstring_prepare(&value_str); - - g_string_append(key_name, "qdisc."); - _nm_utils_string_append_tc_parent(key_name, NULL, nm_tc_qdisc_get_parent(qdisc)); - _nm_utils_string_append_tc_qdisc_rest(value_str, qdisc); - - nm_keyfile_plugin_kf_set_string(info->keyfile, - NM_SETTING_TC_CONFIG_SETTING_NAME, - key_name->str, - value_str->str); - } -} - -static void -tfilter_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) -{ - nm_auto_free_gstring GString *key_name = NULL; - nm_auto_free_gstring GString *value_str = NULL; - GPtrArray * array; - guint i; - - array = g_value_get_boxed(value); - if (!array || !array->len) - return; - - for (i = 0; i < array->len; i++) { - NMTCTfilter *tfilter = array->pdata[i]; - - nm_gstring_prepare(&key_name); - nm_gstring_prepare(&value_str); - - g_string_append(key_name, "tfilter."); - _nm_utils_string_append_tc_parent(key_name, NULL, nm_tc_tfilter_get_parent(tfilter)); - _nm_utils_string_append_tc_tfilter_rest(value_str, tfilter, NULL); - - nm_keyfile_plugin_kf_set_string(info->keyfile, - NM_SETTING_TC_CONFIG_SETTING_NAME, - key_name->str, - value_str->str); - } -} - -static void -_writer_full_ovs_external_ids_data(KeyfileWriterInfo * info, - const NMMetaSettingInfo * setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty * pip, - NMSetting * setting) -{ - GHashTable * hash; - NMUtilsNamedValue data_static[300u / sizeof(NMUtilsNamedValue)]; - gs_free NMUtilsNamedValue *data_free = NULL; - const NMUtilsNamedValue * data; - guint data_len; - char full_key_static[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + 300u]; - guint i; - - nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)); - nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)); - - hash = _nm_setting_ovs_external_ids_get_data(NM_SETTING_OVS_EXTERNAL_IDS(setting)); - if (!hash) - return; - - data = nm_utils_named_values_from_strdict(hash, &data_len, data_static, &data_free); - if (data_len == 0) - return; - - memcpy(full_key_static, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)); - - for (i = 0; i < data_len; i++) { - const char * key = data[i].name; - const char * val = data[i].value_str; - gs_free char *escaped_key_to_free = NULL; - const char * escaped_key; - gsize len; - gs_free char *full_key_free = NULL; - char * full_key = full_key_static; - - escaped_key = nm_keyfile_key_encode(key, &escaped_key_to_free); - - len = strlen(escaped_key) + 1u; - if (len >= G_N_ELEMENTS(full_key_static) - NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)) { - full_key_free = g_new(char, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + len); - full_key = full_key_free; - memcpy(full_key, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)); - } - memcpy(&full_key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)], escaped_key, len); - - nm_keyfile_plugin_kf_set_string(info->keyfile, - NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, - full_key, - val); - } -} - -static void -write_hash_of_string(GKeyFile *file, NMSetting *setting, const char *key, const GValue *value) -{ - GHashTable * hash; - const char * group_name = nm_setting_get_name(setting); - gboolean vpn_secrets = FALSE; - gs_free const char **keys = NULL; - guint i, l; - - nm_assert((NM_IS_SETTING_VPN(setting) && nm_streq(key, NM_SETTING_VPN_DATA)) - || (NM_IS_SETTING_VPN(setting) && nm_streq(key, NM_SETTING_VPN_SECRETS)) - || (NM_IS_SETTING_BOND(setting) && nm_streq(key, NM_SETTING_BOND_OPTIONS)) - || (NM_IS_SETTING_USER(setting) && nm_streq(key, NM_SETTING_USER_DATA))); - - /* Write VPN secrets out to a different group to keep them separate */ - if (NM_IS_SETTING_VPN(setting) && nm_streq(key, NM_SETTING_VPN_SECRETS)) { - group_name = NM_KEYFILE_GROUP_VPN_SECRETS; - vpn_secrets = TRUE; - } - - hash = g_value_get_boxed(value); - - keys = nm_utils_strdict_get_keys(hash, TRUE, &l); - for (i = 0; i < l; i++) { - gs_free char *to_free = NULL; - const char * property, *data; - - property = keys[i]; - - /* Handle VPN secrets specially; they are nested in the property's hash; - * we don't want to write them if the secret is not saved, not required, - * or owned by a user's secret agent. - */ - if (vpn_secrets) { - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - if (!nm_setting_get_secret_flags(setting, property, &secret_flags, NULL)) - nm_assert_not_reached(); - if (!_secret_flags_persist_secret(secret_flags)) - continue; - } - - data = g_hash_table_lookup(hash, property); - nm_keyfile_plugin_kf_set_string(file, - group_name, - nm_keyfile_key_encode(property, &to_free), - data); - } -} - -static void -ssid_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) -{ - GBytes * bytes; - const guint8 *ssid_data; - gsize ssid_len; - const char * setting_name = nm_setting_get_name(setting); - gboolean new_format = TRUE; - gsize semicolons = 0; - gsize i; - - g_return_if_fail(G_VALUE_HOLDS(value, G_TYPE_BYTES)); - - bytes = g_value_get_boxed(value); - if (!bytes) - return; - ssid_data = g_bytes_get_data(bytes, &ssid_len); - if (!ssid_data || !ssid_len) { - nm_keyfile_plugin_kf_set_string(info->keyfile, setting_name, key, ""); - return; - } - - /* Check whether each byte is printable. If not, we have to use an - * integer list, otherwise we can just use a string. - */ - for (i = 0; i < ssid_len; i++) { - const char c = ssid_data[i]; - - if (!g_ascii_isprint(c)) { - new_format = FALSE; - break; - } - if (c == ';') - semicolons++; - } - - if (new_format) { - gs_free char *ssid = NULL; - - if (semicolons == 0) - ssid = g_strndup((char *) ssid_data, ssid_len); - else { - /* Escape semicolons with backslashes to make strings - * containing ';', such as '16;17;' unambiguous */ - gsize j = 0; - - ssid = g_malloc(ssid_len + semicolons + 1); - for (i = 0; i < ssid_len; i++) { - if (ssid_data[i] == ';') - ssid[j++] = '\\'; - ssid[j++] = ssid_data[i]; - } - ssid[j] = '\0'; - } - nm_keyfile_plugin_kf_set_string(info->keyfile, setting_name, key, ssid); - } else - nm_keyfile_plugin_kf_set_integer_list_uint8(info->keyfile, - setting_name, - key, - ssid_data, - ssid_len); -} - -static void -password_raw_writer(KeyfileWriterInfo *info, - NMSetting * setting, - const char * key, - const GValue * value) -{ - const char * setting_name = nm_setting_get_name(setting); - GBytes * array; - gsize len; - const guint8 *data; - - g_return_if_fail(G_VALUE_HOLDS(value, G_TYPE_BYTES)); - - array = (GBytes *) g_value_get_boxed(value); - if (!array) - return; - data = g_bytes_get_data(array, &len); - if (!data) - len = 0; - nm_keyfile_plugin_kf_set_integer_list_uint8(info->keyfile, setting_name, key, data, len); -} - -/*****************************************************************************/ - -static void -cert_writer_default(NMConnection * connection, - GKeyFile * file, - NMSetting8021x * setting, - const char * setting_name, - const NMSetting8021xSchemeVtable *vtable) -{ - NMSetting8021xCKScheme scheme; - - scheme = vtable->scheme_func(setting); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { - gs_free char *path_free = NULL; - gs_free char *base_dir = NULL; - gs_free char *tmp = NULL; - const char * path; - - path = vtable->path_func(setting); - g_assert(path); - - /* If the path is relative, make it an absolute path. - * Relative paths make a keyfile not easily usable in another - * context. */ - if (path[0] && path[0] != '/') { - base_dir = g_get_current_dir(); - path_free = g_strconcat(base_dir, "/", path, NULL); - path = path_free; - } else - base_dir = g_path_get_dirname(path); - - /* path cannot start with "file://" or "data:;base64,", because it is an absolute path. - * Still, make sure that a prefix-less path will be recognized. This can happen - * for example if the path is longer then 500 chars. */ - tmp = nm_keyfile_detect_unqualified_path_scheme(base_dir, path, -1, FALSE, NULL); - if (tmp) - nm_clear_g_free(&tmp); - else { - tmp = g_strconcat(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL); - path = tmp; - } - - /* Path contains at least a '/', hence it cannot be recognized as the old - * binary format consisting of a list of integers. */ - - nm_keyfile_plugin_kf_set_string(file, setting_name, vtable->setting_key, path); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - GBytes * blob; - const guint8 *blob_data; - gsize blob_len; - gs_free char *blob_base64 = NULL; - gs_free char *val = NULL; - - blob = vtable->blob_func(setting); - g_assert(blob); - blob_data = g_bytes_get_data(blob, &blob_len); - - blob_base64 = g_base64_encode(blob_data, blob_len); - val = g_strconcat(NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB, blob_base64, NULL); - - nm_keyfile_plugin_kf_set_string(file, setting_name, vtable->setting_key, val); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - nm_keyfile_plugin_kf_set_string(file, - setting_name, - vtable->setting_key, - vtable->uri_func(setting)); - } else { - /* scheme_func() returns UNKNOWN in all other cases. The only valid case - * where a scheme is allowed to be UNKNOWN, is unsetting the value. In this - * case, we don't expect the writer to be called, because the default value - * will not be serialized. - * The only other reason for the scheme to be UNKNOWN is an invalid cert. - * But our connection verifies, so that cannot happen either. */ - g_return_if_reached(); - } -} - -static void -cert_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) -{ - const NMSetting8021xSchemeVtable *vtable = NULL; - const char * setting_name; - guint i; - - for (i = 0; nm_setting_8021x_scheme_vtable[i].setting_key; i++) { - if (nm_streq0(nm_setting_8021x_scheme_vtable[i].setting_key, key)) { - vtable = &nm_setting_8021x_scheme_vtable[i]; - break; - } - } - if (!vtable) - g_return_if_reached(); - - setting_name = nm_setting_get_name(NM_SETTING(setting)); - - if (info->write_handler) { - NMKeyfileHandlerData handler_data; - - _key_file_handler_data_init_write(&handler_data, - NM_KEYFILE_HANDLER_TYPE_WRITE_CERT, - info, - setting_name, - vtable->setting_key, - setting, - key); - handler_data.write_cert = (NMKeyfileHandlerDataWriteCert){ - .vtable = vtable, - }; - - if (info->write_handler(info->connection, - info->keyfile, - NM_KEYFILE_HANDLER_TYPE_WRITE_CERT, - &handler_data, - info->user_data)) - return; - if (info->error) - return; - } - - cert_writer_default(info->connection, - info->keyfile, - NM_SETTING_802_1X(setting), - setting_name, - vtable); -} - -/*****************************************************************************/ - -struct _ParseInfoProperty { - const char *property_name; - union { - void (*parser)(KeyfileReaderInfo *info, NMSetting *setting, const char *key); - void (*parser_full)(KeyfileReaderInfo * info, - const NMMetaSettingInfo * setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty * pip, - NMSetting * setting); - }; - union { - void (*writer)(KeyfileWriterInfo *info, - NMSetting * setting, - const char * key, - const GValue * value); - void (*writer_full)(KeyfileWriterInfo * info, - const NMMetaSettingInfo * setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty * pip, - NMSetting * setting); - }; - bool parser_skip; - bool parser_no_check_key : 1; - bool writer_skip : 1; - bool has_writer_full : 1; - bool has_parser_full : 1; - - /* usually, we skip to write values that have their - * default value. By setting this flag to TRUE, also - * default values are written. */ - bool writer_persist_default : 1; -}; - -#define PARSE_INFO_PROPERTY(_property_name, ...) \ - (&((const ParseInfoProperty){.property_name = _property_name, __VA_ARGS__})) - -#define PARSE_INFO_PROPERTIES(...) \ - .properties = ((const ParseInfoProperty *const[]){ \ - __VA_ARGS__ NULL, \ - }) - -typedef struct { - const ParseInfoProperty *const *properties; -} ParseInfoSetting; - -#define PARSE_INFO_SETTING(setting_type, ...) \ - [setting_type] = (&((const ParseInfoSetting){__VA_ARGS__})) - -static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_WIRELESS, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_WIRELESS_BSSID, .parser = mac_address_parser_ETHER, ), - PARSE_INFO_PROPERTY(NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, - .parser = mac_address_parser_ETHER_cloned, ), - PARSE_INFO_PROPERTY(NM_SETTING_WIRELESS_MAC_ADDRESS, - .parser = mac_address_parser_ETHER, ), - PARSE_INFO_PROPERTY(NM_SETTING_WIRELESS_SSID, - .parser = ssid_parser, - .writer = ssid_writer, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_802_1X, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_802_1X_CA_CERT, - .parser = cert_parser, - .writer = cert_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_802_1X_CLIENT_CERT, - .parser = cert_parser, - .writer = cert_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PASSWORD_RAW, - .parser = password_raw_parser, - .writer = password_raw_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PHASE2_CA_CERT, - .parser = cert_parser, - .writer = cert_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - .parser = cert_parser, - .writer = cert_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - .parser = cert_parser, - .writer = cert_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PRIVATE_KEY, - .parser = cert_parser, - .writer = cert_writer, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_WIRED, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_WIRED_CLONED_MAC_ADDRESS, - .parser = mac_address_parser_ETHER_cloned, ), - PARSE_INFO_PROPERTY(NM_SETTING_WIRED_MAC_ADDRESS, .parser = mac_address_parser_ETHER, ), - PARSE_INFO_PROPERTY(NM_SETTING_WIRED_S390_OPTIONS, - .parser_no_check_key = TRUE, - .parser_full = wired_s390_options_parser_full, - .writer_full = wired_s390_options_writer_full, - .has_parser_full = TRUE, - .has_writer_full = TRUE, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_BLUETOOTH, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_BLUETOOTH_BDADDR, - .parser = mac_address_parser_ETHER, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_BOND, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_BOND_OPTIONS, .parser_no_check_key = TRUE, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_BRIDGE, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_BRIDGE_MAC_ADDRESS, - .parser = mac_address_parser_ETHER, ), - PARSE_INFO_PROPERTY(NM_SETTING_BRIDGE_VLANS, - .parser_no_check_key = TRUE, - .parser = bridge_vlan_parser, - .writer = bridge_vlan_writer, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_BRIDGE_PORT, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_BRIDGE_PORT_VLANS, - .parser_no_check_key = TRUE, - .parser = bridge_vlan_parser, - .writer = bridge_vlan_writer, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_CONNECTION, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_CONNECTION_READ_ONLY, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_CONNECTION_TYPE, - .parser = setting_alias_parser, - .writer = setting_alias_writer, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_INFINIBAND, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_INFINIBAND_MAC_ADDRESS, - .parser = mac_address_parser_INFINIBAND, ), ), ), - PARSE_INFO_SETTING(NM_META_SETTING_TYPE_IP4_CONFIG, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ADDRESSES, - .parser_no_check_key = TRUE, - .parser = ip_address_or_route_parser, - .writer = addr_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_DNS, - .parser_no_check_key = TRUE, - .parser = ip_dns_parser, - .writer = dns_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_GATEWAY, .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ROUTES, - .parser_no_check_key = TRUE, - .parser = ip_address_or_route_parser, - .writer = route_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ROUTING_RULES, - .parser_no_check_key = TRUE, - .parser_full = ip_routing_rule_parser_full, - .writer_full = ip_routing_rule_writer_full, - .has_parser_full = TRUE, - .has_writer_full = TRUE, ), ), ), - PARSE_INFO_SETTING(NM_META_SETTING_TYPE_IP6_CONFIG, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, - .parser_no_check_key = TRUE, - .parser = ip6_addr_gen_mode_parser, - .writer = ip6_addr_gen_mode_writer, - .writer_persist_default = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ADDRESSES, - .parser_no_check_key = TRUE, - .parser = ip_address_or_route_parser, - .writer = addr_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_DNS, - .parser_no_check_key = TRUE, - .parser = ip_dns_parser, - .writer = dns_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_GATEWAY, .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ROUTES, - .parser_no_check_key = TRUE, - .parser = ip_address_or_route_parser, - .writer = route_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ROUTING_RULES, - .parser_no_check_key = TRUE, - .parser_full = ip_routing_rule_parser_full, - .writer_full = ip_routing_rule_writer_full, - .has_parser_full = TRUE, - .has_writer_full = TRUE, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_OVS_EXTERNAL_IDS_DATA, - .parser_no_check_key = TRUE, - .parser_full = _parser_full_ovs_external_ids_data, - .writer_full = _writer_full_ovs_external_ids_data, - .has_parser_full = TRUE, - .has_writer_full = TRUE, ), ), ), - PARSE_INFO_SETTING(NM_META_SETTING_TYPE_SERIAL, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_SERIAL_PARITY, - .parser = parity_parser, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_SRIOV, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_SRIOV_VFS, - .parser_no_check_key = TRUE, - .parser = sriov_vfs_parser, - .writer = sriov_vfs_writer, ), ), ), - PARSE_INFO_SETTING(NM_META_SETTING_TYPE_TC_CONFIG, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_TC_CONFIG_QDISCS, - .parser_no_check_key = TRUE, - .parser = qdisc_parser, - .writer = qdisc_writer, ), - PARSE_INFO_PROPERTY(NM_SETTING_TC_CONFIG_TFILTERS, - .parser_no_check_key = TRUE, - .parser = tfilter_parser, - .writer = tfilter_writer, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_TEAM, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_CONFIG, .parser = team_config_parser, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_LINK_WATCHERS, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_MCAST_REJOIN_COUNT, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER, .parser_skip = TRUE, .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_ACTIVE, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_FAST_RATE, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_MIN_PORTS, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_SYS_PRIO, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_TX_BALANCER, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_TX_HASH, - .parser_skip = TRUE, - .writer_skip = TRUE, ), ), ), - PARSE_INFO_SETTING(NM_META_SETTING_TYPE_TEAM_PORT, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_TEAM_CONFIG, - .parser = team_config_parser, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_LACP_KEY, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_LACP_PRIO, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_LINK_WATCHERS, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_PRIO, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_QUEUE_ID, - .parser_skip = TRUE, - .writer_skip = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_STICKY, - .parser_skip = TRUE, - .writer_skip = TRUE, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_USER, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_USER_DATA, .parser_no_check_key = TRUE, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_VLAN, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_VLAN_FLAGS, .writer_persist_default = TRUE, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_VPN, - PARSE_INFO_PROPERTIES( - PARSE_INFO_PROPERTY(NM_SETTING_VPN_DATA, .parser_no_check_key = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_VPN_PERSISTENT, .parser_no_check_key = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_VPN_SECRETS, .parser_no_check_key = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_VPN_SERVICE_TYPE, .parser_no_check_key = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_VPN_TIMEOUT, .parser_no_check_key = TRUE, ), - PARSE_INFO_PROPERTY(NM_SETTING_VPN_USER_NAME, .parser_no_check_key = TRUE, ), ), ), - PARSE_INFO_SETTING( - NM_META_SETTING_TYPE_WIMAX, - PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_WIMAX_MAC_ADDRESS, - .parser = mac_address_parser_ETHER, ), ), ), -}; - -static void -_parse_info_find(NMSetting * setting, - const char * property_name, - const NMMetaSettingInfo **out_setting_info, - const ParseInfoSetting ** out_parse_info_setting, - const ParseInfoProperty **out_parse_info_property) -{ - const NMMetaSettingInfo *setting_info; - const ParseInfoSetting * pis; - const ParseInfoProperty *pip; - -#if NM_MORE_ASSERTS > 10 - { - guint i, j; - static int asserted = FALSE; - - if (!asserted) { - for (i = 0; i < G_N_ELEMENTS(parse_infos); i++) { - pis = parse_infos[i]; - - if (!pis) - continue; - if (!pis->properties) - continue; - - g_assert(pis->properties[0]); - for (j = 0; pis->properties[j]; j++) { - const ParseInfoProperty *pip0; - const ParseInfoProperty *pipj = pis->properties[j]; - - g_assert(pipj->property_name); - if (j > 0 && (pip0 = pis->properties[j - 1]) - && strcmp(pip0->property_name, pipj->property_name) >= 0) { - g_error("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", - i, - j - 1, - nm_meta_setting_infos[i].setting_name, - pip0->property_name, - nm_meta_setting_infos[i].setting_name, - pipj->property_name); - } - } - } - asserted = TRUE; - } - } -#endif - - if (!NM_IS_SETTING(setting) || !(setting_info = NM_SETTING_GET_CLASS(setting)->setting_info)) { - /* handle invalid setting objects gracefully. */ - NM_SET_OUT(out_setting_info, NULL); - NM_SET_OUT(out_parse_info_setting, NULL); - NM_SET_OUT(out_parse_info_property, NULL); - return; - } - - nm_assert(setting_info->setting_name); - nm_assert(_NM_INT_NOT_NEGATIVE(setting_info->meta_type)); - nm_assert(setting_info->meta_type < G_N_ELEMENTS(parse_infos)); - - pis = parse_infos[setting_info->meta_type]; - - pip = NULL; - if (pis && property_name) { - gssize idx; - - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(ParseInfoProperty, property_name) == 0); - - idx = nm_utils_ptrarray_find_binary_search((gconstpointer *) pis->properties, - NM_PTRARRAY_LEN(pis->properties), - &property_name, - nm_strcmp_p_with_data, - NULL, - NULL, - NULL); - if (idx >= 0) - pip = pis->properties[idx]; - } - - NM_SET_OUT(out_setting_info, setting_info); - NM_SET_OUT(out_parse_info_setting, pis); - NM_SET_OUT(out_parse_info_property, pip); -} - -/*****************************************************************************/ - -static void -read_one_setting_value(KeyfileReaderInfo * info, - NMSetting * setting, - const NMSettInfoProperty *property_info) -{ - GKeyFile * keyfile = info->keyfile; - gs_free_error GError * err = NULL; - const NMMetaSettingInfo *setting_info; - const ParseInfoProperty *pip; - gs_free char * tmp_str = NULL; - const char * key; - GType type; - guint64 u64; - gint64 i64; - - nm_assert(!info->error); - nm_assert(!property_info->param_spec - || nm_streq(property_info->param_spec->name, property_info->name)); - - key = property_info->name; - - _parse_info_find(setting, key, &setting_info, NULL, &pip); - - nm_assert(setting_info); - - if (!pip) { - if (nm_streq(key, NM_SETTING_NAME)) - return; - if (!property_info->param_spec) - return; - if ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) - != G_PARAM_WRITABLE) - return; - } else { - if (pip->parser_skip) - return; - if (pip->has_parser_full) { - pip->parser_full(info, setting_info, property_info, pip, setting); - return; - } - } - - nm_assert(property_info->param_spec); - nm_assert((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) - == G_PARAM_WRITABLE); - - /* Check for the exact key in the GKeyFile if required. Most setting - * properties map 1:1 to a key in the GKeyFile, but for those properties - * like IP addresses and routes where more than one value is actually - * encoded by the setting property, this won't be true. - */ - if ((!pip || !pip->parser_no_check_key) - && !nm_keyfile_plugin_kf_has_key(keyfile, setting_info->setting_name, key, &err)) { - /* Key doesn't exist or an error occurred, thus nothing to do. */ - if (err) { - if (!handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("error loading setting value: %s"), - err->message)) - return; - } - return; - } - - if (pip && pip->parser) { - pip->parser(info, setting, key); - return; - } - - type = G_PARAM_SPEC_VALUE_TYPE(property_info->param_spec); - - if (type == G_TYPE_STRING) { - gs_free char *str_val = NULL; - - str_val = nm_keyfile_plugin_kf_get_string(keyfile, setting_info->setting_name, key, &err); - if (!err) - nm_g_object_set_property_string_take(G_OBJECT(setting), - key, - g_steal_pointer(&str_val), - &err); - } else if (type == G_TYPE_UINT) { - tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); - if (!err) { - u64 = _nm_utils_ascii_str_to_uint64(tmp_str, 0, 0, G_MAXUINT, G_MAXUINT64); - if (u64 == G_MAXUINT64 && errno != 0) { - g_set_error_literal(&err, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_uint(G_OBJECT(setting), key, u64, &err); - } - } else if (type == G_TYPE_INT) { - tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); - if (!err) { - i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT, G_MAXINT, G_MININT64); - if (i64 == G_MININT64 && errno != 0) { - g_set_error_literal(&err, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_int(G_OBJECT(setting), key, i64, &err); - } - } else if (type == G_TYPE_BOOLEAN) { - gboolean bool_val; - - bool_val = nm_keyfile_plugin_kf_get_boolean(keyfile, setting_info->setting_name, key, &err); - if (!err) - nm_g_object_set_property_boolean(G_OBJECT(setting), key, bool_val, &err); - } else if (type == G_TYPE_CHAR) { - tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); - if (!err) { - /* As documented by glib, G_TYPE_CHAR is really a (signed!) gint8. */ - i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT8, G_MAXINT8, G_MININT64); - if (i64 == G_MININT64 && errno != 0) { - g_set_error_literal(&err, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_char(G_OBJECT(setting), key, i64, &err); - } - } else if (type == G_TYPE_UINT64) { - tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); - if (!err) { - u64 = _nm_utils_ascii_str_to_uint64(tmp_str, 0, 0, G_MAXUINT64, G_MAXUINT64); - if (u64 == G_MAXUINT64 && errno != 0) { - g_set_error_literal(&err, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_uint64(G_OBJECT(setting), key, u64, &err); - } - } else if (type == G_TYPE_INT64) { - tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); - if (!err) { - i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT64, G_MAXINT64, G_MAXINT64); - if (i64 == G_MAXINT64 && errno != 0) { - g_set_error_literal(&err, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_int64(G_OBJECT(setting), key, i64, &err); - } - } else if (type == G_TYPE_BYTES) { - nm_auto_unref_bytearray GByteArray *array = NULL; - gs_unref_bytes GBytes *bytes = NULL; - gs_free guint *tmp = NULL; - gsize length; - int i; - gboolean already_warned = FALSE; - - tmp = nm_keyfile_plugin_kf_get_integer_list_uint(keyfile, - setting_info->setting_name, - key, - &length, - NULL); - - array = g_byte_array_sized_new(length); - for (i = 0; i < length; i++) { - const guint val = tmp[i]; - unsigned char v = (unsigned char) (val & 0xFF); - - if (val > 255u) { - if (!already_warned - && !handle_warn( - info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid byte element '%u' (not between 0 and 255 inclusive)"), - val)) - return; - already_warned = TRUE; - } else - g_byte_array_append(array, (const unsigned char *) &v, sizeof(v)); - } - - bytes = g_byte_array_free_to_bytes(g_steal_pointer(&array)); - g_object_set(setting, key, bytes, NULL); - } else if (type == G_TYPE_STRV) { - gs_strfreev char **sa = NULL; - gsize length; - - sa = nm_keyfile_plugin_kf_get_string_list(keyfile, - setting_info->setting_name, - key, - &length, - NULL); - g_object_set(setting, key, sa, NULL); - } else if (type == G_TYPE_HASH_TABLE) { - read_hash_of_string(info, keyfile, setting, key); - } else if (type == G_TYPE_ARRAY) { - read_array_of_uint(keyfile, setting, key); - } else if (G_TYPE_IS_FLAGS(type)) { - tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); - if (!err) { - u64 = _nm_utils_ascii_str_to_uint64(tmp_str, 0, 0, G_MAXUINT, G_MAXUINT64); - if (u64 == G_MAXUINT64 && errno != 0) { - g_set_error_literal(&err, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_flags(G_OBJECT(setting), key, type, u64, &err); - } - } else if (G_TYPE_IS_ENUM(type)) { - tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); - if (!err) { - i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT, G_MAXINT, G_MAXINT64); - if (i64 == G_MAXINT64 && errno != 0) { - g_set_error_literal(&err, - G_KEY_FILE_ERROR, - G_KEY_FILE_ERROR_INVALID_VALUE, - _("value cannot be interpreted as integer")); - } else - nm_g_object_set_property_enum(G_OBJECT(setting), key, type, i64, &err); - } - } else - g_return_if_reached(); - - if (err) { - if (nm_keyfile_error_is_not_found(err)) { - /* ignore such errors. The key is not present. */ - } else { - handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid setting: %s"), - err->message); - } - } -} - -static void -_read_setting(KeyfileReaderInfo *info) -{ - const NMSettInfoSetting *sett_info; - gs_unref_object NMSetting *setting = NULL; - const char * alias; - GType type; - guint i; - - alias = nm_keyfile_plugin_get_setting_name_for_alias(info->group); - if (!alias) - alias = info->group; - - type = nm_setting_lookup_type(alias); - if (!type) { - handle_warn(info, - NULL, - NULL, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid setting name '%s'"), - info->group); - return; - } - - setting = g_object_new(type, NULL); - - info->setting = setting; - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); - - if (sett_info->detail.gendata_info) { - gs_free char **keys = NULL; - gsize k, n_keys; - - keys = g_key_file_get_keys(info->keyfile, info->group, &n_keys, NULL); - if (!keys) - n_keys = 0; - if (n_keys > 0) { - GHashTable *h = _nm_setting_option_hash(setting, TRUE); - - nm_utils_strv_sort(keys, n_keys); - for (k = 0; k < n_keys; k++) { - gs_free char *key = keys[k]; - gs_free_error GError *local = NULL; - const GVariantType * variant_type; - GVariant * variant; - - /* a GKeyFile can return duplicate keys, there is just no API to make sense - * of them. Skip them. */ - if (k + 1 < n_keys && nm_streq(key, keys[k + 1])) - continue; - - /* currently, the API is very simple. The setting class just returns - * the desired variant type, and keyfile reader will try to parse - * it accordingly. Note, that this does currently not allow, that - * a particular key can contain different variant types, nor is it - * very flexible in general. - * - * We add flexibility when we need it. Keep it simple for now. */ - variant_type = - sett_info->detail.gendata_info->get_variant_type(sett_info, key, &local); - if (!variant_type) { - if (!handle_warn(info, - key, - NULL, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid key '%s.%s'"), - info->group, - key)) - break; - continue; - } - - if (g_variant_type_equal(variant_type, G_VARIANT_TYPE_BOOLEAN)) { - gboolean v; - - v = g_key_file_get_boolean(info->keyfile, info->group, key, &local); - if (local) { - if (!handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not boolean"), - info->group, - key)) - break; - continue; - } - variant = g_variant_new_boolean(v); - } else if (g_variant_type_equal(variant_type, G_VARIANT_TYPE_UINT32)) { - guint64 v; - - v = g_key_file_get_uint64(info->keyfile, info->group, key, &local); - - if (local) { - if (!handle_warn(info, - key, - key, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a uint32"), - info->group, - key)) - break; - continue; - } - variant = g_variant_new_uint32((guint32) v); - } else { - nm_assert_not_reached(); - continue; - } - - g_hash_table_insert(h, g_steal_pointer(&key), g_variant_take_ref(variant)); - } - for (; k < n_keys; k++) - g_free(keys[k]); - } - } - - for (i = 0; i < sett_info->property_infos_len; i++) { - read_one_setting_value(info, setting, &sett_info->property_infos[i]); - if (info->error) - goto out; - } - -out: - info->setting = NULL; - if (!info->error) - nm_connection_add_setting(info->connection, g_steal_pointer(&setting)); -} - -static void -_read_setting_wireguard_peer(KeyfileReaderInfo *info) -{ - gs_unref_object NMSettingWireGuard *s_wg_new = NULL; - nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; - gs_free_error GError *error = NULL; - NMSettingWireGuard * s_wg; - gs_free char * str = NULL; - const char * cstr = NULL; - const char * key; - gint64 i64; - gs_strfreev char ** sa = NULL; - gsize n_sa; - - peer = nm_wireguard_peer_new(); - - nm_assert(g_str_has_prefix(info->group, NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)); - cstr = &info->group[NM_STRLEN(NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)]; - if (!nm_utils_base64secret_normalize(cstr, NM_WIREGUARD_PUBLIC_KEY_LEN, &str) - || !nm_streq0(str, cstr)) { - /* the group name must be identical to the normalized(!) key, so that it - * is uniquely identified. */ - handle_warn(info, - NULL, - NM_SETTING_WIREGUARD_PEERS, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("invalid peer public key in section '%s'"), - info->group); - return; - } - nm_wireguard_peer_set_public_key(peer, cstr, TRUE); - nm_clear_g_free(&str); - - key = NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY; - str = nm_keyfile_plugin_kf_get_string(info->keyfile, info->group, key, NULL); - if (str) { - if (!nm_wireguard_peer_set_preshared_key(peer, str, FALSE)) { - if (!handle_warn(info, - key, - NM_SETTING_WIREGUARD_PEERS, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a valid 256 bit key in base64 encoding"), - info->group, - key)) - return; - } - nm_clear_g_free(&str); - } - - key = NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS; - i64 = nm_keyfile_plugin_kf_get_int64(info->keyfile, - info->group, - key, - 0, - 0, - NM_SETTING_SECRET_FLAG_ALL, - -1, - NULL); - if (errno != ENODATA) { - if (i64 == -1 || !_nm_setting_secret_flags_valid(i64)) { - if (!handle_warn(info, - key, - NM_SETTING_WIREGUARD_PEERS, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a valid secret flag"), - info->group, - key)) - return; - } else - nm_wireguard_peer_set_preshared_key_flags(peer, i64); - } - - key = NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE; - i64 = nm_keyfile_plugin_kf_get_int64(info->keyfile, - info->group, - key, - 0, - 0, - G_MAXUINT32, - -1, - NULL); - if (errno != ENODATA) { - if (i64 == -1) { - if (!handle_warn(info, - key, - NM_SETTING_WIREGUARD_PEERS, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a integer in range 0 to 2^32"), - info->group, - key)) - return; - } else - nm_wireguard_peer_set_persistent_keepalive(peer, i64); - } - - key = NM_WIREGUARD_PEER_ATTR_ENDPOINT; - str = nm_keyfile_plugin_kf_get_string(info->keyfile, info->group, key, NULL); - if (str && str[0]) { - if (!nm_wireguard_peer_set_endpoint(peer, str, FALSE)) { - if (!handle_warn(info, - key, - NM_SETTING_WIREGUARD_PEERS, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' is not a valid endpoint"), - info->group, - key)) - return; - } - } - nm_clear_g_free(&str); - - key = NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS; - sa = nm_keyfile_plugin_kf_get_string_list(info->keyfile, info->group, key, &n_sa, NULL); - if (n_sa > 0) { - gboolean has_error = FALSE; - gsize i; - - for (i = 0; i < n_sa; i++) { - if (!nm_utils_parse_inaddr_prefix_bin(AF_UNSPEC, sa[i], NULL, NULL, NULL)) { - has_error = TRUE; - continue; - } - nm_wireguard_peer_append_allowed_ip(peer, sa[i], TRUE); - } - if (has_error) { - if (!handle_warn(info, - key, - NM_SETTING_WIREGUARD_PEERS, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("key '%s.%s' has invalid allowed-ips"), - info->group, - key)) - return; - } - } - - if (info->error) - return; - - if (!nm_wireguard_peer_is_valid(peer, TRUE, TRUE, &error)) { - handle_warn(info, - NULL, - NM_SETTING_WIREGUARD_PEERS, - NM_KEYFILE_WARN_SEVERITY_WARN, - _("peer '%s' is invalid: %s"), - info->group, - error->message); - return; - } - - s_wg = NM_SETTING_WIREGUARD( - nm_connection_get_setting(info->connection, NM_TYPE_SETTING_WIREGUARD)); - if (!s_wg) { - s_wg_new = NM_SETTING_WIREGUARD(nm_setting_wireguard_new()); - s_wg = s_wg_new; - } - - nm_setting_wireguard_append_peer(s_wg, peer); - - if (s_wg_new) { - nm_connection_add_setting(info->connection, NM_SETTING(g_steal_pointer(&s_wg_new))); - } -} - -static void -_read_setting_vpn_secrets(KeyfileReaderInfo *info) -{ - gs_strfreev char **keys = NULL; - gsize i, n_keys; - NMSettingVpn * s_vpn; - - s_vpn = nm_connection_get_setting_vpn(info->connection); - if (!s_vpn) { - /* if we don't also have a [vpn] section (which must be parsed earlier), - * we don't do anything. */ - nm_assert(!g_key_file_has_group(info->keyfile, "vpn")); - return; - } - - keys = - nm_keyfile_plugin_kf_get_keys(info->keyfile, NM_KEYFILE_GROUP_VPN_SECRETS, &n_keys, NULL); - for (i = 0; i < n_keys; i++) { - gs_free char *secret = NULL; - - secret = nm_keyfile_plugin_kf_get_string(info->keyfile, - NM_KEYFILE_GROUP_VPN_SECRETS, - keys[i], - NULL); - if (secret) - nm_setting_vpn_add_secret(s_vpn, keys[i], secret); - } -} - -gboolean -nm_keyfile_read_ensure_id(NMConnection *connection, const char *fallback_id) -{ - NMSettingConnection *s_con; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); - g_return_val_if_fail(fallback_id, FALSE); - - s_con = nm_connection_get_setting_connection(connection); - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(s_con), FALSE); - - if (nm_setting_connection_get_id(s_con)) - return FALSE; - - g_object_set(s_con, NM_SETTING_CONNECTION_ID, fallback_id, NULL); - return TRUE; -} - -gboolean -nm_keyfile_read_ensure_uuid(NMConnection *connection, const char *fallback_uuid_seed) -{ - NMSettingConnection *s_con; - gs_free char * hashed_uuid = NULL; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); - g_return_val_if_fail(fallback_uuid_seed, FALSE); - - s_con = nm_connection_get_setting_connection(connection); - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(s_con), FALSE); - - if (nm_setting_connection_get_uuid(s_con)) - return FALSE; - - hashed_uuid = _nm_utils_uuid_generate_from_strings("keyfile", fallback_uuid_seed, NULL); - g_object_set(s_con, NM_SETTING_CONNECTION_UUID, hashed_uuid, NULL); - return TRUE; -} - -/** - * nm_keyfile_read: - * @keyfile: the keyfile from which to create the connection - * @base_dir: when reading certificates from files with relative name, - * the relative path is made absolute using @base_dir. This must - * be an absolute path. - * @handler_flags: the #NMKeyfileHandlerFlags. - * @handler: (allow-none) (scope call): read handler - * @user_data: user data for read handler - * @error: (allow-none) (out): error - * - * Tries to create a NMConnection from a keyfile. The resulting keyfile is - * not normalized and might not even verify. - * - * Returns: (transfer full): on success, returns the created connection. - * - * Since: 1.30 - */ -NMConnection * -nm_keyfile_read(GKeyFile * keyfile, - const char * base_dir, - NMKeyfileHandlerFlags handler_flags, - NMKeyfileReadHandler handler, - void * user_data, - GError ** error) -{ - gs_unref_object NMConnection *connection = NULL; - NMSettingConnection * s_con; - gs_strfreev char ** groups = NULL; - gsize n_groups; - gsize i; - gboolean vpn_secrets = FALSE; - KeyfileReaderInfo info; - - g_return_val_if_fail(keyfile, NULL); - g_return_val_if_fail(!error || !*error, NULL); - g_return_val_if_fail(base_dir && base_dir[0] == '/', NULL); - g_return_val_if_fail(handler_flags == NM_KEYFILE_HANDLER_FLAGS_NONE, NULL); - - connection = nm_simple_connection_new(); - - info = (KeyfileReaderInfo){ - .connection = connection, - .keyfile = keyfile, - .base_dir = base_dir, - .read_handler = handler, - .user_data = user_data, - }; - - groups = g_key_file_get_groups(keyfile, &n_groups); - if (!groups) - n_groups = 0; - - for (i = 0; i < n_groups; i++) { - info.group = groups[i]; - - if (nm_streq(groups[i], NM_KEYFILE_GROUP_VPN_SECRETS)) { - /* Only read out secrets when needed */ - vpn_secrets = TRUE; - } else if (NM_STR_HAS_PREFIX(groups[i], NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)) - _read_setting_wireguard_peer(&info); - else if (NM_IN_STRSET(groups[i], - NM_KEYFILE_GROUP_NMMETA, - ETHERNET_S390_OPTIONS_GROUP_NAME)) { - /* pass */ - } else - _read_setting(&info); - - info.group = NULL; - - if (info.error) - goto out_with_info_error; - } - - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) { - s_con = NM_SETTING_CONNECTION(nm_setting_connection_new()); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - } - - /* Make sure that we have 'interface-name' even if it was specified in the - * "wrong" (ie, deprecated) group. - */ - if (!nm_setting_connection_get_interface_name(s_con) - && nm_setting_connection_get_connection_type(s_con)) { - gs_free char *interface_name = NULL; - - interface_name = g_key_file_get_string(keyfile, - nm_setting_connection_get_connection_type(s_con), - "interface-name", - NULL); - if (interface_name) - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name, NULL); - } - - if (vpn_secrets) { - info.group = NM_KEYFILE_GROUP_VPN_SECRETS; - _read_setting_vpn_secrets(&info); - info.group = NULL; - if (info.error) - goto out_with_info_error; - } - - return g_steal_pointer(&connection); - -out_with_info_error: - g_propagate_error(error, info.error); - return NULL; -} - -/*****************************************************************************/ - -static void -write_setting_value(KeyfileWriterInfo * info, - NMSetting * setting, - const NMSettInfoProperty *property_info) -{ - const NMMetaSettingInfo *setting_info; - const ParseInfoProperty *pip; - const char * key; - char numstr[64]; - GValue value; - GType type; - - nm_assert(!info->error); - nm_assert(!property_info->param_spec - || nm_streq(property_info->param_spec->name, property_info->name)); - - key = property_info->name; - - _parse_info_find(setting, key, &setting_info, NULL, &pip); - - if (!pip) { - if (!setting_info) { - /* the setting type is unknown. That is highly unexpected - * (and as this is currently only called from NetworkManager - * daemon, not possible). - * - * Still, handle it gracefully, because later keyfile writer will become - * public API of libnm, where @setting is (untrusted) user input. - * - * Gracefully here just means: ignore the setting. */ - return; - } - if (!property_info->param_spec) - return; - if (nm_streq(key, NM_SETTING_NAME)) - return; - } else { - if (pip->has_writer_full) { - pip->writer_full(info, setting_info, property_info, pip, setting); - return; - } - if (pip->writer_skip) - return; - } - - nm_assert(property_info->param_spec); - - /* Don't write secrets that are owned by user secret agents or aren't - * supposed to be saved. VPN secrets are handled specially though since - * the secret flags there are in a third-level hash in the 'secrets' - * property. - */ - if ((property_info->param_spec->flags & NM_SETTING_PARAM_SECRET) - && !NM_IS_SETTING_VPN(setting)) { - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - if (!nm_setting_get_secret_flags(setting, key, &secret_flags, NULL)) - g_return_if_reached(); - if (!_secret_flags_persist_secret(secret_flags)) - return; - } - - value = (GValue){0}; - - g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(property_info->param_spec)); - g_object_get_property(G_OBJECT(setting), property_info->param_spec->name, &value); - - if ((!pip || !pip->writer_persist_default) - && g_param_value_defaults(property_info->param_spec, &value)) { - nm_assert(!g_key_file_has_key(info->keyfile, setting_info->setting_name, key, NULL)); - goto out_unset_value; - } - - if (pip && pip->writer) { - pip->writer(info, setting, key, &value); - goto out_unset_value; - } - - type = G_VALUE_TYPE(&value); - if (type == G_TYPE_STRING) { - const char *str; - - str = g_value_get_string(&value); - if (str) - nm_keyfile_plugin_kf_set_string(info->keyfile, setting_info->setting_name, key, str); - } else if (type == G_TYPE_UINT) { - nm_sprintf_buf(numstr, "%u", g_value_get_uint(&value)); - nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_INT) { - nm_sprintf_buf(numstr, "%d", g_value_get_int(&value)); - nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_UINT64) { - nm_sprintf_buf(numstr, "%" G_GUINT64_FORMAT, g_value_get_uint64(&value)); - nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_INT64) { - nm_sprintf_buf(numstr, "%" G_GINT64_FORMAT, g_value_get_int64(&value)); - nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_BOOLEAN) { - nm_keyfile_plugin_kf_set_value(info->keyfile, - setting_info->setting_name, - key, - g_value_get_boolean(&value) ? "true" : "false"); - } else if (type == G_TYPE_CHAR) { - nm_sprintf_buf(numstr, "%d", (int) g_value_get_schar(&value)); - nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); - } else if (type == G_TYPE_BYTES) { - GBytes * bytes; - const guint8 *data; - gsize len = 0; - - bytes = g_value_get_boxed(&value); - data = bytes ? g_bytes_get_data(bytes, &len) : NULL; - - if (data != NULL && len > 0) - nm_keyfile_plugin_kf_set_integer_list_uint8(info->keyfile, - setting_info->setting_name, - key, - data, - len); - } else if (type == G_TYPE_STRV) { - char **array; - - array = (char **) g_value_get_boxed(&value); - nm_keyfile_plugin_kf_set_string_list(info->keyfile, - setting_info->setting_name, - key, - (const char **const) array, - g_strv_length(array)); - } else if (type == G_TYPE_HASH_TABLE) { - write_hash_of_string(info->keyfile, setting, key, &value); - } else if (type == G_TYPE_ARRAY) { - write_array_of_uint(info->keyfile, setting, key, &value); - } else if (G_VALUE_HOLDS_FLAGS(&value)) { - nm_sprintf_buf(numstr, "%u", g_value_get_flags(&value)); - nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); - } else if (G_VALUE_HOLDS_ENUM(&value)) { - nm_sprintf_buf(numstr, "%d", g_value_get_enum(&value)); - nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); - } else - g_return_if_reached(); - -out_unset_value: - g_value_unset(&value); -} - -static void -_write_setting_wireguard(NMSetting *setting, KeyfileWriterInfo *info) -{ - NMSettingWireGuard *s_wg; - guint i_peer, n_peers; - - s_wg = NM_SETTING_WIREGUARD(setting); - - n_peers = nm_setting_wireguard_get_peers_len(s_wg); - for (i_peer = 0; i_peer < n_peers; i_peer++) { - NMWireGuardPeer * peer = nm_setting_wireguard_get_peer(s_wg, i_peer); - const char * public_key; - char group[NM_STRLEN(NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER) + 200]; - NMSettingSecretFlags secret_flags; - gboolean any_key = FALSE; - guint i_aip, n_aip; - const char * cstr; - guint32 u32; - - public_key = nm_wireguard_peer_get_public_key(peer); - if (!public_key || !public_key[0] - || !NM_STRCHAR_ALL(public_key, ch, nm_sd_utils_unbase64char(ch, TRUE) >= 0)) { - /* invalid peer. Skip it */ - continue; - } - - if (g_snprintf(group, - sizeof(group), - "%s%s", - NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER, - nm_wireguard_peer_get_public_key(peer)) - >= sizeof(group)) { - /* Too long. Not a valid public key. Skip the peer. */ - continue; - } - - cstr = nm_wireguard_peer_get_endpoint(peer); - if (cstr) { - g_key_file_set_string(info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ENDPOINT, cstr); - any_key = TRUE; - } - - secret_flags = nm_wireguard_peer_get_preshared_key_flags(peer); - if (_secret_flags_persist_secret(secret_flags)) { - cstr = nm_wireguard_peer_get_preshared_key(peer); - if (cstr) { - g_key_file_set_string(info->keyfile, - group, - NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, - cstr); - any_key = TRUE; - } - } - - /* usually, we don't persist the secret-flags 0 (because they are the default). - * For WireGuard peers, the default secret-flags for preshared-key are 4 (not-required). - * So, in this case behave differently: a missing preshared-key-flag setting means - * "not-required". */ - if (secret_flags != NM_SETTING_SECRET_FLAG_NOT_REQUIRED) { - g_key_file_set_int64(info->keyfile, - group, - NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS, - secret_flags); - any_key = TRUE; - } - - u32 = nm_wireguard_peer_get_persistent_keepalive(peer); - if (u32) { - g_key_file_set_uint64(info->keyfile, - group, - NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE, - u32); - any_key = TRUE; - } - - n_aip = nm_wireguard_peer_get_allowed_ips_len(peer); - if (n_aip > 0) { - gs_free const char **strv = NULL; - - strv = g_new(const char *, ((gsize) n_aip) + 1); - for (i_aip = 0; i_aip < n_aip; i_aip++) - strv[i_aip] = nm_wireguard_peer_get_allowed_ip(peer, i_aip, NULL); - strv[n_aip] = NULL; - g_key_file_set_string_list(info->keyfile, - group, - NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS, - strv, - n_aip); - any_key = TRUE; - } - - if (!any_key) { - /* we cannot omit all keys. At an empty endpoint. */ - g_key_file_set_string(info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ENDPOINT, ""); - } - } -} - -/** - * nm_keyfile_write: - * @connection: the #NMConnection to persist to keyfile. - * @handler_flags: the #NMKeyfileHandlerFlags. - * @handler: (allow-none) (scope call): optional handler for events and - * to override the default behavior. - * @user_data: argument for @handler. - * @error: the #GError in case writing fails. - * - * @connection must verify as a valid profile according to - * nm_connection_verify(). - * - * Returns: (transfer full): a new #GKeyFile or %NULL on error. - * - * Since: 1.30 - */ -GKeyFile * -nm_keyfile_write(NMConnection * connection, - NMKeyfileHandlerFlags handler_flags, - NMKeyfileWriteHandler handler, - void * user_data, - GError ** error) -{ - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - GError * local = NULL; - KeyfileWriterInfo info; - gs_free NMSetting **settings = NULL; - guint n_settings = 0; - guint i; - guint j; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - g_return_val_if_fail(!error || !*error, NULL); - g_return_val_if_fail(handler_flags == NM_KEYFILE_HANDLER_FLAGS_NONE, NULL); - - /* Technically, we might not require that a profile is valid in - * order to serialize it. Like also nm_keyfile_read() does not - * ensure that the read profile validates. - * - * However, if the profile does not validate, then there might be - * unexpected edge cases when we try to serialize it. Edge cases - * that might result in dangerous crash. - * - * So, for now we require valid profiles. */ - if (!nm_connection_verify(connection, error ? &local : NULL)) { - if (error) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("the profile is not valid: %s"), - local->message); - g_error_free(local); - } else - nm_assert(!local); - return NULL; - } - - keyfile = g_key_file_new(); - - info = (KeyfileWriterInfo){ - .connection = connection, - .keyfile = keyfile, - .error = NULL, - .write_handler = handler, - .user_data = user_data, - }; - - settings = nm_connection_get_settings(connection, &n_settings); - for (i = 0; i < n_settings; i++) { - const NMSettInfoSetting *sett_info; - NMSetting * setting = settings[i]; - const char * setting_name; - const char * setting_alias; - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); - - setting_name = sett_info->setting_class->setting_info->setting_name; - - if (sett_info->detail.gendata_info) { - guint k, n_keys; - const char *const *keys; - - nm_assert(!nm_keyfile_plugin_get_alias_for_setting_name( - sett_info->setting_class->setting_info->setting_name)); - - n_keys = _nm_setting_option_get_all(setting, &keys, NULL); - - if (n_keys > 0) { - GHashTable *h = _nm_setting_option_hash(setting, FALSE); - - for (k = 0; k < n_keys; k++) { - const char *key = keys[k]; - GVariant * v; - - v = g_hash_table_lookup(h, key); - - if (g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) { - g_key_file_set_boolean(info.keyfile, - setting_name, - key, - g_variant_get_boolean(v)); - } else if (g_variant_is_of_type(v, G_VARIANT_TYPE_UINT32)) { - g_key_file_set_uint64(info.keyfile, - setting_name, - key, - (guint64) g_variant_get_uint32(v)); - } else { - /* BUG: The variant type is not implemented. Since the connection - * verifies, this can only mean we either wrongly didn't reject - * the connection as invalid, or we didn't properly implement the - * variant type. */ - nm_assert_not_reached(); - continue; - } - } - } - } - - for (j = 0; j < sett_info->property_infos_len; j++) { - const NMSettInfoProperty *property_info = - _nm_sett_info_property_info_get_sorted(sett_info, j); - - write_setting_value(&info, setting, property_info); - if (info.error) - goto out_with_info_error; - } - - setting_alias = nm_keyfile_plugin_get_alias_for_setting_name(setting_name); - if ((setting_alias && g_key_file_has_group(info.keyfile, setting_alias)) - || g_key_file_has_group(info.keyfile, setting_name)) { - /* we have a section for the setting. Nothing to do. */ - } else { - /* ensure the group is present. There is no API for that, so add and remove - * a dummy key. */ - g_key_file_set_value(info.keyfile, setting_alias ?: setting_name, ".X", "1"); - g_key_file_remove_key(info.keyfile, setting_alias ?: setting_name, ".X", NULL); - } - - if (NM_IS_SETTING_WIREGUARD(setting)) { - _write_setting_wireguard(setting, &info); - if (info.error) - goto out_with_info_error; - } - - nm_assert(!info.error); - } - - nm_assert(!info.error); - - return g_steal_pointer(&keyfile); - -out_with_info_error: - g_propagate_error(error, info.error); - return NULL; -} - -/*****************************************************************************/ - -static const char temp_letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -/* - * Check '.[a-zA-Z0-9]{6}' file suffix used for temporary files by g_file_set_contents() (mkstemp()). - */ -static gboolean -check_mkstemp_suffix(const char *path) -{ - const char *ptr; - - nm_assert(path); - - /* Matches *.[a-zA-Z0-9]{6} suffix of mkstemp()'s temporary files */ - ptr = strrchr(path, '.'); - if (ptr && strspn(&ptr[1], temp_letters) == 6 && ptr[7] == '\0') - return TRUE; - return FALSE; -} - -#define SWP_TAG ".swp" -#define SWPX_TAG ".swpx" -#define PEM_TAG ".pem" -#define DER_TAG ".der" - -gboolean -nm_keyfile_utils_ignore_filename(const char *filename, gboolean require_extension) -{ - const char *base; - gsize l; - - /* ignore_filename() must mirror nm_keyfile_utils_create_filename() */ - - g_return_val_if_fail(filename, TRUE); - - base = strrchr(filename, '/'); - if (base) - base++; - else - base = filename; - - if (!base[0]) { - /* this check above with strrchr() also rejects "/some/path/with/trailing/slash/", - * but that is fine, because such a path would name a directory, and we are not - * interested in directories. */ - return TRUE; - } - - if (base[0] == '.') { - /* don't allow hidden files */ - return TRUE; - } - - if (require_extension) { - if (!NM_STR_HAS_SUFFIX_WITH_MORE(base, NM_KEYFILE_PATH_SUFFIX_NMCONNECTION)) - return TRUE; - return FALSE; - } - - l = strlen(base); - - /* Ignore backup files */ - if (base[l - 1] == '~') - return TRUE; - - /* Ignore temporary files - * - * This check is also important to ignore .nmload files (see - * %NM_KEYFILE_PATH_SUFFIX_NMMETA). */ - if (check_mkstemp_suffix(base)) - return TRUE; - - /* Ignore 802.1x certificates and keys */ - if (NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(base, PEM_TAG) - || NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(base, DER_TAG)) - return TRUE; - - return FALSE; -} - -char * -nm_keyfile_utils_create_filename(const char *name, gboolean with_extension) -{ - /* keyfile used to escape with '*', do not change that behavior. - * - * But for newly added escapings, use '_' instead. - * Also, @with_extension is new-style. */ - const char ESCAPE_CHAR = with_extension ? '_' : '*'; - const char ESCAPE_CHAR2 = '_'; - NMStrBuf str; - char * p; - gsize len; - gsize i; - - g_return_val_if_fail(name && name[0], NULL); - - nm_str_buf_init(&str, 0, FALSE); - - len = strlen(name); - - p = nm_str_buf_append_len0(&str, name, len); - - /* Convert '/' to ESCAPE_CHAR */ - for (i = 0; i < len; i++) { - if (p[i] == '/') - p[i] = ESCAPE_CHAR; - } - - /* nm_keyfile_utils_create_filename() must avoid anything that ignore_filename() would reject. - * We can escape here more aggressively then what we would read back. */ - if (p[0] == '.') - p[0] = ESCAPE_CHAR2; - if (p[str.len - 1] == '~') - p[str.len - 1] = ESCAPE_CHAR2; - - if (check_mkstemp_suffix(p) || NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(p, PEM_TAG) - || NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(p, DER_TAG)) - nm_str_buf_append_c(&str, ESCAPE_CHAR2); - - if (with_extension) - nm_str_buf_append(&str, NM_KEYFILE_PATH_SUFFIX_NMCONNECTION); - - p = nm_str_buf_finalize(&str, NULL); - - /* nm_keyfile_utils_create_filename() must mirror ignore_filename() */ - nm_assert(!strchr(p, '/')); - nm_assert(!nm_keyfile_utils_ignore_filename(p, with_extension)); - - return p; -} - -/*****************************************************************************/ - -/** - * nm_keyfile_handler_data_fail_with_error: - * @handler_data: the #NMKeyfileHandlerData - * @src: (transfer full): error to move into the return location - * - * Set the error for the handler. This lets the operation fail - * with the provided error. You may only set the error once. - * - * @src must be non-%NULL. - * - * Note that @src is no longer valid after this call. If you want - * to keep using the same GError*, you need to set it to %NULL - * after calling this function on it. - * - * Since: 1.30 - */ -void -nm_keyfile_handler_data_fail_with_error(NMKeyfileHandlerData *handler_data, GError *src) -{ - g_return_if_fail(handler_data); - g_return_if_fail(handler_data->p_error && !*handler_data->p_error); - g_return_if_fail(src); - - *handler_data->p_error = src; -} - -/** - * nm_keyfile_handler_data_get_context: - * @handler_data: the #NMKeyfileHandlerData for any event. - * @out_kf_group_name: (out) (allow-none) (transfer none): if the event is in the - * context of a keyfile group, the group name. - * @out_kf_key_name: (out) (allow-none) (transfer none): if the event is in the - * context of a keyfile value, the key name. - * @out_cur_setting: (out) (allow-none) (transfer none): if the event happens while - * handling a particular #NMSetting instance. - * @out_cur_property_name: (out) (allow-none) (transfer none): the property name if applicable. - * - * Get context information of the current event. This function can be called - * on all events, but the context information may be unset. - * - * Since: 1.30 - */ -void -nm_keyfile_handler_data_get_context(const NMKeyfileHandlerData *handler_data, - const char ** out_kf_group_name, - const char ** out_kf_key_name, - NMSetting ** out_cur_setting, - const char ** out_cur_property_name) -{ - g_return_if_fail(handler_data); - - NM_SET_OUT(out_kf_group_name, handler_data->kf_group_name); - NM_SET_OUT(out_kf_key_name, handler_data->kf_key); - NM_SET_OUT(out_cur_setting, handler_data->cur_setting); - NM_SET_OUT(out_cur_property_name, handler_data->cur_property); -} - -const char * -_nm_keyfile_handler_data_warn_get_message(const NMKeyfileHandlerData *handler_data) -{ - nm_assert(handler_data); - nm_assert(handler_data->type == NM_KEYFILE_HANDLER_TYPE_WARN); - - if (!handler_data->warn.message) { - /* we cast the const away. @handler_data is const w.r.t. visible mutations - * from POV of the user. Internally, we construct the message in - * a lazy manner. It's like a mutable field in C++. */ - NM_PRAGMA_WARNING_DISABLE("-Wformat-nonliteral") - ((NMKeyfileHandlerData *) handler_data)->warn.message = - g_strdup_vprintf(handler_data->warn.fmt, - ((NMKeyfileHandlerData *) handler_data)->warn.ap); - NM_PRAGMA_WARNING_REENABLE - } - return handler_data->warn.message; -} - -/** - * nm_keyfile_handler_data_warn_get: - * @handler_data: the #NMKeyfileHandlerData for a %NM_KEYFILE_HANDLER_TYPE_WARN - * event. - * @out_message: (out) (allow-none) (transfer none): the warning message. - * @out_severity: (out) (allow-none): the #NMKeyfileWarnSeverity warning severity. - * - * Since: 1.30 - */ -void -nm_keyfile_handler_data_warn_get(const NMKeyfileHandlerData *handler_data, - const char ** out_message, - NMKeyfileWarnSeverity * out_severity) -{ - g_return_if_fail(handler_data); - g_return_if_fail(handler_data->type == NM_KEYFILE_HANDLER_TYPE_WARN); - - NM_SET_OUT(out_message, _nm_keyfile_handler_data_warn_get_message(handler_data)); - NM_SET_OUT(out_severity, handler_data->warn.severity); -} diff --git a/libnm-core/nm-keyfile.h b/libnm-core/nm-keyfile.h deleted file mode 100644 index 28c052f999..0000000000 --- a/libnm-core/nm-keyfile.h +++ /dev/null @@ -1,165 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#ifndef __NM_KEYFILE_H__ -#define __NM_KEYFILE_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-core-types.h" - -G_BEGIN_DECLS - -/** - * NMKeyfileHandlerFlags: - * @NM_KEYFILE_HANDLER_FLAGS_NONE: no flags set. - * - * Flags for customizing nm_keyfile_read() and nm_keyfile_write(). - * - * Currently no flags are implemented. - * - * Since: 1.30 - */ -typedef enum { /*< flags >*/ - NM_KEYFILE_HANDLER_FLAGS_NONE = 0, -} NMKeyfileHandlerFlags; - -/** - * NMKeyfileHandlerType: - * @NM_KEYFILE_HANDLER_TYPE_WARN: a warning. - * @NM_KEYFILE_HANDLER_TYPE_WRITE_CERT: for handling certificates while writing - * a connection to keyfile. - * - * The type of the callback for %NMKeyfileReadHandler and %NMKeyfileWriteHandler. - * Depending on the type, you can interpret %NMKeyfileHandlerData. - * - * Since: 1.30 - */ -typedef enum { - NM_KEYFILE_HANDLER_TYPE_WARN = 1, - NM_KEYFILE_HANDLER_TYPE_WRITE_CERT = 2, -} NMKeyfileHandlerType; - -/** - * NMKeyfileHandlerData: - * - * Opaque type with parameters for the callback. The actual content - * depends on the %NMKeyfileHandlerType. - * - * Since: 1.30 - */ -typedef struct _NMKeyfileHandlerData NMKeyfileHandlerData; - -/** - * NMKeyfileReadHandler: - * @keyfile: the #GKeyFile that is currently read - * @connection: the #NMConnection that is being constructed. - * @handler_type: the %NMKeyfileHandlerType that indicates which type - * the request is. - * @handler_data: the #NMKeyfileHandlerData. What you can do with it - * depends on the @handler_type. - * @user_data: the user-data argument to nm_keyfile_read(). - * - * Hook to nm_keyfile_read(). - * - * The callee may abort the reading by setting an error via nm_keyfile_handler_data_fail_with_error(). - * - * Returns: the callee should return TRUE, if the event was handled and/or recognized. - * Otherwise, a default action will be performed that depends on the @type. - * For %NM_KEYFILE_HANDLER_TYPE_WARN type, the default action is doing nothing. - * - * Since: 1.30 - */ -typedef gboolean (*NMKeyfileReadHandler)(GKeyFile * keyfile, - NMConnection * connection, - NMKeyfileHandlerType handler_type, - NMKeyfileHandlerData *handler_data, - void * user_data); - -NM_AVAILABLE_IN_1_30 -NMConnection *nm_keyfile_read(GKeyFile * keyfile, - const char * base_dir, - NMKeyfileHandlerFlags handler_flags, - NMKeyfileReadHandler handler, - void * user_data, - GError ** error); - -/** - * NMKeyfileWriteHandler: - * @connection: the #NMConnection that is currently written. - * @keyfile: the #GKeyFile that is currently constructed. - * @handler_type: the %NMKeyfileHandlerType that indicates which type - * the request is. - * @handler_data: the #NMKeyfileHandlerData. What you can do with it - * depends on the @handler_type. - * @user_data: the user-data argument to nm_keyfile_read(). - * - * This is a hook to tweak the serialization. - * - * Handler for certain properties or events that are not entirely contained - * within the keyfile or that might be serialized differently. The @type and - * @handler_data arguments tell which kind of argument we have at hand. - * - * Currently only the type %NM_KEYFILE_HANDLER_TYPE_WRITE_CERT is supported. - * - * The callee may call nm_keyfile_handler_data_fail_with_error() to abort - * the writing with error. - * - * Returns: the callee should return %TRUE if the event was handled. If the - * event was unhandled, a default action will be performed that depends on - * the @handler_type. - * - * Since: 1.30 - */ -typedef gboolean (*NMKeyfileWriteHandler)(NMConnection * connection, - GKeyFile * keyfile, - NMKeyfileHandlerType handler_type, - NMKeyfileHandlerData *handler_data, - void * user_data); - -NM_AVAILABLE_IN_1_30 -GKeyFile *nm_keyfile_write(NMConnection * connection, - NMKeyfileHandlerFlags handler_flags, - NMKeyfileWriteHandler handler, - void * user_data, - GError ** error); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_30 -void nm_keyfile_handler_data_fail_with_error(NMKeyfileHandlerData *handler_data, GError *src); - -NM_AVAILABLE_IN_1_30 -void nm_keyfile_handler_data_get_context(const NMKeyfileHandlerData *handler_data, - const char ** out_kf_group_name, - const char ** out_kf_key_name, - NMSetting ** out_cur_setting, - const char ** out_cur_property_name); - -/** - * NMKeyfileWarnSeverity: - * @NM_KEYFILE_WARN_SEVERITY_DEBUG: debug message - * @NM_KEYFILE_WARN_SEVERITY_INFO: info message - * @NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE: info message about a missing file - * @NM_KEYFILE_WARN_SEVERITY_WARN: a warning message - * - * The severity level of %NM_KEYFILE_HANDLER_TYPE_WARN events. - * - * Since: 1.30 - */ -typedef enum { - NM_KEYFILE_WARN_SEVERITY_DEBUG = 1000, - NM_KEYFILE_WARN_SEVERITY_INFO = 2000, - NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE = 2901, - NM_KEYFILE_WARN_SEVERITY_WARN = 3000, -} NMKeyfileWarnSeverity; - -NM_AVAILABLE_IN_1_30 -void nm_keyfile_handler_data_warn_get(const NMKeyfileHandlerData *handler_data, - const char ** out_message, - NMKeyfileWarnSeverity * out_severity); - -G_END_DECLS - -#endif /* __NM_KEYFILE_H__ */ diff --git a/libnm-core/nm-libnm-core-aux/README.md b/libnm-core/nm-libnm-core-aux/README.md deleted file mode 100644 index 01f361b44d..0000000000 --- a/libnm-core/nm-libnm-core-aux/README.md +++ /dev/null @@ -1,21 +0,0 @@ -nm-libnm-core-aux is a static library that: - - - uses parts of "libnm-core", that are public API of "libnm" - - can be statically linked into users of libnm-core (like libnm - and NetworkManager). - - that can also be statically linked into other users of libnm. - -Basically, it is a static library with utility functions that extends -libnm-core (the part that is public API of libnm), but can also be -used without full libnm. - -That means: - - - you can use it everywhere where you either statically link - with libnm-core, or dynamically link with libnm. - - you cannot use it inside libnm-core itself. This is the difference - between nm-libnm-core-intern and nm-libnm-core-aux. - -Also, since nm-libnm-core-aux itself only uses public (stable) -API of libnm, you theoretically can copy the sources into your -own source tree. diff --git a/libnm-core/nm-libnm-core-aux/nm-dispatcher-api.h b/libnm-core/nm-libnm-core-aux/nm-dispatcher-api.h deleted file mode 100644 index 7776c84f9a..0000000000 --- a/libnm-core/nm-libnm-core-aux/nm-dispatcher-api.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2008 - 2012 Red Hat, Inc. - */ - -#ifndef __NM_DISPACHER_API_H__ -#define __NM_DISPACHER_API_H__ - -#define NM_DISPATCHER_DBUS_SERVICE "org.freedesktop.nm_dispatcher" -#define NM_DISPATCHER_DBUS_INTERFACE "org.freedesktop.nm_dispatcher" -#define NM_DISPATCHER_DBUS_PATH "/org/freedesktop/nm_dispatcher" - -#define NMD_CONNECTION_PROPS_PATH "path" -#define NMD_CONNECTION_PROPS_FILENAME "filename" -#define NMD_CONNECTION_PROPS_EXTERNAL "external" - -#define NMD_DEVICE_PROPS_INTERFACE "interface" -#define NMD_DEVICE_PROPS_IP_INTERFACE "ip-interface" -#define NMD_DEVICE_PROPS_TYPE "type" -#define NMD_DEVICE_PROPS_STATE "state" -#define NMD_DEVICE_PROPS_PATH "path" - -/* Actions */ -#define NMD_ACTION_HOSTNAME "hostname" -#define NMD_ACTION_PRE_UP "pre-up" -#define NMD_ACTION_UP "up" -#define NMD_ACTION_PRE_DOWN "pre-down" -#define NMD_ACTION_DOWN "down" -#define NMD_ACTION_VPN_PRE_UP "vpn-pre-up" -#define NMD_ACTION_VPN_UP "vpn-up" -#define NMD_ACTION_VPN_PRE_DOWN "vpn-pre-down" -#define NMD_ACTION_VPN_DOWN "vpn-down" -#define NMD_ACTION_DHCP4_CHANGE "dhcp4-change" -#define NMD_ACTION_DHCP6_CHANGE "dhcp6-change" -#define NMD_ACTION_CONNECTIVITY_CHANGE "connectivity-change" - -typedef enum { - DISPATCH_RESULT_UNKNOWN = 0, - DISPATCH_RESULT_SUCCESS = 1, - DISPATCH_RESULT_EXEC_FAILED = 2, - DISPATCH_RESULT_FAILED = 3, - DISPATCH_RESULT_TIMEOUT = 4, -} DispatchResult; - -#endif /* __NM_DISPACHER_API_H__ */ diff --git a/libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.c b/libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.c deleted file mode 100644 index 888dbac4b2..0000000000 --- a/libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.c +++ /dev/null @@ -1,436 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#include "nm-glib-aux/nm-default-glib-i18n-lib.h" - -#include "nm-libnm-core-aux.h" - -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" - -/*****************************************************************************/ - -typedef enum { - KEY_TYPE_STRING, - KEY_TYPE_INT, - KEY_TYPE_BOOL, -} KeyType; - -typedef struct { - const char *str_val; - union { - int vint; - bool vbool; - } typ_val; -} ParseData; - -typedef struct { - const char * name; - NMTeamLinkWatcherType watcher_type; - KeyType key_type; - union { - int (*fint)(const NMTeamLinkWatcher *watcher); - gboolean (*fbool)(const NMTeamLinkWatcher *watcher); - const char *(*fstring)(const NMTeamLinkWatcher *watcher); - } get_fcn; - union { - int vint; - bool vbool; - } def_val; -} TeamLinkWatcherKeyInfo; - -static gboolean -_team_link_watcher_validate_active(const NMTeamLinkWatcher *watcher) -{ - return NM_FLAGS_HAS(nm_team_link_watcher_get_flags(watcher), - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE); -} - -static gboolean -_team_link_watcher_validate_inactive(const NMTeamLinkWatcher *watcher) -{ - return NM_FLAGS_HAS(nm_team_link_watcher_get_flags(watcher), - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE); -} - -static gboolean -_team_link_watcher_send_always(const NMTeamLinkWatcher *watcher) -{ - return NM_FLAGS_HAS(nm_team_link_watcher_get_flags(watcher), - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS); -} - -static const TeamLinkWatcherKeyInfo _team_link_watcher_key_infos[_NM_TEAM_LINK_WATCHER_KEY_NUM] = { - -#define _KEY_INFO(key_id, _name, _watcher_type, _key_type, ...) \ - [key_id] = {.name = ""_name \ - "", \ - .watcher_type = (_watcher_type), \ - .key_type = _key_type, \ - ##__VA_ARGS__} - - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_NAME, - "name", - NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL | NM_TEAM_LINK_WATCHER_TYPE_NSNAPING - | NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_STRING, - .get_fcn.fstring = nm_team_link_watcher_get_name, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_DELAY_UP, - "delay-up", - NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL, - KEY_TYPE_INT, - .get_fcn.fint = nm_team_link_watcher_get_delay_up, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_DELAY_DOWN, - "delay-down", - NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL, - KEY_TYPE_INT, - .get_fcn.fint = nm_team_link_watcher_get_delay_down, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT, - "init-wait", - NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_INT, - .get_fcn.fint = nm_team_link_watcher_get_init_wait, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_INTERVAL, - "interval", - NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_INT, - .get_fcn.fint = nm_team_link_watcher_get_interval, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX, - "missed-max", - NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_INT, - .get_fcn.fint = nm_team_link_watcher_get_missed_max, - .def_val.vint = 3, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST, - "target-host", - NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_STRING, - .get_fcn.fstring = nm_team_link_watcher_get_target_host, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_VLANID, - "vlanid", - NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_INT, - .get_fcn.fint = nm_team_link_watcher_get_vlanid, - .def_val.vint = -1, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_SOURCE_HOST, - "source-host", - NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_STRING, - .get_fcn.fstring = nm_team_link_watcher_get_source_host, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_VALIDATE_ACTIVE, - "validate-active", - NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_BOOL, - .get_fcn.fbool = _team_link_watcher_validate_active, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_VALIDATE_INACTIVE, - "validate-inactive", - NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_BOOL, - .get_fcn.fbool = _team_link_watcher_validate_inactive, ), - _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_SEND_ALWAYS, - "send-always", - NM_TEAM_LINK_WATCHER_TYPE_ARPING, - KEY_TYPE_BOOL, - .get_fcn.fbool = _team_link_watcher_send_always, ), - -}; - -static NMTeamLinkWatcherType -_team_link_watcher_get_watcher_type_from_name(const char *name) -{ - if (name) { - if (nm_streq(name, NM_TEAM_LINK_WATCHER_ETHTOOL)) - return NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL; - if (nm_streq(name, NM_TEAM_LINK_WATCHER_NSNA_PING)) - return NM_TEAM_LINK_WATCHER_TYPE_NSNAPING; - if (nm_streq(name, NM_TEAM_LINK_WATCHER_ARP_PING)) - return NM_TEAM_LINK_WATCHER_TYPE_ARPING; - } - return NM_TEAM_LINK_WATCHER_TYPE_NONE; -} - -static const char * -_parse_data_get_str(const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM], - NMTeamLinkWatcherKeyId key_id) -{ - nm_assert(_NM_INT_NOT_NEGATIVE(key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM); - nm_assert(_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_STRING); - - return parse_data[key_id].str_val; -} - -static int -_parse_data_get_int(const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM], - NMTeamLinkWatcherKeyId key_id) -{ - nm_assert(_NM_INT_NOT_NEGATIVE(key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM); - nm_assert(_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_INT); - - if (parse_data[key_id].str_val) - return parse_data[key_id].typ_val.vint; - return _team_link_watcher_key_infos[key_id].def_val.vint; -} - -static int -_parse_data_get_bool(const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM], - NMTeamLinkWatcherKeyId key_id) -{ - nm_assert(_NM_INT_NOT_NEGATIVE(key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM); - nm_assert(_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_BOOL); - - if (parse_data[key_id].str_val) - return parse_data[key_id].typ_val.vbool; - return _team_link_watcher_key_infos[key_id].def_val.vbool; -} - -char * -nm_utils_team_link_watcher_to_string(const NMTeamLinkWatcher *watcher) -{ - nm_auto_free_gstring GString *str = NULL; - const char * name; - NMTeamLinkWatcherType watcher_type; - NMTeamLinkWatcherKeyId key_id; - - if (!watcher) - return NULL; - - str = g_string_new(NULL); - - name = nm_team_link_watcher_get_name(watcher); - g_string_append_printf(str, "name=%s", name ?: ""); - - watcher_type = _team_link_watcher_get_watcher_type_from_name(name); - - for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) { - const TeamLinkWatcherKeyInfo *info = &_team_link_watcher_key_infos[key_id]; - const char * vstr; - int vint; - bool vbool; - - nm_assert( - info->name && info->name - && NM_STRCHAR_ALL(info->name, ch, ((ch >= 'a' && ch <= 'z') || NM_IN_SET(ch, '-')))); - nm_assert(NM_IN_SET(info->key_type, KEY_TYPE_STRING, KEY_TYPE_INT, KEY_TYPE_BOOL)); - - if (key_id == NM_TEAM_LINK_WATCHER_KEY_NAME) - continue; - - if (!NM_FLAGS_ALL(info->watcher_type, watcher_type)) - continue; - - switch (info->key_type) { - case KEY_TYPE_STRING: - vstr = info->get_fcn.fstring(watcher); - if (vstr) { - g_string_append_printf(nm_gstring_add_space_delimiter(str), - "%s=%s", - info->name, - vstr); - } - break; - case KEY_TYPE_INT: - vint = info->get_fcn.fint(watcher); - if (vint != info->def_val.vint) { - g_string_append_printf(nm_gstring_add_space_delimiter(str), - "%s=%d", - info->name, - vint); - } - break; - case KEY_TYPE_BOOL: - vbool = info->get_fcn.fbool(watcher); - if (vbool != info->def_val.vbool) { - g_string_append_printf(nm_gstring_add_space_delimiter(str), - "%s=%s", - info->name, - vbool ? "true" : "false"); - } - break; - } - } - - return g_string_free(g_steal_pointer(&str), FALSE); -} - -NMTeamLinkWatcher * -nm_utils_team_link_watcher_from_string(const char *str, GError **error) -{ - gs_free const char ** tokens = NULL; - ParseData parse_data[_NM_TEAM_LINK_WATCHER_KEY_NUM] = {}; - NMTeamLinkWatcherType watcher_type; - NMTeamLinkWatcherKeyId key_id; - gsize i_token; - NMTeamLinkWatcher * watcher; - int errsv; - - g_return_val_if_fail(str, NULL); - g_return_val_if_fail(!error || !*error, NULL); - - tokens = nm_utils_escaped_tokens_split(str, NM_ASCII_SPACES); - if (!tokens) { - g_set_error(error, 1, 0, "'%s' is not valid", str); - return NULL; - } - - for (i_token = 0; tokens[i_token]; i_token++) { - const TeamLinkWatcherKeyInfo *info; - const char * key = tokens[i_token]; - const char * val; - - val = strchr(key, '='); - if (!val) { - nm_utils_error_set( - error, - NM_UTILS_ERROR_UNKNOWN, - _("'%s' is not valid: properties should be specified as 'key=value'"), - key); - return NULL; - } - ((char *) val)[0] = '\0'; - val++; - - for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) { - info = &_team_link_watcher_key_infos[key_id]; - if (nm_streq(key, info->name)) - break; - } - - if (key_id == _NM_TEAM_LINK_WATCHER_KEY_NUM) { - nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("'%s' is not a valid key"), key); - return NULL; - } - - if (parse_data[key_id].str_val) { - nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("duplicate key '%s'"), key); - return NULL; - } - - parse_data[key_id].str_val = val; - - if (info->key_type == KEY_TYPE_INT) { - gint64 v64; - - v64 = _nm_utils_ascii_str_to_int64(val, 10, G_MININT, G_MAXINT, G_MAXINT64); - if (v64 == G_MAXINT64 && ((errsv = errno) != 0)) { - if (errsv == ERANGE) { - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("number for '%s' is out of range"), - key); - } else { - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("value for '%s' must be a number"), - key); - } - return NULL; - } - parse_data[key_id].typ_val.vint = v64; - } else if (info->key_type == KEY_TYPE_BOOL) { - int vbool; - - vbool = _nm_utils_ascii_str_to_bool(val, -1); - if (vbool == -1) { - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("value for '%s' must be a boolean"), - key); - return NULL; - } - parse_data[key_id].typ_val.vbool = vbool; - } - } - - if (!parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val) { - nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("missing 'name' attribute")); - return NULL; - } - - watcher_type = _team_link_watcher_get_watcher_type_from_name( - parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val); - if (watcher_type == NM_TEAM_LINK_WATCHER_TYPE_NONE) { - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("invalid 'name' \"%s\""), - parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val); - return NULL; - } - - for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) { - const TeamLinkWatcherKeyInfo *info = &_team_link_watcher_key_infos[key_id]; - - if (!parse_data[key_id].str_val) - continue; - if (!NM_FLAGS_ALL(info->watcher_type, watcher_type)) { - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("attribute '%s' is invalid for \"%s\""), - info->name, - parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val); - return NULL; - } - } - - switch (watcher_type) { - case NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL: - watcher = nm_team_link_watcher_new_ethtool( - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_DELAY_UP), - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_DELAY_DOWN), - error); - break; - case NM_TEAM_LINK_WATCHER_TYPE_NSNAPING: - watcher = nm_team_link_watcher_new_nsna_ping( - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT), - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_INTERVAL), - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX), - _parse_data_get_str(parse_data, NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST), - error); - break; - default: - nm_assert(watcher_type == NM_TEAM_LINK_WATCHER_TYPE_ARPING); - watcher = nm_team_link_watcher_new_arp_ping2( - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT), - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_INTERVAL), - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX), - _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_VLANID), - _parse_data_get_str(parse_data, NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST), - _parse_data_get_str(parse_data, NM_TEAM_LINK_WATCHER_KEY_SOURCE_HOST), - (NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE - | (_parse_data_get_bool(parse_data, NM_TEAM_LINK_WATCHER_KEY_VALIDATE_ACTIVE) - ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE - : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE) - | (_parse_data_get_bool(parse_data, NM_TEAM_LINK_WATCHER_KEY_VALIDATE_INACTIVE) - ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE - : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE) - | (_parse_data_get_bool(parse_data, NM_TEAM_LINK_WATCHER_KEY_SEND_ALWAYS) - ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS - : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE)), - error); - break; - } - -#if NM_MORE_ASSERTS > 5 - if (watcher) { - gs_free char * str2 = NULL; - nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher2 = NULL; - static _nm_thread_local int recursive; - - nm_assert(!error || !*error); - if (recursive == 0) { - recursive = 1; - str2 = nm_utils_team_link_watcher_to_string(watcher); - nm_assert(str2); - watcher2 = nm_utils_team_link_watcher_from_string(str2, NULL); - nm_assert(watcher2); - nm_assert(nm_team_link_watcher_equal(watcher, watcher2)); - nm_assert(nm_team_link_watcher_equal(watcher2, watcher)); - nm_assert(recursive == 1); - recursive = 0; - } - } else - nm_assert(!error || *error); -#endif - - return watcher; -} diff --git a/libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.h b/libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.h deleted file mode 100644 index 905f24331e..0000000000 --- a/libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#ifndef __NM_LIBNM_CORE_AUX_H__ -#define __NM_LIBNM_CORE_AUX_H__ - -#include "nm-setting-team.h" - -typedef enum { - NM_TEAM_LINK_WATCHER_TYPE_NONE = 0, - NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL = (1u << 0), - NM_TEAM_LINK_WATCHER_TYPE_NSNAPING = (1u << 1), - NM_TEAM_LINK_WATCHER_TYPE_ARPING = (1u << 2), -} NMTeamLinkWatcherType; - -typedef enum { - NM_TEAM_LINK_WATCHER_KEY_NAME, - NM_TEAM_LINK_WATCHER_KEY_DELAY_UP, - NM_TEAM_LINK_WATCHER_KEY_DELAY_DOWN, - NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT, - NM_TEAM_LINK_WATCHER_KEY_INTERVAL, - NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX, - NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST, - NM_TEAM_LINK_WATCHER_KEY_VLANID, - NM_TEAM_LINK_WATCHER_KEY_SOURCE_HOST, - NM_TEAM_LINK_WATCHER_KEY_VALIDATE_ACTIVE, - NM_TEAM_LINK_WATCHER_KEY_VALIDATE_INACTIVE, - NM_TEAM_LINK_WATCHER_KEY_SEND_ALWAYS, - _NM_TEAM_LINK_WATCHER_KEY_NUM, -} NMTeamLinkWatcherKeyId; - -char *nm_utils_team_link_watcher_to_string(const NMTeamLinkWatcher *watcher); - -NMTeamLinkWatcher *nm_utils_team_link_watcher_from_string(const char *str, GError **error); - -#endif /* __NM_LIBNM_CORE_AUX_H__ */ diff --git a/libnm-core/nm-libnm-core-intern/README.md b/libnm-core/nm-libnm-core-intern/README.md deleted file mode 100644 index 2dcc3c80cd..0000000000 --- a/libnm-core/nm-libnm-core-intern/README.md +++ /dev/null @@ -1,21 +0,0 @@ -nm-libnm-core-intern is a static library that: - - - uses parts of "libnm-core", that are public API of "libnm" - - that is statically linked into libnm-core (and thus libnm - and NetworkManager). - - that can also be statically linked into other users of libnm. - -Basically, it is a static library with utility functions that extends -libnm-core (the part that is public API of libnm), but it is used -by libnm-core. - -That means: - - - you can use it everywhere where you either statically link - with libnm-core, or dynamically link with libnm. - - you can even use it inside of libnm-core itself. This is the difference - between nm-libnm-core-intern and nm-libnm-core-aux. - -Also, since nm-libnm-core-intern itself only uses public (stable) -API of libnm, you theoretically can copy the sources into your -own source tree. diff --git a/libnm-core/nm-libnm-core-intern/nm-auth-subject.c b/libnm-core/nm-libnm-core-intern/nm-auth-subject.c deleted file mode 100644 index 1866662c2d..0000000000 --- a/libnm-core/nm-libnm-core-intern/nm-auth-subject.c +++ /dev/null @@ -1,468 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2013 - 2014 Red Hat, Inc. - */ - -/** - * SECTION:nm-auth-subject - * @short_description: Encapsulates authentication information about a requestor - * - * #NMAuthSubject encpasulates identifying information about an entity that - * makes requests, like process identifier and user UID. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-auth-subject.h" - -#include - -enum { - PROP_0, - PROP_SUBJECT_TYPE, - PROP_UNIX_PROCESS_DBUS_SENDER, - PROP_UNIX_PROCESS_PID, - PROP_UNIX_PROCESS_UID, - PROP_UNIX_SESSION_ID, - - PROP_LAST, -}; - -typedef struct { - NMAuthSubjectType subject_type; - struct { - gulong pid; - gulong uid; - guint64 start_time; - char * dbus_sender; - } unix_process; - - struct { - char *id; - } unix_session; -} NMAuthSubjectPrivate; - -struct _NMAuthSubject { - GObject parent; - NMAuthSubjectPrivate _priv; -}; - -struct _NMAuthSubjectClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE(NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT) - -#define NM_AUTH_SUBJECT_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMAuthSubject, NM_IS_AUTH_SUBJECT) - -/*****************************************************************************/ - -#define CHECK_SUBJECT(self, error_value) \ - NMAuthSubjectPrivate *priv; \ - g_return_val_if_fail(NM_IS_AUTH_SUBJECT(self), error_value); \ - priv = NM_AUTH_SUBJECT_GET_PRIVATE(self); - -#define CHECK_SUBJECT_TYPED(self, expected_subject_type, error_value) \ - CHECK_SUBJECT(self, error_value); \ - g_return_val_if_fail(priv->subject_type == (expected_subject_type), error_value); - -const char * -nm_auth_subject_to_string(NMAuthSubject *self, char *buf, gsize buf_len) -{ - CHECK_SUBJECT(self, NULL); - - switch (priv->subject_type) { - case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS: - g_snprintf(buf, - buf_len, - "unix-process[pid=%lu, uid=%lu, start=%llu]", - (unsigned long) priv->unix_process.pid, - (unsigned long) priv->unix_process.uid, - (unsigned long long) priv->unix_process.start_time); - break; - case NM_AUTH_SUBJECT_TYPE_INTERNAL: - g_strlcpy(buf, "internal", buf_len); - break; - case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION: - g_snprintf(buf, buf_len, "unix-session[id=%s]", priv->unix_session.id); - break; - default: - g_strlcpy(buf, "invalid", buf_len); - break; - } - return buf; -} - -/* returns a floating variant */ -GVariant * -nm_auth_subject_unix_to_polkit_gvariant(NMAuthSubject *self) -{ - GVariantBuilder builder; - CHECK_SUBJECT(self, NULL); - - switch (priv->subject_type) { - case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION: - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&builder, - "{sv}", - "session-id", - g_variant_new_string(priv->unix_session.id)); - return g_variant_new("(sa{sv})", "unix-session", &builder); - - case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS: - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&builder, - "{sv}", - "pid", - g_variant_new_uint32(priv->unix_process.pid)); - g_variant_builder_add(&builder, - "{sv}", - "start-time", - g_variant_new_uint64(priv->unix_process.start_time)); - g_variant_builder_add(&builder, "{sv}", "uid", g_variant_new_int32(priv->unix_process.uid)); - return g_variant_new("(sa{sv})", "unix-process", &builder); - - default: - g_return_val_if_reached(NULL); - } -} - -NMAuthSubjectType -nm_auth_subject_get_subject_type(NMAuthSubject *subject) -{ - CHECK_SUBJECT(subject, NM_AUTH_SUBJECT_TYPE_INVALID); - - return priv->subject_type; -} - -gulong -nm_auth_subject_get_unix_process_pid(NMAuthSubject *subject) -{ - CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, G_MAXULONG); - - return priv->unix_process.pid; -} - -gulong -nm_auth_subject_get_unix_process_uid(NMAuthSubject *subject) -{ - CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, G_MAXULONG); - - return priv->unix_process.uid; -} - -const char * -nm_auth_subject_get_unix_process_dbus_sender(NMAuthSubject *subject) -{ - CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, NULL); - - return priv->unix_process.dbus_sender; -} - -const char * -nm_auth_subject_get_unix_session_id(NMAuthSubject *subject) -{ - CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_SESSION, NULL); - - return priv->unix_session.id; -} - -/*****************************************************************************/ - -/** - * nm_auth_subject_new_internal(): - * - * Creates a new auth subject representing the NetworkManager process itself. - * - * Returns: the new #NMAuthSubject - */ -NMAuthSubject * -nm_auth_subject_new_internal(void) -{ - return g_object_new(NM_TYPE_AUTH_SUBJECT, - NM_AUTH_SUBJECT_SUBJECT_TYPE, - (int) NM_AUTH_SUBJECT_TYPE_INTERNAL, - NULL); -} - -/** - * nm_auth_subject_new_unix_session(): - * - * Creates a new auth subject representing a given unix session. - * - * Returns: the new #NMAuthSubject - */ -NMAuthSubject * -nm_auth_subject_new_unix_session(const char *session_id) -{ - return g_object_new(NM_TYPE_AUTH_SUBJECT, - NM_AUTH_SUBJECT_SUBJECT_TYPE, - (int) NM_AUTH_SUBJECT_TYPE_UNIX_SESSION, - NM_AUTH_SUBJECT_UNIX_SESSION_ID, - session_id, - NULL); -} - -/** - * nm_auth_subject_new_unix_process(): - * - * Creates a new auth subject representing a given unix process. - * - * Returns: the new #NMAuthSubject - */ -NMAuthSubject * -nm_auth_subject_new_unix_process(const char *dbus_sender, gulong pid, gulong uid) -{ - return g_object_new(NM_TYPE_AUTH_SUBJECT, - NM_AUTH_SUBJECT_SUBJECT_TYPE, - (int) NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, - NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER, - dbus_sender, - NM_AUTH_SUBJECT_UNIX_PROCESS_PID, - pid, - NM_AUTH_SUBJECT_UNIX_PROCESS_UID, - uid, - NULL); -} - -/** - * nm_auth_subject_new_unix_process_self(): - * - * Creates a new auth subject representing the current executing process. - * - * Returns: the new #NMAuthSubject - */ -NMAuthSubject * -nm_auth_subject_new_unix_process_self(void) -{ - return nm_auth_subject_new_unix_process(NULL, getpid(), getuid()); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_SUBJECT_TYPE: - g_value_set_int(value, priv->subject_type); - break; - case PROP_UNIX_PROCESS_DBUS_SENDER: - g_value_set_string(value, priv->unix_process.dbus_sender); - break; - case PROP_UNIX_PROCESS_PID: - g_value_set_ulong(value, priv->unix_process.pid); - break; - case PROP_UNIX_PROCESS_UID: - g_value_set_ulong(value, priv->unix_process.uid); - break; - case PROP_UNIX_SESSION_ID: - g_value_set_string(value, priv->unix_session.id); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(object); - NMAuthSubjectType subject_type; - int i; - const char * str; - gulong id; - - switch (prop_id) { - case PROP_SUBJECT_TYPE: - /* construct-only */ - i = g_value_get_int(value); - g_return_if_fail(NM_IN_SET(i, - (int) NM_AUTH_SUBJECT_TYPE_INTERNAL, - (int) NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, - (int) NM_AUTH_SUBJECT_TYPE_UNIX_SESSION)); - subject_type = i; - priv->subject_type |= subject_type; - g_return_if_fail(priv->subject_type == subject_type); - break; - case PROP_UNIX_PROCESS_DBUS_SENDER: - /* construct-only */ - if ((str = g_value_get_string(value))) { - priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS; - g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS); - priv->unix_process.dbus_sender = g_strdup(str); - } - break; - case PROP_UNIX_PROCESS_PID: - /* construct-only */ - if ((id = g_value_get_ulong(value)) != G_MAXULONG) { - priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS; - g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS); - priv->unix_process.pid = id; - } - break; - case PROP_UNIX_PROCESS_UID: - /* construct-only */ - if ((id = g_value_get_ulong(value)) != G_MAXULONG) { - priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS; - g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS); - priv->unix_process.uid = id; - } - break; - case PROP_UNIX_SESSION_ID: - /* construct-only */ - if ((str = g_value_get_string(value))) { - priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_SESSION; - g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_SESSION); - priv->unix_session.id = g_strdup(str); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -_clear_private(NMAuthSubject *self) -{ - NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(self); - - priv->subject_type = NM_AUTH_SUBJECT_TYPE_INVALID; - priv->unix_process.pid = G_MAXULONG; - priv->unix_process.uid = G_MAXULONG; - nm_clear_g_free(&priv->unix_process.dbus_sender); - - nm_clear_g_free(&priv->unix_session.id); -} - -static void -nm_auth_subject_init(NMAuthSubject *self) -{ - _clear_private(self); -} - -static void -constructed(GObject *object) -{ - NMAuthSubject * self = NM_AUTH_SUBJECT(object); - NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(self); - - /* validate that the created instance. */ - - switch (priv->subject_type) { - case NM_AUTH_SUBJECT_TYPE_INTERNAL: - priv->unix_process.pid = G_MAXULONG; - priv->unix_process.uid = 0; /* internal uses 'root' user */ - return; - case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS: - /* Ensure pid and uid to be representable as int32. - * DBUS treats them as uint32, polkit library as int. */ - if (priv->unix_process.pid > MIN(G_MAXINT, G_MAXINT32)) - break; - if (priv->unix_process.uid > MIN(G_MAXINT, G_MAXINT32)) { - /* for uid==-1, libpolkit-gobject-1 detects the user based on the process id. - * Don't bother and require the user id as parameter. */ - break; - } - - priv->unix_process.start_time = - nm_utils_get_start_time_for_pid(priv->unix_process.pid, NULL, NULL); - - if (!priv->unix_process.start_time) { - /* Is the process already gone? Then fail creation of the auth subject - * by clearing the type. */ - if (kill(priv->unix_process.pid, 0) != 0) - _clear_private(self); - - /* Otherwise, although we didn't detect a start_time, the process is still around. - * That could be due to procfs mounted with hidepid. So just accept the request. - * - * Polkit on the other side, will accept 0 and try to lookup /proc/$PID/stat - * itself (and if it fails to do so, assume a start-time of 0 and proceed). - * The only combination that would fail here, is when NM is able to read the - * start-time, but polkit is not. */ - } - return; - case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION: - return; - default: - break; - } - - _clear_private(self); - g_return_if_reached(); -} - -static void -finalize(GObject *object) -{ - _clear_private((NMAuthSubject *) object); - - G_OBJECT_CLASS(nm_auth_subject_parent_class)->finalize(object); -} - -static void -nm_auth_subject_class_init(NMAuthSubjectClass *config_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(config_class); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->constructed = constructed; - object_class->finalize = finalize; - - g_object_class_install_property( - object_class, - PROP_SUBJECT_TYPE, - g_param_spec_int(NM_AUTH_SUBJECT_SUBJECT_TYPE, - "", - "", - NM_AUTH_SUBJECT_TYPE_INVALID, - NM_AUTH_SUBJECT_TYPE_UNIX_SESSION, - NM_AUTH_SUBJECT_TYPE_INVALID, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property( - object_class, - PROP_UNIX_PROCESS_DBUS_SENDER, - g_param_spec_string(NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property( - object_class, - PROP_UNIX_PROCESS_PID, - g_param_spec_ulong(NM_AUTH_SUBJECT_UNIX_PROCESS_PID, - "", - "", - 0, - G_MAXULONG, - G_MAXULONG, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property( - object_class, - PROP_UNIX_PROCESS_UID, - g_param_spec_ulong(NM_AUTH_SUBJECT_UNIX_PROCESS_UID, - "", - "", - 0, - G_MAXULONG, - G_MAXULONG, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property( - object_class, - PROP_UNIX_SESSION_ID, - g_param_spec_string(NM_AUTH_SUBJECT_UNIX_SESSION_ID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); -} diff --git a/libnm-core/nm-libnm-core-intern/nm-auth-subject.h b/libnm-core/nm-libnm-core-intern/nm-auth-subject.h deleted file mode 100644 index 2c9c4f71a9..0000000000 --- a/libnm-core/nm-libnm-core-intern/nm-auth-subject.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2013 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_AUTH_SUBJECT_H__ -#define __NETWORKMANAGER_AUTH_SUBJECT_H__ - -#define NM_TYPE_AUTH_SUBJECT (nm_auth_subject_get_type()) -#define NM_AUTH_SUBJECT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubject)) -#define NM_AUTH_SUBJECT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass)) -#define NM_IS_AUTH_SUBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_AUTH_SUBJECT)) -#define NM_IS_AUTH_SUBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_AUTH_SUBJECT)) -#define NM_AUTH_SUBJECT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass)) - -typedef enum { - NM_AUTH_SUBJECT_TYPE_INVALID = 0, - NM_AUTH_SUBJECT_TYPE_INTERNAL = 1, - NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS = 2, - NM_AUTH_SUBJECT_TYPE_UNIX_SESSION = 4, -} NMAuthSubjectType; - -#define NM_AUTH_SUBJECT_SUBJECT_TYPE "subject-type" -#define NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER "unix-process-dbus-sender" -#define NM_AUTH_SUBJECT_UNIX_PROCESS_PID "unix-process-pid" -#define NM_AUTH_SUBJECT_UNIX_PROCESS_UID "unix-process-uid" -#define NM_AUTH_SUBJECT_UNIX_SESSION_ID "unix-session-id" - -typedef struct _NMAuthSubjectClass NMAuthSubjectClass; -typedef struct _NMAuthSubject NMAuthSubject; - -GType nm_auth_subject_get_type(void); - -NMAuthSubject *nm_auth_subject_new_internal(void); - -NMAuthSubject *nm_auth_subject_new_unix_session(const char *session_id); - -NMAuthSubject *nm_auth_subject_new_unix_process(const char *dbus_sender, gulong pid, gulong uid); - -NMAuthSubject *nm_auth_subject_new_unix_process_self(void); - -NMAuthSubjectType nm_auth_subject_get_subject_type(NMAuthSubject *subject); - -gulong nm_auth_subject_get_unix_process_pid(NMAuthSubject *subject); - -const char *nm_auth_subject_get_unix_process_dbus_sender(NMAuthSubject *subject); - -gulong nm_auth_subject_get_unix_process_uid(NMAuthSubject *subject); - -const char *nm_auth_subject_get_unix_session_id(NMAuthSubject *subject); - -const char *nm_auth_subject_to_string(NMAuthSubject *self, char *buf, gsize buf_len); - -GVariant *nm_auth_subject_unix_to_polkit_gvariant(NMAuthSubject *self); - -#endif /* __NETWORKMANAGER_AUTH_SUBJECT_H__ */ diff --git a/libnm-core/nm-libnm-core-intern/nm-common-macros.h b/libnm-core/nm-libnm-core-intern/nm-common-macros.h deleted file mode 100644 index c452b7d3cb..0000000000 --- a/libnm-core/nm-libnm-core-intern/nm-common-macros.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2016 Red Hat, Inc. - */ - -#ifndef __NM_COMMON_MACROS_H__ -#define __NM_COMMON_MACROS_H__ - -/*****************************************************************************/ - -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK \ - "org.freedesktop.NetworkManager.enable-disable-network" -#define NM_AUTH_PERMISSION_SLEEP_WAKE "org.freedesktop.NetworkManager.sleep-wake" -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi" -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan" -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX \ - "org.freedesktop.NetworkManager.enable-disable-wimax" -#define NM_AUTH_PERMISSION_NETWORK_CONTROL "org.freedesktop.NetworkManager.network-control" -#define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED \ - "org.freedesktop.NetworkManager.wifi.share.protected" -#define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN "org.freedesktop.NetworkManager.wifi.share.open" -#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM \ - "org.freedesktop.NetworkManager.settings.modify.system" -#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own" -#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME \ - "org.freedesktop.NetworkManager.settings.modify.hostname" -#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS \ - "org.freedesktop.NetworkManager.settings.modify.global-dns" -#define NM_AUTH_PERMISSION_RELOAD "org.freedesktop.NetworkManager.reload" -#define NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK "org.freedesktop.NetworkManager.checkpoint-rollback" -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS \ - "org.freedesktop.NetworkManager.enable-disable-statistics" -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK \ - "org.freedesktop.NetworkManager.enable-disable-connectivity-check" -#define NM_AUTH_PERMISSION_WIFI_SCAN "org.freedesktop.NetworkManager.wifi.scan" - -#define NM_CLONED_MAC_PRESERVE "preserve" -#define NM_CLONED_MAC_PERMANENT "permanent" -#define NM_CLONED_MAC_RANDOM "random" -#define NM_CLONED_MAC_STABLE "stable" - -static inline gboolean -NM_CLONED_MAC_IS_SPECIAL(const char *str) -{ - return NM_IN_STRSET(str, - NM_CLONED_MAC_PRESERVE, - NM_CLONED_MAC_PERMANENT, - NM_CLONED_MAC_RANDOM, - NM_CLONED_MAC_STABLE); -} - -#define NM_IAID_MAC "mac" -#define NM_IAID_PERM_MAC "perm-mac" -#define NM_IAID_IFNAME "ifname" -#define NM_IAID_STABLE "stable" - -#define NM_CONNECTION_MUD_URL_NONE "none" - -static inline gboolean -NM_IAID_IS_SPECIAL(const char *str) -{ - return NM_IN_STRSET(str, NM_IAID_MAC, NM_IAID_PERM_MAC, NM_IAID_IFNAME, NM_IAID_STABLE); -} - -#endif /* __NM_COMMON_MACROS_H__ */ diff --git a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c deleted file mode 100644 index 1ab0fcf253..0000000000 --- a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c +++ /dev/null @@ -1,387 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-libnm-core-utils.h" - -#include - -#include "nm-common-macros.h" -#include "nm-errors.h" - -/*****************************************************************************/ - -const char ** -nm_utils_bond_option_arp_ip_targets_split(const char *arp_ip_target) -{ - return nm_utils_strsplit_set_full(arp_ip_target, ",", NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP); -} - -void -_nm_setting_bond_remove_options_miimon(NMSettingBond *s_bond) -{ - g_return_if_fail(NM_IS_SETTING_BOND(s_bond)); - - nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_MIIMON); - nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_UPDELAY); - nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY); -} - -void -_nm_setting_bond_remove_options_arp_interval(NMSettingBond *s_bond) -{ - g_return_if_fail(NM_IS_SETTING_BOND(s_bond)); - - nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); -} - -/*****************************************************************************/ - -NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( - _nm_setting_bond_mode_from_string, - NMBondMode, - { - G_STATIC_ASSERT_EXPR(_NM_BOND_MODE_NUM <= 9); - - if (name && name[0] < '0' + _NM_BOND_MODE_NUM && name[0] >= '0' && name[1] == '\0') { - return name[0] - '0'; - } - }, - { return NM_BOND_MODE_UNKNOWN; }, - {"802.3ad", NM_BOND_MODE_8023AD}, - {"active-backup", NM_BOND_MODE_ACTIVEBACKUP}, - {"balance-alb", NM_BOND_MODE_ALB}, - {"balance-rr", NM_BOND_MODE_ROUNDROBIN}, - {"balance-tlb", NM_BOND_MODE_TLB}, - {"balance-xor", NM_BOND_MODE_XOR}, - {"broadcast", NM_BOND_MODE_BROADCAST}, ); - -const char * -_nm_setting_bond_mode_to_string(int mode) -{ - static const char *const modes[] = { - [NM_BOND_MODE_8023AD] = "802.3ad", - [NM_BOND_MODE_ACTIVEBACKUP] = "active-backup", - [NM_BOND_MODE_ALB] = "balance-alb", - [NM_BOND_MODE_BROADCAST] = "broadcast", - [NM_BOND_MODE_ROUNDROBIN] = "balance-rr", - [NM_BOND_MODE_TLB] = "balance-tlb", - [NM_BOND_MODE_XOR] = "balance-xor", - }; - - G_STATIC_ASSERT(G_N_ELEMENTS(modes) == _NM_BOND_MODE_NUM); - - if (NM_MORE_ASSERT_ONCE(5)) { - char sbuf[100]; - int i; - NMBondMode m; - - for (i = 0; i < (int) G_N_ELEMENTS(modes); i++) { - nm_assert(modes[i]); - nm_assert(i == _nm_setting_bond_mode_from_string(modes[i])); - nm_assert(i == _nm_setting_bond_mode_from_string(nm_sprintf_buf(sbuf, "%d", i))); - } - nm_assert(NM_BOND_MODE_UNKNOWN == _nm_setting_bond_mode_from_string(NULL)); - nm_assert(NM_BOND_MODE_UNKNOWN == _nm_setting_bond_mode_from_string("")); - for (i = -2; i < ((int) G_N_ELEMENTS(modes)) + 20; i++) { - if (i < 0 || i >= G_N_ELEMENTS(modes)) - m = NM_BOND_MODE_UNKNOWN; - else - m = i; - nm_assert(m == _nm_setting_bond_mode_from_string(nm_sprintf_buf(sbuf, "%d", i))); - } - } - - if (mode >= 0 && mode < (int) G_N_ELEMENTS(modes)) - return modes[mode]; - return NULL; -} - -/*****************************************************************************/ - -gboolean -nm_utils_vlan_priority_map_parse_str(NMVlanPriorityMap map_type, - const char * str, - gboolean allow_wildcard_to, - guint32 * out_from, - guint32 * out_to, - gboolean * out_has_wildcard_to) -{ - const char *s2; - gint64 v1, v2; - - nm_assert(str); - - s2 = strchr(str, ':'); - - if (!s2) { - if (!allow_wildcard_to) - return FALSE; - v1 = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT32, -1); - v2 = -1; - } else { - gs_free char *s1_free = NULL; - gsize s1_len = (s2 - str); - - s2 = nm_str_skip_leading_spaces(&s2[1]); - if (s2[0] == '\0' || (s2[0] == '*' && NM_STRCHAR_ALL(&s2[1], ch, g_ascii_isspace(ch)))) { - if (!allow_wildcard_to) - return FALSE; - v2 = -1; - } else { - v2 = _nm_utils_ascii_str_to_int64(s2, 10, 0, G_MAXUINT32, -1); - if (v2 < 0 || (guint32) v2 > nm_utils_vlan_priority_map_get_max_prio(map_type, FALSE)) - return FALSE; - } - - v1 = _nm_utils_ascii_str_to_int64(nm_strndup_a(100, str, s1_len, &s1_free), - 10, - 0, - G_MAXUINT32, - -1); - } - - if (v1 < 0 || (guint32) v1 > nm_utils_vlan_priority_map_get_max_prio(map_type, TRUE)) - return FALSE; - - NM_SET_OUT(out_from, v1); - NM_SET_OUT(out_to, v2 < 0 ? 0u : (guint) v2); - NM_SET_OUT(out_has_wildcard_to, v2 < 0); - return TRUE; -} - -/*****************************************************************************/ - -const char *const nm_auth_permission_names_by_idx[NM_CLIENT_PERMISSION_LAST] = { - [NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK - 1] = NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, - [NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK - 1] = - NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, - [NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, - [NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS - 1] = - NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS, - [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, - [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, - [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, - [NM_CLIENT_PERMISSION_NETWORK_CONTROL - 1] = NM_AUTH_PERMISSION_NETWORK_CONTROL, - [NM_CLIENT_PERMISSION_RELOAD - 1] = NM_AUTH_PERMISSION_RELOAD, - [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS - 1] = - NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, - [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME - 1] = - NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, - [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, - [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, - [NM_CLIENT_PERMISSION_SLEEP_WAKE - 1] = NM_AUTH_PERMISSION_SLEEP_WAKE, - [NM_CLIENT_PERMISSION_WIFI_SCAN - 1] = NM_AUTH_PERMISSION_WIFI_SCAN, - [NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN - 1] = NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, - [NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED - 1] = NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, -}; - -const NMClientPermission nm_auth_permission_sorted[NM_CLIENT_PERMISSION_LAST] = { - NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX, - NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN, - NM_CLIENT_PERMISSION_NETWORK_CONTROL, - NM_CLIENT_PERMISSION_RELOAD, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN, - NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM, - NM_CLIENT_PERMISSION_SLEEP_WAKE, - NM_CLIENT_PERMISSION_WIFI_SCAN, - NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN, - NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED, -}; - -const char * -nm_auth_permission_to_string(NMClientPermission permission) -{ - if (permission < 1) - return NULL; - if (permission > NM_CLIENT_PERMISSION_LAST) - return NULL; - return nm_auth_permission_names_by_idx[permission - 1]; -} - -#define AUTH_PERMISSION_PREFIX "org.freedesktop.NetworkManager." - -static int -_nm_auth_permission_from_string_cmp(gconstpointer a, gconstpointer b, gpointer user_data) -{ - const NMClientPermission *const p = a; - const char *const needle = b; - const char * ss = nm_auth_permission_names_by_idx[*p - 1]; - - nm_assert(NM_STR_HAS_PREFIX(ss, AUTH_PERMISSION_PREFIX)); - nm_assert(ss[NM_STRLEN(AUTH_PERMISSION_PREFIX)] != '\0'); - - return strcmp(&ss[NM_STRLEN(AUTH_PERMISSION_PREFIX)], needle); -} - -NMClientPermission -nm_auth_permission_from_string(const char *str) -{ - gssize idx; - - if (!str) - return NM_CLIENT_PERMISSION_NONE; - - if (!NM_STR_HAS_PREFIX(str, AUTH_PERMISSION_PREFIX)) - return NM_CLIENT_PERMISSION_NONE; - idx = nm_utils_array_find_binary_search(nm_auth_permission_sorted, - sizeof(nm_auth_permission_sorted[0]), - G_N_ELEMENTS(nm_auth_permission_sorted), - &str[NM_STRLEN(AUTH_PERMISSION_PREFIX)], - _nm_auth_permission_from_string_cmp, - NULL); - if (idx < 0) - return NM_CLIENT_PERMISSION_NONE; - return nm_auth_permission_sorted[idx]; -} - -/*****************************************************************************/ - -NMClientPermissionResult -nm_client_permission_result_from_string(const char *nm) -{ - if (!nm) - return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; - if (nm_streq(nm, "yes")) - return NM_CLIENT_PERMISSION_RESULT_YES; - if (nm_streq(nm, "no")) - return NM_CLIENT_PERMISSION_RESULT_NO; - if (nm_streq(nm, "auth")) - return NM_CLIENT_PERMISSION_RESULT_AUTH; - return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; -} - -const char * -nm_client_permission_result_to_string(NMClientPermissionResult permission) -{ - switch (permission) { - case NM_CLIENT_PERMISSION_RESULT_YES: - return "yes"; - case NM_CLIENT_PERMISSION_RESULT_NO: - return "no"; - case NM_CLIENT_PERMISSION_RESULT_AUTH: - return "auth"; - case NM_CLIENT_PERMISSION_RESULT_UNKNOWN: - return "unknown"; - } - nm_assert_not_reached(); - return NULL; -} - -NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( - nm_utils_route_type_by_name, - guint8, - { nm_assert(name); }, - { return RTN_UNSPEC; }, - {"blackhole", RTN_BLACKHOLE}, - {"broadcast", RTN_BROADCAST}, - {"local", RTN_LOCAL}, - {"multicast", RTN_MULTICAST}, - {"nat", RTN_NAT}, - {"prohibit", RTN_PROHIBIT}, - {"throw", RTN_THROW}, - {"unicast", RTN_UNICAST}, - {"unreachable", RTN_UNREACHABLE}, ); - -NM_UTILS_ENUM2STR_DEFINE(nm_utils_route_type2str, - guint8, - NM_UTILS_ENUM2STR(RTN_BLACKHOLE, "blackhole"), - NM_UTILS_ENUM2STR(RTN_BROADCAST, "broadcast"), - NM_UTILS_ENUM2STR(RTN_LOCAL, "local"), - NM_UTILS_ENUM2STR(RTN_MULTICAST, "multicast"), - NM_UTILS_ENUM2STR(RTN_NAT, "nat"), - NM_UTILS_ENUM2STR(RTN_PROHIBIT, "prohibit"), - NM_UTILS_ENUM2STR(RTN_THROW, "throw"), - NM_UTILS_ENUM2STR(RTN_UNICAST, "unicast"), - NM_UTILS_ENUM2STR(RTN_UNREACHABLE, "unreachable"), - NM_UTILS_ENUM2STR(RTN_UNSPEC, "unspecified"), ); - -gboolean -nm_utils_validate_dhcp4_vendor_class_id(const char *vci, GError **error) -{ - const char * bin; - gsize unescaped_len; - gs_free char *to_free = NULL; - - g_return_val_if_fail(!error || !(*error), FALSE); - g_return_val_if_fail(vci, FALSE); - - if (vci[0] == '\0') { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property cannot be an empty string")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER); - return FALSE; - } - - bin = nm_utils_buf_utf8safe_unescape(vci, - NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, - &unescaped_len, - (gpointer *) &to_free); - /* a DHCP option cannot be longer than 255 bytes */ - if (unescaped_len > 255) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property cannot be longer than 255 bytes")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER); - return FALSE; - } - if (strlen(bin) != unescaped_len) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property cannot contain any nul bytes")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER); - return FALSE; - } - - return TRUE; -} - -gboolean -nm_settings_connection_validate_permission_user(const char *item, gssize len) -{ - gsize l; - - if (!item) - return FALSE; - - if (len < 0) { - nm_assert(len == -1); - l = strlen(item); - } else - l = (gsize) len; - - if (l == 0) - return FALSE; - - if (!g_utf8_validate(item, l, NULL)) - return FALSE; - - if (l >= 100) - return FALSE; - - if (memchr(item, ':', l)) - return FALSE; - - return TRUE; -} diff --git a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h deleted file mode 100644 index 946c7a2c0e..0000000000 --- a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h +++ /dev/null @@ -1,162 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#ifndef __NM_LIBNM_SHARED_UTILS_H__ -#define __NM_LIBNM_SHARED_UTILS_H__ - -/****************************************************************************/ - -#include "nm-setting-bond.h" -#include "nm-setting-bridge.h" -#include "nm-setting-connection.h" -#include "nm-setting-ip-config.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-setting-sriov.h" -#include "nm-setting-team.h" -#include "nm-setting-vlan.h" -#include "nm-setting-wireguard.h" - -/****************************************************************************/ - -#define nm_auto_unref_ip_address nm_auto(_nm_ip_address_unref) -NM_AUTO_DEFINE_FCN0(NMIPAddress *, _nm_ip_address_unref, nm_ip_address_unref); - -#define nm_auto_unref_ip_route nm_auto(_nm_auto_unref_ip_route) -NM_AUTO_DEFINE_FCN0(NMIPRoute *, _nm_auto_unref_ip_route, nm_ip_route_unref); - -#define nm_auto_unref_ip_routing_rule nm_auto(_nm_auto_unref_ip_routing_rule) -NM_AUTO_DEFINE_FCN0(NMIPRoutingRule *, _nm_auto_unref_ip_routing_rule, nm_ip_routing_rule_unref); - -#define nm_auto_unref_sriov_vf nm_auto(_nm_auto_unref_sriov_vf) -NM_AUTO_DEFINE_FCN0(NMSriovVF *, _nm_auto_unref_sriov_vf, nm_sriov_vf_unref); - -#define nm_auto_unref_tc_qdisc nm_auto(_nm_auto_unref_tc_qdisc) -NM_AUTO_DEFINE_FCN0(NMTCQdisc *, _nm_auto_unref_tc_qdisc, nm_tc_qdisc_unref); - -#define nm_auto_unref_tc_tfilter nm_auto(_nm_auto_unref_tc_tfilter) -NM_AUTO_DEFINE_FCN0(NMTCTfilter *, _nm_auto_unref_tc_tfilter, nm_tc_tfilter_unref); - -#define nm_auto_unref_bridge_vlan nm_auto(_nm_auto_unref_bridge_vlan) -NM_AUTO_DEFINE_FCN0(NMBridgeVlan *, _nm_auto_unref_bridge_vlan, nm_bridge_vlan_unref); - -#define nm_auto_unref_team_link_watcher nm_auto(_nm_auto_unref_team_link_watcher) -NM_AUTO_DEFINE_FCN0(NMTeamLinkWatcher *, - _nm_auto_unref_team_link_watcher, - nm_team_link_watcher_unref); - -#define nm_auto_unref_wgpeer nm_auto(_nm_auto_unref_wgpeer) -NM_AUTO_DEFINE_FCN0(NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer_unref); - -/****************************************************************************/ - -const char **nm_utils_bond_option_arp_ip_targets_split(const char *arp_ip_target); - -void _nm_setting_bond_remove_options_miimon(NMSettingBond *s_bond); -void _nm_setting_bond_remove_options_arp_interval(NMSettingBond *s_bond); - -typedef enum { - NM_BOND_MODE_UNKNOWN = -1, - - /* The numeric values correspond to kernel's numbering of the modes. */ - NM_BOND_MODE_ROUNDROBIN = 0, - NM_BOND_MODE_ACTIVEBACKUP = 1, - NM_BOND_MODE_XOR = 2, - NM_BOND_MODE_BROADCAST = 3, - NM_BOND_MODE_8023AD = 4, - NM_BOND_MODE_TLB = 5, - NM_BOND_MODE_ALB = 6, - - _NM_BOND_MODE_NUM, -} NMBondMode; - -NMBondMode _nm_setting_bond_mode_from_string(const char *str); - -const char *_nm_setting_bond_mode_to_string(int mode); - -gboolean _nm_setting_bond_validate_option(const char *name, const char *value, GError **error); - -/*****************************************************************************/ - -static inline guint32 -nm_utils_vlan_priority_map_get_max_prio(NMVlanPriorityMap map, gboolean from) -{ - if (map == NM_VLAN_INGRESS_MAP) { - return from ? 7u /* MAX_8021P_PRIO */ - : (guint32) G_MAXUINT32 /* MAX_SKB_PRIO */; - } - nm_assert(map == NM_VLAN_EGRESS_MAP); - return from ? (guint32) G_MAXUINT32 /* MAX_SKB_PRIO */ - : 7u /* MAX_8021P_PRIO */; -} - -gboolean nm_utils_vlan_priority_map_parse_str(NMVlanPriorityMap map_type, - const char * str, - gboolean allow_wildcard_to, - guint32 * out_from, - guint32 * out_to, - gboolean * out_has_wildcard_to); - -/*****************************************************************************/ - -#define NM_OVS_EXTERNAL_ID_NM_PREFIX "NM." -#define NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID "NM.connection.uuid" - -/*****************************************************************************/ - -static inline int -nm_setting_ip_config_get_addr_family(NMSettingIPConfig *s_ip) -{ - if (NM_IS_SETTING_IP4_CONFIG(s_ip)) - return AF_INET; - if (NM_IS_SETTING_IP6_CONFIG(s_ip)) - return AF_INET6; - g_return_val_if_reached(AF_UNSPEC); -} - -/*****************************************************************************/ - -/* The maximum MTU for infiniband. - * - * This is both in transport-mode "datagram" and "connected" - * and they both have the same maximum define. - * - * Note that in the past, MTU in "datagram" mode was restricted - * to 2044 bytes. That is no longer the case and we accept large - * MTUs. - * - * This define is the maxiumum for the MTU in a connection profile (the - * setting). Whether large MTUs can be configured later (at activation time) - * depends on other factors. */ -#define NM_INFINIBAND_MAX_MTU ((guint) 65520) - -/*****************************************************************************/ - -#define _NM_CAPABILITY_MAX NM_CAPABILITY_OVS - -/*****************************************************************************/ - -extern const char *const nm_auth_permission_names_by_idx[NM_CLIENT_PERMISSION_LAST]; -extern const NMClientPermission nm_auth_permission_sorted[NM_CLIENT_PERMISSION_LAST]; - -const char * nm_auth_permission_to_string(NMClientPermission permission); -NMClientPermission nm_auth_permission_from_string(const char *str); - -/*****************************************************************************/ - -NMClientPermissionResult nm_client_permission_result_from_string(const char *nm); -const char * nm_client_permission_result_to_string(NMClientPermissionResult permission); - -guint8 nm_utils_route_type_by_name(const char *name); - -const char *nm_utils_route_type2str(guint8 val, char *buf, gsize len); - -gboolean nm_utils_validate_dhcp4_vendor_class_id(const char *vci, GError **error); - -/*****************************************************************************/ - -#define NM_SETTINGS_CONNECTION_PERMISSION_USER "user" -#define NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX "user:" - -gboolean nm_settings_connection_validate_permission_user(const char *item, gssize len); - -#endif /* __NM_LIBNM_SHARED_UTILS_H__ */ diff --git a/libnm-core/nm-meta-setting-base-impl.c b/libnm-core/nm-meta-setting-base-impl.c deleted file mode 100644 index 523c0d5db3..0000000000 --- a/libnm-core/nm-meta-setting-base-impl.c +++ /dev/null @@ -1,641 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 - 2018 Red Hat, Inc. - */ - -#include "nm-glib-aux/nm-default-glib-i18n-lib.h" - -#include "nm-meta-setting-base.h" - -#include "nm-setting-6lowpan.h" -#include "nm-setting-8021x.h" -#include "nm-setting-adsl.h" -#include "nm-setting-bluetooth.h" -#include "nm-setting-bond.h" -#include "nm-setting-bridge-port.h" -#include "nm-setting-bridge.h" -#include "nm-setting-cdma.h" -#include "nm-setting-connection.h" -#include "nm-setting-dcb.h" -#include "nm-setting-dummy.h" -#include "nm-setting-ethtool.h" -#include "nm-setting-generic.h" -#include "nm-setting-gsm.h" -#include "nm-setting-hostname.h" -#include "nm-setting-infiniband.h" -#include "nm-setting-ip-config.h" -#include "nm-setting-ip-tunnel.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-setting-macsec.h" -#include "nm-setting-macvlan.h" -#include "nm-setting-match.h" -#include "nm-setting-olpc-mesh.h" -#include "nm-setting-ovs-bridge.h" -#include "nm-setting-ovs-interface.h" -#include "nm-setting-ovs-dpdk.h" -#include "nm-setting-ovs-external-ids.h" -#include "nm-setting-ovs-patch.h" -#include "nm-setting-ovs-port.h" -#include "nm-setting-ppp.h" -#include "nm-setting-pppoe.h" -#include "nm-setting-proxy.h" -#include "nm-setting-serial.h" -#include "nm-setting-tc-config.h" -#include "nm-setting-team-port.h" -#include "nm-setting-team.h" -#include "nm-setting-tun.h" -#include "nm-setting-user.h" -#include "nm-setting-veth.h" -#include "nm-setting-vlan.h" -#include "nm-setting-vpn.h" -#include "nm-setting-vrf.h" -#include "nm-setting-vxlan.h" -#include "nm-setting-wifi-p2p.h" -#include "nm-setting-wimax.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireguard.h" -#include "nm-setting-wireless-security.h" -#include "nm-setting-wireless.h" -#include "nm-setting-wpan.h" - -/*****************************************************************************/ - -const NMSetting8021xSchemeVtable nm_setting_8021x_scheme_vtable[] = { - -#define _D(_scheme_type, ...) [(_scheme_type)] = {.scheme_type = (_scheme_type), __VA_ARGS__} - - _D(NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN), - - _D(NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT, - .setting_key = NM_SETTING_802_1X_CA_CERT, - .scheme_func = nm_setting_802_1x_get_ca_cert_scheme, - .format_func = NULL, - .path_func = nm_setting_802_1x_get_ca_cert_path, - .blob_func = nm_setting_802_1x_get_ca_cert_blob, - .uri_func = nm_setting_802_1x_get_ca_cert_uri, - .passwd_func = nm_setting_802_1x_get_ca_cert_password, - .pwflag_func = nm_setting_802_1x_get_ca_cert_password_flags, - .set_cert_func = nm_setting_802_1x_set_ca_cert, - .file_suffix = "ca-cert", ), - - _D(NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT, - .setting_key = NM_SETTING_802_1X_PHASE2_CA_CERT, - .scheme_func = nm_setting_802_1x_get_phase2_ca_cert_scheme, - .format_func = NULL, - .path_func = nm_setting_802_1x_get_phase2_ca_cert_path, - .blob_func = nm_setting_802_1x_get_phase2_ca_cert_blob, - .uri_func = nm_setting_802_1x_get_phase2_ca_cert_uri, - .passwd_func = nm_setting_802_1x_get_phase2_ca_cert_password, - .pwflag_func = nm_setting_802_1x_get_phase2_ca_cert_password_flags, - .set_cert_func = nm_setting_802_1x_set_phase2_ca_cert, - .file_suffix = "inner-ca-cert", ), - - _D(NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT, - .setting_key = NM_SETTING_802_1X_CLIENT_CERT, - .scheme_func = nm_setting_802_1x_get_client_cert_scheme, - .format_func = NULL, - .path_func = nm_setting_802_1x_get_client_cert_path, - .blob_func = nm_setting_802_1x_get_client_cert_blob, - .uri_func = nm_setting_802_1x_get_client_cert_uri, - .passwd_func = nm_setting_802_1x_get_client_cert_password, - .pwflag_func = nm_setting_802_1x_get_client_cert_password_flags, - .set_cert_func = nm_setting_802_1x_set_client_cert, - .file_suffix = "client-cert", ), - - _D(NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT, - .setting_key = NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - .scheme_func = nm_setting_802_1x_get_phase2_client_cert_scheme, - .format_func = NULL, - .path_func = nm_setting_802_1x_get_phase2_client_cert_path, - .blob_func = nm_setting_802_1x_get_phase2_client_cert_blob, - .uri_func = nm_setting_802_1x_get_phase2_client_cert_uri, - .passwd_func = nm_setting_802_1x_get_phase2_client_cert_password, - .pwflag_func = nm_setting_802_1x_get_phase2_client_cert_password_flags, - .set_cert_func = nm_setting_802_1x_set_phase2_client_cert, - .file_suffix = "inner-client-cert", ), - - _D(NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY, - .setting_key = NM_SETTING_802_1X_PRIVATE_KEY, - .scheme_func = nm_setting_802_1x_get_private_key_scheme, - .format_func = nm_setting_802_1x_get_private_key_format, - .path_func = nm_setting_802_1x_get_private_key_path, - .blob_func = nm_setting_802_1x_get_private_key_blob, - .uri_func = nm_setting_802_1x_get_private_key_uri, - .passwd_func = nm_setting_802_1x_get_private_key_password, - .pwflag_func = nm_setting_802_1x_get_private_key_password_flags, - .set_private_key_func = nm_setting_802_1x_set_private_key, - .file_suffix = "private-key", - .is_secret = TRUE, ), - - _D(NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY, - .setting_key = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - .scheme_func = nm_setting_802_1x_get_phase2_private_key_scheme, - .format_func = nm_setting_802_1x_get_phase2_private_key_format, - .path_func = nm_setting_802_1x_get_phase2_private_key_path, - .blob_func = nm_setting_802_1x_get_phase2_private_key_blob, - .uri_func = nm_setting_802_1x_get_phase2_private_key_uri, - .passwd_func = nm_setting_802_1x_get_phase2_private_key_password, - .pwflag_func = nm_setting_802_1x_get_phase2_private_key_password_flags, - .set_private_key_func = nm_setting_802_1x_set_phase2_private_key, - .file_suffix = "inner-private-key", - .is_secret = TRUE, ), - -#undef _D -}; - -/*****************************************************************************/ - -const NMMetaSettingInfo nm_meta_setting_infos[] = { - [NM_META_SETTING_TYPE_6LOWPAN] = - { - .meta_type = NM_META_SETTING_TYPE_6LOWPAN, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_6LOWPAN_SETTING_NAME, - .get_setting_gtype = nm_setting_6lowpan_get_type, - }, - [NM_META_SETTING_TYPE_802_1X] = - { - .meta_type = NM_META_SETTING_TYPE_802_1X, - .setting_priority = NM_SETTING_PRIORITY_HW_AUX, - .setting_name = NM_SETTING_802_1X_SETTING_NAME, - .get_setting_gtype = nm_setting_802_1x_get_type, - }, - [NM_META_SETTING_TYPE_ADSL] = - { - .meta_type = NM_META_SETTING_TYPE_ADSL, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_ADSL_SETTING_NAME, - .get_setting_gtype = nm_setting_adsl_get_type, - }, - [NM_META_SETTING_TYPE_BLUETOOTH] = - { - .meta_type = NM_META_SETTING_TYPE_BLUETOOTH, - .setting_priority = NM_SETTING_PRIORITY_HW_NON_BASE, - .setting_name = NM_SETTING_BLUETOOTH_SETTING_NAME, - .get_setting_gtype = nm_setting_bluetooth_get_type, - }, - [NM_META_SETTING_TYPE_BOND] = - { - .meta_type = NM_META_SETTING_TYPE_BOND, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_BOND_SETTING_NAME, - .get_setting_gtype = nm_setting_bond_get_type, - }, - [NM_META_SETTING_TYPE_BRIDGE] = - { - .meta_type = NM_META_SETTING_TYPE_BRIDGE, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_BRIDGE_SETTING_NAME, - .get_setting_gtype = nm_setting_bridge_get_type, - }, - [NM_META_SETTING_TYPE_BRIDGE_PORT] = - { - .meta_type = NM_META_SETTING_TYPE_BRIDGE_PORT, - .setting_priority = NM_SETTING_PRIORITY_AUX, - .setting_name = NM_SETTING_BRIDGE_PORT_SETTING_NAME, - .get_setting_gtype = nm_setting_bridge_port_get_type, - }, - [NM_META_SETTING_TYPE_CDMA] = - { - .meta_type = NM_META_SETTING_TYPE_CDMA, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_CDMA_SETTING_NAME, - .get_setting_gtype = nm_setting_cdma_get_type, - }, - [NM_META_SETTING_TYPE_CONNECTION] = - { - .meta_type = NM_META_SETTING_TYPE_CONNECTION, - .setting_priority = NM_SETTING_PRIORITY_CONNECTION, - .setting_name = NM_SETTING_CONNECTION_SETTING_NAME, - .get_setting_gtype = nm_setting_connection_get_type, - }, - [NM_META_SETTING_TYPE_DCB] = - { - .meta_type = NM_META_SETTING_TYPE_DCB, - .setting_priority = NM_SETTING_PRIORITY_HW_AUX, - .setting_name = NM_SETTING_DCB_SETTING_NAME, - .get_setting_gtype = nm_setting_dcb_get_type, - }, - [NM_META_SETTING_TYPE_DUMMY] = - { - .meta_type = NM_META_SETTING_TYPE_DUMMY, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_DUMMY_SETTING_NAME, - .get_setting_gtype = nm_setting_dummy_get_type, - }, - [NM_META_SETTING_TYPE_ETHTOOL] = - { - .meta_type = NM_META_SETTING_TYPE_ETHTOOL, - .setting_priority = NM_SETTING_PRIORITY_AUX, - .setting_name = NM_SETTING_ETHTOOL_SETTING_NAME, - .get_setting_gtype = nm_setting_ethtool_get_type, - }, - [NM_META_SETTING_TYPE_GENERIC] = - { - .meta_type = NM_META_SETTING_TYPE_GENERIC, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_GENERIC_SETTING_NAME, - .get_setting_gtype = nm_setting_generic_get_type, - }, - [NM_META_SETTING_TYPE_GSM] = - { - .meta_type = NM_META_SETTING_TYPE_GSM, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_GSM_SETTING_NAME, - .get_setting_gtype = nm_setting_gsm_get_type, - }, - [NM_META_SETTING_TYPE_HOSTNAME] = - { - .meta_type = NM_META_SETTING_TYPE_HOSTNAME, - .setting_priority = NM_SETTING_PRIORITY_IP, - .setting_name = NM_SETTING_HOSTNAME_SETTING_NAME, - .get_setting_gtype = nm_setting_hostname_get_type, - }, - [NM_META_SETTING_TYPE_INFINIBAND] = - { - .meta_type = NM_META_SETTING_TYPE_INFINIBAND, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_INFINIBAND_SETTING_NAME, - .get_setting_gtype = nm_setting_infiniband_get_type, - }, - [NM_META_SETTING_TYPE_IP4_CONFIG] = - { - .meta_type = NM_META_SETTING_TYPE_IP4_CONFIG, - .setting_priority = NM_SETTING_PRIORITY_IP, - .setting_name = NM_SETTING_IP4_CONFIG_SETTING_NAME, - .get_setting_gtype = nm_setting_ip4_config_get_type, - }, - [NM_META_SETTING_TYPE_IP6_CONFIG] = - { - .meta_type = NM_META_SETTING_TYPE_IP6_CONFIG, - .setting_priority = NM_SETTING_PRIORITY_IP, - .setting_name = NM_SETTING_IP6_CONFIG_SETTING_NAME, - .get_setting_gtype = nm_setting_ip6_config_get_type, - }, - [NM_META_SETTING_TYPE_IP_TUNNEL] = - { - .meta_type = NM_META_SETTING_TYPE_IP_TUNNEL, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_IP_TUNNEL_SETTING_NAME, - .get_setting_gtype = nm_setting_ip_tunnel_get_type, - }, - [NM_META_SETTING_TYPE_MACSEC] = - { - .meta_type = NM_META_SETTING_TYPE_MACSEC, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_MACSEC_SETTING_NAME, - .get_setting_gtype = nm_setting_macsec_get_type, - }, - [NM_META_SETTING_TYPE_MACVLAN] = - { - .meta_type = NM_META_SETTING_TYPE_MACVLAN, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_MACVLAN_SETTING_NAME, - .get_setting_gtype = nm_setting_macvlan_get_type, - }, - [NM_META_SETTING_TYPE_MATCH] = - { - .meta_type = NM_META_SETTING_TYPE_MATCH, - .setting_priority = NM_SETTING_PRIORITY_AUX, - .setting_name = NM_SETTING_MATCH_SETTING_NAME, - .get_setting_gtype = nm_setting_match_get_type, - }, - [NM_META_SETTING_TYPE_OLPC_MESH] = - { - .meta_type = NM_META_SETTING_TYPE_OLPC_MESH, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_OLPC_MESH_SETTING_NAME, - .get_setting_gtype = nm_setting_olpc_mesh_get_type, - }, - [NM_META_SETTING_TYPE_OVS_BRIDGE] = - { - .meta_type = NM_META_SETTING_TYPE_OVS_BRIDGE, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_OVS_BRIDGE_SETTING_NAME, - .get_setting_gtype = nm_setting_ovs_bridge_get_type, - }, - [NM_META_SETTING_TYPE_OVS_DPDK] = - { - .meta_type = NM_META_SETTING_TYPE_OVS_DPDK, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_OVS_DPDK_SETTING_NAME, - .get_setting_gtype = nm_setting_ovs_dpdk_get_type, - }, - [NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS] = - { - .meta_type = NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, - .setting_priority = NM_SETTING_PRIORITY_AUX, - .setting_name = NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, - .get_setting_gtype = nm_setting_ovs_external_ids_get_type, - }, - [NM_META_SETTING_TYPE_OVS_INTERFACE] = - { - .meta_type = NM_META_SETTING_TYPE_OVS_INTERFACE, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_OVS_INTERFACE_SETTING_NAME, - .get_setting_gtype = nm_setting_ovs_interface_get_type, - }, - [NM_META_SETTING_TYPE_OVS_PATCH] = - { - .meta_type = NM_META_SETTING_TYPE_OVS_PATCH, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_OVS_PATCH_SETTING_NAME, - .get_setting_gtype = nm_setting_ovs_patch_get_type, - }, - [NM_META_SETTING_TYPE_OVS_PORT] = - { - .meta_type = NM_META_SETTING_TYPE_OVS_PORT, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_OVS_PORT_SETTING_NAME, - .get_setting_gtype = nm_setting_ovs_port_get_type, - }, - [NM_META_SETTING_TYPE_PPPOE] = - { - .meta_type = NM_META_SETTING_TYPE_PPPOE, - .setting_priority = NM_SETTING_PRIORITY_AUX, - .setting_name = NM_SETTING_PPPOE_SETTING_NAME, - .get_setting_gtype = nm_setting_pppoe_get_type, - }, - [NM_META_SETTING_TYPE_PPP] = - { - .meta_type = NM_META_SETTING_TYPE_PPP, - .setting_priority = NM_SETTING_PRIORITY_AUX, - .setting_name = NM_SETTING_PPP_SETTING_NAME, - .get_setting_gtype = nm_setting_ppp_get_type, - }, - [NM_META_SETTING_TYPE_PROXY] = - { - .meta_type = NM_META_SETTING_TYPE_PROXY, - .setting_priority = NM_SETTING_PRIORITY_IP, - .setting_name = NM_SETTING_PROXY_SETTING_NAME, - .get_setting_gtype = nm_setting_proxy_get_type, - }, - [NM_META_SETTING_TYPE_SERIAL] = - { - .meta_type = NM_META_SETTING_TYPE_SERIAL, - .setting_priority = NM_SETTING_PRIORITY_HW_AUX, - .setting_name = NM_SETTING_SERIAL_SETTING_NAME, - .get_setting_gtype = nm_setting_serial_get_type, - }, - [NM_META_SETTING_TYPE_SRIOV] = - { - .meta_type = NM_META_SETTING_TYPE_SRIOV, - .setting_priority = NM_SETTING_PRIORITY_HW_AUX, - .setting_name = NM_SETTING_SRIOV_SETTING_NAME, - .get_setting_gtype = nm_setting_sriov_get_type, - }, - [NM_META_SETTING_TYPE_TC_CONFIG] = - { - .meta_type = NM_META_SETTING_TYPE_TC_CONFIG, - .setting_priority = NM_SETTING_PRIORITY_IP, - .setting_name = NM_SETTING_TC_CONFIG_SETTING_NAME, - .get_setting_gtype = nm_setting_tc_config_get_type, - }, - [NM_META_SETTING_TYPE_TEAM] = - { - .meta_type = NM_META_SETTING_TYPE_TEAM, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_TEAM_SETTING_NAME, - .get_setting_gtype = nm_setting_team_get_type, - }, - [NM_META_SETTING_TYPE_TEAM_PORT] = - { - .meta_type = NM_META_SETTING_TYPE_TEAM_PORT, - .setting_priority = NM_SETTING_PRIORITY_AUX, - .setting_name = NM_SETTING_TEAM_PORT_SETTING_NAME, - .get_setting_gtype = nm_setting_team_port_get_type, - }, - [NM_META_SETTING_TYPE_TUN] = - { - .meta_type = NM_META_SETTING_TYPE_TUN, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_TUN_SETTING_NAME, - .get_setting_gtype = nm_setting_tun_get_type, - }, - [NM_META_SETTING_TYPE_USER] = - { - .meta_type = NM_META_SETTING_TYPE_USER, - .setting_priority = NM_SETTING_PRIORITY_USER, - .setting_name = NM_SETTING_USER_SETTING_NAME, - .get_setting_gtype = nm_setting_user_get_type, - }, - [NM_META_SETTING_TYPE_VETH] = - { - .meta_type = NM_META_SETTING_TYPE_VETH, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_VETH_SETTING_NAME, - .get_setting_gtype = nm_setting_veth_get_type, - }, - [NM_META_SETTING_TYPE_VLAN] = - { - .meta_type = NM_META_SETTING_TYPE_VLAN, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_VLAN_SETTING_NAME, - .get_setting_gtype = nm_setting_vlan_get_type, - }, - [NM_META_SETTING_TYPE_VPN] = - { - .meta_type = NM_META_SETTING_TYPE_VPN, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_VPN_SETTING_NAME, - .get_setting_gtype = nm_setting_vpn_get_type, - }, - [NM_META_SETTING_TYPE_VRF] = - { - .meta_type = NM_META_SETTING_TYPE_VRF, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_VRF_SETTING_NAME, - .get_setting_gtype = nm_setting_vrf_get_type, - }, - [NM_META_SETTING_TYPE_VXLAN] = - { - .meta_type = NM_META_SETTING_TYPE_VXLAN, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_VXLAN_SETTING_NAME, - .get_setting_gtype = nm_setting_vxlan_get_type, - }, - [NM_META_SETTING_TYPE_WIFI_P2P] = - { - .meta_type = NM_META_SETTING_TYPE_WIFI_P2P, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_WIFI_P2P_SETTING_NAME, - .get_setting_gtype = nm_setting_wifi_p2p_get_type, - }, - [NM_META_SETTING_TYPE_WIMAX] = - { - .meta_type = NM_META_SETTING_TYPE_WIMAX, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_WIMAX_SETTING_NAME, - .get_setting_gtype = nm_setting_wimax_get_type, - }, - [NM_META_SETTING_TYPE_WIRED] = - { - .meta_type = NM_META_SETTING_TYPE_WIRED, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_WIRED_SETTING_NAME, - .get_setting_gtype = nm_setting_wired_get_type, - }, - [NM_META_SETTING_TYPE_WIREGUARD] = - { - .meta_type = NM_META_SETTING_TYPE_WIREGUARD, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_WIREGUARD_SETTING_NAME, - .get_setting_gtype = nm_setting_wireguard_get_type, - }, - [NM_META_SETTING_TYPE_WIRELESS] = - { - .meta_type = NM_META_SETTING_TYPE_WIRELESS, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_WIRELESS_SETTING_NAME, - .get_setting_gtype = nm_setting_wireless_get_type, - }, - [NM_META_SETTING_TYPE_WIRELESS_SECURITY] = - { - .meta_type = NM_META_SETTING_TYPE_WIRELESS_SECURITY, - .setting_priority = NM_SETTING_PRIORITY_HW_AUX, - .setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - .get_setting_gtype = nm_setting_wireless_security_get_type, - }, - [NM_META_SETTING_TYPE_WPAN] = - { - .meta_type = NM_META_SETTING_TYPE_WPAN, - .setting_priority = NM_SETTING_PRIORITY_HW_BASE, - .setting_name = NM_SETTING_WPAN_SETTING_NAME, - .get_setting_gtype = nm_setting_wpan_get_type, - }, - - [NM_META_SETTING_TYPE_UNKNOWN] = - { - .meta_type = NM_META_SETTING_TYPE_UNKNOWN, - }, -}; - -const NMMetaSettingInfo * -nm_meta_setting_infos_by_name(const char *name) -{ - gssize idx; - - if (NM_MORE_ASSERTS > 10) { - guint i, j; - - for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { - const NMMetaSettingInfo *setting_info = &nm_meta_setting_infos[i]; - - nm_assert(setting_info->meta_type == (NMMetaSettingType) i); - nm_assert(setting_info->setting_name); - nm_assert(setting_info->setting_name[0]); - nm_assert(setting_info->get_setting_gtype); - nm_assert(setting_info->setting_priority != NM_SETTING_PRIORITY_INVALID); - if (i > 0 - && strcmp(nm_meta_setting_infos[i - 1].setting_name, setting_info->setting_name) - >= 0) { - g_error("nm_meta_setting_infos[%u, \"%s\"] is wrongly sorted before " - "nm_meta_setting_infos[%u, \"%s\"]. Rearange NMMetaSettingType enum", - i - 1, - nm_meta_setting_infos[i - 1].setting_name, - i, - setting_info->setting_name); - } - for (j = 0; j < i; j++) { - const NMMetaSettingInfo *s = &nm_meta_setting_infos[j]; - - nm_assert(setting_info->get_setting_gtype != s->get_setting_gtype); - } - } - } - - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMMetaSettingInfo, setting_name) == 0); - idx = nm_utils_array_find_binary_search(nm_meta_setting_infos, - sizeof(NMMetaSettingInfo), - _NM_META_SETTING_TYPE_NUM, - &name, - nm_strcmp_p_with_data, - NULL); - - return idx >= 0 ? &nm_meta_setting_infos[idx] : NULL; -} - -const NMMetaSettingInfo * -nm_meta_setting_infos_by_gtype(GType gtype) -{ -#if _NM_META_SETTING_BASE_IMPL_LIBNM - nm_auto_unref_gtypeclass GTypeClass *gtypeclass_unref = NULL; - GTypeClass * gtypeclass; - NMSettingClass * klass; - - if (!g_type_is_a(gtype, NM_TYPE_SETTING)) - goto out_none; - - gtypeclass = g_type_class_peek(gtype); - if (!gtypeclass) - gtypeclass = gtypeclass_unref = g_type_class_ref(gtype); - - nm_assert(NM_IS_SETTING_CLASS(gtypeclass)); - - klass = (NMSettingClass *) gtypeclass; - - if (!klass->setting_info) - goto out_none; - - nm_assert(klass->setting_info->get_setting_gtype); - nm_assert(klass->setting_info->get_setting_gtype() == gtype); - - return klass->setting_info; - -out_none: - - if (NM_MORE_ASSERTS > 10) { - int i; - - /* this might hint to a bug, but it would be expected for NM_TYPE_SETTING - * and NM_TYPE_SETTING_IP_CONFIG. - * - * Assert that we didn't lookup for a gtype, which we would expect to find. - * An assertion failure here, hints to a bug in nm_setting_*_class_init(). - */ - for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) - nm_assert(nm_meta_setting_infos[i].get_setting_gtype() != gtype); - } - - return NULL; -#else - guint i; - - for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { - if (nm_meta_setting_infos[i].get_setting_gtype() == gtype) - return &nm_meta_setting_infos[i]; - } - return NULL; -#endif -} - -/*****************************************************************************/ - -NMSettingPriority -nm_meta_setting_info_get_base_type_priority(const NMMetaSettingInfo *setting_info, GType gtype) -{ - /* Historical oddity: PPPoE is a base-type even though it's not - * priority 1. It needs to be sorted *after* lower-level stuff like - * Wi-Fi security or 802.1x for secrets, but it's still allowed as a - * base type. - */ - - if (setting_info) { - if (NM_IN_SET(setting_info->setting_priority, - NM_SETTING_PRIORITY_HW_BASE, - NM_SETTING_PRIORITY_HW_NON_BASE) - || gtype == NM_TYPE_SETTING_PPPOE) - return setting_info->setting_priority; - } - - return NM_SETTING_PRIORITY_INVALID; -} - -NMSettingPriority -_nm_setting_type_get_base_type_priority(GType type) -{ - return nm_meta_setting_info_get_base_type_priority(nm_meta_setting_infos_by_gtype(type), type); -} - -/*****************************************************************************/ diff --git a/libnm-core/nm-meta-setting-base-impl.h b/libnm-core/nm-meta-setting-base-impl.h deleted file mode 100644 index 94b14e844f..0000000000 --- a/libnm-core/nm-meta-setting-base-impl.h +++ /dev/null @@ -1,187 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 - 2018 Red Hat, Inc. - */ - -#ifndef __NM_META_SETTING_BASE_IMPL_H__ -#define __NM_META_SETTING_BASE_IMPL_H__ - -#include "nm-setting-8021x.h" - -/*****************************************************************************/ - -/* - * A setting's priority should roughly follow the OSI layer model, but it also - * controls which settings get asked for secrets first. Thus settings which - * relate to things that must be working first, like hardware, should get a - * higher priority than things which layer on top of the hardware. For example, - * the GSM/CDMA settings should provide secrets before the PPP setting does, - * because a PIN is required to unlock the device before PPP can even start. - * Even settings without secrets should be assigned the right priority. - * - * 0: reserved for invalid - * - * 1: reserved for the Connection setting - * - * 2,3: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc. - * These priority 1 settings are also "base types", which means that at least - * one of them is required for the connection to be valid, and their name is - * valid in the 'type' property of the Connection setting. - * - * 4: hardware-related auxiliary settings that require a base setting to be - * successful first, like Wi-Fi security, 802.1x, etc. - * - * 5: hardware-independent settings that are required before IP connectivity - * can be established, like PPP, PPPoE, etc. - * - * 6: IP-level stuff - * - * 10: NMSettingUser - */ -typedef enum { /*< skip >*/ - NM_SETTING_PRIORITY_INVALID = 0, - NM_SETTING_PRIORITY_CONNECTION = 1, - NM_SETTING_PRIORITY_HW_BASE = 2, - NM_SETTING_PRIORITY_HW_NON_BASE = 3, - NM_SETTING_PRIORITY_HW_AUX = 4, - NM_SETTING_PRIORITY_AUX = 5, - NM_SETTING_PRIORITY_IP = 6, - NM_SETTING_PRIORITY_USER = 10, -} NMSettingPriority; - -/*****************************************************************************/ - -typedef enum { - NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT, - NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT, - NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT, - NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT, - NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY, - NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY, - - NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN, - - _NM_SETTING_802_1X_SCHEME_TYPE_NUM = NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN, -} NMSetting8021xSchemeType; - -typedef struct { - const char *setting_key; - NMSetting8021xCKScheme (*scheme_func)(NMSetting8021x *setting); - NMSetting8021xCKFormat (*format_func)(NMSetting8021x *setting); - const char *(*path_func)(NMSetting8021x *setting); - GBytes *(*blob_func)(NMSetting8021x *setting); - const char *(*uri_func)(NMSetting8021x *setting); - const char *(*passwd_func)(NMSetting8021x *setting); - NMSettingSecretFlags (*pwflag_func)(NMSetting8021x *setting); - gboolean (*set_cert_func)(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error); - gboolean (*set_private_key_func)(NMSetting8021x * setting, - const char * value, - const char * password, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error); - const char * file_suffix; - NMSetting8021xSchemeType scheme_type; - bool is_secret : 1; -} NMSetting8021xSchemeVtable; - -extern const NMSetting8021xSchemeVtable - nm_setting_8021x_scheme_vtable[_NM_SETTING_802_1X_SCHEME_TYPE_NUM + 1]; - -/*****************************************************************************/ - -typedef enum { - /* the enum (and their numeric values) are internal API. Do not assign - * any meaning the numeric values, because they already have one: - * - * they are sorted in a way, that corresponds to the asciibetical sort - * order of the corresponding setting-name. */ - - NM_META_SETTING_TYPE_6LOWPAN, - NM_META_SETTING_TYPE_OLPC_MESH, - NM_META_SETTING_TYPE_WIRELESS, - NM_META_SETTING_TYPE_WIRELESS_SECURITY, - NM_META_SETTING_TYPE_802_1X, - NM_META_SETTING_TYPE_WIRED, - NM_META_SETTING_TYPE_ADSL, - NM_META_SETTING_TYPE_BLUETOOTH, - NM_META_SETTING_TYPE_BOND, - NM_META_SETTING_TYPE_BRIDGE, - NM_META_SETTING_TYPE_BRIDGE_PORT, - NM_META_SETTING_TYPE_CDMA, - NM_META_SETTING_TYPE_CONNECTION, - NM_META_SETTING_TYPE_DCB, - NM_META_SETTING_TYPE_DUMMY, - NM_META_SETTING_TYPE_ETHTOOL, - NM_META_SETTING_TYPE_GENERIC, - NM_META_SETTING_TYPE_GSM, - NM_META_SETTING_TYPE_HOSTNAME, - NM_META_SETTING_TYPE_INFINIBAND, - NM_META_SETTING_TYPE_IP_TUNNEL, - NM_META_SETTING_TYPE_IP4_CONFIG, - NM_META_SETTING_TYPE_IP6_CONFIG, - NM_META_SETTING_TYPE_MACSEC, - NM_META_SETTING_TYPE_MACVLAN, - NM_META_SETTING_TYPE_MATCH, - NM_META_SETTING_TYPE_OVS_BRIDGE, - NM_META_SETTING_TYPE_OVS_DPDK, - NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, - NM_META_SETTING_TYPE_OVS_INTERFACE, - NM_META_SETTING_TYPE_OVS_PATCH, - NM_META_SETTING_TYPE_OVS_PORT, - NM_META_SETTING_TYPE_PPP, - NM_META_SETTING_TYPE_PPPOE, - NM_META_SETTING_TYPE_PROXY, - NM_META_SETTING_TYPE_SERIAL, - NM_META_SETTING_TYPE_SRIOV, - NM_META_SETTING_TYPE_TC_CONFIG, - NM_META_SETTING_TYPE_TEAM, - NM_META_SETTING_TYPE_TEAM_PORT, - NM_META_SETTING_TYPE_TUN, - NM_META_SETTING_TYPE_USER, - NM_META_SETTING_TYPE_VETH, - NM_META_SETTING_TYPE_VLAN, - NM_META_SETTING_TYPE_VPN, - NM_META_SETTING_TYPE_VRF, - NM_META_SETTING_TYPE_VXLAN, - NM_META_SETTING_TYPE_WIFI_P2P, - NM_META_SETTING_TYPE_WIMAX, - NM_META_SETTING_TYPE_WIREGUARD, - NM_META_SETTING_TYPE_WPAN, - - NM_META_SETTING_TYPE_UNKNOWN, - - _NM_META_SETTING_TYPE_NUM = NM_META_SETTING_TYPE_UNKNOWN, -} NMMetaSettingType; - -#if _NM_META_SETTING_BASE_IMPL_LIBNM - #define _NMMetaSettingInfo_Alias _NMMetaSettingInfo -#else - #define _NMMetaSettingInfo_Alias _NMMetaSettingInfoCli -#endif - -struct _NMMetaSettingInfo_Alias { - const char *setting_name; - GType (*get_setting_gtype)(void); - NMMetaSettingType meta_type; - NMSettingPriority setting_priority; -}; - -typedef struct _NMMetaSettingInfo_Alias NMMetaSettingInfo; - -extern const NMMetaSettingInfo nm_meta_setting_infos[_NM_META_SETTING_TYPE_NUM + 1]; - -const NMMetaSettingInfo *nm_meta_setting_infos_by_name(const char *name); -const NMMetaSettingInfo *nm_meta_setting_infos_by_gtype(GType gtype); - -/*****************************************************************************/ - -NMSettingPriority nm_meta_setting_info_get_base_type_priority(const NMMetaSettingInfo *setting_info, - GType gtype); -NMSettingPriority _nm_setting_type_get_base_type_priority(GType type); - -#endif /* __NM_META_SETTING_BASE_IMPL_H__ */ diff --git a/libnm-core/nm-meta-setting-base.h b/libnm-core/nm-meta-setting-base.h deleted file mode 100644 index 72fa8e6602..0000000000 --- a/libnm-core/nm-meta-setting-base.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#ifndef __NM_META_SETTING_BASE_H__ -#define __NM_META_SETTING_BASE_H__ - -#define _NM_META_SETTING_BASE_IMPL_LIBNM 1 - -#include "nm-meta-setting-base-impl.h" - -#endif /* __NM_META_SETTING_BASE_H__ */ diff --git a/libnm-core/nm-property-compare.c b/libnm-core/nm-property-compare.c deleted file mode 100644 index c7cf10a26b..0000000000 --- a/libnm-core/nm-property-compare.c +++ /dev/null @@ -1,136 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-property-compare.h" - -#include - -static int -_nm_property_compare_collection(GVariant *value1, GVariant *value2) -{ - GVariant *child1, *child2; - int i, len1, len2; - int ret; - - len1 = g_variant_n_children(value1); - len2 = g_variant_n_children(value2); - - if (len1 != len2) - return len1 < len2 ? -1 : len1 > len2; - - for (i = 0; i < len1; i++) { - child1 = g_variant_get_child_value(value1, i); - child2 = g_variant_get_child_value(value2, i); - - ret = nm_property_compare(child1, child2); - g_variant_unref(child1); - g_variant_unref(child2); - - if (ret) - return ret; - } - - return 0; -} - -static int -_nm_property_compare_vardict(GVariant *value1, GVariant *value2) -{ - GVariantIter iter; - int len1, len2; - const char * key; - GVariant * val1, *val2; - - len1 = g_variant_n_children(value1); - len2 = g_variant_n_children(value2); - - if (len1 != len2) - return len1 < len2 ? -1 : 1; - - g_variant_iter_init(&iter, value1); - while (g_variant_iter_next(&iter, "{&sv}", &key, &val1)) { - if (!g_variant_lookup(value2, key, "v", &val2)) { - g_variant_unref(val1); - return -1; - } - if (!g_variant_equal(val1, val2)) { - g_variant_unref(val1); - g_variant_unref(val2); - return -1; - } - g_variant_unref(val1); - g_variant_unref(val2); - } - - return 0; -} - -static int -_nm_property_compare_strdict(GVariant *value1, GVariant *value2) -{ - GVariantIter iter; - int len1, len2; - const char * key, *val1, *val2; - int ret; - - len1 = g_variant_n_children(value1); - len2 = g_variant_n_children(value2); - - if (len1 != len2) - return len1 < len2 ? -1 : len1 > len2; - - g_variant_iter_init(&iter, value1); - while (g_variant_iter_next(&iter, "{&s&s}", &key, &val1)) { - if (!g_variant_lookup(value2, key, "&s", &val2)) - return -1; - - ret = strcmp(val1, val2); - if (ret) - return ret; - } - - return 0; -} - -int -nm_property_compare(GVariant *value1, GVariant *value2) -{ - const GVariantType *type1; - const GVariantType *type2; - int ret; - - if (value1 == value2) - return 0; - if (!value1) - return 1; - if (!value2) - return -1; - - type1 = g_variant_get_type(value1); - type2 = g_variant_get_type(value2); - - if (!g_variant_type_equal(type1, type2)) - return type1 < type2 ? -1 : type1 > type2; - - if (g_variant_type_is_basic(type1)) - ret = g_variant_compare(value1, value2); - else if (g_variant_is_of_type(value1, G_VARIANT_TYPE("a{ss}"))) - ret = _nm_property_compare_strdict(value1, value2); - else if (g_variant_is_of_type(value1, G_VARIANT_TYPE("a{sv}"))) - ret = _nm_property_compare_vardict(value1, value2); - else if (g_variant_type_is_array(type1)) - ret = _nm_property_compare_collection(value1, value2); - else if (g_variant_type_is_tuple(type1)) - ret = _nm_property_compare_collection(value1, value2); - else { - g_warning("Don't know how to compare variant type '%s'", (const char *) type1); - ret = value1 == value2; - } - - return ret; -} diff --git a/libnm-core/nm-property-compare.h b/libnm-core/nm-property-compare.h deleted file mode 100644 index d422b1c8a4..0000000000 --- a/libnm-core/nm-property-compare.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_PROPERTY_COMPARE_H__ -#define __NM_PROPERTY_COMPARE_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) - #error Cannot use this header. -#endif - -int nm_property_compare(GVariant *value1, GVariant *value2); - -#endif /* __NM_PROPERTY_COMPARE_H__ */ diff --git a/libnm-core/nm-setting-6lowpan.c b/libnm-core/nm-setting-6lowpan.c deleted file mode 100644 index f71daf3258..0000000000 --- a/libnm-core/nm-setting-6lowpan.c +++ /dev/null @@ -1,228 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-6lowpan.h" - -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-6lowpan - * @short_description: Describes connection properties for 6LoWPAN interfaces - * - * The #NMSetting6Lowpan object is a #NMSetting subclass that describes properties - * necessary for connection to 6LoWPAN interfaces. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, ); - -typedef struct { - char *parent; -} NMSetting6LowpanPrivate; - -/** - * NMSetting6Lowpan: - * - * 6LoWPAN Settings - */ -struct _NMSetting6Lowpan { - NMSetting parent; -}; - -struct _NMSetting6LowpanClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSetting6Lowpan, nm_setting_6lowpan, NM_TYPE_SETTING) - -#define NM_SETTING_6LOWPAN_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_6lowpan_get_parent: - * @setting: the #NMSetting6Lowpan - * - * Returns: the #NMSetting6Lowpan:parent property of the setting - * - * Since: 1.14 - **/ -const char * -nm_setting_6lowpan_get_parent(NMSetting6Lowpan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_6LOWPAN(setting), NULL); - return NM_SETTING_6LOWPAN_GET_PRIVATE(setting)->parent; -} - -/*********************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE(setting); - NMSettingConnection * s_con = NULL; - - if (connection) - s_con = nm_connection_get_setting_connection(connection); - - if (!priv->parent) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is not specified")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_6LOWPAN_SETTING_NAME, - NM_SETTING_6LOWPAN_PARENT); - return FALSE; - } - - if (nm_utils_is_uuid(priv->parent)) { - /* If we have an NMSettingConnection:master with slave-type="6lowpan", - * then it must be the same UUID. - */ - if (s_con) { - const char *master = NULL, *slave_type = NULL; - - slave_type = nm_setting_connection_get_slave_type(s_con); - if (!g_strcmp0(slave_type, NM_SETTING_6LOWPAN_SETTING_NAME)) - master = nm_setting_connection_get_master(s_con); - - if (master && g_strcmp0(priv->parent, master) != 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' value doesn't match '%s=%s'"), - priv->parent, - NM_SETTING_CONNECTION_MASTER, - master); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_6LOWPAN_SETTING_NAME, - NM_SETTING_6LOWPAN_PARENT); - return FALSE; - } - } - } else if (!nm_utils_iface_valid_name(priv->parent)) { - /* parent must be either a UUID or an interface name */ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is neither an UUID nor an interface name"), - priv->parent); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_6LOWPAN_SETTING_NAME, - NM_SETTING_6LOWPAN_PARENT); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSetting6Lowpan * setting = NM_SETTING_6LOWPAN(object); - NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_value_set_string(value, priv->parent); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSetting6Lowpan * setting = NM_SETTING_6LOWPAN(object); - NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_free(priv->parent); - priv->parent = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_6lowpan_init(NMSetting6Lowpan *setting) -{} - -/** - * nm_setting_6lowpan_new: - * - * Creates a new #NMSetting6Lowpan object with default values. - * - * Returns: (transfer full): the new empty #NMSetting6Lowpan object - * - * Since: 1.14 - **/ -NMSetting * -nm_setting_6lowpan_new(void) -{ - return g_object_new(NM_TYPE_SETTING_6LOWPAN, NULL); -} - -static void -finalize(GObject *object) -{ - NMSetting6Lowpan * setting = NM_SETTING_6LOWPAN(object); - NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE(setting); - - g_free(priv->parent); - - G_OBJECT_CLASS(nm_setting_6lowpan_parent_class)->finalize(object); -} - -static void -nm_setting_6lowpan_class_init(NMSetting6LowpanClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSetting6LowpanPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSetting6Lowpan:parent: - * - * If given, specifies the parent interface name or parent connection UUID - * from which this 6LowPAN interface should be created. - * - * Since: 1.14 - **/ - obj_properties[PROP_PARENT] = g_param_spec_string( - NM_SETTING_6LOWPAN_PARENT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_6LOWPAN); -} diff --git a/libnm-core/nm-setting-6lowpan.h b/libnm-core/nm-setting-6lowpan.h deleted file mode 100644 index 5a7c39866b..0000000000 --- a/libnm-core/nm-setting-6lowpan.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_6LOWPAN_H__ -#define __NM_SETTING_6LOWPAN_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_6LOWPAN (nm_setting_6lowpan_get_type()) -#define NM_SETTING_6LOWPAN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_6LOWPAN, NMSetting6Lowpan)) -#define NM_SETTING_6LOWPAN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_6LOWPANCONFIG, NMSetting6LowpanClass)) -#define NM_IS_SETTING_6LOWPAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_6LOWPAN)) -#define NM_IS_SETTING_6LOWPAN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_6LOWPAN)) -#define NM_SETTING_6LOWPAN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanClass)) - -#define NM_SETTING_6LOWPAN_SETTING_NAME "6lowpan" - -#define NM_SETTING_6LOWPAN_PARENT "parent" - -typedef struct _NMSetting6LowpanClass NMSetting6LowpanClass; - -NM_AVAILABLE_IN_1_14 -GType nm_setting_6lowpan_get_type(void); -NM_AVAILABLE_IN_1_14 -NMSetting *nm_setting_6lowpan_new(void); - -NM_AVAILABLE_IN_1_14 -const char *nm_setting_6lowpan_get_parent(NMSetting6Lowpan *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_6LOWPAN_H__ */ diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c deleted file mode 100644 index 1b38aa1416..0000000000 --- a/libnm-core/nm-setting-8021x.c +++ /dev/null @@ -1,4683 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-8021x.h" - -#include "nm-glib-aux/nm-secret-utils.h" -#include "nm-utils.h" -#include "nm-crypto.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" -#include "nm-core-enum-types.h" - -/** - * SECTION:nm-setting-8021x - * @short_description: Describes 802.1x-authenticated connection properties - * - * The #NMSetting8021x object is a #NMSetting subclass that describes - * properties necessary for connection to 802.1x-authenticated networks, such as - * WPA and WPA2 Enterprise Wi-Fi networks and wired 802.1x networks. 802.1x - * connections typically use certificates and/or EAP authentication methods to - * securely verify, identify, and authenticate the client to the network itself, - * instead of simply relying on a widely shared static key. - * - * It's a good idea to read up on wpa_supplicant configuration before using this - * setting extensively, since most of the options here correspond closely with - * the relevant wpa_supplicant configuration options. - * - * Furthermore, to get a good idea of 802.1x, EAP, TLS, TTLS, etc and their - * applications to Wi-Fi and wired networks, you'll want to get copies of the - * following books. - * - * 802.11 Wireless Networks: The Definitive Guide, Second Edition - * Author: Matthew Gast - * ISBN: 978-0596100520 - * - * Cisco Wireless LAN Security - * Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky - * ISBN: 978-1587051548 - **/ - -/*****************************************************************************/ - -static NMSetting8021xCKFormat -_crypto_format_to_ck(NMCryptoFileFormat format) -{ - G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_UNKNOWN - == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_UNKNOWN)); - G_STATIC_ASSERT( - (NM_SETTING_802_1X_CK_FORMAT_X509 == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_X509)); - G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_RAW_KEY - == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_RAW_KEY)); - G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_PKCS12 - == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_PKCS12)); - - nm_assert(NM_IN_SET(format, - NM_CRYPTO_FILE_FORMAT_UNKNOWN, - NM_CRYPTO_FILE_FORMAT_X509, - NM_CRYPTO_FILE_FORMAT_RAW_KEY, - NM_CRYPTO_FILE_FORMAT_PKCS12)); - return (NMSetting8021xCKFormat) format; -} - -/*****************************************************************************/ - -typedef void (*EAPMethodNeedSecretsFunc)(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2); - -typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self, gboolean phase2, GError **error); - -typedef struct { - const char * method; - EAPMethodNeedSecretsFunc ns_func; - EAPMethodValidateFunc v_func; -} EAPMethodsTable; - -static const EAPMethodsTable eap_methods_table[]; - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSetting8021x, - PROP_EAP, - PROP_IDENTITY, - PROP_ANONYMOUS_IDENTITY, - PROP_PAC_FILE, - PROP_CA_CERT, - PROP_CA_CERT_PASSWORD, - PROP_CA_CERT_PASSWORD_FLAGS, - PROP_CA_PATH, - PROP_SUBJECT_MATCH, - PROP_ALTSUBJECT_MATCHES, - PROP_DOMAIN_SUFFIX_MATCH, - PROP_DOMAIN_MATCH, - PROP_CLIENT_CERT, - PROP_CLIENT_CERT_PASSWORD, - PROP_CLIENT_CERT_PASSWORD_FLAGS, - PROP_PHASE1_PEAPVER, - PROP_PHASE1_PEAPLABEL, - PROP_PHASE1_FAST_PROVISIONING, - PROP_PHASE1_AUTH_FLAGS, - PROP_PHASE2_AUTH, - PROP_PHASE2_AUTHEAP, - PROP_PHASE2_CA_CERT, - PROP_PHASE2_CA_CERT_PASSWORD, - PROP_PHASE2_CA_CERT_PASSWORD_FLAGS, - PROP_PHASE2_CA_PATH, - PROP_PHASE2_SUBJECT_MATCH, - PROP_PHASE2_ALTSUBJECT_MATCHES, - PROP_PHASE2_DOMAIN_SUFFIX_MATCH, - PROP_PHASE2_DOMAIN_MATCH, - PROP_PHASE2_CLIENT_CERT, - PROP_PHASE2_CLIENT_CERT_PASSWORD, - PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, - PROP_PASSWORD, - PROP_PASSWORD_FLAGS, - PROP_PASSWORD_RAW, - PROP_PASSWORD_RAW_FLAGS, - PROP_PRIVATE_KEY, - PROP_PRIVATE_KEY_PASSWORD, - PROP_PRIVATE_KEY_PASSWORD_FLAGS, - PROP_PHASE2_PRIVATE_KEY, - PROP_PHASE2_PRIVATE_KEY_PASSWORD, - PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, - PROP_PIN, - PROP_PIN_FLAGS, - PROP_SYSTEM_CA_CERTS, - PROP_OPTIONAL, - PROP_AUTH_TIMEOUT, ); - -typedef struct { - GSList * eap; /* GSList of strings */ - char * identity; - char * anonymous_identity; - char * pac_file; - GBytes * ca_cert; - char * ca_cert_password; - char * ca_path; - char * subject_match; - GSList * altsubject_matches; - char * domain_suffix_match; - char * domain_match; - GBytes * client_cert; - char * client_cert_password; - char * phase1_peapver; - char * phase1_peaplabel; - char * phase1_fast_provisioning; - char * phase2_auth; - char * phase2_autheap; - GBytes * phase2_ca_cert; - char * phase2_ca_cert_password; - char * phase2_ca_path; - char * phase2_subject_match; - GSList * phase2_altsubject_matches; - char * phase2_domain_suffix_match; - char * phase2_domain_match; - GBytes * phase2_client_cert; - char * phase2_client_cert_password; - char * password; - GBytes * password_raw; - char * pin; - GBytes * private_key; - char * private_key_password; - GBytes * phase2_private_key; - char * phase2_private_key_password; - int auth_timeout; - NMSetting8021xAuthFlags phase1_auth_flags; - NMSettingSecretFlags ca_cert_password_flags; - NMSettingSecretFlags client_cert_password_flags; - NMSettingSecretFlags phase2_ca_cert_password_flags; - NMSettingSecretFlags phase2_client_cert_password_flags; - NMSettingSecretFlags password_flags; - NMSettingSecretFlags password_raw_flags; - NMSettingSecretFlags pin_flags; - NMSettingSecretFlags private_key_password_flags; - NMSettingSecretFlags phase2_private_key_password_flags; - bool optional : 1; - bool system_ca_certs : 1; -} NMSetting8021xPrivate; - -G_DEFINE_TYPE(NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING) - -#define NM_SETTING_802_1X_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_802_1x_check_cert_scheme: - * @pdata: (allow-none): the data pointer - * @length: the length of the data - * @error: (allow-none) (out): validation reason - * - * Determines and verifies the blob type. - * When setting certificate properties of NMSetting8021x - * the blob must be not UNKNOWN (or NULL). - * - * Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN. - * For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN. - * - * Since: 1.2 - **/ -NMSetting8021xCKScheme -nm_setting_802_1x_check_cert_scheme(gconstpointer pdata, gsize length, GError **error) -{ - const char * data = pdata; - NMSetting8021xCKScheme scheme; - gsize prefix_length; - - g_return_val_if_fail(!length || data, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); - - if (!length || !data) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("binary data missing")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - - if (length >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) - && !memcmp(data, - NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, - NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH))) { - scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; - prefix_length = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); - } else if (length >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11) - && !memcmp(data, - NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11, - NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11))) { - scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11; - prefix_length = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11); - } else { - scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB; - prefix_length = 0; - } - - if (scheme != NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* An actual URI must be NUL terminated, contain at least - * one non-NUL character, and contain only one trailing NUL - * character. - * And ensure it's UTF-8 valid too so we can pass it through - * D-Bus and stuff like that. */ - - if (data[length - 1] != '\0') { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("URI not NUL terminated")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - length--; - - if (length <= prefix_length) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("URI is empty")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - - if (!g_utf8_validate(data + prefix_length, length - prefix_length, NULL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("URI is not valid UTF-8")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - } - - return scheme; -} - -NMSetting8021xCKScheme -_nm_setting_802_1x_cert_get_scheme(GBytes *bytes, GError **error) -{ - const char *data; - gsize length; - - if (!bytes) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("data missing")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - - data = g_bytes_get_data(bytes, &length); - return nm_setting_802_1x_check_cert_scheme(data, length, error); -} - -static gboolean -_cert_verify_scheme(NMSetting8021xCKScheme scheme, GBytes *bytes, GError **error) -{ - GError * local = NULL; - NMSetting8021xCKScheme scheme_detected; - - nm_assert(bytes); - - scheme_detected = _nm_setting_802_1x_cert_get_scheme(bytes, &local); - if (scheme_detected == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("certificate is invalid: %s"), - local->message); - return FALSE; - } - - if (scheme_detected != scheme) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("certificate detected as invalid scheme")); - return FALSE; - } - - return TRUE; -} - -GBytes * -_nm_setting_802_1x_cert_value_to_bytes(NMSetting8021xCKScheme scheme, - const guint8 * val_bin, - gssize val_len, - GError ** error) -{ - gs_unref_bytes GBytes *bytes = NULL; - guint8 * mem; - gsize total_len; - - nm_assert(val_bin); - - switch (scheme) { - case NM_SETTING_802_1X_CK_SCHEME_PKCS11: - if (val_len < 0) - val_len = strlen((char *) val_bin) + 1; - - bytes = g_bytes_new(val_bin, val_len); - break; - case NM_SETTING_802_1X_CK_SCHEME_PATH: - if (val_len < 0) - val_len = strlen((char *) val_bin) + 1; - - total_len = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + ((gsize) val_len); - - mem = g_new(guint8, total_len); - memcpy(mem, - NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, - NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); - memcpy(&mem[NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)], val_bin, val_len); - bytes = g_bytes_new_take(mem, total_len); - break; - default: - g_return_val_if_reached(NULL); - } - - if (!_cert_verify_scheme(scheme, bytes, error)) - return NULL; - - return g_steal_pointer(&bytes); -} - -static const char * -_cert_get_path(GBytes *bytes) -{ - const guint8 *bin; - - nm_assert(bytes); - nm_assert(g_bytes_get_size(bytes) >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); - - bin = g_bytes_get_data(bytes, NULL); - - nm_assert(bin); - nm_assert(bin[g_bytes_get_size(bytes) - 1] == '\0'); - nm_assert(g_str_has_prefix((const char *) bin, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); - - return (const char *) &bin[NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)]; -} - -#define _cert_assert_scheme(cert, check_scheme, ret_val) \ - G_STMT_START \ - { \ - NMSetting8021xCKScheme scheme; \ - \ - scheme = _nm_setting_802_1x_cert_get_scheme((cert), NULL); \ - if (scheme != check_scheme) { \ - g_return_val_if_fail(scheme == check_scheme, ret_val); \ - return ret_val; \ - } \ - } \ - G_STMT_END - -#define _cert_impl_get_scheme(setting, cert_field) \ - G_STMT_START \ - { \ - NMSetting8021x *const _setting = (setting); \ - GBytes * _cert; \ - \ - g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); \ - \ - _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field; \ - \ - return _nm_setting_802_1x_cert_get_scheme(_cert, NULL); \ - } \ - G_STMT_END - -#define _cert_impl_get_blob(setting, cert_field) \ - G_STMT_START \ - { \ - NMSetting8021x *const _setting = (setting); \ - GBytes * _cert; \ - \ - g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL); \ - \ - _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field; \ - \ - _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); \ - \ - return _cert; \ - } \ - G_STMT_END - -#define _cert_impl_get_path(setting, cert_field) \ - G_STMT_START \ - { \ - NMSetting8021x *const _setting = (setting); \ - GBytes * _cert; \ - \ - g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL); \ - \ - _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field; \ - \ - _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); \ - \ - return _cert_get_path(_cert); \ - } \ - G_STMT_END - -#define _cert_impl_get_uri(setting, cert_field) \ - G_STMT_START \ - { \ - NMSetting8021x *const _setting = (setting); \ - GBytes * _cert; \ - \ - g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL); \ - \ - _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field; \ - \ - _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); \ - \ - return g_bytes_get_data(_cert, NULL); \ - } \ - G_STMT_END - -static gboolean -_cert_impl_set(NMSetting8021x * setting, - _PropertyEnums property, - const char * value, - const char * password, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error) -{ - NMSetting8021xPrivate *priv; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gs_unref_bytes GBytes *cert = NULL; - GBytes ** p_cert = NULL; - GBytes ** p_client_cert = NULL; - char ** p_password = NULL; - _PropertyEnums notify_cert = property; - _PropertyEnums notify_password = PROP_0; - _PropertyEnums notify_client_cert = PROP_0; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - if (value) { - g_return_val_if_fail(g_utf8_validate(value, -1, NULL), FALSE); - g_return_val_if_fail(NM_IN_SET(scheme, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - NM_SETTING_802_1X_CK_SCHEME_PATH, - NM_SETTING_802_1X_CK_SCHEME_PKCS11), - FALSE); - } - - if (!value) { - /* coerce password to %NULL. It should be already. */ - password = NULL; - } - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - - if (!value) { - /* pass. */ - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - cert = _nm_setting_802_1x_cert_value_to_bytes(scheme, (guint8 *) value, -1, error); - if (!cert) - goto err; - } else { - gs_unref_bytes GBytes *file = NULL; - - if (NM_IN_SET(property, PROP_PRIVATE_KEY, PROP_PHASE2_PRIVATE_KEY)) { - file = nm_crypto_read_file(value, error); - if (!file) - goto err; - format = nm_crypto_verify_private_key_data(g_bytes_get_data(file, NULL), - g_bytes_get_size(file), - password, - NULL, - error); - if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) - goto err; - } else { - if (!nm_crypto_load_and_verify_certificate(value, &format, &file, error)) - goto err; - } - - nm_assert(format != NM_CRYPTO_FILE_FORMAT_UNKNOWN); - nm_assert(file); - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - cert = g_steal_pointer(&file); - if (!_cert_verify_scheme(scheme, cert, error)) - goto err; - } else { - cert = _nm_setting_802_1x_cert_value_to_bytes(scheme, (guint8 *) value, -1, error); - if (!cert) - goto err; - } - } - - switch (property) { - case PROP_CA_CERT: - case PROP_PHASE2_CA_CERT: - if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && format != NM_CRYPTO_FILE_FORMAT_X509) { - /* wpa_supplicant can only use raw x509 CA certs */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("CA certificate must be in X.509 format")); - goto err; - } - p_cert = (property == PROP_CA_CERT) ? &priv->ca_cert : &priv->phase2_ca_cert; - break; - case PROP_CLIENT_CERT: - case PROP_PHASE2_CLIENT_CERT: - if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !NM_IN_SET(format, NM_CRYPTO_FILE_FORMAT_X509, NM_CRYPTO_FILE_FORMAT_PKCS12)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid certificate format")); - goto err; - } - p_cert = (property == PROP_CLIENT_CERT) ? &priv->client_cert : &priv->phase2_client_cert; - break; - case PROP_PRIVATE_KEY: - p_cert = &priv->private_key; - p_password = &priv->private_key_password; - p_client_cert = &priv->client_cert; - notify_password = PROP_PRIVATE_KEY_PASSWORD; - notify_client_cert = PROP_CLIENT_CERT; - break; - case PROP_PHASE2_PRIVATE_KEY: - p_cert = &priv->phase2_private_key; - p_password = &priv->phase2_private_key_password; - p_client_cert = &priv->phase2_client_cert; - notify_password = PROP_PHASE2_PRIVATE_KEY_PASSWORD; - notify_client_cert = PROP_PHASE2_CLIENT_CERT; - break; - default: - nm_assert_not_reached(); - break; - } - - /* As required by NM and wpa_supplicant, set the client-cert - * property to the same PKCS#12 data. - */ - if (cert && p_client_cert && format == NM_CRYPTO_FILE_FORMAT_PKCS12 - && !nm_gbytes_equal0(cert, *p_client_cert)) { - g_bytes_unref(*p_client_cert); - *p_client_cert = g_bytes_ref(cert); - } else - notify_client_cert = PROP_0; - - if (p_cert && !nm_gbytes_equal0(cert, *p_cert)) { - g_bytes_unref(*p_cert); - *p_cert = g_steal_pointer(&cert); - } else - notify_cert = PROP_0; - - if (p_password && !nm_streq0(password, *p_password)) { - nm_free_secret(*p_password); - *p_password = g_strdup(password); - } else - notify_password = PROP_0; - - nm_gobject_notify_together(setting, notify_cert, notify_password, notify_client_cert); - - NM_SET_OUT(out_format, _crypto_format_to_ck(format)); - return TRUE; - -err: - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - obj_properties[property]->name); - NM_SET_OUT(out_format, NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - return FALSE; -} - -static NMSetting8021xCKFormat -_cert_impl_get_key_format_from_bytes(GBytes *private_key) -{ - const char *path; - GError * error = NULL; - - if (!private_key) - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - - switch (_nm_setting_802_1x_cert_get_scheme(private_key, NULL)) { - case NM_SETTING_802_1X_CK_SCHEME_BLOB: - if (nm_crypto_is_pkcs12_data(g_bytes_get_data(private_key, NULL), - g_bytes_get_size(private_key), - NULL)) - return NM_SETTING_802_1X_CK_FORMAT_PKCS12; - return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; - case NM_SETTING_802_1X_CK_SCHEME_PATH: - path = _cert_get_path(private_key); - if (nm_crypto_is_pkcs12_file(path, &error)) - return NM_SETTING_802_1X_CK_FORMAT_PKCS12; - if (error && error->domain == G_FILE_ERROR) { - g_error_free(error); - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - } - g_error_free(error); - return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; - default: - break; - } - - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; -} -#define _cert_impl_get_key_format(setting, private_key_field) \ - ({ \ - NMSetting8021x * _setting = (setting); \ - NMSetting8021xPrivate *_priv; \ - \ - g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); \ - \ - _priv = NM_SETTING_802_1X_GET_PRIVATE(_setting); \ - _cert_impl_get_key_format_from_bytes(_priv->private_key_field); \ - }) - -static gboolean -_cert_verify_property(GBytes * bytes, - const char *prop_name, - const char *password, - const char *password_prop_name, - GError ** error) -{ - GError * local = NULL; - NMSetting8021xCKScheme scheme; - - if (!bytes) - return TRUE; - - scheme = _nm_setting_802_1x_cert_get_scheme(bytes, &local); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("certificate is invalid: %s"), - local->message); - g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name); - g_error_free(local); - return FALSE; - } - - if (password && (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("password is not supported when certificate is not on a PKCS#11 token")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, password_prop_name); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -/** - * nm_setting_802_1x_get_num_eap_methods: - * @setting: the #NMSetting8021x - * - * Returns the number of eap methods allowed for use when connecting to the - * network. Generally only one EAP method is used. Use the functions - * nm_setting_802_1x_get_eap_method(), nm_setting_802_1x_add_eap_method(), - * and nm_setting_802_1x_remove_eap_method() for adding, removing, and retrieving - * allowed EAP methods. - * - * Returns: the number of allowed EAP methods - **/ -guint32 -nm_setting_802_1x_get_num_eap_methods(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); - - return g_slist_length(NM_SETTING_802_1X_GET_PRIVATE(setting)->eap); -} - -/** - * nm_setting_802_1x_get_eap_method: - * @setting: the #NMSetting8021x - * @i: the index of the EAP method name to return - * - * Returns the name of the allowed EAP method at index @i. - * - * Returns: the name of the allowed EAP method at index @i - **/ -const char * -nm_setting_802_1x_get_eap_method(NMSetting8021x *setting, guint32 i) -{ - NMSetting8021xPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - g_return_val_if_fail(i <= g_slist_length(priv->eap), NULL); - - return (const char *) g_slist_nth_data(priv->eap, i); -} - -/** - * nm_setting_802_1x_add_eap_method: - * @setting: the #NMSetting8021x - * @eap: the name of the EAP method to allow for this connection - * - * Adds an allowed EAP method. The setting is not valid until at least one - * EAP method has been added. See #NMSetting8021x:eap property for a list of - * allowed EAP methods. - * - * Returns: %TRUE if the EAP method was successfully added, %FALSE if it was - * not a valid method or if it was already allowed. - **/ -gboolean -nm_setting_802_1x_add_eap_method(NMSetting8021x *setting, const char *eap) -{ - NMSetting8021xPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - g_return_val_if_fail(eap != NULL, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - for (iter = priv->eap; iter; iter = g_slist_next(iter)) { - if (!strcmp(eap, (char *) iter->data)) - return FALSE; - } - - priv->eap = g_slist_append(priv->eap, g_ascii_strdown(eap, -1)); - _notify(setting, PROP_EAP); - return TRUE; -} - -/** - * nm_setting_802_1x_remove_eap_method: - * @setting: the #NMSetting8021x - * @i: the index of the EAP method to remove - * - * Removes the allowed EAP method at the specified index. - **/ -void -nm_setting_802_1x_remove_eap_method(NMSetting8021x *setting, guint32 i) -{ - NMSetting8021xPrivate *priv; - GSList * elt; - - g_return_if_fail(NM_IS_SETTING_802_1X(setting)); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - elt = g_slist_nth(priv->eap, i); - g_return_if_fail(elt != NULL); - - g_free(elt->data); - priv->eap = g_slist_delete_link(priv->eap, elt); - _notify(setting, PROP_EAP); -} - -/** - * nm_setting_802_1x_remove_eap_method_by_value: - * @setting: the #NMSetting8021x - * @eap: the name of the EAP method to remove - * - * Removes the allowed EAP method @method. - * - * Returns: %TRUE if the EAP method was founs and removed, %FALSE if it was not. - **/ -gboolean -nm_setting_802_1x_remove_eap_method_by_value(NMSetting8021x *setting, const char *eap) -{ - NMSetting8021xPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - g_return_val_if_fail(eap != NULL, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - for (iter = priv->eap; iter; iter = g_slist_next(iter)) { - if (!strcmp(eap, (char *) iter->data)) { - priv->eap = g_slist_delete_link(priv->eap, iter); - _notify(setting, PROP_EAP); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_802_1x_clear_eap_methods: - * @setting: the #NMSetting8021x - * - * Clears all allowed EAP methods. - **/ -void -nm_setting_802_1x_clear_eap_methods(NMSetting8021x *setting) -{ - NMSetting8021xPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_802_1X(setting)); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - g_slist_free_full(priv->eap, g_free); - priv->eap = NULL; - _notify(setting, PROP_EAP); -} - -/** - * nm_setting_802_1x_get_identity: - * @setting: the #NMSetting8021x - * - * Returns the identifier used by some EAP methods (like TLS) to - * authenticate the user. Often this is a username or login name. - * - * Returns: the user identifier - **/ -const char * -nm_setting_802_1x_get_identity(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->identity; -} - -/** - * nm_setting_802_1x_get_anonymous_identity: - * @setting: the #NMSetting8021x - * - * Returns the anonymous identifier used by some EAP methods (like TTLS) to - * authenticate the user in the outer unencrypted "phase 1" authentication. The - * inner "phase 2" authentication will use the #NMSetting8021x:identity in - * a secure form, if applicable for that EAP method. - * - * Returns: the anonymous identifier - **/ -const char * -nm_setting_802_1x_get_anonymous_identity(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->anonymous_identity; -} - -/** - * nm_setting_802_1x_get_pac_file: - * @setting: the #NMSetting8021x - * - * Returns the file containing PAC credentials used by EAP-FAST method. - * - * Returns: the PAC file - **/ -const char * -nm_setting_802_1x_get_pac_file(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->pac_file; -} - -/** - * nm_setting_802_1x_get_ca_path: - * @setting: the #NMSetting8021x - * - * Returns the path of the CA certificate directory if previously set. Systems - * will often have a directory that contains multiple individual CA certificates - * which the supplicant can then add to the verification chain. This may be - * used in addition to the #NMSetting8021x:ca-cert property to add more CA - * certificates for verifying the network to client. - * - * Returns: the CA certificate directory path - **/ -const char * -nm_setting_802_1x_get_ca_path(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_path; -} - -/** - * nm_setting_802_1x_get_system_ca_certs: - * @setting: the #NMSetting8021x - * - * Sets the #NMSetting8021x:system-ca-certs property. The - * #NMSetting8021x:ca-path and #NMSetting8021x:phase2-ca-path - * properties are ignored if the #NMSetting8021x:system-ca-certs property is - * %TRUE, in which case a system-wide CA certificate directory specified at - * compile time (using the --system-ca-path configure option) is used in place - * of these properties. - * - * Returns: %TRUE if a system CA certificate path should be used, %FALSE if not - **/ -gboolean -nm_setting_802_1x_get_system_ca_certs(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->system_ca_certs; -} - -/** - * nm_setting_802_1x_get_ca_cert_scheme: - * @setting: the #NMSetting8021x - * - * Returns the scheme used to store the CA certificate. If the returned scheme - * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_ca_cert_blob(); - * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_ca_cert_path(); - * if %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use nm_setting_802_1x_get_ca_cert_uri(). - * - * Returns: scheme used to store the CA certificate (blob or path) - **/ -NMSetting8021xCKScheme -nm_setting_802_1x_get_ca_cert_scheme(NMSetting8021x *setting) -{ - _cert_impl_get_scheme(setting, ca_cert); -} - -/** - * nm_setting_802_1x_get_ca_cert_blob: - * @setting: the #NMSetting8021x - * - * Returns the CA certificate blob if the CA certificate is stored using the - * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use a - * CA certificate (LEAP for example), and those that can take advantage of the - * CA certificate allow it to be unset. Note that lack of a CA certificate - * reduces security by allowing man-in-the-middle attacks, because the identity - * of the network cannot be confirmed by the client. - * - * Returns: (transfer none): the CA certificate data - **/ -GBytes * -nm_setting_802_1x_get_ca_cert_blob(NMSetting8021x *setting) -{ - _cert_impl_get_blob(setting, ca_cert); -} - -/** - * nm_setting_802_1x_get_ca_cert_path: - * @setting: the #NMSetting8021x - * - * Returns the CA certificate path if the CA certificate is stored using the - * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use a - * CA certificate (LEAP for example), and those that can take advantage of the - * CA certificate allow it to be unset. Note that lack of a CA certificate - * reduces security by allowing man-in-the-middle attacks, because the identity - * of the network cannot be confirmed by the client. - * - * Returns: path to the CA certificate file - **/ -const char * -nm_setting_802_1x_get_ca_cert_path(NMSetting8021x *setting) -{ - _cert_impl_get_path(setting, ca_cert); -} - -/** - * nm_setting_802_1x_get_ca_cert_uri: - * @setting: the #NMSetting8021x - * - * Returns the CA certificate URI analogously to - * nm_setting_802_1x_get_ca_cert_blob() and - * nm_setting_802_1x_get_ca_cert_path(). - * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC - * 7512), but may be extended to other schemes in future (such as 'file' URIs - * for local files and 'data' URIs for inline certificate data). - * - * Returns: the URI string - * - * Since: 1.6 - **/ -const char * -nm_setting_802_1x_get_ca_cert_uri(NMSetting8021x *setting) -{ - _cert_impl_get_uri(setting, ca_cert); -} - -/** - * nm_setting_802_1x_set_ca_cert: - * @setting: the #NMSetting8021x - * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH - * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the CA certificate - * file (PEM or DER format). The path must be UTF-8 encoded; use - * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme - * clears the CA certificate. - * @scheme: desired storage scheme for the certificate - * @out_format: on successful return, the type of the certificate added - * @error: on unsuccessful return, an error - * - * Reads a certificate from disk and sets the #NMSetting8021x:ca-cert property - * with the raw certificate data if using the %NM_SETTING_802_1X_CK_SCHEME_BLOB - * scheme, or with the path to the certificate file if using the - * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. - * - * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful - **/ -gboolean -nm_setting_802_1x_set_ca_cert(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error) -{ - return _cert_impl_set(setting, PROP_CA_CERT, value, NULL, scheme, out_format, error); -} - -/** - * nm_setting_802_1x_get_ca_cert_password: - * @setting: the #NMSetting8021x - * - * Returns: the password used to access the CA certificate stored in - * #NMSetting8021x:ca-cert property. Only makes sense if the certificate - * is stored on a PKCS#11 token that requires a login. - * - * Since: 1.8 - **/ -const char * -nm_setting_802_1x_get_ca_cert_password(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_cert_password; -} - -/** - * nm_setting_802_1x_get_ca_cert_password_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSetting8021x:ca-cert-password - * - * Since: 1.8 - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_ca_cert_password_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_cert_password_flags; -} - -/** - * nm_setting_802_1x_get_subject_match: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSetting8021x:subject-match property. This is the - * substring to be matched against the subject of the authentication - * server certificate, or %NULL no subject verification is to be - * performed. - **/ -const char * -nm_setting_802_1x_get_subject_match(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->subject_match; -} - -/** - * nm_setting_802_1x_get_num_altsubject_matches: - * @setting: the #NMSetting8021x - * - * Returns the number of entries in the - * #NMSetting8021x:altsubject-matches property of this setting. - * - * Returns: the number of altsubject-matches entries. - **/ -guint32 -nm_setting_802_1x_get_num_altsubject_matches(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); - - return g_slist_length(NM_SETTING_802_1X_GET_PRIVATE(setting)->altsubject_matches); -} - -/** - * nm_setting_802_1x_get_altsubject_match: - * @setting: the #NMSettingConnection - * @i: the zero-based index of the array of altSubjectName matches - * - * Returns the altSubjectName match at index @i. - * - * Returns: the altSubjectName match at index @i - **/ -const char * -nm_setting_802_1x_get_altsubject_match(NMSetting8021x *setting, guint32 i) -{ - NMSetting8021xPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - g_return_val_if_fail(i <= g_slist_length(priv->altsubject_matches), NULL); - - return (const char *) g_slist_nth_data(priv->altsubject_matches, i); -} - -/** - * nm_setting_802_1x_add_altsubject_match: - * @setting: the #NMSetting8021x - * @altsubject_match: the altSubjectName to allow for this connection - * - * Adds an allowed alternate subject name match. Until at least one - * match is added, the altSubjectName of the remote authentication - * server is not verified. - * - * Returns: %TRUE if the alternative subject name match was - * successfully added, %FALSE if it was already allowed. - **/ -gboolean -nm_setting_802_1x_add_altsubject_match(NMSetting8021x *setting, const char *altsubject_match) -{ - NMSetting8021xPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - g_return_val_if_fail(altsubject_match != NULL, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - for (iter = priv->altsubject_matches; iter; iter = g_slist_next(iter)) { - if (!strcmp(altsubject_match, (char *) iter->data)) - return FALSE; - } - - priv->altsubject_matches = g_slist_append(priv->altsubject_matches, g_strdup(altsubject_match)); - _notify(setting, PROP_ALTSUBJECT_MATCHES); - return TRUE; -} - -/** - * nm_setting_802_1x_remove_altsubject_match: - * @setting: the #NMSetting8021x - * @i: the index of the altSubjectName match to remove - * - * Removes the allowed altSubjectName at the specified index. - **/ -void -nm_setting_802_1x_remove_altsubject_match(NMSetting8021x *setting, guint32 i) -{ - NMSetting8021xPrivate *priv; - GSList * elt; - - g_return_if_fail(NM_IS_SETTING_802_1X(setting)); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - elt = g_slist_nth(priv->altsubject_matches, i); - g_return_if_fail(elt != NULL); - - g_free(elt->data); - priv->altsubject_matches = g_slist_delete_link(priv->altsubject_matches, elt); - _notify(setting, PROP_ALTSUBJECT_MATCHES); -} - -/** - * nm_setting_802_1x_remove_altsubject_match_by_value: - * @setting: the #NMSetting8021x - * @altsubject_match: the altSubjectName to remove - * - * Removes the allowed altSubjectName @altsubject_match. - * - * Returns: %TRUE if the alternative subject name match was found and removed, - * %FALSE if it was not. - **/ -gboolean -nm_setting_802_1x_remove_altsubject_match_by_value(NMSetting8021x *setting, - const char * altsubject_match) -{ - NMSetting8021xPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - g_return_val_if_fail(altsubject_match != NULL, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - for (iter = priv->altsubject_matches; iter; iter = g_slist_next(iter)) { - if (!strcmp(altsubject_match, (char *) iter->data)) { - priv->altsubject_matches = g_slist_delete_link(priv->altsubject_matches, iter); - _notify(setting, PROP_ALTSUBJECT_MATCHES); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_802_1x_clear_altsubject_matches: - * @setting: the #NMSetting8021x - * - * Clears all altSubjectName matches. - **/ -void -nm_setting_802_1x_clear_altsubject_matches(NMSetting8021x *setting) -{ - NMSetting8021xPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_802_1X(setting)); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - g_slist_free_full(priv->altsubject_matches, g_free); - priv->altsubject_matches = NULL; - _notify(setting, PROP_ALTSUBJECT_MATCHES); -} - -/** - * nm_setting_802_1x_get_domain_suffix_match: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSetting8021x:domain-suffix-match property. - * - * Since: 1.2 - **/ -const char * -nm_setting_802_1x_get_domain_suffix_match(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->domain_suffix_match; -} - -/** - * nm_setting_802_1x_get_domain_match: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSetting8021x:domain-match property. - * - * Since: 1.24 - **/ -const char * -nm_setting_802_1x_get_domain_match(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->domain_match; -} - -/** - * nm_setting_802_1x_get_client_cert_scheme: - * @setting: the #NMSetting8021x - * - * Returns the scheme used to store the client certificate. If the returned scheme - * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_client_cert_blob(); - * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_client_cert_path(); - * if %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use nm_setting_802_1x_get_client_cert_uri(). - * - * Returns: scheme used to store the client certificate (blob or path) - **/ -NMSetting8021xCKScheme -nm_setting_802_1x_get_client_cert_scheme(NMSetting8021x *setting) -{ - _cert_impl_get_scheme(setting, client_cert); -} - -/** - * nm_setting_802_1x_get_client_cert_blob: - * @setting: the #NMSetting8021x - * - * Client certificates are used to identify the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * Returns: (transfer none): the client certificate data - **/ -GBytes * -nm_setting_802_1x_get_client_cert_blob(NMSetting8021x *setting) -{ - _cert_impl_get_blob(setting, client_cert); -} - -/** - * nm_setting_802_1x_get_client_cert_path: - * @setting: the #NMSetting8021x - * - * Client certificates are used to identify the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * Returns: path to the client certificate file - **/ -const char * -nm_setting_802_1x_get_client_cert_path(NMSetting8021x *setting) -{ - _cert_impl_get_path(setting, client_cert); -} - -/** - * nm_setting_802_1x_get_client_cert_uri: - * @setting: the #NMSetting8021x - * - * Returns the client certificate URI analogously to - * nm_setting_802_1x_get_client_cert_blob() and - * nm_setting_802_1x_get_client_cert_path(). - * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC - * 7512), but may be extended to other schemes in future (such as 'file' URIs - * for local files and 'data' URIs for inline certificate data). - * - * Returns: the URI string - * - * Since: 1.6 - **/ -const char * -nm_setting_802_1x_get_client_cert_uri(NMSetting8021x *setting) -{ - _cert_impl_get_uri(setting, client_cert); -} - -/** - * nm_setting_802_1x_set_client_cert: - * @setting: the #NMSetting8021x - * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH - * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the client - * certificate file (PEM, DER, or PKCS#12 format). The path must be UTF-8 - * encoded; use g_filename_to_utf8() to convert if needed. Passing %NULL with - * any @scheme clears the client certificate. - * @scheme: desired storage scheme for the certificate - * @out_format: on successful return, the type of the certificate added - * @error: on unsuccessful return, an error - * - * Reads a certificate from disk and sets the #NMSetting8021x:client-cert - * property with the raw certificate data if using the - * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate - * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. - * - * Client certificates are used to identify the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful - **/ -gboolean -nm_setting_802_1x_set_client_cert(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error) -{ - return _cert_impl_set(setting, PROP_CLIENT_CERT, value, NULL, scheme, out_format, error); -} - -/** - * nm_setting_802_1x_get_client_cert_password: - * @setting: the #NMSetting8021x - * - * Returns: the password used to access the client certificate stored in - * #NMSetting8021x:client-cert property. Only makes sense if the certificate - * is stored on a PKCS#11 token that requires a login. - * - * Since: 1.8 - **/ -const char * -nm_setting_802_1x_get_client_cert_password(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->client_cert_password; -} - -/** - * nm_setting_802_1x_get_client_cert_password_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSetting8021x:client-cert-password - * - * Since: 1.8 - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_client_cert_password_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->client_cert_password_flags; -} - -/** - * nm_setting_802_1x_get_phase1_peapver: - * @setting: the #NMSetting8021x - * - * Returns: the "phase 1" PEAP version to be used when authenticating with - * EAP-PEAP as contained in the #NMSetting8021x:phase1-peapver property. Valid - * values are %NULL (unset), "0" (PEAP version 0), and "1" (PEAP version 1). - **/ -const char * -nm_setting_802_1x_get_phase1_peapver(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_peapver; -} - -/** - * nm_setting_802_1x_get_phase1_peaplabel: - * @setting: the #NMSetting8021x - * - * Returns: whether the "phase 1" PEAP label is new-style or old-style, to be - * used when authenticating with EAP-PEAP, as contained in the - * #NMSetting8021x:phase1-peaplabel property. Valid values are %NULL (unset), - * "0" (use old-style label), and "1" (use new-style label). See the - * wpa_supplicant documentation for more details. - **/ -const char * -nm_setting_802_1x_get_phase1_peaplabel(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_peaplabel; -} - -/** - * nm_setting_802_1x_get_phase1_fast_provisioning: - * @setting: the #NMSetting8021x - * - * Returns: whether "phase 1" PEAP fast provisioning should be used, as specified - * by the #NMSetting8021x:phase1-fast-provisioning property. See the - * wpa_supplicant documentation for more details. - **/ -const char * -nm_setting_802_1x_get_phase1_fast_provisioning(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_fast_provisioning; -} - -/** - * nm_setting_802_1x_get_phase1_auth_flags: - * @setting: the #NMSetting8021x - * - * Returns: the authentication flags for "phase 1". - * - * Since: 1.8 - */ -NMSetting8021xAuthFlags -nm_setting_802_1x_get_phase1_auth_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_auth_flags; -} - -/** - * nm_setting_802_1x_get_phase2_auth: - * @setting: the #NMSetting8021x - * - * Returns: the "phase 2" non-EAP (ex MD5) allowed authentication method as - * specified by the #NMSetting8021x:phase2-auth property. - **/ -const char * -nm_setting_802_1x_get_phase2_auth(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_auth; -} - -/** - * nm_setting_802_1x_get_phase2_autheap: - * @setting: the #NMSetting8021x - * - * Returns: the "phase 2" EAP-based (ex TLS) allowed authentication method as - * specified by the #NMSetting8021x:phase2-autheap property. - **/ -const char * -nm_setting_802_1x_get_phase2_autheap(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_autheap; -} - -/** - * nm_setting_802_1x_get_phase2_ca_path: - * @setting: the #NMSetting8021x - * - * Returns the path of the "phase 2" CA certificate directory if previously set. - * Systems will often have a directory that contains multiple individual CA - * certificates which the supplicant can then add to the verification chain. - * This may be used in addition to the #NMSetting8021x:phase2-ca-cert property - * to add more CA certificates for verifying the network to client. - * - * Returns: the "phase 2" CA certificate directory path - **/ -const char * -nm_setting_802_1x_get_phase2_ca_path(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_path; -} - -/** - * nm_setting_802_1x_get_phase2_ca_cert_scheme: - * @setting: the #NMSetting8021x - * - * Returns the scheme used to store the "phase 2" CA certificate. If the - * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use - * nm_setting_802_1x_get_ca_cert_blob(); if %NM_SETTING_802_1X_CK_SCHEME_PATH, - * use nm_setting_802_1x_get_ca_cert_path(); if %NM_SETTING_802_1X_CK_SCHEME_PKCS11, - * use nm_setting_802_1x_get_ca_cert_uri(). - * - * Returns: scheme used to store the "phase 2" CA certificate (blob or path) - **/ -NMSetting8021xCKScheme -nm_setting_802_1x_get_phase2_ca_cert_scheme(NMSetting8021x *setting) -{ - _cert_impl_get_scheme(setting, phase2_ca_cert); -} - -/** - * nm_setting_802_1x_get_phase2_ca_cert_blob: - * @setting: the #NMSetting8021x - * - * Returns the "phase 2" CA certificate blob if the CA certificate is stored - * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use - * a CA certificate (LEAP for example), and those that can take advantage of the - * CA certificate allow it to be unset. Note that lack of a CA certificate - * reduces security by allowing man-in-the-middle attacks, because the identity - * of the network cannot be confirmed by the client. - * - * Returns: (transfer none): the "phase 2" CA certificate data - **/ -GBytes * -nm_setting_802_1x_get_phase2_ca_cert_blob(NMSetting8021x *setting) -{ - _cert_impl_get_blob(setting, phase2_ca_cert); -} - -/** - * nm_setting_802_1x_get_phase2_ca_cert_path: - * @setting: the #NMSetting8021x - * - * Returns the "phase 2" CA certificate path if the CA certificate is stored - * using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use - * a CA certificate (LEAP for example), and those that can take advantage of the - * CA certificate allow it to be unset. Note that lack of a CA certificate - * reduces security by allowing man-in-the-middle attacks, because the identity - * of the network cannot be confirmed by the client. - * - * Returns: path to the "phase 2" CA certificate file - **/ -const char * -nm_setting_802_1x_get_phase2_ca_cert_path(NMSetting8021x *setting) -{ - _cert_impl_get_path(setting, phase2_ca_cert); -} - -/** - * nm_setting_802_1x_get_phase2_ca_cert_uri: - * @setting: the #NMSetting8021x - * - * Returns the "phase 2" CA certificate URI analogously to - * nm_setting_802_1x_get_phase2_ca_cert_blob() and - * nm_setting_802_1x_get_phase2_ca_cert_path(). - * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC - * 7512), but may be extended to other schemes in future (such as 'file' URIs - * for local files and 'data' URIs for inline certificate data). - * - * Returns: the URI string - * - * Since: 1.6 - **/ -const char * -nm_setting_802_1x_get_phase2_ca_cert_uri(NMSetting8021x *setting) -{ - _cert_impl_get_uri(setting, phase2_ca_cert); -} - -/** - * nm_setting_802_1x_set_phase2_ca_cert: - * @setting: the #NMSetting8021x - * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH - * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" CA - * certificate file (PEM or DER format). The path must be UTF-8 encoded; use - * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme - * clears the "phase2" CA certificate. - * @scheme: desired storage scheme for the certificate - * @out_format: on successful return, the type of the certificate added - * @error: on unsuccessful return, an error - * - * Reads a certificate from disk and sets the #NMSetting8021x:phase2-ca-cert - * property with the raw certificate data if using the - * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate - * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. - * - * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful - **/ -gboolean -nm_setting_802_1x_set_phase2_ca_cert(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error) -{ - return _cert_impl_set(setting, PROP_PHASE2_CA_CERT, value, NULL, scheme, out_format, error); -} - -/** - * nm_setting_802_1x_get_phase2_ca_cert_password: - * @setting: the #NMSetting8021x - * - * Returns: the password used to access the "phase2" CA certificate stored in - * #NMSetting8021x:phase2-ca-cert property. Only makes sense if the certificate - * is stored on a PKCS#11 token that requires a login. - * - * Since: 1.8 - **/ -const char * -nm_setting_802_1x_get_phase2_ca_cert_password(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_cert_password; -} - -/** - * nm_setting_802_1x_get_phase2_ca_cert_password_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSetting8021x:phase2-private-key-password - * - * Since: 1.8 - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_phase2_ca_cert_password_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_cert_password_flags; -} - -/** - * nm_setting_802_1x_get_phase2_subject_match: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSetting8021x:phase2-subject-match property. This is - * the substring to be matched against the subject of the "phase 2" - * authentication server certificate, or %NULL no subject verification - * is to be performed. - **/ -const char * -nm_setting_802_1x_get_phase2_subject_match(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_subject_match; -} - -/** - * nm_setting_802_1x_get_num_phase2_altsubject_matches: - * @setting: the #NMSetting8021x - * - * Returns the number of entries in the - * #NMSetting8021x:phase2-altsubject-matches property of this setting. - * - * Returns: the number of phase2-altsubject-matches entries. - **/ -guint32 -nm_setting_802_1x_get_num_phase2_altsubject_matches(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); - - return g_slist_length(NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_altsubject_matches); -} - -/** - * nm_setting_802_1x_get_phase2_domain_suffix_match: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSetting8021x:phase2-domain-suffix-match property. - * - * Since: 1.2 - **/ -const char * -nm_setting_802_1x_get_phase2_domain_suffix_match(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_domain_suffix_match; -} - -/** - * nm_setting_802_1x_get_phase2_domain_match: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSetting8021x:phase2-domain-match property. - * - * Since: 1.24 - **/ -const char * -nm_setting_802_1x_get_phase2_domain_match(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_domain_match; -} - -/** - * nm_setting_802_1x_get_phase2_altsubject_match: - * @setting: the #NMSettingConnection - * @i: the zero-based index of the array of "phase 2" altSubjectName matches - * - * Returns the "phase 2" altSubjectName match at index @i. - * - * Returns: the "phase 2" altSubjectName match at index @i - **/ -const char * -nm_setting_802_1x_get_phase2_altsubject_match(NMSetting8021x *setting, guint32 i) -{ - NMSetting8021xPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - g_return_val_if_fail(i <= g_slist_length(priv->phase2_altsubject_matches), NULL); - - return (const char *) g_slist_nth_data(priv->phase2_altsubject_matches, i); -} - -/** - * nm_setting_802_1x_add_phase2_altsubject_match: - * @setting: the #NMSetting8021x - * @phase2_altsubject_match: the "phase 2" altSubjectName to allow for this - * connection - * - * Adds an allowed alternate subject name match for "phase 2". Until - * at least one match is added, the altSubjectName of the "phase 2" - * remote authentication server is not verified. - * - * Returns: %TRUE if the "phase 2" alternative subject name match was - * successfully added, %FALSE if it was already allowed. - **/ -gboolean -nm_setting_802_1x_add_phase2_altsubject_match(NMSetting8021x *setting, - const char * phase2_altsubject_match) -{ - NMSetting8021xPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - g_return_val_if_fail(phase2_altsubject_match != NULL, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - for (iter = priv->phase2_altsubject_matches; iter; iter = g_slist_next(iter)) { - if (!strcmp(phase2_altsubject_match, (char *) iter->data)) - return FALSE; - } - - priv->phase2_altsubject_matches = - g_slist_append(priv->phase2_altsubject_matches, g_strdup(phase2_altsubject_match)); - _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES); - return TRUE; -} - -/** - * nm_setting_802_1x_remove_phase2_altsubject_match: - * @setting: the #NMSetting8021x - * @i: the index of the "phase 2" altSubjectName match to remove - * - * Removes the allowed "phase 2" altSubjectName at the specified index. - **/ -void -nm_setting_802_1x_remove_phase2_altsubject_match(NMSetting8021x *setting, guint32 i) -{ - NMSetting8021xPrivate *priv; - GSList * elt; - - g_return_if_fail(NM_IS_SETTING_802_1X(setting)); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - elt = g_slist_nth(priv->phase2_altsubject_matches, i); - g_return_if_fail(elt != NULL); - - g_free(elt->data); - priv->phase2_altsubject_matches = g_slist_delete_link(priv->phase2_altsubject_matches, elt); - _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES); -} - -/** - * nm_setting_802_1x_remove_phase2_altsubject_match_by_value: - * @setting: the #NMSetting8021x - * @phase2_altsubject_match: the "phase 2" altSubjectName to remove - * - * Removes the allowed "phase 2" altSubjectName @phase2_altsubject_match. - * - * Returns: %TRUE if the alternative subject name match for "phase 2" was found and removed, - * %FALSE if it was not. - **/ -gboolean -nm_setting_802_1x_remove_phase2_altsubject_match_by_value(NMSetting8021x *setting, - const char * phase2_altsubject_match) -{ - NMSetting8021xPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - g_return_val_if_fail(phase2_altsubject_match != NULL, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - for (iter = priv->phase2_altsubject_matches; iter; iter = g_slist_next(iter)) { - if (!strcmp(phase2_altsubject_match, (char *) iter->data)) { - priv->phase2_altsubject_matches = - g_slist_delete_link(priv->phase2_altsubject_matches, iter); - _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_802_1x_clear_phase2_altsubject_matches: - * @setting: the #NMSetting8021x - * - * Clears all "phase 2" altSubjectName matches. - **/ -void -nm_setting_802_1x_clear_phase2_altsubject_matches(NMSetting8021x *setting) -{ - NMSetting8021xPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_802_1X(setting)); - - priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - g_slist_free_full(priv->phase2_altsubject_matches, g_free); - priv->phase2_altsubject_matches = NULL; - _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES); -} - -/** - * nm_setting_802_1x_get_phase2_client_cert_scheme: - * @setting: the #NMSetting8021x - * - * Returns the scheme used to store the "phase 2" client certificate. If the - * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use - * nm_setting_802_1x_get_client_cert_blob(); if - * %NM_SETTING_802_1X_CK_SCHEME_PATH, use - * nm_setting_802_1x_get_client_cert_path(); if - * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use - * nm_setting_802_1x_get_client_cert_uri(). - * - * Returns: scheme used to store the "phase 2" client certificate (blob or path) - **/ -NMSetting8021xCKScheme -nm_setting_802_1x_get_phase2_client_cert_scheme(NMSetting8021x *setting) -{ - _cert_impl_get_scheme(setting, phase2_client_cert); -} - -/** - * nm_setting_802_1x_get_phase2_client_cert_blob: - * @setting: the #NMSetting8021x - * - * Client certificates are used to identify the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * Returns: (transfer none): the "phase 2" client certificate data - **/ -GBytes * -nm_setting_802_1x_get_phase2_client_cert_blob(NMSetting8021x *setting) -{ - _cert_impl_get_blob(setting, phase2_client_cert); -} - -/** - * nm_setting_802_1x_get_phase2_client_cert_path: - * @setting: the #NMSetting8021x - * - * Client certificates are used to identify the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * Returns: path to the "phase 2" client certificate file - **/ -const char * -nm_setting_802_1x_get_phase2_client_cert_path(NMSetting8021x *setting) -{ - _cert_impl_get_path(setting, phase2_client_cert); -} - -/** - * nm_setting_802_1x_get_phase2_client_cert_uri: - * @setting: the #NMSetting8021x - * - * Returns the "phase 2" client certificate URI analogously to - * nm_setting_802_1x_get_phase2_ca_cert_blob() and - * nm_setting_802_1x_get_phase2_ca_cert_path(). - * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC - * 7512), but may be extended to other schemes in future (such as 'file' URIs - * for local files and 'data' URIs for inline certificate data). - * - * Returns: the URI string - * - * Since: 1.6 - **/ -const char * -nm_setting_802_1x_get_phase2_client_cert_uri(NMSetting8021x *setting) -{ - _cert_impl_get_uri(setting, phase2_client_cert); -} - -/** - * nm_setting_802_1x_set_phase2_client_cert: - * @setting: the #NMSetting8021x - * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH - * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" client - * certificate file (PEM, DER, or PKCS#12 format). The path must be UTF-8 - * encoded; use g_filename_to_utf8() to convert if needed. Passing %NULL with - * any @scheme clears the "phase2" client certificate. - * @scheme: desired storage scheme for the certificate - * @out_format: on successful return, the type of the certificate added - * @error: on unsuccessful return, an error - * - * Reads a certificate from disk and sets the #NMSetting8021x:phase2-client-cert - * property with the raw certificate data if using the - * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate - * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. - * - * Client certificates are used to identify the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful - **/ -gboolean -nm_setting_802_1x_set_phase2_client_cert(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error) -{ - return _cert_impl_set(setting, PROP_PHASE2_CLIENT_CERT, value, NULL, scheme, out_format, error); -} - -/** - * nm_setting_802_1x_get_phase2_client_cert_password: - * @setting: the #NMSetting8021x - * - * Returns: the password used to access the "phase2" client certificate stored in - * #NMSetting8021x:phase2-client-cert property. Only makes sense if the certificate - * is stored on a PKCS#11 token that requires a login. - * - * Since: 1.8 - **/ -const char * -nm_setting_802_1x_get_phase2_client_cert_password(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_client_cert_password; -} - -/** - * nm_setting_802_1x_get_phase2_client_cert_password_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSetting8021x:phase2-client-cert-password - * - * Since: 1.8 - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_phase2_client_cert_password_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_client_cert_password_flags; -} - -/** - * nm_setting_802_1x_get_password: - * @setting: the #NMSetting8021x - * - * Returns: the password used by the authentication method, if any, as specified - * by the #NMSetting8021x:password property - **/ -const char * -nm_setting_802_1x_get_password(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->password; -} - -/** - * nm_setting_802_1x_get_password_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the #NMSetting8021x:password - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_password_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_flags; -} - -/** - * nm_setting_802_1x_get_password_raw: - * @setting: the #NMSetting8021x - * - * Returns: (transfer none): the password used by the authentication method as a - * UTF-8-encoded array of bytes, as specified by the - * #NMSetting8021x:password-raw property - **/ -GBytes * -nm_setting_802_1x_get_password_raw(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_raw; -} - -/** - * nm_setting_802_1x_get_password_raw_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSetting8021x:password-raw - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_password_raw_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_raw_flags; -} - -/** - * nm_setting_802_1x_get_pin: - * @setting: the #NMSetting8021x - * - * Returns: the PIN used by the authentication method, if any, as specified - * by the #NMSetting8021x:pin property - **/ -const char * -nm_setting_802_1x_get_pin(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->pin; -} - -/** - * nm_setting_802_1x_get_pin_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSetting8021x:pin - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_pin_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->pin_flags; -} - -/** - * nm_setting_802_1x_get_private_key_scheme: - * @setting: the #NMSetting8021x - * - * Returns the scheme used to store the private key. If the returned scheme is - * %NM_SETTING_802_1X_CK_SCHEME_BLOB, use - * nm_setting_802_1x_get_client_cert_blob(); if - * %NM_SETTING_802_1X_CK_SCHEME_PATH, use - * nm_setting_802_1x_get_client_cert_path(); if - * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use - * nm_setting_802_1x_get_client_cert_uri(). - * - * Returns: scheme used to store the private key (blob or path) - **/ -NMSetting8021xCKScheme -nm_setting_802_1x_get_private_key_scheme(NMSetting8021x *setting) -{ - _cert_impl_get_scheme(setting, private_key); -} - -/** - * nm_setting_802_1x_get_private_key_blob: - * @setting: the #NMSetting8021x - * - * Private keys are used to authenticate the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * WARNING: the private key property is not a "secret" property, and thus - * unencrypted private key data may be readable by unprivileged users. Private - * keys should always be encrypted with a private key password. - * - * Returns: (transfer none): the private key data - **/ -GBytes * -nm_setting_802_1x_get_private_key_blob(NMSetting8021x *setting) -{ - _cert_impl_get_blob(setting, private_key); -} - -/** - * nm_setting_802_1x_get_private_key_path: - * @setting: the #NMSetting8021x - * - * Private keys are used to authenticate the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * Returns: path to the private key file - **/ -const char * -nm_setting_802_1x_get_private_key_path(NMSetting8021x *setting) -{ - _cert_impl_get_path(setting, private_key); -} - -/** - * nm_setting_802_1x_get_private_key_uri: - * @setting: the #NMSetting8021x - * - * Returns the private key URI analogously to - * nm_setting_802_1x_get_private_key_blob() and - * nm_setting_802_1x_get_private_key_path(). - * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC - * 7512), but may be extended to other schemes in future (such as 'file' URIs - * for local files and 'data' URIs for inline certificate data). - * - * Returns: the URI string - * - * Since: 1.6 - **/ -const char * -nm_setting_802_1x_get_private_key_uri(NMSetting8021x *setting) -{ - _cert_impl_get_uri(setting, private_key); -} - -/** - * nm_setting_802_1x_set_private_key: - * @setting: the #NMSetting8021x - * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or - * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the private key file - * (PEM, DER, or PKCS#12 format). The path must be UTF-8 encoded; use - * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme - * clears the private key. - * @password: password used to decrypt the private key, or %NULL if the password - * is unknown. If the password is given but fails to decrypt the private key, - * an error is returned. - * @scheme: desired storage scheme for the private key - * @out_format: on successful return, the type of the private key added - * @error: on unsuccessful return, an error - * - * Private keys are used to authenticate the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * This function reads a private key from disk and sets the - * #NMSetting8021x:private-key property with the private key file data if using - * the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the private - * key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. - * - * If @password is given, this function attempts to decrypt the private key to - * verify that @password is correct, and if it is, updates the - * #NMSetting8021x:private-key-password property with the given @password. If - * the decryption is unsuccessful, %FALSE is returned, @error is set, and no - * internal data is changed. If no @password is given, the private key is - * assumed to be valid, no decryption is performed, and the password may be set - * at a later time. - * - * WARNING: the private key property is not a "secret" property, and thus - * unencrypted private key data using the BLOB scheme may be readable by - * unprivileged users. Private keys should always be encrypted with a private - * key password to prevent unauthorized access to unencrypted private key data. - * - * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful - **/ -gboolean -nm_setting_802_1x_set_private_key(NMSetting8021x * setting, - const char * value, - const char * password, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error) -{ - return _cert_impl_set(setting, PROP_PRIVATE_KEY, value, password, scheme, out_format, error); -} - -/** - * nm_setting_802_1x_get_private_key_password: - * @setting: the #NMSetting8021x - * - * Returns: the private key password used to decrypt the private key if - * previously set with nm_setting_802_1x_set_private_key(), or the - * #NMSetting8021x:private-key-password property. - **/ -const char * -nm_setting_802_1x_get_private_key_password(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->private_key_password; -} - -/** - * nm_setting_802_1x_get_private_key_password_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSetting8021x:private-key-password - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_private_key_password_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->private_key_password_flags; -} - -/** - * nm_setting_802_1x_get_private_key_format: - * @setting: the #NMSetting8021x - * - * Returns: the data format of the private key data stored in the - * #NMSetting8021x:private-key property - **/ -NMSetting8021xCKFormat -nm_setting_802_1x_get_private_key_format(NMSetting8021x *setting) -{ - return _cert_impl_get_key_format(setting, private_key); -} - -/** - * nm_setting_802_1x_get_phase2_private_key_password: - * @setting: the #NMSetting8021x - * - * Returns: the private key password used to decrypt the private key if - * previously set with nm_setting_802_1x_set_phase2_private_key() or the - * #NMSetting8021x:phase2-private-key-password property. - **/ -const char * -nm_setting_802_1x_get_phase2_private_key_password(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_private_key_password; -} - -/** - * nm_setting_802_1x_get_phase2_private_key_password_flags: - * @setting: the #NMSetting8021x - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSetting8021x:phase2-private-key-password - **/ -NMSettingSecretFlags -nm_setting_802_1x_get_phase2_private_key_password_flags(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_private_key_password_flags; -} - -/** - * nm_setting_802_1x_get_phase2_private_key_scheme: - * @setting: the #NMSetting8021x - * - * Returns the scheme used to store the "phase 2" private key. If the returned - * scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use - * nm_setting_802_1x_get_client_cert_blob(); if - * %NM_SETTING_802_1X_CK_SCHEME_PATH, use - * nm_setting_802_1x_get_client_cert_path(); if - * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use - * nm_setting_802_1x_get_client_cert_uri(). - * - * Returns: scheme used to store the "phase 2" private key (blob or path) - **/ -NMSetting8021xCKScheme -nm_setting_802_1x_get_phase2_private_key_scheme(NMSetting8021x *setting) -{ - _cert_impl_get_scheme(setting, phase2_private_key); -} - -/** - * nm_setting_802_1x_get_phase2_private_key_blob: - * @setting: the #NMSetting8021x - * - * Private keys are used to authenticate the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * WARNING: the phase2 private key property is not a "secret" property, and thus - * unencrypted private key data may be readable by unprivileged users. Private - * keys should always be encrypted with a private key password. - * - * Returns: (transfer none): the "phase 2" private key data - **/ -GBytes * -nm_setting_802_1x_get_phase2_private_key_blob(NMSetting8021x *setting) -{ - _cert_impl_get_blob(setting, phase2_private_key); -} - -/** - * nm_setting_802_1x_get_phase2_private_key_path: - * @setting: the #NMSetting8021x - * - * Private keys are used to authenticate the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * Returns: path to the "phase 2" private key file - **/ -const char * -nm_setting_802_1x_get_phase2_private_key_path(NMSetting8021x *setting) -{ - _cert_impl_get_path(setting, phase2_private_key); -} - -/** - * nm_setting_802_1x_get_phase2_private_key_uri: - * @setting: the #NMSetting8021x - * - * Returns the "phase 2" private key URI analogously to - * nm_setting_802_1x_get_phase2_private_key_blob() and - * nm_setting_802_1x_get_phase2_private_key_path(). - * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC - * 7512), but may be extended to other schemes in future (such as 'file' URIs - * for local files and 'data' URIs for inline certificate data). - * - * Returns: the URI string - * - * Since: 1.6 - **/ -const char * -nm_setting_802_1x_get_phase2_private_key_uri(NMSetting8021x *setting) -{ - _cert_impl_get_uri(setting, phase2_private_key); -} - -/** - * nm_setting_802_1x_set_phase2_private_key: - * @setting: the #NMSetting8021x - * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or - * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" private - * key file (PEM, DER, or PKCS#12 format). The path must be UTF-8 encoded; - * use g_filename_to_utf8() to convert if needed. Passing %NULL with any - * @scheme clears the private key. - * @password: password used to decrypt the private key, or %NULL if the password - * is unknown. If the password is given but fails to decrypt the private key, - * an error is returned. - * @scheme: desired storage scheme for the private key - * @out_format: on successful return, the type of the private key added - * @error: on unsuccessful return, an error - * - * Private keys are used to authenticate the connecting client to the network - * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x - * authentication method. - * - * This function reads a private key from disk and sets the - * #NMSetting8021x:phase2-private-key property with the private key file data if - * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the - * private key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. - * - * If @password is given, this function attempts to decrypt the private key to - * verify that @password is correct, and if it is, updates the - * #NMSetting8021x:phase2-private-key-password property with the given - * @password. If the decryption is unsuccessful, %FALSE is returned, @error is - * set, and no internal data is changed. If no @password is given, the private - * key is assumed to be valid, no decryption is performed, and the password may - * be set at a later time. - * - * WARNING: the "phase2" private key property is not a "secret" property, and - * thus unencrypted private key data using the BLOB scheme may be readable by - * unprivileged users. Private keys should always be encrypted with a private - * key password to prevent unauthorized access to unencrypted private key data. - * - * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful - **/ -gboolean -nm_setting_802_1x_set_phase2_private_key(NMSetting8021x * setting, - const char * value, - const char * password, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error) -{ - return _cert_impl_set(setting, - PROP_PHASE2_PRIVATE_KEY, - value, - password, - scheme, - out_format, - error); -} - -/** - * nm_setting_802_1x_get_phase2_private_key_format: - * @setting: the #NMSetting8021x - * - * Returns: the data format of the "phase 2" private key data stored in the - * #NMSetting8021x:phase2-private-key property - **/ -NMSetting8021xCKFormat -nm_setting_802_1x_get_phase2_private_key_format(NMSetting8021x *setting) -{ - return _cert_impl_get_key_format(setting, phase2_private_key); -} - -/** - * nm_setting_802_1x_get_auth_timeout: - * @setting: the #NMSetting8021x - * - * Returns the value contained in the #NMSetting8021x:auth-timeout property. - * - * Returns: the configured authentication timeout in seconds. Zero means the - * global default value. - * - * Since: 1.8 - **/ -int -nm_setting_802_1x_get_auth_timeout(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->auth_timeout; -} - -/** - * nm_setting_802_1x_get_optional: - * @setting: the #NMSetting8021x - * - * Returns the value contained in the #NMSetting8021x:optional property. - * - * Returns: %TRUE if the activation should proceed even when the 802.1X - * authentication fails; %FALSE otherwise - * - * Since: 1.22 - **/ -gboolean -nm_setting_802_1x_get_optional(NMSetting8021x *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); - - return NM_SETTING_802_1X_GET_PRIVATE(setting)->optional; -} - -/*****************************************************************************/ - -static void -need_secrets_password(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) -{ - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - - if ((!priv->password || !strlen(priv->password)) - && (!priv->password_raw || !g_bytes_get_size(priv->password_raw))) { - g_ptr_array_add(secrets, NM_SETTING_802_1X_PASSWORD); - g_ptr_array_add(secrets, NM_SETTING_802_1X_PASSWORD_RAW); - } -} - -static void -need_secrets_sim(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) -{ - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - - if (!priv->pin || !strlen(priv->pin)) - g_ptr_array_add(secrets, NM_SETTING_802_1X_PIN); -} - -static gboolean -need_private_key_password(GBytes * blob, - NMSetting8021xCKScheme scheme, - const char * path, - const char * password, - NMSettingSecretFlags flags) -{ - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - - if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) - return FALSE; - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 && flags == NM_SETTING_SECRET_FLAG_NONE) - return FALSE; - - /* Private key password is required */ - if (password) { - if (path) - format = nm_crypto_verify_private_key(path, password, NULL, NULL); - else if (blob) - format = nm_crypto_verify_private_key_data(g_bytes_get_data(blob, NULL), - g_bytes_get_size(blob), - password, - NULL, - NULL); - else - return FALSE; - } - - return (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN); -} - -static void -need_secrets_tls(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) -{ - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - NMSetting8021xCKScheme scheme; - GBytes * blob = NULL; - const char * path = NULL; - - if (phase2) { - scheme = nm_setting_802_1x_get_phase2_private_key_scheme(self); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) - path = nm_setting_802_1x_get_phase2_private_key_path(self); - else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) - blob = nm_setting_802_1x_get_phase2_private_key_blob(self); - else if (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) - g_warning("%s: unknown phase2 private key scheme %d", __func__, scheme); - - if (need_private_key_password(blob, - scheme, - path, - priv->phase2_private_key_password, - priv->phase2_private_key_password_flags)) - g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); - - scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme(self); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !(priv->phase2_ca_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE - || priv->phase2_ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) - && !priv->phase2_ca_cert_password) - g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD); - - scheme = nm_setting_802_1x_get_phase2_client_cert_scheme(self); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !(priv->phase2_client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED - || priv->phase2_client_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE) - && !priv->phase2_client_cert_password) - g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD); - } else { - scheme = nm_setting_802_1x_get_private_key_scheme(self); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) - path = nm_setting_802_1x_get_private_key_path(self); - else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) - blob = nm_setting_802_1x_get_private_key_blob(self); - else if (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) - g_warning("%s: unknown private key scheme %d", __func__, scheme); - - if (need_private_key_password(blob, - scheme, - path, - priv->private_key_password, - priv->private_key_password_flags)) - g_ptr_array_add(secrets, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); - - scheme = nm_setting_802_1x_get_ca_cert_scheme(self); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !(priv->ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED - || priv->ca_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE) - && !priv->ca_cert_password) - g_ptr_array_add(secrets, NM_SETTING_802_1X_CA_CERT_PASSWORD); - - scheme = nm_setting_802_1x_get_client_cert_scheme(self); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !(priv->client_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE - || priv->client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) - && !priv->client_cert_password) - g_ptr_array_add(secrets, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD); - } -} - -static gboolean -verify_tls(NMSetting8021x *self, gboolean phase2, GError **error) -{ - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - - if (phase2) { - if (!priv->phase2_client_cert) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_CLIENT_CERT); - return FALSE; - } else if (!g_bytes_get_size(priv->phase2_client_cert)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_CLIENT_CERT); - return FALSE; - } - - /* Private key is required for TLS */ - if (!priv->phase2_private_key) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - return FALSE; - } else if (!g_bytes_get_size(priv->phase2_private_key)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - return FALSE; - } - - /* If the private key is PKCS#12, check that it matches the client cert */ - if (nm_crypto_is_pkcs12_data(g_bytes_get_data(priv->phase2_private_key, NULL), - g_bytes_get_size(priv->phase2_private_key), - NULL)) { - if (!g_bytes_equal(priv->phase2_private_key, priv->phase2_client_cert)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("has to match '%s' property for PKCS#12"), - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_CLIENT_CERT); - return FALSE; - } - } - } else { - if (!priv->client_cert) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_CLIENT_CERT); - return FALSE; - } else if (!g_bytes_get_size(priv->client_cert)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_CLIENT_CERT); - return FALSE; - } - - /* Private key is required for TLS */ - if (!priv->private_key) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PRIVATE_KEY); - return FALSE; - } else if (!g_bytes_get_size(priv->private_key)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PRIVATE_KEY); - return FALSE; - } - - /* If the private key is PKCS#12, check that it matches the client cert */ - if (nm_crypto_is_pkcs12_data(g_bytes_get_data(priv->private_key, NULL), - g_bytes_get_size(priv->private_key), - NULL)) { - if (!g_bytes_equal(priv->private_key, priv->client_cert)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("has to match '%s' property for PKCS#12"), - NM_SETTING_802_1X_PRIVATE_KEY); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_CLIENT_CERT); - return FALSE; - } - } - } - - return TRUE; -} - -static gboolean -verify_ttls(NMSetting8021x *self, gboolean phase2, GError **error) -{ - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - - if ((!priv->identity || !strlen(priv->identity)) - && (!priv->anonymous_identity || !strlen(priv->anonymous_identity))) { - if (!priv->identity) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_IDENTITY); - } else if (!strlen(priv->identity)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_IDENTITY); - } else if (!priv->anonymous_identity) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_ANONYMOUS_IDENTITY); - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_ANONYMOUS_IDENTITY); - } - return FALSE; - } - - if ((!priv->phase2_auth || !strlen(priv->phase2_auth)) - && (!priv->phase2_autheap || !strlen(priv->phase2_autheap))) { - if (!priv->phase2_auth) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_AUTH); - } else if (!strlen(priv->phase2_auth)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_AUTH); - } else if (!priv->phase2_autheap) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_AUTHEAP); - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_AUTHEAP); - } - return FALSE; - } - - return TRUE; -} - -static gboolean -verify_identity(NMSetting8021x *self, gboolean phase2, GError **error) -{ - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - - if (!priv->identity) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_IDENTITY); - return FALSE; - } else if (!strlen(priv->identity)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_IDENTITY); - return FALSE; - } - - return TRUE; -} - -static void -need_secrets_phase2(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) -{ - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - char * method = NULL; - int i; - - g_return_if_fail(phase2 == FALSE); - - /* Check phase2_auth and phase2_autheap */ - method = priv->phase2_auth; - if (!method && priv->phase2_autheap) - method = priv->phase2_autheap; - - if (!method) { - g_warning("Couldn't find EAP method."); - g_assert_not_reached(); - return; - } - - /* Ask the configured phase2 method if it needs secrets */ - for (i = 0; eap_methods_table[i].method; i++) { - if (eap_methods_table[i].ns_func == NULL) - continue; - if (!strcmp(eap_methods_table[i].method, method)) { - (*eap_methods_table[i].ns_func)(self, secrets, TRUE); - break; - } - } -} - -static const EAPMethodsTable eap_methods_table[] = { - {"leap", need_secrets_password, verify_identity}, - {"pwd", need_secrets_password, verify_identity}, - {"md5", need_secrets_password, verify_identity}, - {"pap", need_secrets_password, verify_identity}, - {"chap", need_secrets_password, verify_identity}, - {"mschap", need_secrets_password, verify_identity}, - {"mschapv2", need_secrets_password, verify_identity}, - {"fast", need_secrets_password, verify_identity}, - {"tls", need_secrets_tls, verify_tls}, - {"peap", need_secrets_phase2, verify_ttls}, - {"ttls", need_secrets_phase2, verify_ttls}, - {"sim", need_secrets_sim, NULL}, - {"gtc", need_secrets_password, verify_identity}, - {"otp", NULL, NULL}, // FIXME: implement - {"external", NULL, NULL}, - {NULL, NULL, NULL}}; - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSetting8021x * self = NM_SETTING_802_1X(setting); - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - const char * valid_eap[] = - {"leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", "external", NULL}; - GSList *iter; - - if (error) - g_return_val_if_fail(*error == NULL, FALSE); - - if (connection && priv->optional - && !nm_streq0(nm_connection_get_connection_type(connection), - NM_SETTING_WIRED_SETTING_NAME)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("can be enabled only on Ethernet connections")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_OPTIONAL); - return FALSE; - } - - if (!priv->eap) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP); - return FALSE; - } - - if (!_nm_utils_string_slist_validate(priv->eap, valid_eap)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP); - return FALSE; - } - - /* Ask each configured EAP method if its valid */ - for (iter = priv->eap; iter; iter = g_slist_next(iter)) { - const char *method = (const char *) iter->data; - int i; - - for (i = 0; eap_methods_table[i].method; i++) { - if (eap_methods_table[i].v_func == NULL) - continue; - if (!strcmp(eap_methods_table[i].method, method)) { - if (!(*eap_methods_table[i].v_func)(self, FALSE, error)) - return FALSE; - break; - } - } - } - - if (!NM_IN_STRSET(priv->phase1_peapver, NULL, "0", "1")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - priv->phase1_peapver); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE1_PEAPVER); - return FALSE; - } - - if (!NM_IN_STRSET(priv->phase1_peaplabel, NULL, "0", "1")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - priv->phase1_peaplabel); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE1_PEAPLABEL); - return FALSE; - } - - if (!NM_IN_STRSET(priv->phase1_fast_provisioning, NULL, "0", "1", "2", "3")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - priv->phase1_fast_provisioning); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING); - return FALSE; - } - - if (NM_FLAGS_ANY(priv->phase1_auth_flags, ~NM_SETTING_802_1X_AUTH_FLAGS_ALL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid auth flags")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE1_AUTH_FLAGS); - return FALSE; - } - - if (!NM_IN_STRSET(priv->phase2_auth, - NULL, - "pap", - "chap", - "mschap", - "mschapv2", - "gtc", - "otp", - "md5", - "tls")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - priv->phase2_auth); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_AUTH); - return FALSE; - } - - if (!NM_IN_STRSET(priv->phase2_autheap, NULL, "md5", "mschapv2", "otp", "gtc", "tls")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - priv->phase2_autheap); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_802_1X_SETTING_NAME, - NM_SETTING_802_1X_PHASE2_AUTHEAP); - return FALSE; - } - - if (!_cert_verify_property(priv->ca_cert, - NM_SETTING_802_1X_CA_CERT, - priv->ca_cert_password, - NM_SETTING_802_1X_CA_CERT_PASSWORD, - error)) - return FALSE; - if (!_cert_verify_property(priv->phase2_ca_cert, - NM_SETTING_802_1X_PHASE2_CA_CERT, - priv->phase2_ca_cert_password, - NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, - error)) - return FALSE; - - if (!_cert_verify_property(priv->client_cert, - NM_SETTING_802_1X_CLIENT_CERT, - priv->client_cert_password, - NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, - error)) - return FALSE; - if (!_cert_verify_property(priv->phase2_client_cert, - NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - priv->phase2_client_cert_password, - NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, - error)) - return FALSE; - - if (!_cert_verify_property(priv->private_key, NM_SETTING_802_1X_PRIVATE_KEY, NULL, NULL, error)) - return FALSE; - if (!_cert_verify_property(priv->phase2_private_key, - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - NULL, - NULL, - error)) - return FALSE; - - return TRUE; -} - -/*****************************************************************************/ - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - NMSetting8021x * self = NM_SETTING_802_1X(setting); - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - GSList * iter; - GPtrArray * secrets; - gboolean eap_method_found = FALSE; - - secrets = g_ptr_array_sized_new(4); - - /* Ask each configured EAP method if it needs secrets */ - for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next(iter)) { - const char *method = (const char *) iter->data; - int i; - - for (i = 0; eap_methods_table[i].method; i++) { - if (eap_methods_table[i].ns_func == NULL) - continue; - if (!strcmp(eap_methods_table[i].method, method)) { - (*eap_methods_table[i].ns_func)(self, secrets, FALSE); - - /* Only break out of the outer loop if this EAP method - * needed secrets. - */ - if (secrets->len > 0) - eap_method_found = TRUE; - break; - } - } - } - - if (secrets->len == 0) { - g_ptr_array_free(secrets, TRUE); - return NULL; - } - - return secrets; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSetting8021x * setting = NM_SETTING_802_1X(object); - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_EAP: - g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->eap, TRUE)); - break; - case PROP_IDENTITY: - g_value_set_string(value, priv->identity); - break; - case PROP_ANONYMOUS_IDENTITY: - g_value_set_string(value, priv->anonymous_identity); - break; - case PROP_PAC_FILE: - g_value_set_string(value, priv->pac_file); - break; - case PROP_CA_CERT: - g_value_set_boxed(value, priv->ca_cert); - break; - case PROP_CA_CERT_PASSWORD: - g_value_set_string(value, priv->ca_cert_password); - break; - case PROP_CA_CERT_PASSWORD_FLAGS: - g_value_set_flags(value, priv->ca_cert_password_flags); - break; - case PROP_CA_PATH: - g_value_set_string(value, priv->ca_path); - break; - case PROP_SUBJECT_MATCH: - g_value_set_string(value, priv->subject_match); - break; - case PROP_ALTSUBJECT_MATCHES: - g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->altsubject_matches, TRUE)); - break; - case PROP_DOMAIN_SUFFIX_MATCH: - g_value_set_string(value, priv->domain_suffix_match); - break; - case PROP_DOMAIN_MATCH: - g_value_set_string(value, priv->domain_match); - break; - case PROP_CLIENT_CERT: - g_value_set_boxed(value, priv->client_cert); - break; - case PROP_CLIENT_CERT_PASSWORD: - g_value_set_string(value, priv->client_cert_password); - break; - case PROP_CLIENT_CERT_PASSWORD_FLAGS: - g_value_set_flags(value, priv->client_cert_password_flags); - break; - case PROP_PHASE1_PEAPVER: - g_value_set_string(value, priv->phase1_peapver); - break; - case PROP_PHASE1_PEAPLABEL: - g_value_set_string(value, priv->phase1_peaplabel); - break; - case PROP_PHASE1_FAST_PROVISIONING: - g_value_set_string(value, priv->phase1_fast_provisioning); - break; - case PROP_PHASE1_AUTH_FLAGS: - g_value_set_uint(value, priv->phase1_auth_flags); - break; - case PROP_PHASE2_AUTH: - g_value_set_string(value, priv->phase2_auth); - break; - case PROP_PHASE2_AUTHEAP: - g_value_set_string(value, priv->phase2_autheap); - break; - case PROP_PHASE2_CA_CERT: - g_value_set_boxed(value, priv->phase2_ca_cert); - break; - case PROP_PHASE2_CA_CERT_PASSWORD: - g_value_set_string(value, priv->phase2_ca_cert_password); - break; - case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS: - g_value_set_flags(value, priv->phase2_ca_cert_password_flags); - break; - case PROP_PHASE2_CA_PATH: - g_value_set_string(value, priv->phase2_ca_path); - break; - case PROP_PHASE2_SUBJECT_MATCH: - g_value_set_string(value, priv->phase2_subject_match); - break; - case PROP_PHASE2_ALTSUBJECT_MATCHES: - g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->phase2_altsubject_matches, TRUE)); - break; - case PROP_PHASE2_DOMAIN_SUFFIX_MATCH: - g_value_set_string(value, priv->phase2_domain_suffix_match); - break; - case PROP_PHASE2_DOMAIN_MATCH: - g_value_set_string(value, priv->phase2_domain_match); - break; - case PROP_PHASE2_CLIENT_CERT: - g_value_set_boxed(value, priv->phase2_client_cert); - break; - case PROP_PHASE2_CLIENT_CERT_PASSWORD: - g_value_set_string(value, priv->phase2_client_cert_password); - break; - case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS: - g_value_set_flags(value, priv->phase2_client_cert_password_flags); - break; - case PROP_PASSWORD: - g_value_set_string(value, priv->password); - break; - case PROP_PASSWORD_FLAGS: - g_value_set_flags(value, priv->password_flags); - break; - case PROP_PASSWORD_RAW: - g_value_set_boxed(value, priv->password_raw); - break; - case PROP_PASSWORD_RAW_FLAGS: - g_value_set_flags(value, priv->password_raw_flags); - break; - case PROP_PRIVATE_KEY: - g_value_set_boxed(value, priv->private_key); - break; - case PROP_PRIVATE_KEY_PASSWORD: - g_value_set_string(value, priv->private_key_password); - break; - case PROP_PRIVATE_KEY_PASSWORD_FLAGS: - g_value_set_flags(value, priv->private_key_password_flags); - break; - case PROP_PHASE2_PRIVATE_KEY: - g_value_set_boxed(value, priv->phase2_private_key); - break; - case PROP_PHASE2_PRIVATE_KEY_PASSWORD: - g_value_set_string(value, priv->phase2_private_key_password); - break; - case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS: - g_value_set_flags(value, priv->phase2_private_key_password_flags); - break; - case PROP_PIN: - g_value_set_string(value, priv->pin); - break; - case PROP_PIN_FLAGS: - g_value_set_flags(value, priv->pin_flags); - break; - case PROP_SYSTEM_CA_CERTS: - g_value_set_boolean(value, priv->system_ca_certs); - break; - case PROP_AUTH_TIMEOUT: - g_value_set_int(value, priv->auth_timeout); - break; - case PROP_OPTIONAL: - g_value_set_boolean(value, priv->optional); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSetting8021x * setting = NM_SETTING_802_1X(object); - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_EAP: - g_slist_free_full(priv->eap, g_free); - priv->eap = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); - break; - case PROP_IDENTITY: - g_free(priv->identity); - priv->identity = g_value_dup_string(value); - break; - case PROP_ANONYMOUS_IDENTITY: - g_free(priv->anonymous_identity); - priv->anonymous_identity = g_value_dup_string(value); - break; - case PROP_PAC_FILE: - g_free(priv->pac_file); - priv->pac_file = g_value_dup_string(value); - break; - case PROP_CA_CERT: - g_bytes_unref(priv->ca_cert); - priv->ca_cert = g_value_dup_boxed(value); - break; - case PROP_CA_CERT_PASSWORD: - g_free(priv->ca_cert_password); - priv->ca_cert_password = g_value_dup_string(value); - break; - case PROP_CA_CERT_PASSWORD_FLAGS: - priv->ca_cert_password_flags = g_value_get_flags(value); - break; - case PROP_CA_PATH: - g_free(priv->ca_path); - priv->ca_path = g_value_dup_string(value); - break; - case PROP_SUBJECT_MATCH: - g_free(priv->subject_match); - priv->subject_match = nm_strdup_not_empty(g_value_get_string(value)); - break; - case PROP_ALTSUBJECT_MATCHES: - g_slist_free_full(priv->altsubject_matches, g_free); - priv->altsubject_matches = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); - break; - case PROP_DOMAIN_SUFFIX_MATCH: - g_free(priv->domain_suffix_match); - priv->domain_suffix_match = nm_strdup_not_empty(g_value_get_string(value)); - break; - case PROP_DOMAIN_MATCH: - g_free(priv->domain_match); - priv->domain_match = nm_strdup_not_empty(g_value_get_string(value)); - break; - case PROP_CLIENT_CERT: - g_bytes_unref(priv->client_cert); - priv->client_cert = g_value_dup_boxed(value); - break; - case PROP_CLIENT_CERT_PASSWORD: - g_free(priv->client_cert_password); - priv->client_cert_password = g_value_dup_string(value); - break; - case PROP_CLIENT_CERT_PASSWORD_FLAGS: - priv->client_cert_password_flags = g_value_get_flags(value); - break; - case PROP_PHASE1_PEAPVER: - g_free(priv->phase1_peapver); - priv->phase1_peapver = g_value_dup_string(value); - break; - case PROP_PHASE1_PEAPLABEL: - g_free(priv->phase1_peaplabel); - priv->phase1_peaplabel = g_value_dup_string(value); - break; - case PROP_PHASE1_FAST_PROVISIONING: - g_free(priv->phase1_fast_provisioning); - priv->phase1_fast_provisioning = g_value_dup_string(value); - break; - case PROP_PHASE1_AUTH_FLAGS: - priv->phase1_auth_flags = g_value_get_uint(value); - break; - case PROP_PHASE2_AUTH: - g_free(priv->phase2_auth); - priv->phase2_auth = g_value_dup_string(value); - break; - case PROP_PHASE2_AUTHEAP: - g_free(priv->phase2_autheap); - priv->phase2_autheap = g_value_dup_string(value); - break; - case PROP_PHASE2_CA_CERT: - g_bytes_unref(priv->phase2_ca_cert); - priv->phase2_ca_cert = g_value_dup_boxed(value); - break; - case PROP_PHASE2_CA_CERT_PASSWORD: - g_free(priv->phase2_ca_cert_password); - priv->phase2_ca_cert_password = g_value_dup_string(value); - break; - case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS: - priv->phase2_ca_cert_password_flags = g_value_get_flags(value); - break; - case PROP_PHASE2_CA_PATH: - g_free(priv->phase2_ca_path); - priv->phase2_ca_path = g_value_dup_string(value); - break; - case PROP_PHASE2_SUBJECT_MATCH: - g_free(priv->phase2_subject_match); - priv->phase2_subject_match = nm_strdup_not_empty(g_value_get_string(value)); - break; - case PROP_PHASE2_ALTSUBJECT_MATCHES: - g_slist_free_full(priv->phase2_altsubject_matches, g_free); - priv->phase2_altsubject_matches = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); - break; - case PROP_PHASE2_DOMAIN_SUFFIX_MATCH: - g_free(priv->phase2_domain_suffix_match); - priv->phase2_domain_suffix_match = nm_strdup_not_empty(g_value_get_string(value)); - break; - case PROP_PHASE2_DOMAIN_MATCH: - g_free(priv->phase2_domain_match); - priv->phase2_domain_match = nm_strdup_not_empty(g_value_get_string(value)); - break; - case PROP_PHASE2_CLIENT_CERT: - g_bytes_unref(priv->phase2_client_cert); - priv->phase2_client_cert = g_value_dup_boxed(value); - break; - case PROP_PHASE2_CLIENT_CERT_PASSWORD: - g_free(priv->phase2_client_cert_password); - priv->phase2_client_cert_password = g_value_dup_string(value); - break; - case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS: - priv->phase2_client_cert_password_flags = g_value_get_flags(value); - break; - case PROP_PASSWORD: - g_free(priv->password); - priv->password = g_value_dup_string(value); - break; - case PROP_PASSWORD_FLAGS: - priv->password_flags = g_value_get_flags(value); - break; - case PROP_PASSWORD_RAW: - g_bytes_unref(priv->password_raw); - priv->password_raw = g_value_dup_boxed(value); - break; - case PROP_PASSWORD_RAW_FLAGS: - priv->password_raw_flags = g_value_get_flags(value); - break; - case PROP_PRIVATE_KEY: - g_bytes_unref(priv->private_key); - priv->private_key = g_value_dup_boxed(value); - break; - case PROP_PRIVATE_KEY_PASSWORD: - nm_free_secret(priv->private_key_password); - priv->private_key_password = g_value_dup_string(value); - break; - case PROP_PRIVATE_KEY_PASSWORD_FLAGS: - priv->private_key_password_flags = g_value_get_flags(value); - break; - case PROP_PHASE2_PRIVATE_KEY: - g_bytes_unref(priv->phase2_private_key); - priv->phase2_private_key = g_value_dup_boxed(value); - break; - case PROP_PHASE2_PRIVATE_KEY_PASSWORD: - nm_free_secret(priv->phase2_private_key_password); - priv->phase2_private_key_password = g_value_dup_string(value); - break; - case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS: - priv->phase2_private_key_password_flags = g_value_get_flags(value); - break; - case PROP_PIN: - g_free(priv->pin); - priv->pin = g_value_dup_string(value); - break; - case PROP_PIN_FLAGS: - priv->pin_flags = g_value_get_flags(value); - break; - case PROP_SYSTEM_CA_CERTS: - priv->system_ca_certs = g_value_get_boolean(value); - break; - case PROP_AUTH_TIMEOUT: - priv->auth_timeout = g_value_get_int(value); - break; - case PROP_OPTIONAL: - priv->optional = g_value_get_boolean(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_802_1x_init(NMSetting8021x *setting) -{} - -/** - * nm_setting_802_1x_new: - * - * Creates a new #NMSetting8021x object with default values. - * - * Returns: the new empty #NMSetting8021x object - **/ -NMSetting * -nm_setting_802_1x_new(void) -{ - return g_object_new(NM_TYPE_SETTING_802_1X, NULL); -} - -static void -finalize(GObject *object) -{ - NMSetting8021x * self = NM_SETTING_802_1X(object); - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - - g_free(priv->identity); - g_free(priv->anonymous_identity); - g_free(priv->ca_path); - g_free(priv->subject_match); - g_free(priv->domain_suffix_match); - g_free(priv->phase1_peapver); - g_free(priv->phase1_peaplabel); - g_free(priv->phase1_fast_provisioning); - g_free(priv->phase2_auth); - g_free(priv->phase2_autheap); - g_free(priv->phase2_ca_path); - g_free(priv->phase2_subject_match); - g_free(priv->phase2_domain_suffix_match); - g_free(priv->password); - g_bytes_unref(priv->password_raw); - g_free(priv->pin); - - g_slist_free_full(priv->eap, g_free); - g_slist_free_full(priv->altsubject_matches, g_free); - g_slist_free_full(priv->phase2_altsubject_matches, g_free); - - g_bytes_unref(priv->ca_cert); - g_free(priv->ca_cert_password); - g_bytes_unref(priv->client_cert); - g_free(priv->client_cert_password); - g_bytes_unref(priv->private_key); - nm_free_secret(priv->private_key_password); - g_bytes_unref(priv->phase2_ca_cert); - g_free(priv->phase2_ca_cert_password); - g_bytes_unref(priv->phase2_client_cert); - g_free(priv->phase2_client_cert_password); - g_bytes_unref(priv->phase2_private_key); - nm_free_secret(priv->phase2_private_key_password); - - G_OBJECT_CLASS(nm_setting_802_1x_parent_class)->finalize(object); -} - -static void -nm_setting_802_1x_class_init(NMSetting8021xClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSetting8021xPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->need_secrets = need_secrets; - - /** - * NMSetting8021x:eap: - * - * The allowed EAP method to be used when authenticating to the network with - * 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd", - * and "fast". Each method requires different configuration using the - * properties of this setting; refer to wpa_supplicant documentation for the - * allowed combinations. - **/ - /* ---ifcfg-rh--- - * property: eap - * variable: IEEE_8021X_EAP_METHODS(+) - * values: "LEAP", "PWD", "TLS", "PEAP", "TTLS", "FAST" - * description: EAP method for 802.1X authentication. - * example: IEEE_8021X_EAP_METHODS=PEAP - * ---end--- - */ - obj_properties[PROP_EAP] = g_param_spec_boxed(NM_SETTING_802_1X_EAP, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:identity: - * - * Identity string for EAP authentication methods. Often the user's user or - * login name. - **/ - /* ---ifcfg-rh--- - * property: identity - * variable: IEEE_8021X_IDENTITY(+) - * description: Identity for EAP authentication methods. - * example: IEEE_8021X_IDENTITY=itsme - * ---end--- - */ - obj_properties[PROP_IDENTITY] = g_param_spec_string(NM_SETTING_802_1X_IDENTITY, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:anonymous-identity: - * - * Anonymous identity string for EAP authentication methods. Used as the - * unencrypted identity with EAP types that support different tunneled - * identity like EAP-TTLS. - **/ - /* ---ifcfg-rh--- - * property: anonymous-identity - * variable: IEEE_8021X_ANON_IDENTITY(+) - * description: Anonymous identity for EAP authentication methods. - * ---end--- - */ - obj_properties[PROP_ANONYMOUS_IDENTITY] = - g_param_spec_string(NM_SETTING_802_1X_ANONYMOUS_IDENTITY, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:pac-file: - * - * UTF-8 encoded file path containing PAC for EAP-FAST. - **/ - /* ---ifcfg-rh--- - * property: pac-file - * variable: IEEE_8021X_PAC_FILE(+) - * description: File with PAC (Protected Access Credential) for EAP-FAST. - * example: IEEE_8021X_PAC_FILE=/home/joe/my-fast.pac - * ---end--- - */ - obj_properties[PROP_PAC_FILE] = g_param_spec_string(NM_SETTING_802_1X_PAC_FILE, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:ca-cert: - * - * Contains the CA certificate if used by the EAP method specified in the - * #NMSetting8021x:eap property. - * - * Certificate data is specified using a "scheme"; three are currently - * supported: blob, path and pkcs#11 URL. When using the blob scheme this property - * should be set to the certificate's DER encoded data. When using the path - * scheme, this property should be set to the full UTF-8 encoded path of the - * certificate, prefixed with the string "file://" and ending with a terminating - * NUL byte. - * This property can be unset even if the EAP method supports CA certificates, - * but this allows man-in-the-middle attacks and is NOT recommended. - * - * Note that enabling NMSetting8021x:system-ca-certs will override this - * setting to use the built-in path, if the built-in path is not a directory. - * - * Setting this property directly is discouraged; use the - * nm_setting_802_1x_set_ca_cert() function instead. - **/ - /* ---ifcfg-rh--- - * property: ca-cert - * variable: IEEE_8021X_CA_CERT(+) - * description: CA certificate for EAP. - * example: IEEE_8021X_CA_CERT=/home/joe/cacert.crt - * ---end--- - */ - obj_properties[PROP_CA_CERT] = g_param_spec_boxed(NM_SETTING_802_1X_CA_CERT, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:ca-cert-password: - * - * The password used to access the CA certificate stored in - * #NMSetting8021x:ca-cert property. Only makes sense if the certificate - * is stored on a PKCS#11 token that requires a login. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * ---end--- - */ - obj_properties[PROP_CA_CERT_PASSWORD] = - g_param_spec_string(NM_SETTING_802_1X_CA_CERT_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:ca-cert-password-flags: - * - * Flags indicating how to handle the #NMSetting8021x:ca-cert-password property. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * ---end--- - */ - obj_properties[PROP_CA_CERT_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:ca-path: - * - * UTF-8 encoded path to a directory containing PEM or DER formatted - * certificates to be added to the verification chain in addition to the - * certificate specified in the #NMSetting8021x:ca-cert property. - * - * If NMSetting8021x:system-ca-certs is enabled and the built-in CA - * path is an existing directory, then this setting is ignored. - **/ - /* ---ifcfg-rh--- - * property: ca-path - * variable: IEEE_8021X_CA_PATH(+) - * description: The search path for the certificate. - * ---end--- - */ - obj_properties[PROP_CA_PATH] = g_param_spec_string(NM_SETTING_802_1X_CA_PATH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:subject-match: - * - * Substring to be matched against the subject of the certificate presented - * by the authentication server. When unset, no verification of the - * authentication server certificate's subject is performed. This property - * provides little security, if any, and its use is deprecated in favor of - * NMSetting8021x:domain-suffix-match. - **/ - /* ---ifcfg-rh--- - * property: subject-match - * variable: IEEE_8021X_SUBJECT_MATCH(+) - * description: Substring to match subject of server certificate against. - * example: IEEE_8021X_SUBJECT_MATCH="Red Hat" - * ---end--- - */ - obj_properties[PROP_SUBJECT_MATCH] = - g_param_spec_string(NM_SETTING_802_1X_SUBJECT_MATCH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:altsubject-matches: - * - * List of strings to be matched against the altSubjectName of the - * certificate presented by the authentication server. If the list is empty, - * no verification of the server certificate's altSubjectName is performed. - **/ - /* ---ifcfg-rh--- - * property: altsubject-matches - * variable: IEEE_8021X_ALTSUBJECT_MATCHES(+) - * description: List of strings to be matched against the altSubjectName. - * example: IEEE_8021X_ALTSUBJECT_MATCHES="s1.domain.cc" - * ---end--- - */ - obj_properties[PROP_ALTSUBJECT_MATCHES] = - g_param_spec_boxed(NM_SETTING_802_1X_ALTSUBJECT_MATCHES, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:domain-suffix-match: - * - * Constraint for server domain name. If set, this FQDN is used as a suffix - * match requirement for dNSName element(s) of the certificate presented by - * the authentication server. If a matching dNSName is found, this - * constraint is met. If no dNSName values are present, this constraint is - * matched against SubjectName CN using same suffix match comparison. - * Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited - * list. - * - * Since: 1.2 - **/ - /* ---ifcfg-rh--- - * property: domain-suffix-match - * description: Suffix to match domain of server certificate against. - * variable: IEEE_8021X_DOMAIN_SUFFIX_MATCH(+) - * ---end--- - */ - obj_properties[PROP_DOMAIN_SUFFIX_MATCH] = - g_param_spec_string(NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:domain-match: - * - * Constraint for server domain name. If set, this list of FQDNs is used as - * a match requirement for dNSName element(s) of the certificate presented - * by the authentication server. If a matching dNSName is found, this - * constraint is met. If no dNSName values are present, this constraint is - * matched against SubjectName CN using the same comparison. - * Multiple valid FQDNs can be passed as a ";" delimited list. - * - * Since: 1.24 - **/ - /* ---ifcfg-rh--- - * property: domain-match - * description: Value to match domain of server certificate against. - * variable: IEEE_8021X_DOMAIN_MATCH(+) - * ---end--- - */ - obj_properties[PROP_DOMAIN_MATCH] = - g_param_spec_string(NM_SETTING_802_1X_DOMAIN_MATCH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:client-cert: - * - * Contains the client certificate if used by the EAP method specified in - * the #NMSetting8021x:eap property. - * - * Certificate data is specified using a "scheme"; two are currently - * supported: blob and path. When using the blob scheme (which is backwards - * compatible with NM 0.7.x) this property should be set to the - * certificate's DER encoded data. When using the path scheme, this property - * should be set to the full UTF-8 encoded path of the certificate, prefixed - * with the string "file://" and ending with a terminating NUL byte. - * - * Setting this property directly is discouraged; use the - * nm_setting_802_1x_set_client_cert() function instead. - **/ - /* ---ifcfg-rh--- - * property: client-cert - * variable: IEEE_8021X_CLIENT_CERT(+) - * description: Client certificate for EAP. - * example: IEEE_8021X_CLIENT_CERT=/home/joe/mycert.crt - * ---end--- - */ - obj_properties[PROP_CLIENT_CERT] = - g_param_spec_boxed(NM_SETTING_802_1X_CLIENT_CERT, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:client-cert-password: - * - * The password used to access the client certificate stored in - * #NMSetting8021x:client-cert property. Only makes sense if the certificate - * is stored on a PKCS#11 token that requires a login. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * ---end--- - */ - obj_properties[PROP_CLIENT_CERT_PASSWORD] = - g_param_spec_string(NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:client-cert-password-flags: - * - * Flags indicating how to handle the #NMSetting8021x:client-cert-password property. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * ---end--- - */ - obj_properties[PROP_CLIENT_CERT_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase1-peapver: - * - * Forces which PEAP version is used when PEAP is set as the EAP method in - * the #NMSetting8021x:eap property. When unset, the version reported by - * the server will be used. Sometimes when using older RADIUS servers, it - * is necessary to force the client to use a particular PEAP version. To do - * so, this property may be set to "0" or "1" to force that specific PEAP - * version. - **/ - /* ---ifcfg-rh--- - * property: phase1-peapver - * variable: IEEE_8021X_PEAP_VERSION(+) - * values: 0, 1 - * description: Use to force a specific PEAP version. - * ---end--- - */ - obj_properties[PROP_PHASE1_PEAPVER] = - g_param_spec_string(NM_SETTING_802_1X_PHASE1_PEAPVER, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase1-peaplabel: - * - * Forces use of the new PEAP label during key derivation. Some RADIUS - * servers may require forcing the new PEAP label to interoperate with - * PEAPv1. Set to "1" to force use of the new PEAP label. See the - * wpa_supplicant documentation for more details. - **/ - /* ---ifcfg-rh--- - * property: phase1-peaplabel - * variable: IEEE_8021X_PEAP_FORCE_NEW_LABEL(+) - * values: yes, no - * default: no - * description: Use to force the new PEAP label during key derivation. - * ---end--- - */ - obj_properties[PROP_PHASE1_PEAPLABEL] = - g_param_spec_string(NM_SETTING_802_1X_PHASE1_PEAPLABEL, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase1-fast-provisioning: - * - * Enables or disables in-line provisioning of EAP-FAST credentials when - * FAST is specified as the EAP method in the #NMSetting8021x:eap property. - * Recognized values are "0" (disabled), "1" (allow unauthenticated - * provisioning), "2" (allow authenticated provisioning), and "3" (allow - * both authenticated and unauthenticated provisioning). See the - * wpa_supplicant documentation for more details. - **/ - /* ---ifcfg-rh--- - * property: phase1-fast-provisioning - * variable: IEEE_8021X_FAST_PROVISIONING(+) - * values: space-separated list of these values [allow-auth, allow-unauth] - * description: Enable in-line provisioning of EAP-FAST credentials. - * example: IEEE_8021X_FAST_PROVISIONING="allow-auth allow-unauth" - * ---end--- - */ - obj_properties[PROP_PHASE1_FAST_PROVISIONING] = - g_param_spec_string(NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase1-auth-flags: - * - * Specifies authentication flags to use in "phase 1" outer - * authentication using #NMSetting8021xAuthFlags options. - * The individual TLS versions can be explicitly disabled. If a certain - * TLS disable flag is not set, it is up to the supplicant to allow - * or forbid it. The TLS options map to tls_disable_tlsv1_x settings. - * See the wpa_supplicant documentation for more details. - * - * Since: 1.8 - */ - /* ---ifcfg-rh--- - * property: phase1-auth-flags - * variable: IEEE_8021X_PHASE1_AUTH_FLAGS(+) - * values: space-separated list of authentication flags names - * description: Authentication flags for the supplicant - * example: IEEE_8021X_PHASE1_AUTH_FLAGS="tls-1-0-disable tls-1-1-disable" - * ---end--- - */ - obj_properties[PROP_PHASE1_AUTH_FLAGS] = - g_param_spec_uint(NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, - "", - "", - 0, - G_MAXUINT32, - NM_SETTING_802_1X_AUTH_FLAGS_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-auth: - * - * Specifies the allowed "phase 2" inner authentication method when an EAP - * method that uses an inner TLS tunnel is specified in the #NMSetting8021x:eap - * property. For TTLS this property selects one of the supported non-EAP - * inner methods: "pap", "chap", "mschap", "mschapv2" while - * #NMSetting8021x:phase2-autheap selects an EAP inner method. For PEAP - * this selects an inner EAP method, one of: "gtc", "otp", "md5" and "tls". - * Each "phase 2" inner method requires specific parameters for successful - * authentication; see the wpa_supplicant documentation for more details. - * Both #NMSetting8021x:phase2-auth and #NMSetting8021x:phase2-autheap cannot - * be specified. - **/ - /* ---ifcfg-rh--- - * property: phase2-auth - * variable: IEEE_8021X_INNER_AUTH_METHODS(+) - * values: "PAP", "CHAP", "MSCHAP", "MSCHAPV2", "GTC", "OTP", "MD5" and "TLS" - * description: Inner non-EAP authentication methods for TTLS or the inner EAP - * authentication method for PEAP. IEEE_8021X_INNER_AUTH_METHODS can contain - * values both for 'phase2-auth' and 'phase2-autheap' properties. - * example: IEEE_8021X_INNER_AUTH_METHODS=PAP - * ---end--- - */ - obj_properties[PROP_PHASE2_AUTH] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_AUTH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-autheap: - * - * Specifies the allowed "phase 2" inner EAP-based authentication method - * when TTLS is specified in the #NMSetting8021x:eap property. Recognized - * EAP-based "phase 2" methods are "md5", "mschapv2", "otp", "gtc", and - * "tls". Each "phase 2" inner method requires specific parameters for - * successful authentication; see the wpa_supplicant documentation for - * more details. - **/ - /* ---ifcfg-rh--- - * property: phase2-autheap - * variable: IEEE_8021X_INNER_AUTH_METHODS(+) - * values: "EAP-MD5", "EAP-MSCHAPV2", "EAP-GTC", "EAP-OTP" and "EAP-TLS" - * description: Inner EAP-based authentication methods. Note that - * IEEE_8021X_INNER_AUTH_METHODS is also used for 'phase2-auth' values. - * example: IEEE_8021X_INNER_AUTH_METHODS="MSCHAPV2 EAP-TLS" - * ---end--- - */ - obj_properties[PROP_PHASE2_AUTHEAP] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_AUTHEAP, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-ca-cert: - * - * Contains the "phase 2" CA certificate if used by the EAP method specified - * in the #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap - * properties. - * - * Certificate data is specified using a "scheme"; three are currently - * supported: blob, path and pkcs#11 URL. When using the blob scheme this property - * should be set to the certificate's DER encoded data. When using the path - * scheme, this property should be set to the full UTF-8 encoded path of the - * certificate, prefixed with the string "file://" and ending with a terminating - * NUL byte. - * This property can be unset even if the EAP method supports CA certificates, - * but this allows man-in-the-middle attacks and is NOT recommended. - * - * Note that enabling NMSetting8021x:system-ca-certs will override this - * setting to use the built-in path, if the built-in path is not a directory. - * - * Setting this property directly is discouraged; use the - * nm_setting_802_1x_set_phase2_ca_cert() function instead. - **/ - obj_properties[PROP_PHASE2_CA_CERT] = - g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_CA_CERT, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-ca-cert-password: - * - * The password used to access the "phase2" CA certificate stored in - * #NMSetting8021x:phase2-ca-cert property. Only makes sense if the certificate - * is stored on a PKCS#11 token that requires a login. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * ---end--- - */ - obj_properties[PROP_PHASE2_CA_CERT_PASSWORD] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-ca-cert-password-flags: - * - * Flags indicating how to handle the #NMSetting8021x:phase2-ca-cert-password property. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * ---end--- - */ - obj_properties[PROP_PHASE2_CA_CERT_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-ca-path: - * - * UTF-8 encoded path to a directory containing PEM or DER formatted - * certificates to be added to the verification chain in addition to the - * certificate specified in the #NMSetting8021x:phase2-ca-cert property. - * - * If NMSetting8021x:system-ca-certs is enabled and the built-in CA - * path is an existing directory, then this setting is ignored. - **/ - /* ---ifcfg-rh--- - * property: phase2-ca-path - * variable: IEEE_8021X_PHASE2_CA_PATH(+) - * description: The search path for the certificate. - * ---end--- - */ - obj_properties[PROP_PHASE2_CA_PATH] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_CA_PATH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-subject-match: - * - * Substring to be matched against the subject of the certificate presented - * by the authentication server during the inner "phase 2" - * authentication. When unset, no verification of the authentication server - * certificate's subject is performed. This property provides little security, - * if any, and its use is deprecated in favor of - * NMSetting8021x:phase2-domain-suffix-match. - **/ - /* ---ifcfg-rh--- - * property: phase2-subject-match - * variable: IEEE_8021X_PHASE2_SUBJECT_MATCH(+) - * description: Substring to match subject of server certificate against. - * example: IEEE_8021X_PHASE2_SUBJECT_MATCH="Red Hat" - * ---end--- - */ - obj_properties[PROP_PHASE2_SUBJECT_MATCH] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-altsubject-matches: - * - * List of strings to be matched against the altSubjectName of the - * certificate presented by the authentication server during the inner - * "phase 2" authentication. If the list is empty, no verification of the - * server certificate's altSubjectName is performed. - **/ - /* ---ifcfg-rh--- - * property: phase2-altsubject-matches - * variable: IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES(+) - * ---end--- - */ - obj_properties[PROP_PHASE2_ALTSUBJECT_MATCHES] = - g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-domain-suffix-match: - * - * Constraint for server domain name. If set, this FQDN is used as a suffix - * match requirement for dNSName element(s) of the certificate presented by - * the authentication server during the inner "phase 2" authentication. If - * a matching dNSName is found, this constraint is met. If no dNSName - * values are present, this constraint is matched against SubjectName CN - * using same suffix match comparison. - * Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited - * list. - * - * Since: 1.2 - **/ - /* ---ifcfg-rh--- - * property: phase2-domain-suffix-match - * description: Suffix to match domain of server certificate for phase 2 against. - * variable: IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH(+) - * ---end--- - */ - obj_properties[PROP_PHASE2_DOMAIN_SUFFIX_MATCH] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-domain-match: - * - * Constraint for server domain name. If set, this list of FQDNs is used as - * a match requirement for dNSName element(s) of the certificate presented - * by the authentication server during the inner "phase 2" authentication. - * If a matching dNSName is found, this constraint is met. If no dNSName - * values are present, this constraint is matched against SubjectName CN - * using the same comparison. - * Multiple valid FQDNs can be passed as a ";" delimited list. - * - * Since: 1.24 - **/ - /* ---ifcfg-rh--- - * property: phase2-domain-match - * description: Value to match domain of server certificate for phase 2 against. - * variable: IEEE_8021X_PHASE2_DOMAIN_MATCH(+) - * ---end--- - */ - obj_properties[PROP_PHASE2_DOMAIN_MATCH] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-client-cert: - * - * Contains the "phase 2" client certificate if used by the EAP method - * specified in the #NMSetting8021x:phase2-auth or - * #NMSetting8021x:phase2-autheap properties. - * - * Certificate data is specified using a "scheme"; two are currently - * supported: blob and path. When using the blob scheme (which is backwards - * compatible with NM 0.7.x) this property should be set to the - * certificate's DER encoded data. When using the path scheme, this property - * should be set to the full UTF-8 encoded path of the certificate, prefixed - * with the string "file://" and ending with a terminating NUL byte. This - * property can be unset even if the EAP method supports CA certificates, - * but this allows man-in-the-middle attacks and is NOT recommended. - * - * Setting this property directly is discouraged; use the - * nm_setting_802_1x_set_phase2_client_cert() function instead. - **/ - /* ---ifcfg-rh--- - * property: phase2-client-cert - * variable: IEEE_8021X_INNER_CLIENT_CERT(+) - * description: Client certificate for inner EAP method. - * example: IEEE_8021X_INNER_CLIENT_CERT=/home/joe/mycert.crt - * ---end--- - */ - obj_properties[PROP_PHASE2_CLIENT_CERT] = - g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-client-cert-password: - * - * The password used to access the "phase2" client certificate stored in - * #NMSetting8021x:phase2-client-cert property. Only makes sense if the certificate - * is stored on a PKCS#11 token that requires a login. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * ---end--- - */ - obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-client-cert-password-flags: - * - * Flags indicating how to handle the #NMSetting8021x:phase2-client-cert-password property. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * ---end--- - */ - obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:password: - * - * UTF-8 encoded password used for EAP authentication methods. If both the - * #NMSetting8021x:password property and the #NMSetting8021x:password-raw - * property are specified, #NMSetting8021x:password is preferred. - **/ - /* ---ifcfg-rh--- - * property: password - * variable: IEEE_8021X_PASSWORD(+) - * description: UTF-8 encoded password used for EAP. It can also go to "key-" - * lookaside file, or it can be owned by a secret agent. - * ---end--- - */ - obj_properties[PROP_PASSWORD] = - g_param_spec_string(NM_SETTING_802_1X_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:password-flags: - * - * Flags indicating how to handle the #NMSetting8021x:password property. - **/ - /* ---ifcfg-rh--- - * property: password-flags - * variable: IEEE_8021X_PASSWORD_FLAGS(+) - * format: NMSettingSecretFlags - * description: Password flags for IEEE_8021X_PASSWORD password. - * ---end--- - */ - obj_properties[PROP_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_802_1X_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:password-raw: - * - * Password used for EAP authentication methods, given as a byte array to - * allow passwords in other encodings than UTF-8 to be used. If both the - * #NMSetting8021x:password property and the #NMSetting8021x:password-raw - * property are specified, #NMSetting8021x:password is preferred. - **/ - /* ---ifcfg-rh--- - * property: password-raw - * variable: IEEE_8021X_PASSWORD_RAW(+) - * description: password used for EAP, encoded as a hexadecimal string. It - * can also go to "key-" lookaside file. - * example: IEEE_8021X_PASSWORD_RAW=041c8320083aa4bf - * ---end--- - */ - obj_properties[PROP_PASSWORD_RAW] = - g_param_spec_boxed(NM_SETTING_802_1X_PASSWORD_RAW, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:password-raw-flags: - * - * Flags indicating how to handle the #NMSetting8021x:password-raw property. - **/ - /* ---ifcfg-rh--- - * property: password-raw-flags - * variable: IEEE_8021X_PASSWORD_RAW_FLAGS(+) - * description: The secret flags for password-raw. - * ---end--- - */ - obj_properties[PROP_PASSWORD_RAW_FLAGS] = - g_param_spec_flags(NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:private-key: - * - * Contains the private key when the #NMSetting8021x:eap property is set to - * "tls". - * - * Key data is specified using a "scheme"; two are currently supported: blob - * and path. When using the blob scheme and private keys, this property - * should be set to the key's encrypted PEM encoded data. When using private - * keys with the path scheme, this property should be set to the full UTF-8 - * encoded path of the key, prefixed with the string "file://" and ending - * with a terminating NUL byte. When using PKCS#12 format private - * keys and the blob scheme, this property should be set to the - * PKCS#12 data and the #NMSetting8021x:private-key-password - * property must be set to password used to decrypt the PKCS#12 - * certificate and key. When using PKCS#12 files and the path - * scheme, this property should be set to the full UTF-8 encoded path of the - * key, prefixed with the string "file://" and ending with a terminating - * NUL byte, and as with the blob scheme the "private-key-password" property - * must be set to the password used to decode the PKCS#12 private - * key and certificate. - * - * Setting this property directly is discouraged; use the - * nm_setting_802_1x_set_private_key() function instead. - * - * WARNING: #NMSetting8021x:private-key is not a "secret" property, and thus - * unencrypted private key data using the BLOB scheme may be readable by - * unprivileged users. Private keys should always be encrypted with a - * private key password to prevent unauthorized access to unencrypted - * private key data. - **/ - /* ---ifcfg-rh--- - * property: private-key - * variable: IEEE_8021X_PRIVATE_KEY(+) - * description: Private key for EAP-TLS. - * example: IEEE_8021X_PRIVATE_KEY=/home/joe/mykey.p12 - * ---end--- - */ - obj_properties[PROP_PRIVATE_KEY] = - g_param_spec_boxed(NM_SETTING_802_1X_PRIVATE_KEY, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:private-key-password: - * - * The password used to decrypt the private key specified in the - * #NMSetting8021x:private-key property when the private key either uses the - * path scheme, or if the private key is a PKCS#12 format key. Setting this - * property directly is not generally necessary except when returning - * secrets to NetworkManager; it is generally set automatically when setting - * the private key by the nm_setting_802_1x_set_private_key() function. - **/ - /* ---ifcfg-rh--- - * property: private-key-password - * variable: IEEE_8021X_PRIVATE_KEY_PASSWORD(+) - * description: Password for IEEE_8021X_PRIVATE_KEY. It can also go to "key-" - * lookaside file, or it can be owned by a secret agent. - * ---end--- - */ - obj_properties[PROP_PRIVATE_KEY_PASSWORD] = - g_param_spec_string(NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:private-key-password-flags: - * - * Flags indicating how to handle the #NMSetting8021x:private-key-password - * property. - **/ - /* ---ifcfg-rh--- - * property: private-key-password-flags - * variable: IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS(+) - * format: NMSettingSecretFlags - * description: Password flags for IEEE_8021X_PRIVATE_KEY_PASSWORD password. - * ---end--- - */ - obj_properties[PROP_PRIVATE_KEY_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-private-key: - * - * Contains the "phase 2" inner private key when the - * #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap property is - * set to "tls". - * - * Key data is specified using a "scheme"; two are currently supported: blob - * and path. When using the blob scheme and private keys, this property - * should be set to the key's encrypted PEM encoded data. When using private - * keys with the path scheme, this property should be set to the full UTF-8 - * encoded path of the key, prefixed with the string "file://" and ending - * with a terminating NUL byte. When using PKCS#12 format private - * keys and the blob scheme, this property should be set to the - * PKCS#12 data and the #NMSetting8021x:phase2-private-key-password - * property must be set to password used to decrypt the PKCS#12 - * certificate and key. When using PKCS#12 files and the path - * scheme, this property should be set to the full UTF-8 encoded path of the - * key, prefixed with the string "file://" and ending with a terminating - * NUL byte, and as with the blob scheme the - * #NMSetting8021x:phase2-private-key-password property must be set to the - * password used to decode the PKCS#12 private key and certificate. - * - * Setting this property directly is discouraged; use the - * nm_setting_802_1x_set_phase2_private_key() function instead. - **/ - /* ---ifcfg-rh--- - * property: phase2-private-key - * variable: IEEE_8021X_INNER_PRIVATE_KEY(+) - * description: Private key for inner authentication method for EAP-TLS. - * ---end--- - */ - obj_properties[PROP_PHASE2_PRIVATE_KEY] = - g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-private-key-password: - * - * The password used to decrypt the "phase 2" private key specified in the - * #NMSetting8021x:phase2-private-key property when the private key either - * uses the path scheme, or is a PKCS#12 format key. Setting this - * property directly is not generally necessary except when returning - * secrets to NetworkManager; it is generally set automatically when setting - * the private key by the nm_setting_802_1x_set_phase2_private_key() - * function. - **/ - /* ---ifcfg-rh--- - * property: phase2-private-key-password - * variable: IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD(+) - * description: Password for IEEE_8021X_INNER_PRIVATE_KEY. It can also go to "key-" - * lookaside file, or it can be owned by a secret agent. - * ---end--- - */ - obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD] = - g_param_spec_string(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:phase2-private-key-password-flags: - * - * Flags indicating how to handle the - * #NMSetting8021x:phase2-private-key-password property. - **/ - /* ---ifcfg-rh--- - * property: phase2-private-key-password-flags - * variable: IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS(+) - * format: NMSettingSecretFlags - * description: Password flags for IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD password. - * ---end--- - */ - obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:pin: - * - * PIN used for EAP authentication methods. - **/ - /* ---ifcfg-rh--- - * property: pin - * variable: IEEE_8021X_PIN(+) - * description: The pin secret used for EAP authentication methods. - * ---end--- - */ - obj_properties[PROP_PIN] = - g_param_spec_string(NM_SETTING_802_1X_PIN, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:pin-flags: - * - * Flags indicating how to handle the #NMSetting8021x:pin property. - **/ - /* ---ifcfg-rh--- - * property: pin-flags - * variable: IEEE_8021X_PIN_FLAGS(+) - * description: The secret flags for the pin property. - * ---end--- - */ - obj_properties[PROP_PIN_FLAGS] = g_param_spec_flags(NM_SETTING_802_1X_PIN_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:system-ca-certs: - * - * When %TRUE, overrides the #NMSetting8021x:ca-path and - * #NMSetting8021x:phase2-ca-path properties using the system CA directory - * specified at configure time with the --system-ca-path switch. The - * certificates in this directory are added to the verification chain in - * addition to any certificates specified by the #NMSetting8021x:ca-cert and - * #NMSetting8021x:phase2-ca-cert properties. If the path provided with - * --system-ca-path is rather a file name (bundle of trusted CA certificates), - * it overrides #NMSetting8021x:ca-cert and #NMSetting8021x:phase2-ca-cert - * properties instead (sets ca_cert/ca_cert2 options for wpa_supplicant). - **/ - /* ---ifcfg-rh--- - * property: system-ca-certs - * variable: IEEE_8021X_SYSTEM_CA_CERTS(+) - * description: a boolean value. - * ---end--- - */ - obj_properties[PROP_SYSTEM_CA_CERTS] = - g_param_spec_boolean(NM_SETTING_802_1X_SYSTEM_CA_CERTS, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:auth-timeout: - * - * A timeout for the authentication. Zero means the global default; if the - * global default is not set, the authentication timeout is 25 seconds. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * property: auth-timeout - * variable: IEEE_8021X_AUTH_TIMEOUT(+) - * default: 0 - * description: Timeout in seconds for the 802.1X authentication. Zero means the global default or 25. - * ---end--- - */ - obj_properties[PROP_AUTH_TIMEOUT] = g_param_spec_int( - NM_SETTING_802_1X_AUTH_TIMEOUT, - "", - "", - 0, - G_MAXINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSetting8021x:optional: - * - * Whether the 802.1X authentication is optional. If %TRUE, the activation - * will continue even after a timeout or an authentication failure. Setting - * the property to %TRUE is currently allowed only for Ethernet connections. - * If set to %FALSE, the activation can continue only after a successful - * authentication. - * - * Since: 1.22 - **/ - /* ---ifcfg-rh--- - * property: optional - * variable: IEEE_8021X_OPTIONAL(+) - * default=no - * description: whether the 802.1X authentication is optional - * ---end--- - */ - obj_properties[PROP_OPTIONAL] = - g_param_spec_boolean(NM_SETTING_802_1X_OPTIONAL, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_802_1X); -} diff --git a/libnm-core/nm-setting-8021x.h b/libnm-core/nm-setting-8021x.h deleted file mode 100644 index 30b725be59..0000000000 --- a/libnm-core/nm-setting-8021x.h +++ /dev/null @@ -1,366 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_8021X_H__ -#define __NM_SETTING_8021X_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH "file://" -#define NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11 "pkcs11:" - -/** - * NMSetting8021xCKFormat: - * @NM_SETTING_802_1X_CK_FORMAT_UNKNOWN: unknown file format - * @NM_SETTING_802_1X_CK_FORMAT_X509: file contains an X.509 format certificate - * @NM_SETTING_802_1X_CK_FORMAT_RAW_KEY: file contains an old-style OpenSSL PEM - * or DER private key - * @NM_SETTING_802_1X_CK_FORMAT_PKCS12: file contains a PKCS#12 certificate - * and private key - * - * #NMSetting8021xCKFormat values indicate the general type of a certificate - * or private key - */ -typedef enum { /*< underscore_name=nm_setting_802_1x_ck_format >*/ - NM_SETTING_802_1X_CK_FORMAT_UNKNOWN = 0, - NM_SETTING_802_1X_CK_FORMAT_X509, - NM_SETTING_802_1X_CK_FORMAT_RAW_KEY, - NM_SETTING_802_1X_CK_FORMAT_PKCS12 -} NMSetting8021xCKFormat; - -/** - * NMSetting8021xCKScheme: - * @NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: unknown certificate or private key - * scheme - * @NM_SETTING_802_1X_CK_SCHEME_BLOB: certificate or key is stored as the raw - * item data - * @NM_SETTING_802_1X_CK_SCHEME_PATH: certificate or key is stored as a path - * to a file containing the certificate or key data - * @NM_SETTING_802_1X_CK_SCHEME_PKCS11: certificate or key is stored as a - * URI of an object on a PKCS#11 token - * - * #NMSetting8021xCKScheme values indicate how a certificate or private key is - * stored in the setting properties, either as a blob of the item's data, or as - * a path to a certificate or private key file on the filesystem - */ -typedef enum { /*< underscore_name=nm_setting_802_1x_ck_scheme >*/ - NM_SETTING_802_1X_CK_SCHEME_UNKNOWN = 0, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - NM_SETTING_802_1X_CK_SCHEME_PATH, - NM_SETTING_802_1X_CK_SCHEME_PKCS11, -} NMSetting8021xCKScheme; - -/** - * NMSetting8021xAuthFlags: - * @NM_SETTING_802_1X_AUTH_FLAGS_NONE: No flags - * @NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE: Disable TLSv1.0 - * @NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE: Disable TLSv1.1 - * @NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_2_DISABLE: Disable TLSv1.2 - * @NM_SETTING_802_1X_AUTH_FLAGS_ALL: All supported flags - * - * #NMSetting8021xAuthFlags values indicate which authentication settings - * should be used. - * - * Before 1.22, this was wrongly marked as a enum and not as a flags - * type. - * - * Since: 1.8 - */ -typedef enum { /*< flags, underscore_name=nm_setting_802_1x_auth_flags >*/ - NM_SETTING_802_1X_AUTH_FLAGS_NONE = 0, - NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE = 0x1, - NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE = 0x2, - NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_2_DISABLE = 0x4, - - NM_SETTING_802_1X_AUTH_FLAGS_ALL = 0x7, -} NMSetting8021xAuthFlags; - -#define NM_TYPE_SETTING_802_1X (nm_setting_802_1x_get_type()) -#define NM_SETTING_802_1X(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_802_1X, NMSetting8021x)) -#define NM_SETTING_802_1X_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_802_1X, NMSetting8021xClass)) -#define NM_IS_SETTING_802_1X(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_802_1X)) -#define NM_IS_SETTING_802_1X_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_802_1X)) -#define NM_SETTING_802_1X_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_802_1X, NMSetting8021xClass)) - -#define NM_SETTING_802_1X_SETTING_NAME "802-1x" - -#define NM_SETTING_802_1X_EAP "eap" -#define NM_SETTING_802_1X_IDENTITY "identity" -#define NM_SETTING_802_1X_ANONYMOUS_IDENTITY "anonymous-identity" -#define NM_SETTING_802_1X_PAC_FILE "pac-file" -#define NM_SETTING_802_1X_CA_CERT "ca-cert" -#define NM_SETTING_802_1X_CA_CERT_PASSWORD "ca-cert-password" -#define NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS "ca-cert-password-flags" -#define NM_SETTING_802_1X_CA_PATH "ca-path" -#define NM_SETTING_802_1X_SUBJECT_MATCH "subject-match" -#define NM_SETTING_802_1X_ALTSUBJECT_MATCHES "altsubject-matches" -#define NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH "domain-suffix-match" -#define NM_SETTING_802_1X_DOMAIN_MATCH "domain-match" -#define NM_SETTING_802_1X_CLIENT_CERT "client-cert" -#define NM_SETTING_802_1X_CLIENT_CERT_PASSWORD "client-cert-password" -#define NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS "client-cert-password-flags" -#define NM_SETTING_802_1X_PHASE1_PEAPVER "phase1-peapver" -#define NM_SETTING_802_1X_PHASE1_PEAPLABEL "phase1-peaplabel" -#define NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING "phase1-fast-provisioning" -#define NM_SETTING_802_1X_PHASE1_AUTH_FLAGS "phase1-auth-flags" -#define NM_SETTING_802_1X_PHASE2_AUTH "phase2-auth" -#define NM_SETTING_802_1X_PHASE2_AUTHEAP "phase2-autheap" -#define NM_SETTING_802_1X_PHASE2_CA_CERT "phase2-ca-cert" -#define NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD "phase2-ca-cert-password" -#define NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS "phase2-ca-cert-password-flags" -#define NM_SETTING_802_1X_PHASE2_CA_PATH "phase2-ca-path" -#define NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH "phase2-subject-match" -#define NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES "phase2-altsubject-matches" -#define NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH "phase2-domain-suffix-match" -#define NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH "phase2-domain-match" -#define NM_SETTING_802_1X_PHASE2_CLIENT_CERT "phase2-client-cert" -#define NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD "phase2-client-cert-password" -#define NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS "phase2-client-cert-password-flags" -#define NM_SETTING_802_1X_PASSWORD "password" -#define NM_SETTING_802_1X_PASSWORD_FLAGS "password-flags" -#define NM_SETTING_802_1X_PASSWORD_RAW "password-raw" -#define NM_SETTING_802_1X_PASSWORD_RAW_FLAGS "password-raw-flags" -#define NM_SETTING_802_1X_PRIVATE_KEY "private-key" -#define NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD "private-key-password" -#define NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS "private-key-password-flags" -#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY "phase2-private-key" -#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD "phase2-private-key-password" -#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS "phase2-private-key-password-flags" -#define NM_SETTING_802_1X_PIN "pin" -#define NM_SETTING_802_1X_PIN_FLAGS "pin-flags" -#define NM_SETTING_802_1X_SYSTEM_CA_CERTS "system-ca-certs" -#define NM_SETTING_802_1X_AUTH_TIMEOUT "auth-timeout" -#define NM_SETTING_802_1X_OPTIONAL "optional" - -/* PRIVATE KEY NOTE: when setting PKCS#12 private keys directly via properties - * using the "blob" scheme, the data must be passed in PKCS#12 binary format. - * In this case, the appropriate "client-cert" (or "phase2-client-cert") - * property of the NMSetting8021x object must also contain the exact same - * PKCS#12 binary data that the private key does. This is because the - * PKCS#12 file contains both the private key and client certificate, so both - * properties need to be set to the same thing. When using the "path" scheme, - * just set both the private-key and client-cert properties to the same path. - * - * When setting OpenSSL-derived "traditional" format (ie S/MIME style, not - * PKCS#8) RSA and DSA keys directly via properties with the "blob" scheme, they - * should be passed to NetworkManager in PEM format with the "DEK-Info" and - * "Proc-Type" tags intact. Decrypted private keys should not be used as this - * is insecure and could allow unprivileged users to access the decrypted - * private key data. - * - * When using the "path" scheme, just set the private-key and client-cert - * properties to the paths to their respective objects. - */ - -/** - * NMSetting8021x: - * - * IEEE 802.1x Authentication Settings - */ -struct _NMSetting8021x { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSetting8021xClass; - -GType nm_setting_802_1x_get_type(void); - -NMSetting *nm_setting_802_1x_new(void); - -NM_AVAILABLE_IN_1_2 -NMSetting8021xCKScheme -nm_setting_802_1x_check_cert_scheme(gconstpointer pdata, gsize length, GError **error); - -guint32 nm_setting_802_1x_get_num_eap_methods(NMSetting8021x *setting); -const char *nm_setting_802_1x_get_eap_method(NMSetting8021x *setting, guint32 i); -gboolean nm_setting_802_1x_add_eap_method(NMSetting8021x *setting, const char *eap); -void nm_setting_802_1x_remove_eap_method(NMSetting8021x *setting, guint32 i); -gboolean nm_setting_802_1x_remove_eap_method_by_value(NMSetting8021x *setting, const char *eap); -void nm_setting_802_1x_clear_eap_methods(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_identity(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_anonymous_identity(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_pac_file(NMSetting8021x *setting); - -gboolean nm_setting_802_1x_get_system_ca_certs(NMSetting8021x *setting); -const char *nm_setting_802_1x_get_ca_path(NMSetting8021x *setting); -const char *nm_setting_802_1x_get_phase2_ca_path(NMSetting8021x *setting); - -NMSetting8021xCKScheme nm_setting_802_1x_get_ca_cert_scheme(NMSetting8021x *setting); -GBytes * nm_setting_802_1x_get_ca_cert_blob(NMSetting8021x *setting); -const char * nm_setting_802_1x_get_ca_cert_path(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_802_1x_get_ca_cert_uri(NMSetting8021x *setting); -gboolean nm_setting_802_1x_set_ca_cert(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error); - -NM_AVAILABLE_IN_1_8 -const char *nm_setting_802_1x_get_ca_cert_password(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_8 -NMSettingSecretFlags nm_setting_802_1x_get_ca_cert_password_flags(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_subject_match(NMSetting8021x *setting); - -guint32 nm_setting_802_1x_get_num_altsubject_matches(NMSetting8021x *setting); -const char *nm_setting_802_1x_get_altsubject_match(NMSetting8021x *setting, guint32 i); -gboolean nm_setting_802_1x_add_altsubject_match(NMSetting8021x *setting, - const char * altsubject_match); -void nm_setting_802_1x_remove_altsubject_match(NMSetting8021x *setting, guint32 i); -gboolean nm_setting_802_1x_remove_altsubject_match_by_value(NMSetting8021x *setting, - const char * altsubject_match); -void nm_setting_802_1x_clear_altsubject_matches(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_802_1x_get_domain_suffix_match(NMSetting8021x *setting); - -NM_AVAILABLE_IN_1_24 -const char *nm_setting_802_1x_get_domain_match(NMSetting8021x *setting); - -NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme(NMSetting8021x *setting); -GBytes * nm_setting_802_1x_get_client_cert_blob(NMSetting8021x *setting); -const char * nm_setting_802_1x_get_client_cert_path(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_802_1x_get_client_cert_uri(NMSetting8021x *setting); -gboolean nm_setting_802_1x_set_client_cert(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error); - -NM_AVAILABLE_IN_1_8 -const char *nm_setting_802_1x_get_client_cert_password(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_8 -NMSettingSecretFlags nm_setting_802_1x_get_client_cert_password_flags(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_phase1_peapver(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_phase1_peaplabel(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_phase1_fast_provisioning(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_phase2_auth(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_phase2_autheap(NMSetting8021x *setting); - -NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_ca_cert_scheme(NMSetting8021x *setting); -GBytes * nm_setting_802_1x_get_phase2_ca_cert_blob(NMSetting8021x *setting); -const char * nm_setting_802_1x_get_phase2_ca_cert_path(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_802_1x_get_phase2_ca_cert_uri(NMSetting8021x *setting); -gboolean nm_setting_802_1x_set_phase2_ca_cert(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error); - -NM_AVAILABLE_IN_1_8 -const char *nm_setting_802_1x_get_phase2_ca_cert_password(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_8 -NMSettingSecretFlags nm_setting_802_1x_get_phase2_ca_cert_password_flags(NMSetting8021x *setting); - -const char *nm_setting_802_1x_get_phase2_subject_match(NMSetting8021x *setting); - -guint32 nm_setting_802_1x_get_num_phase2_altsubject_matches(NMSetting8021x *setting); -const char *nm_setting_802_1x_get_phase2_altsubject_match(NMSetting8021x *setting, guint32 i); -gboolean nm_setting_802_1x_add_phase2_altsubject_match(NMSetting8021x *setting, - const char * phase2_altsubject_match); -void nm_setting_802_1x_remove_phase2_altsubject_match(NMSetting8021x *setting, guint32 i); -gboolean - nm_setting_802_1x_remove_phase2_altsubject_match_by_value(NMSetting8021x *setting, - const char * phase2_altsubject_match); -void nm_setting_802_1x_clear_phase2_altsubject_matches(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_802_1x_get_phase2_domain_suffix_match(NMSetting8021x *setting); - -NM_AVAILABLE_IN_1_24 -const char *nm_setting_802_1x_get_phase2_domain_match(NMSetting8021x *setting); - -NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme(NMSetting8021x *setting); -GBytes * nm_setting_802_1x_get_phase2_client_cert_blob(NMSetting8021x *setting); -const char * nm_setting_802_1x_get_phase2_client_cert_path(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_802_1x_get_phase2_client_cert_uri(NMSetting8021x *setting); -gboolean nm_setting_802_1x_set_phase2_client_cert(NMSetting8021x * setting, - const char * value, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error); - -NM_AVAILABLE_IN_1_8 -const char *nm_setting_802_1x_get_phase2_client_cert_password(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_8 -NMSettingSecretFlags -nm_setting_802_1x_get_phase2_client_cert_password_flags(NMSetting8021x *setting); - -const char * nm_setting_802_1x_get_password(NMSetting8021x *setting); -NMSettingSecretFlags nm_setting_802_1x_get_password_flags(NMSetting8021x *setting); -GBytes * nm_setting_802_1x_get_password_raw(NMSetting8021x *setting); -NMSettingSecretFlags nm_setting_802_1x_get_password_raw_flags(NMSetting8021x *setting); - -const char * nm_setting_802_1x_get_pin(NMSetting8021x *setting); -NMSettingSecretFlags nm_setting_802_1x_get_pin_flags(NMSetting8021x *setting); - -NMSetting8021xCKScheme nm_setting_802_1x_get_private_key_scheme(NMSetting8021x *setting); -GBytes * nm_setting_802_1x_get_private_key_blob(NMSetting8021x *setting); -const char * nm_setting_802_1x_get_private_key_path(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_6 -const char * nm_setting_802_1x_get_private_key_uri(NMSetting8021x *setting); -gboolean nm_setting_802_1x_set_private_key(NMSetting8021x * setting, - const char * value, - const char * password, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error); -const char * nm_setting_802_1x_get_private_key_password(NMSetting8021x *setting); -NMSettingSecretFlags nm_setting_802_1x_get_private_key_password_flags(NMSetting8021x *setting); - -NMSetting8021xCKFormat nm_setting_802_1x_get_private_key_format(NMSetting8021x *setting); - -NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_private_key_scheme(NMSetting8021x *setting); -GBytes * nm_setting_802_1x_get_phase2_private_key_blob(NMSetting8021x *setting); -const char * nm_setting_802_1x_get_phase2_private_key_path(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_802_1x_get_phase2_private_key_uri(NMSetting8021x *setting); -gboolean nm_setting_802_1x_set_phase2_private_key(NMSetting8021x * setting, - const char * value, - const char * password, - NMSetting8021xCKScheme scheme, - NMSetting8021xCKFormat *out_format, - GError ** error); -const char *nm_setting_802_1x_get_phase2_private_key_password(NMSetting8021x *setting); -NMSettingSecretFlags -nm_setting_802_1x_get_phase2_private_key_password_flags(NMSetting8021x *setting); - -NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format(NMSetting8021x *setting); - -NM_AVAILABLE_IN_1_8 -NMSetting8021xAuthFlags nm_setting_802_1x_get_phase1_auth_flags(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_8 -int nm_setting_802_1x_get_auth_timeout(NMSetting8021x *setting); -NM_AVAILABLE_IN_1_22 -gboolean nm_setting_802_1x_get_optional(NMSetting8021x *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_8021X_H__ */ diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c deleted file mode 100644 index f26698b6da..0000000000 --- a/libnm-core/nm-setting-adsl.c +++ /dev/null @@ -1,439 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2013 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-adsl.h" - -#include "nm-setting-ppp.h" -#include "nm-setting-private.h" -#include "nm-utils.h" -#include "nm-core-enum-types.h" - -/** - * SECTION:nm-setting-adsl - * @short_description: Describes ADSL-based properties - * - * The #NMSettingAdsl object is a #NMSetting subclass that describes - * properties of ADSL connections. - */ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_USERNAME, - PROP_PASSWORD, - PROP_PASSWORD_FLAGS, - PROP_PROTOCOL, - PROP_ENCAPSULATION, - PROP_VPI, - PROP_VCI, ); - -typedef struct { - char * username; - char * password; - NMSettingSecretFlags password_flags; - char * protocol; - char * encapsulation; - guint32 vpi; - guint32 vci; -} NMSettingAdslPrivate; - -G_DEFINE_TYPE(NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING) - -#define NM_SETTING_ADSL_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_ADSL, NMSettingAdslPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_adsl_get_username: - * @setting: the #NMSettingAdsl - * - * Returns: the #NMSettingAdsl:username property of the setting - **/ -const char * -nm_setting_adsl_get_username(NMSettingAdsl *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NULL); - - return NM_SETTING_ADSL_GET_PRIVATE(setting)->username; -} - -/** - * nm_setting_adsl_get_password: - * @setting: the #NMSettingAdsl - * - * Returns: the #NMSettingAdsl:password property of the setting - **/ -const char * -nm_setting_adsl_get_password(NMSettingAdsl *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NULL); - - return NM_SETTING_ADSL_GET_PRIVATE(setting)->password; -} - -/** - * nm_setting_adsl_get_password_flags: - * @setting: the #NMSettingAdsl - * - * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingAdsl:password - **/ -NMSettingSecretFlags -nm_setting_adsl_get_password_flags(NMSettingAdsl *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_ADSL_GET_PRIVATE(setting)->password_flags; -} - -/** - * nm_setting_adsl_get_protocol: - * @setting: the #NMSettingAdsl - * - * Returns: the #NMSettingAdsl:protocol property of the setting - **/ -const char * -nm_setting_adsl_get_protocol(NMSettingAdsl *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NULL); - - return NM_SETTING_ADSL_GET_PRIVATE(setting)->protocol; -} - -/** - * nm_setting_adsl_get_encapsulation: - * @setting: the #NMSettingAdsl - * - * Returns: the #NMSettingAdsl:encapsulation property of the setting - **/ -const char * -nm_setting_adsl_get_encapsulation(NMSettingAdsl *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NULL); - - return NM_SETTING_ADSL_GET_PRIVATE(setting)->encapsulation; -} - -/** - * nm_setting_adsl_get_vpi: - * @setting: the #NMSettingAdsl - * - * Returns: the #NMSettingAdsl:vpi property of the setting - **/ -guint32 -nm_setting_adsl_get_vpi(NMSettingAdsl *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), 0); - - return NM_SETTING_ADSL_GET_PRIVATE(setting)->vpi; -} - -/** - * nm_setting_adsl_get_vci: - * @setting: the #NMSettingAdsl - * - * Returns: the #NMSettingAdsl:vci property of the setting - **/ -guint32 -nm_setting_adsl_get_vci(NMSettingAdsl *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), 0); - - return NM_SETTING_ADSL_GET_PRIVATE(setting)->vci; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(setting); - - if (!priv->username) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME); - return FALSE; - } - if (!priv->username[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME); - return FALSE; - } - - if (!NM_IN_STRSET(priv->protocol, - NM_SETTING_ADSL_PROTOCOL_PPPOA, - NM_SETTING_ADSL_PROTOCOL_PPPOE, - NM_SETTING_ADSL_PROTOCOL_IPOATM)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - priv->protocol ?: "(null)"); - g_prefix_error(error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_PROTOCOL); - return FALSE; - } - - if (!NM_IN_STRSET(priv->encapsulation, - NULL, - NM_SETTING_ADSL_ENCAPSULATION_VCMUX, - NM_SETTING_ADSL_ENCAPSULATION_LLC)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - priv->encapsulation); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_ADSL_SETTING_NAME, - NM_SETTING_ADSL_ENCAPSULATION); - return FALSE; - } - - return TRUE; -} - -static gboolean -verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) -{ - return _nm_setting_verify_secret_string(NM_SETTING_ADSL_GET_PRIVATE(setting)->password, - NM_SETTING_ADSL_SETTING_NAME, - NM_SETTING_ADSL_PASSWORD, - error); -} - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(setting); - GPtrArray * secrets = NULL; - - if (priv->password && *priv->password) - return NULL; - - if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { - secrets = g_ptr_array_sized_new(1); - g_ptr_array_add(secrets, NM_SETTING_ADSL_PASSWORD); - } - - return secrets; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingAdsl *setting = NM_SETTING_ADSL(object); - - switch (prop_id) { - case PROP_USERNAME: - g_value_set_string(value, nm_setting_adsl_get_username(setting)); - break; - case PROP_PASSWORD: - g_value_set_string(value, nm_setting_adsl_get_password(setting)); - break; - case PROP_PASSWORD_FLAGS: - g_value_set_flags(value, nm_setting_adsl_get_password_flags(setting)); - break; - case PROP_PROTOCOL: - g_value_set_string(value, nm_setting_adsl_get_protocol(setting)); - break; - case PROP_ENCAPSULATION: - g_value_set_string(value, nm_setting_adsl_get_encapsulation(setting)); - break; - case PROP_VPI: - g_value_set_uint(value, nm_setting_adsl_get_vpi(setting)); - break; - case PROP_VCI: - g_value_set_uint(value, nm_setting_adsl_get_vci(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(object); - const char * str; - - switch (prop_id) { - case PROP_USERNAME: - g_free(priv->username); - priv->username = g_value_dup_string(value); - break; - case PROP_PASSWORD: - g_free(priv->password); - priv->password = g_value_dup_string(value); - break; - case PROP_PASSWORD_FLAGS: - priv->password_flags = g_value_get_flags(value); - break; - case PROP_PROTOCOL: - g_free(priv->protocol); - str = g_value_get_string(value); - priv->protocol = str ? g_ascii_strdown(str, -1) : NULL; - break; - case PROP_ENCAPSULATION: - g_free(priv->encapsulation); - str = g_value_get_string(value); - priv->encapsulation = str ? g_ascii_strdown(str, -1) : NULL; - break; - case PROP_VPI: - priv->vpi = g_value_get_uint(value); - break; - case PROP_VCI: - priv->vci = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_adsl_init(NMSettingAdsl *setting) -{} - -/** - * nm_setting_adsl_new: - * - * Creates a new #NMSettingAdsl object with default values. - * - * Returns: the new empty #NMSettingAdsl object - **/ -NMSetting * -nm_setting_adsl_new(void) -{ - return g_object_new(NM_TYPE_SETTING_ADSL, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(object); - - g_free(priv->username); - g_free(priv->password); - g_free(priv->protocol); - g_free(priv->encapsulation); - - G_OBJECT_CLASS(nm_setting_adsl_parent_class)->finalize(object); -} - -static void -nm_setting_adsl_class_init(NMSettingAdslClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingAdslPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->verify_secrets = verify_secrets; - setting_class->need_secrets = need_secrets; - - /** - * NMSettingAdsl:username: - * - * Username used to authenticate with the ADSL service. - **/ - obj_properties[PROP_USERNAME] = g_param_spec_string(NM_SETTING_ADSL_USERNAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingAdsl:password: - * - * Password used to authenticate with the ADSL service. - **/ - obj_properties[PROP_PASSWORD] = - g_param_spec_string(NM_SETTING_ADSL_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingAdsl:password-flags: - * - * Flags indicating how to handle the #NMSettingAdsl:password property. - **/ - obj_properties[PROP_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_ADSL_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingAdsl:protocol: - * - * ADSL connection protocol. Can be "pppoa", "pppoe" or "ipoatm". - **/ - obj_properties[PROP_PROTOCOL] = g_param_spec_string(NM_SETTING_ADSL_PROTOCOL, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingAdsl:encapsulation: - * - * Encapsulation of ADSL connection. Can be "vcmux" or "llc". - **/ - obj_properties[PROP_ENCAPSULATION] = - g_param_spec_string(NM_SETTING_ADSL_ENCAPSULATION, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingAdsl:vpi: - * - * VPI of ADSL connection - **/ - obj_properties[PROP_VPI] = g_param_spec_uint(NM_SETTING_ADSL_VPI, - "", - "", - 0, - 65536, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingAdsl:vci: - * - * VCI of ADSL connection - **/ - obj_properties[PROP_VCI] = g_param_spec_uint(NM_SETTING_ADSL_VCI, - "", - "", - 0, - 65536, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_ADSL); -} diff --git a/libnm-core/nm-setting-adsl.h b/libnm-core/nm-setting-adsl.h deleted file mode 100644 index 3d8e99c9f1..0000000000 --- a/libnm-core/nm-setting-adsl.h +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2008 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_ADSL_H__ -#define __NM_SETTING_ADSL_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_ADSL (nm_setting_adsl_get_type()) -#define NM_SETTING_ADSL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_ADSL, NMSettingAdsl)) -#define NM_SETTING_ADSL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_ADSL, NMSettingAdslClass)) -#define NM_IS_SETTING_ADSL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_ADSL)) -#define NM_IS_SETTING_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_ADSL)) -#define NM_SETTING_ADSL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_ADSL, NMSettingAdslClass)) - -#define NM_SETTING_ADSL_SETTING_NAME "adsl" - -#define NM_SETTING_ADSL_USERNAME "username" -#define NM_SETTING_ADSL_PASSWORD "password" -#define NM_SETTING_ADSL_PASSWORD_FLAGS "password-flags" -#define NM_SETTING_ADSL_PROTOCOL "protocol" -#define NM_SETTING_ADSL_ENCAPSULATION "encapsulation" -#define NM_SETTING_ADSL_VPI "vpi" -#define NM_SETTING_ADSL_VCI "vci" - -#define NM_SETTING_ADSL_PROTOCOL_PPPOA "pppoa" -#define NM_SETTING_ADSL_PROTOCOL_PPPOE "pppoe" -#define NM_SETTING_ADSL_PROTOCOL_IPOATM "ipoatm" - -#define NM_SETTING_ADSL_ENCAPSULATION_VCMUX "vcmux" -#define NM_SETTING_ADSL_ENCAPSULATION_LLC "llc" - -/** - * NMSettingAdsl: - * - * ADSL Settings - */ -struct _NMSettingAdsl { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingAdslClass; - -GType nm_setting_adsl_get_type(void); - -NMSetting * nm_setting_adsl_new(void); -const char * nm_setting_adsl_get_username(NMSettingAdsl *setting); -const char * nm_setting_adsl_get_password(NMSettingAdsl *setting); -const char * nm_setting_adsl_get_protocol(NMSettingAdsl *setting); -const char * nm_setting_adsl_get_encapsulation(NMSettingAdsl *setting); -guint32 nm_setting_adsl_get_vpi(NMSettingAdsl *setting); -guint32 nm_setting_adsl_get_vci(NMSettingAdsl *setting); -NMSettingSecretFlags nm_setting_adsl_get_password_flags(NMSettingAdsl *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_ADSL_H__ */ diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c deleted file mode 100644 index eb0e59300d..0000000000 --- a/libnm-core/nm-setting-bluetooth.c +++ /dev/null @@ -1,332 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-bluetooth.h" - -#include - -#include "nm-connection-private.h" -#include "nm-setting-cdma.h" -#include "nm-setting-gsm.h" -#include "nm-setting-private.h" -#include "nm-utils.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-bluetooth - * @short_description: Describes Bluetooth connection properties - * - * The #NMSettingBluetooth object is a #NMSetting subclass that describes - * properties necessary for connection to devices that provide network - * connections via the Bluetooth Dial-Up Networking (DUN) and Network Access - * Point (NAP) profiles. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_BDADDR, PROP_TYPE, ); - -typedef struct { - char *bdaddr; - char *type; -} NMSettingBluetoothPrivate; - -G_DEFINE_TYPE(NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING) - -#define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_bluetooth_get_connection_type: - * @setting: the #NMSettingBluetooth - * - * Returns the connection method for communicating with the remote device (i.e. - * either DUN to a DUN-capable device or PANU to a NAP-capable device). - * - * Returns: the type, either %NM_SETTING_BLUETOOTH_TYPE_PANU, - * %NM_SETTING_BLUETOOTH_TYPE_NAP or %NM_SETTING_BLUETOOTH_TYPE_DUN - **/ -const char * -nm_setting_bluetooth_get_connection_type(NMSettingBluetooth *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BLUETOOTH(setting), NULL); - - return NM_SETTING_BLUETOOTH_GET_PRIVATE(setting)->type; -} - -/** - * nm_setting_bluetooth_get_bdaddr: - * @setting: the #NMSettingBluetooth - * - * Gets the Bluetooth address of the remote device which this setting - * describes a connection to. - * - * Returns: the Bluetooth address - **/ -const char * -nm_setting_bluetooth_get_bdaddr(NMSettingBluetooth *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BLUETOOTH(setting), NULL); - - return NM_SETTING_BLUETOOTH_GET_PRIVATE(setting)->bdaddr; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE(setting); - const char * type; - gboolean missing_nap_bridge = FALSE; - - if (priv->bdaddr && !nm_utils_hwaddr_valid(priv->bdaddr, ETH_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BLUETOOTH_SETTING_NAME, - NM_SETTING_BLUETOOTH_BDADDR); - return FALSE; - } - - type = priv->type; - if (!type) { - if (connection) { - /* We may infer the type from the (non-)existence of gsm/cdma/bridge settings. */ - type = _nm_connection_detect_bluetooth_type(connection); - } - if (!type) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BLUETOOTH_SETTING_NAME, - NM_SETTING_BLUETOOTH_TYPE); - return FALSE; - } - } - - if (!NM_IN_STRSET(type, - NM_SETTING_BLUETOOTH_TYPE_DUN, - NM_SETTING_BLUETOOTH_TYPE_NAP, - NM_SETTING_BLUETOOTH_TYPE_PANU)) { - nm_assert(priv->type == type); - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BLUETOOTH_SETTING_NAME, - NM_SETTING_BLUETOOTH_TYPE); - return FALSE; - } - - /* Make sure the corresponding 'type' setting is present */ - if (connection && nm_streq(type, NM_SETTING_BLUETOOTH_TYPE_DUN)) { - gboolean gsm = FALSE, cdma = FALSE; - - gsm = !!nm_connection_get_setting_gsm(connection); - cdma = !!nm_connection_get_setting_cdma(connection); - - if (!gsm && !cdma) { - /* We can't return MISSING_SETTING here, because we don't know - * whether to prefix the message with NM_SETTING_GSM_SETTING_NAME or - * NM_SETTING_CDMA_SETTING_NAME. - */ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("'%s' connection requires '%s' or '%s' setting"), - NM_SETTING_BLUETOOTH_TYPE_DUN, - NM_SETTING_GSM_SETTING_NAME, - NM_SETTING_CDMA_SETTING_NAME); - g_prefix_error(error, "%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME); - return FALSE; - } - } - /* PANU doesn't need a 'type' setting since no further configuration - * is required at the interface level. - */ - - /* NAP mode needs a bridge setting, and a bridge needs a name. */ - if (nm_streq(type, NM_SETTING_BLUETOOTH_TYPE_NAP)) { - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - if (connection && !nm_connection_get_setting_bridge(connection)) - missing_nap_bridge = TRUE; - } else { - if (!priv->bdaddr) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BLUETOOTH_SETTING_NAME, - NM_SETTING_BLUETOOTH_BDADDR); - return FALSE; - } - } - - /* errors form here are normalizable. */ - - if (!priv->type) { - /* as determined above, we can detect the bluetooth type. */ - nm_assert(!missing_nap_bridge); - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BLUETOOTH_SETTING_NAME, - NM_SETTING_BLUETOOTH_TYPE); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - - if (missing_nap_bridge) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("'%s' connection requires '%s' setting"), - NM_SETTING_BLUETOOTH_TYPE_NAP, - NM_SETTING_BRIDGE_SETTING_NAME); - g_prefix_error(error, "%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingBluetooth *setting = NM_SETTING_BLUETOOTH(object); - - switch (prop_id) { - case PROP_BDADDR: - g_value_set_string(value, nm_setting_bluetooth_get_bdaddr(setting)); - break; - case PROP_TYPE: - g_value_set_string(value, nm_setting_bluetooth_get_connection_type(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_BDADDR: - g_free(priv->bdaddr); - priv->bdaddr = g_value_dup_string(value); - break; - case PROP_TYPE: - g_free(priv->type); - priv->type = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_bluetooth_init(NMSettingBluetooth *setting) -{} - -/** - * nm_setting_bluetooth_new: - * - * Creates a new #NMSettingBluetooth object with default values. - * - * Returns: (transfer full): the new empty #NMSettingBluetooth object - **/ -NMSetting * -nm_setting_bluetooth_new(void) -{ - return g_object_new(NM_TYPE_SETTING_BLUETOOTH, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE(object); - - g_free(priv->bdaddr); - g_free(priv->type); - - G_OBJECT_CLASS(nm_setting_bluetooth_parent_class)->finalize(object); -} - -static void -nm_setting_bluetooth_class_init(NMSettingBluetoothClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingBluetoothPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingBluetooth:bdaddr: - * - * The Bluetooth address of the device. - **/ - obj_properties[PROP_BDADDR] = g_param_spec_string( - NM_SETTING_BLUETOOTH_BDADDR, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_BDADDR], - &nm_sett_info_propert_type_mac_address); - - /** - * NMSettingBluetooth:type: - * - * Either "dun" for Dial-Up Networking connections or "panu" for Personal - * Area Networking connections to devices supporting the NAP profile. - **/ - obj_properties[PROP_TYPE] = g_param_spec_string(NM_SETTING_BLUETOOTH_TYPE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_BLUETOOTH, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-bluetooth.h b/libnm-core/nm-setting-bluetooth.h deleted file mode 100644 index 4f001ef7fe..0000000000 --- a/libnm-core/nm-setting-bluetooth.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2009 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_BLUETOOTH_H__ -#define __NM_SETTING_BLUETOOTH_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_BLUETOOTH (nm_setting_bluetooth_get_type()) -#define NM_SETTING_BLUETOOTH(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetooth)) -#define NM_SETTING_BLUETOOTH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothClass)) -#define NM_IS_SETTING_BLUETOOTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_BLUETOOTH)) -#define NM_IS_SETTING_BLUETOOTH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_BLUETOOTH)) -#define NM_SETTING_BLUETOOTH_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothClass)) - -#define NM_SETTING_BLUETOOTH_SETTING_NAME "bluetooth" - -#define NM_SETTING_BLUETOOTH_BDADDR "bdaddr" -#define NM_SETTING_BLUETOOTH_TYPE "type" - -/** - * NM_SETTING_BLUETOOTH_TYPE_DUN: - * - * Connection type describing a connection to devices that support the Bluetooth - * DUN profile. - */ -#define NM_SETTING_BLUETOOTH_TYPE_DUN "dun" - -/** - * NM_SETTING_BLUETOOTH_TYPE_PANU: - * - * Connection type describing PANU connection to a Bluetooth NAP (Network - * Access Point). - */ -#define NM_SETTING_BLUETOOTH_TYPE_PANU "panu" - -/** - * NM_SETTING_BLUETOOTH_TYPE_NAP: - * - * Connection type describing a Bluetooth NAP (Network Access Point), - * which accepts PANU clients. - */ -#define NM_SETTING_BLUETOOTH_TYPE_NAP "nap" - -/** - * NMSettingBluetooth: - * - * Bluetooth Settings - */ -struct _NMSettingBluetooth { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingBluetoothClass; - -GType nm_setting_bluetooth_get_type(void); - -NMSetting * nm_setting_bluetooth_new(void); -const char *nm_setting_bluetooth_get_bdaddr(NMSettingBluetooth *setting); -const char *nm_setting_bluetooth_get_connection_type(NMSettingBluetooth *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_BLUETOOTH_H__ */ diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c deleted file mode 100644 index 2d64ef02b4..0000000000 --- a/libnm-core/nm-setting-bond.c +++ /dev/null @@ -1,1185 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2013 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-bond.h" - -#include -#include -#include -#include - -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-connection-private.h" -#include "nm-setting-infiniband.h" -#include "nm-core-internal.h" - -/*****************************************************************************/ - -/** - * SECTION:nm-setting-bond - * @short_description: Describes connection properties for bonds - * - * The #NMSettingBond object is a #NMSetting subclass that describes properties - * necessary for bond connections. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingBond, PROP_OPTIONS, ); - -typedef struct { - GHashTable * options; - NMUtilsNamedValue *options_idx_cache; -} NMSettingBondPrivate; - -G_DEFINE_TYPE(NMSettingBond, nm_setting_bond, NM_TYPE_SETTING) - -#define NM_SETTING_BOND_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_BOND, NMSettingBondPrivate)) - -/*****************************************************************************/ - -static const char *const valid_options_lst[] = { - /* mode must be the first element. nm-device-bond.c relies on that. */ - NM_SETTING_BOND_OPTION_MODE, - NM_SETTING_BOND_OPTION_MIIMON, - NM_SETTING_BOND_OPTION_DOWNDELAY, - NM_SETTING_BOND_OPTION_UPDELAY, - NM_SETTING_BOND_OPTION_ARP_INTERVAL, - NM_SETTING_BOND_OPTION_ARP_IP_TARGET, - NM_SETTING_BOND_OPTION_ARP_VALIDATE, - NM_SETTING_BOND_OPTION_PRIMARY, - NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, - NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, - NM_SETTING_BOND_OPTION_USE_CARRIER, - NM_SETTING_BOND_OPTION_AD_SELECT, - NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, - NM_SETTING_BOND_OPTION_RESEND_IGMP, - NM_SETTING_BOND_OPTION_LACP_RATE, - NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, - NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, - NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, - NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, - NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, - NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, - NM_SETTING_BOND_OPTION_MIN_LINKS, - NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, - NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, - NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, - NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, - NM_SETTING_BOND_OPTION_LP_INTERVAL, - NULL, -}; - -typedef struct { - const char * val; - NMBondOptionType opt_type; - guint min; - guint max; - const char *const *list; -} OptionMeta; - -static gboolean -_nm_assert_bond_meta(const OptionMeta *option_meta) -{ - nm_assert(option_meta); - - switch (option_meta->opt_type) { - case NM_BOND_OPTION_TYPE_BOTH: - nm_assert(option_meta->val); - nm_assert(option_meta->list); - nm_assert(option_meta->list[0]); - nm_assert(option_meta->min == 0); - nm_assert(option_meta->max == NM_PTRARRAY_LEN(option_meta->list) - 1); - nm_assert(g_strv_contains(option_meta->list, option_meta->val)); - return TRUE; - case NM_BOND_OPTION_TYPE_INT: - nm_assert(option_meta->val); - nm_assert(!option_meta->list); - nm_assert(option_meta->min < option_meta->max); - nm_assert(NM_STRCHAR_ALL(option_meta->val, ch, g_ascii_isdigit(ch))); - nm_assert(NM_STRCHAR_ALL(option_meta->val, ch, g_ascii_isdigit(ch))); - nm_assert(({ - _nm_utils_ascii_str_to_uint64(option_meta->val, - 10, - option_meta->min, - option_meta->max, - 0); - errno == 0; - })); - return TRUE; - case NM_BOND_OPTION_TYPE_IP: - nm_assert(option_meta->val); - /* fall-through */ - case NM_BOND_OPTION_TYPE_IFNAME: - case NM_BOND_OPTION_TYPE_MAC: - nm_assert(!option_meta->list); - nm_assert(option_meta->min == 0); - nm_assert(option_meta->max == 0); - return TRUE; - } - - nm_assert_not_reached(); - return FALSE; -} - -static char const *const _option_default_strv_ad_select[] = - NM_MAKE_STRV("stable", "bandwidth", "count"); -static char const *const _option_default_strv_arp_all_targets[] = NM_MAKE_STRV("any", "all"); -static char const *const _option_default_strv_arp_validate[] = - NM_MAKE_STRV("none", "active", "backup", "all", "filter", "filter_active", "filter_backup"); -static char const *const _option_default_strv_fail_over_mac[] = - NM_MAKE_STRV("none", "active", "follow"); -static char const *const _option_default_strv_lacp_rate[] = NM_MAKE_STRV("slow", "fast"); -static char const *const _option_default_strv_mode[] = NM_MAKE_STRV("balance-rr", - "active-backup", - "balance-xor", - "broadcast", - "802.3ad", - "balance-tlb", - "balance-alb"); -static char const *const _option_default_strv_primary_reselect[] = - NM_MAKE_STRV("always", "better", "failure"); -static char const *const _option_default_strv_xmit_hash_policy[] = - NM_MAKE_STRV("layer2", "layer3+4", "layer2+3", "encap2+3", "encap3+4", "vlan+srcmac"); - -static NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE( - _get_option_meta, - OptionMeta, - { - G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(LIST) == G_N_ELEMENTS(valid_options_lst) - 1); - - if (NM_MORE_ASSERT_ONCE(5)) { - int i; - - nm_assert(G_N_ELEMENTS(LIST) == NM_PTRARRAY_LEN(valid_options_lst)); - for (i = 0; i < G_N_ELEMENTS(LIST); i++) - _nm_assert_bond_meta(&LIST[i].value); - nm_assert(nm_streq(valid_options_lst[0], NM_SETTING_BOND_OPTION_MODE)); - } - }, - { return NULL; }, - {NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, {NULL, NM_BOND_OPTION_TYPE_IFNAME}}, - {NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, {"65535", NM_BOND_OPTION_TYPE_INT, 1, 65535}}, - {NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, {NULL, NM_BOND_OPTION_TYPE_MAC}}, - {NM_SETTING_BOND_OPTION_AD_SELECT, - {"stable", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_ad_select}}, - {NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, {"0", NM_BOND_OPTION_TYPE_INT, 0, 1023}}, - {NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, {"0", NM_BOND_OPTION_TYPE_INT, 0, 1}}, - {NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, - {"any", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_arp_all_targets}}, - {NM_SETTING_BOND_OPTION_ARP_INTERVAL, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, - {NM_SETTING_BOND_OPTION_ARP_IP_TARGET, {"", NM_BOND_OPTION_TYPE_IP}}, - {NM_SETTING_BOND_OPTION_ARP_VALIDATE, - {"none", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_arp_validate}}, - {NM_SETTING_BOND_OPTION_DOWNDELAY, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, - {NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, - {"none", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_fail_over_mac}}, - {NM_SETTING_BOND_OPTION_LACP_RATE, - {"slow", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_lacp_rate}}, - {NM_SETTING_BOND_OPTION_LP_INTERVAL, {"1", NM_BOND_OPTION_TYPE_INT, 1, G_MAXINT}}, - {NM_SETTING_BOND_OPTION_MIIMON, {"100", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, - {NM_SETTING_BOND_OPTION_MIN_LINKS, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, - {NM_SETTING_BOND_OPTION_MODE, - {"balance-rr", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_mode}}, - {NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, {"1", NM_BOND_OPTION_TYPE_INT, 0, 255}}, - {NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, {"1", NM_BOND_OPTION_TYPE_INT, 0, 255}}, - {NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, {"1", NM_BOND_OPTION_TYPE_INT, 0, 65535}}, - {NM_SETTING_BOND_OPTION_PRIMARY, {"", NM_BOND_OPTION_TYPE_IFNAME}}, - {NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, - {"always", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_primary_reselect}}, - {NM_SETTING_BOND_OPTION_RESEND_IGMP, {"1", NM_BOND_OPTION_TYPE_INT, 0, 255}}, - {NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, {"1", NM_BOND_OPTION_TYPE_INT, 0, 1}}, - {NM_SETTING_BOND_OPTION_UPDELAY, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, - {NM_SETTING_BOND_OPTION_USE_CARRIER, {"1", NM_BOND_OPTION_TYPE_INT, 0, 1}}, - {NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, - {"layer2", NM_BOND_OPTION_TYPE_BOTH, 0, 5, _option_default_strv_xmit_hash_policy}}, ); - -/*****************************************************************************/ - -#define BIT(x) (((guint32) 1) << (x)) - -static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( - _bond_option_unsupp_mode, - guint32, - { ; }, - { return 0; }, - {NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, - ~(BIT(NM_BOND_MODE_ACTIVEBACKUP) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, - {NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, ~(BIT(NM_BOND_MODE_8023AD))}, - {NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, ~(BIT(NM_BOND_MODE_8023AD))}, - {NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, ~(BIT(NM_BOND_MODE_8023AD))}, - {NM_SETTING_BOND_OPTION_ARP_INTERVAL, - (BIT(NM_BOND_MODE_8023AD) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, - {NM_SETTING_BOND_OPTION_ARP_IP_TARGET, - (BIT(NM_BOND_MODE_8023AD) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, - {NM_SETTING_BOND_OPTION_ARP_VALIDATE, - (BIT(NM_BOND_MODE_8023AD) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, - {NM_SETTING_BOND_OPTION_LACP_RATE, ~(BIT(NM_BOND_MODE_8023AD))}, - {NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, ~(BIT(NM_BOND_MODE_ROUNDROBIN))}, - {NM_SETTING_BOND_OPTION_PRIMARY, - ~(BIT(NM_BOND_MODE_ACTIVEBACKUP) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, - {NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, ~(BIT(NM_BOND_MODE_TLB))}, ); - -gboolean -_nm_setting_bond_option_supported(const char *option, NMBondMode mode) -{ - nm_assert(option); - nm_assert(mode != NM_BOND_MODE_UNKNOWN); - nm_assert(_NM_INT_NOT_NEGATIVE(mode) && mode < 32); - - return !NM_FLAGS_ANY(_bond_option_unsupp_mode(option), BIT(mode)); -} - -static const char * -_bond_get_option(NMSettingBond *self, const char *option) -{ - g_return_val_if_fail(NM_IS_SETTING_BOND(self), NULL); - g_return_val_if_fail(option, NULL); - - return g_hash_table_lookup(NM_SETTING_BOND_GET_PRIVATE(self)->options, option); -} - -static const char * -_bond_get_option_default(NMSettingBond *self, const char *option) -{ - const OptionMeta *option_meta; - - g_return_val_if_fail(NM_IS_SETTING_BOND(self), NULL); - - option_meta = _get_option_meta(option); - - g_return_val_if_fail(option_meta, NULL); - - return option_meta->val; -} - -static const char * -_bond_get_option_or_default(NMSettingBond *self, const char *option) -{ - return _bond_get_option(self, option) ?: _bond_get_option_default(self, option); -} - -static const char * -_bond_get_option_normalized(NMSettingBond *self, const char *option, gboolean get_default_only) -{ - const char *mode_str; - NMBondMode mode; - const char *value = NULL; - - g_return_val_if_fail(NM_IS_SETTING_BOND(self), NULL); - g_return_val_if_fail(option, NULL); - - mode_str = _bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_MODE); - mode = _nm_setting_bond_mode_from_string(mode_str); - - if (mode == NM_BOND_MODE_UNKNOWN) { - /* the mode is unknown, consequently, there is no normalized/default - * value either. */ - return NULL; - } - - if (!_nm_setting_bond_option_supported(option, mode)) - return NULL; - - /* Apply custom NetworkManager policies here */ - if (!get_default_only) { - if (NM_IN_STRSET(option, - NM_SETTING_BOND_OPTION_ARP_INTERVAL, - NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) { - int miimon; - - /* if arp_interval is explicitly set and miimon is not, then disable miimon - * (and related updelay and downdelay) as recommended by the kernel docs */ - miimon = - _nm_utils_ascii_str_to_int64(_bond_get_option(self, NM_SETTING_BOND_OPTION_MIIMON), - 10, - 0, - G_MAXINT, - 0); - if (miimon != 0) { - /* miimon is enabled. arp_interval values are unset. */ - if (nm_streq(option, NM_SETTING_BOND_OPTION_ARP_INTERVAL)) - return "0"; - return ""; - } - value = _bond_get_option(self, option); - } else if (NM_IN_STRSET(option, - NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, - NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)) { - /* just get one of the 2, at kernel level they're the same bond option */ - value = _bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); - if (!value) - value = _bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); - } else if (NM_IN_STRSET(option, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE)) { - /* "active_slave" is deprecated, and an alias for "primary". The property - * itself always normalizes to %NULL. */ - value = NULL; - } else if (NM_IN_STRSET(option, NM_SETTING_BOND_OPTION_PRIMARY)) { - /* "active_slave" is deprecated, and an alias for "primary". */ - value = _bond_get_option(self, NM_SETTING_BOND_OPTION_PRIMARY); - if (!value) - value = _bond_get_option(self, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE); - } else - value = _bond_get_option(self, option); - - if (value) - return value; - } - - /* Apply rules that change the default value of an option */ - if (nm_streq(option, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) { - /* The default value depends on the current mode */ - if (mode == NM_BOND_MODE_8023AD) - return "00:00:00:00:00:00"; - return ""; - } - - return _bond_get_option_or_default(self, option); -} - -const char * -nm_setting_bond_get_option_or_default(NMSettingBond *self, const char *option) -{ - g_return_val_if_fail(NM_IS_SETTING_BOND(self), NULL); - g_return_val_if_fail(option, NULL); - - return _bond_get_option_normalized(self, option, FALSE); -} - -static int -_atoi(const char *value) -{ - int v; - - v = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXINT, -1); - nm_assert(v >= 0); - return v; -}; - -/** - * nm_setting_bond_get_num_options: - * @setting: the #NMSettingBond - * - * Returns the number of options that should be set for this bond when it - * is activated. This can be used to retrieve each option individually - * using nm_setting_bond_get_option(). - * - * Returns: the number of bonding options - **/ -guint32 -nm_setting_bond_get_num_options(NMSettingBond *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BOND(setting), 0); - - return g_hash_table_size(NM_SETTING_BOND_GET_PRIVATE(setting)->options); -} - -static int -_get_option_sort(gconstpointer p_a, gconstpointer p_b, gpointer _unused) -{ - const char *a = *((const char *const *) p_a); - const char *b = *((const char *const *) p_b); - - NM_CMP_DIRECT(nm_streq(b, NM_SETTING_BOND_OPTION_MODE), - nm_streq(a, NM_SETTING_BOND_OPTION_MODE)); - NM_CMP_DIRECT_STRCMP(a, b); - nm_assert_not_reached(); - return 0; -} - -static void -_ensure_options_idx_cache(NMSettingBondPrivate *priv) -{ - if (!G_UNLIKELY(priv->options_idx_cache)) - priv->options_idx_cache = nm_utils_named_values_from_strdict_full(priv->options, - NULL, - _get_option_sort, - NULL, - NULL, - 0, - NULL); -} - -/** - * nm_setting_bond_get_option: - * @setting: the #NMSettingBond - * @idx: index of the desired option, from 0 to - * nm_setting_bond_get_num_options() - 1 - * @out_name: (out) (transfer none): on return, the name of the bonding option; - * this value is owned by the setting and should not be modified - * @out_value: (out) (transfer none): on return, the value of the name of the - * bonding option; this value is owned by the setting and should not be - * modified - * - * Given an index, return the value of the bonding option at that index. Indexes - * are *not* guaranteed to be static across modifications to options done by - * nm_setting_bond_add_option() and nm_setting_bond_remove_option(), - * and should not be used to refer to options except for short periods of time - * such as during option iteration. - * - * Returns: %TRUE on success if the index was valid and an option was found, - * %FALSE if the index was invalid (ie, greater than the number of options - * currently held by the setting) - **/ -gboolean -nm_setting_bond_get_option(NMSettingBond *setting, - guint32 idx, - const char ** out_name, - const char ** out_value) -{ - NMSettingBondPrivate *priv; - guint len; - - g_return_val_if_fail(NM_IS_SETTING_BOND(setting), FALSE); - - priv = NM_SETTING_BOND_GET_PRIVATE(setting); - - len = g_hash_table_size(priv->options); - if (idx >= len) - return FALSE; - - _ensure_options_idx_cache(priv); - - NM_SET_OUT(out_name, priv->options_idx_cache[idx].name); - NM_SET_OUT(out_value, priv->options_idx_cache[idx].value_str); - return TRUE; -} - -static gboolean -validate_int(const char *name, const char *value, const OptionMeta *option_meta) -{ - guint64 num; - - if (!NM_STRCHAR_ALL(value, ch, g_ascii_isdigit(ch))) - return FALSE; - - num = _nm_utils_ascii_str_to_uint64(value, 10, option_meta->min, option_meta->max, G_MAXUINT64); - if (num == G_MAXUINT64 && errno != 0) - return FALSE; - - return TRUE; -} - -static gboolean -validate_list(const char *name, const char *value, const OptionMeta *option_meta) -{ - int i; - - nm_assert(option_meta->list); - - for (i = 0; option_meta->list[i]; i++) { - if (nm_streq(option_meta->list[i], value)) - return TRUE; - } - return FALSE; -} - -static gboolean -validate_ip(const char *name, const char *value, GError **error) -{ - gs_free const char **addrs = NULL; - gsize i; - - addrs = nm_utils_bond_option_arp_ip_targets_split(value); - if (!addrs) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option is empty"), - name); - return FALSE; - } - for (i = 0; addrs[i]; i++) { - if (!nm_utils_parse_inaddr_bin(AF_INET, addrs[i], NULL, NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IPv4 address for '%s' option"), - addrs[i], - name); - return FALSE; - } - } - return TRUE; -} - -static gboolean -validate_ifname(const char *name, const char *value) -{ - return nm_utils_ifname_valid_kernel(value, NULL); -} - -gboolean -_nm_setting_bond_validate_option(const char *name, const char *value, GError **error) -{ - const OptionMeta *option_meta; - gboolean success; - - option_meta = _get_option_meta(name); - if (!option_meta) { - if (!name) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing option name")); - } else { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid option '%s'"), - name); - } - return FALSE; - } - - if (!value) - return TRUE; - - switch (option_meta->opt_type) { - case NM_BOND_OPTION_TYPE_INT: - success = validate_int(name, value, option_meta); - goto handle_error; - case NM_BOND_OPTION_TYPE_BOTH: - success = - (validate_int(name, value, option_meta) || validate_list(name, value, option_meta)); - goto handle_error; - case NM_BOND_OPTION_TYPE_IP: - nm_assert(nm_streq0(name, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)); - return validate_ip(name, value, error); - case NM_BOND_OPTION_TYPE_MAC: - success = nm_utils_hwaddr_valid(value, ETH_ALEN); - goto handle_error; - case NM_BOND_OPTION_TYPE_IFNAME: - success = validate_ifname(name, value); - goto handle_error; - } - - nm_assert_not_reached(); - success = FALSE; - -handle_error: - if (!success) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid value '%s' for option '%s'"), - value, - name); - } - return success; -} - -/** - * nm_setting_bond_validate_option: - * @name: the name of the option to validate - * @value (allow-none): the value of the option to validate. - * - * Checks whether @name is a valid bond option and @value is a valid value for - * the @name. If @value is %NULL, the function only validates the option name. - * - * Returns: %TRUE, if the @value is valid for the given name. - * If the @name is not a valid option, %FALSE will be returned. - **/ -gboolean -nm_setting_bond_validate_option(const char *name, const char *value) -{ - return _nm_setting_bond_validate_option(name, value, NULL); -} - -/** - * nm_setting_bond_get_option_by_name: - * @setting: the #NMSettingBond - * @name: the option name for which to retrieve the value - * - * Returns the value associated with the bonding option specified by - * @name, if it exists. - * - * Returns: the value, or %NULL if the key/value pair was never added to the - * setting; the value is owned by the setting and must not be modified - **/ -const char * -nm_setting_bond_get_option_by_name(NMSettingBond *setting, const char *name) -{ - g_return_val_if_fail(NM_IS_SETTING_BOND(setting), NULL); - - return _bond_get_option(setting, name); -} - -/** - * nm_setting_bond_add_option: - * @setting: the #NMSettingBond - * @name: name for the option - * @value: value for the option - * - * Add an option to the table. Adding a new name replaces any existing name/value pair - * that may already exist. - * - * Returns: returns %FALSE if either @name or @value is %NULL, in that case - * the option is not set. Otherwise, the function does not fail and does not validate - * the arguments. All validation happens via nm_connection_verify() or do basic validation - * yourself with nm_setting_bond_validate_option(). - * - * Note: Before 1.30, libnm would perform basic validation of the name and the value - * via nm_setting_bond_validate_option() and reject the request by returning FALSE. - * Since 1.30, libnm no longer rejects any values as the setter is not supposed - * to perform validation. - **/ -gboolean -nm_setting_bond_add_option(NMSettingBond *setting, const char *name, const char *value) -{ - NMSettingBondPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_BOND(setting), FALSE); - - if (!name) - return FALSE; - if (!value) - return FALSE; - - priv = NM_SETTING_BOND_GET_PRIVATE(setting); - - nm_clear_g_free(&priv->options_idx_cache); - g_hash_table_insert(priv->options, g_strdup(name), g_strdup(value)); - _notify(setting, PROP_OPTIONS); - return TRUE; -} - -/** - * nm_setting_bond_remove_option: - * @setting: the #NMSettingBond - * @name: name of the option to remove - * - * Remove the bonding option referenced by @name from the internal option - * list. - * - * Returns: %TRUE if the option was found and removed from the internal option - * list, %FALSE if it was not. - **/ -gboolean -nm_setting_bond_remove_option(NMSettingBond *setting, const char *name) -{ - NMSettingBondPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_BOND(setting), FALSE); - - priv = NM_SETTING_BOND_GET_PRIVATE(setting); - - if (!g_hash_table_remove(priv->options, name)) - return FALSE; - - nm_clear_g_free(&priv->options_idx_cache); - _notify(setting, PROP_OPTIONS); - return TRUE; -} - -/** - * nm_setting_bond_get_valid_options: - * @setting: (allow-none): the #NMSettingBond - * - * Returns a list of valid bond options. - * - * The @setting argument is unused and may be passed as %NULL. - * - * Returns: (transfer none): a %NULL-terminated array of strings of valid bond options. - **/ -const char ** -nm_setting_bond_get_valid_options(NMSettingBond *setting) -{ - return (const char **) valid_options_lst; -} - -/** - * nm_setting_bond_get_option_default: - * @setting: the #NMSettingBond - * @name: the name of the option - * - * Returns: the value of the bond option if not overridden by an entry in - * the #NMSettingBond:options property. - **/ -const char * -nm_setting_bond_get_option_default(NMSettingBond *setting, const char *name) -{ - g_return_val_if_fail(NM_IS_SETTING_BOND(setting), NULL); - - if (!name) - return NULL; - - return _bond_get_option_normalized(setting, name, TRUE); -} - -/** - * nm_setting_bond_get_option_normalized: - * @setting: the #NMSettingBond - * @name: the name of the option - * - * Since: 1.24 - * - * Returns: the value of the bond option after normalization, which is what NetworkManager - * will actually apply when activating the connection. %NULL if the option won't be applied - * to the connection. - **/ -const char * -nm_setting_bond_get_option_normalized(NMSettingBond *setting, const char *name) -{ - g_return_val_if_fail(NM_IS_SETTING_BOND(setting), NULL); - g_return_val_if_fail(name, NULL); - - return _bond_get_option_normalized(setting, name, FALSE); -} - -/** - * nm_setting_bond_get_option_type: - * @setting: the #NMSettingBond - * @name: the name of the option - * - * Returns: the type of the bond option. - **/ -NMBondOptionType -_nm_setting_bond_get_option_type(NMSettingBond *setting, const char *name) -{ - const OptionMeta *option_meta; - - g_return_val_if_fail(NM_IS_SETTING_BOND(setting), NM_BOND_OPTION_TYPE_INT); - - option_meta = _get_option_meta(name); - - g_return_val_if_fail(option_meta, NM_BOND_OPTION_TYPE_INT); - - return option_meta->opt_type; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingBond * self = NM_SETTING_BOND(setting); - NMSettingBondPrivate * priv = NM_SETTING_BOND_GET_PRIVATE(setting); - int miimon; - int arp_interval; - int num_grat_arp; - int num_unsol_na; - const char * mode_str; - const char * arp_ip_target = NULL; - const char * lacp_rate; - const char * primary; - NMBondMode bond_mode; - guint i; - const NMUtilsNamedValue *n; - - _ensure_options_idx_cache(priv); - - if (priv->options_idx_cache) { - for (i = 0; priv->options_idx_cache[i].name; i++) { - n = &priv->options_idx_cache[i]; - - if (!n->value_str || !_nm_setting_bond_validate_option(n->name, n->value_str, error)) { - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BOND_SETTING_NAME, - NM_SETTING_BOND_OPTIONS); - return FALSE; - } - } - } - - miimon = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_MIIMON)); - arp_interval = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_ARP_INTERVAL)); - num_grat_arp = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP)); - num_unsol_na = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)); - - /* Option restrictions: - * - * arp_interval conflicts [ alb, tlb ] - * arp_interval needs arp_ip_target - * arp_validate does not work with [ BOND_MODE_8023AD, BOND_MODE_TLB, BOND_MODE_ALB ] - * downdelay needs miimon - * updelay needs miimon - * primary needs [ active-backup, tlb, alb ] - */ - - /* Verify bond mode */ - mode_str = _bond_get_option(self, NM_SETTING_BOND_OPTION_MODE); - if (!mode_str) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("mandatory option '%s' is missing"), - NM_SETTING_BOND_OPTION_MODE); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - bond_mode = _nm_setting_bond_mode_from_string(mode_str); - if (bond_mode == NM_BOND_MODE_UNKNOWN) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for '%s'"), - mode_str, - NM_SETTING_BOND_OPTION_MODE); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - - /* Make sure mode is compatible with other settings */ - if (NM_IN_SET(bond_mode, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB)) { - if (arp_interval > 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s=%s' is incompatible with '%s > 0'"), - NM_SETTING_BOND_OPTION_MODE, - mode_str, - NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - } - - primary = _bond_get_option(self, NM_SETTING_BOND_OPTION_PRIMARY); - if (NM_IN_SET(bond_mode, NM_BOND_MODE_ACTIVEBACKUP, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB)) { - GError *tmp_error = NULL; - - if (primary && !nm_utils_ifname_valid_kernel(primary, &tmp_error)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not valid for the '%s' option: %s"), - primary, - NM_SETTING_BOND_OPTION_PRIMARY, - tmp_error->message); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - g_error_free(tmp_error); - return FALSE; - } - } else if (primary) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option is only valid for '%s=%s'"), - NM_SETTING_BOND_OPTION_PRIMARY, - NM_SETTING_BOND_OPTION_MODE, - "active-backup"); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - - if (connection && nm_connection_get_setting_infiniband(connection)) { - if (bond_mode != NM_BOND_MODE_ACTIVEBACKUP) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s=%s' is not a valid configuration for '%s'"), - NM_SETTING_BOND_OPTION_MODE, - mode_str, - NM_SETTING_INFINIBAND_SETTING_NAME); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - } - - if (miimon == 0) { - /* updelay and downdelay need miimon to be enabled to be valid */ - if (_atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_UPDELAY))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option requires '%s' option to be enabled"), - NM_SETTING_BOND_OPTION_UPDELAY, - NM_SETTING_BOND_OPTION_MIIMON); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - - if (_atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_DOWNDELAY))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option requires '%s' option to be enabled"), - NM_SETTING_BOND_OPTION_DOWNDELAY, - NM_SETTING_BOND_OPTION_MIIMON); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - } - - /* arp_ip_target can only be used with arp_interval, and must - * contain a comma-separated list of IPv4 addresses. - */ - arp_ip_target = _bond_get_option(self, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - if (arp_interval > 0) { - if (!arp_ip_target) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option requires '%s' option to be set"), - NM_SETTING_BOND_OPTION_ARP_INTERVAL, - NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - } else { - if (arp_ip_target) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option requires '%s' option to be set"), - NM_SETTING_BOND_OPTION_ARP_IP_TARGET, - NM_SETTING_BOND_OPTION_ARP_INTERVAL); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - } - - lacp_rate = _bond_get_option(self, NM_SETTING_BOND_OPTION_LACP_RATE); - if (lacp_rate && bond_mode != NM_BOND_MODE_8023AD && !NM_IN_STRSET(lacp_rate, "0", "slow")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option is only valid with mode '%s'"), - NM_SETTING_BOND_OPTION_LACP_RATE, - "802.3ad"); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - - if (_bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP) - && _bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA) - && num_grat_arp != num_unsol_na) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' and '%s' cannot have different values"), - NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, - NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return FALSE; - } - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ - - if (!NM_IN_STRSET(mode_str, - "802.3ad", - "active-backup", - "balance-rr", - "balance-alb", - "balance-tlb", - "balance-xor", - "broadcast")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option should be string"), - NM_SETTING_BOND_OPTION_MODE); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - - /* normalize unsupported options for the current mode */ - for (i = 0; priv->options_idx_cache[i].name; i++) { - n = &priv->options_idx_cache[i]; - if (!_nm_setting_bond_option_supported(n->name, bond_mode)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option is not valid with mode '%s'"), - n->name, - mode_str); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - } - - return TRUE; -} - -/*****************************************************************************/ - -static gboolean -options_equal_asym(NMSettingBond *s_bond, NMSettingBond *s_bond2, NMSettingCompareFlags flags) -{ - GHashTableIter iter; - const char * key, *value; - - g_hash_table_iter_init(&iter, NM_SETTING_BOND_GET_PRIVATE(s_bond)->options); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) { - /* when doing an inferrable match, the active-slave should be ignored - * as it might be differ from the setting in the connection. - * - * Also, the fail_over_mac setting can change, see for example - * https://bugzilla.redhat.com/show_bug.cgi?id=1375558#c8 */ - if (NM_IN_STRSET(key, "fail_over_mac", "active_slave")) - continue; - } - - if (!nm_streq0(value, _bond_get_option(s_bond2, key))) - return FALSE; - } - - return TRUE; -} - -static gboolean -options_equal(NMSettingBond *s_bond, NMSettingBond *s_bond2, NMSettingCompareFlags flags) -{ - return options_equal_asym(s_bond, s_bond2, flags) && options_equal_asym(s_bond2, s_bond, flags); -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_BOND_OPTIONS)) { - return (!set_b || options_equal(NM_SETTING_BOND(set_a), NM_SETTING_BOND(set_b), flags)); - } - - return NM_SETTING_CLASS(nm_setting_bond_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_OPTIONS: - g_value_take_boxed(value, _nm_utils_copy_strdict(priv->options)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_OPTIONS: - nm_clear_g_free(&priv->options_idx_cache); - g_hash_table_unref(priv->options); - priv->options = _nm_utils_copy_strdict(g_value_get_boxed(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_bond_init(NMSettingBond *setting) -{ - NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(setting); - - priv->options = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); - - /* Default values: */ - nm_setting_bond_add_option(setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr"); -} - -/** - * nm_setting_bond_new: - * - * Creates a new #NMSettingBond object with default values. - * - * Returns: (transfer full): the new empty #NMSettingBond object - **/ -NMSetting * -nm_setting_bond_new(void) -{ - return g_object_new(NM_TYPE_SETTING_BOND, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(object); - - nm_clear_g_free(&priv->options_idx_cache); - g_hash_table_destroy(priv->options); - - G_OBJECT_CLASS(nm_setting_bond_parent_class)->finalize(object); -} - -static void -nm_setting_bond_class_init(NMSettingBondClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingBondPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->compare_property = compare_property; - - /** - * NMSettingBond:options: (type GHashTable(utf8,utf8)): - * - * Dictionary of key/value pairs of bonding options. Both keys and values - * must be strings. Option names must contain only alphanumeric characters - * (ie, [a-zA-Z0-9]). - **/ - /* ---ifcfg-rh--- - * property: options - * variable: BONDING_OPTS - * description: Bonding options. - * example: BONDING_OPTS="miimon=100 mode=broadcast" - * ---end--- - */ - obj_properties[PROP_OPTIONS] = g_param_spec_boxed( - NM_SETTING_BOND_OPTIONS, - "", - "", - G_TYPE_HASH_TABLE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_OPTIONS], - &nm_sett_info_propert_type_strdict); - - /* ---dbus--- - * property: interface-name - * format: string - * description: Deprecated in favor of connection.interface-name, but can - * be used for backward-compatibility with older daemons, to set the - * bond's interface name. - * ---end--- - */ - _nm_properties_override_dbus(properties_override, - "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_BOND, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-bond.h b/libnm-core/nm-setting-bond.h deleted file mode 100644 index 25ae8c36e7..0000000000 --- a/libnm-core/nm-setting-bond.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2013 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_BOND_H__ -#define __NM_SETTING_BOND_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_BOND (nm_setting_bond_get_type()) -#define NM_SETTING_BOND(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_BOND, NMSettingBond)) -#define NM_SETTING_BOND_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_BOND, NMSettingBondClass)) -#define NM_IS_SETTING_BOND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_BOND)) -#define NM_IS_SETTING_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_BOND)) -#define NM_SETTING_BOND_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_BOND, NMSettingBondClass)) - -#define NM_SETTING_BOND_SETTING_NAME "bond" - -#define NM_SETTING_BOND_OPTIONS "options" - -/* Valid options for the 'options' property */ -#define NM_SETTING_BOND_OPTION_MODE "mode" -#define NM_SETTING_BOND_OPTION_MIIMON "miimon" -#define NM_SETTING_BOND_OPTION_DOWNDELAY "downdelay" -#define NM_SETTING_BOND_OPTION_UPDELAY "updelay" -#define NM_SETTING_BOND_OPTION_ARP_INTERVAL "arp_interval" -#define NM_SETTING_BOND_OPTION_ARP_IP_TARGET "arp_ip_target" -#define NM_SETTING_BOND_OPTION_ARP_VALIDATE "arp_validate" -#define NM_SETTING_BOND_OPTION_PRIMARY "primary" -#define NM_SETTING_BOND_OPTION_PRIMARY_RESELECT "primary_reselect" -#define NM_SETTING_BOND_OPTION_FAIL_OVER_MAC "fail_over_mac" -#define NM_SETTING_BOND_OPTION_USE_CARRIER "use_carrier" -#define NM_SETTING_BOND_OPTION_AD_SELECT "ad_select" -#define NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY "xmit_hash_policy" -#define NM_SETTING_BOND_OPTION_RESEND_IGMP "resend_igmp" -#define NM_SETTING_BOND_OPTION_LACP_RATE "lacp_rate" -#define NM_SETTING_BOND_OPTION_ACTIVE_SLAVE "active_slave" -#define NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO "ad_actor_sys_prio" -#define NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM "ad_actor_system" -#define NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY "ad_user_port_key" -#define NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE "all_slaves_active" -#define NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS "arp_all_targets" -#define NM_SETTING_BOND_OPTION_MIN_LINKS "min_links" -#define NM_SETTING_BOND_OPTION_NUM_GRAT_ARP "num_grat_arp" -#define NM_SETTING_BOND_OPTION_NUM_UNSOL_NA "num_unsol_na" -#define NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE "packets_per_slave" -#define NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB "tlb_dynamic_lb" -#define NM_SETTING_BOND_OPTION_LP_INTERVAL "lp_interval" - -/** - * NMSettingBond: - * - * Bonding Settings - */ -struct _NMSettingBond { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingBondClass; - -GType nm_setting_bond_get_type(void); - -NMSetting * nm_setting_bond_new(void); -guint32 nm_setting_bond_get_num_options(NMSettingBond *setting); -gboolean nm_setting_bond_get_option(NMSettingBond *setting, - guint32 idx, - const char ** out_name, - const char ** out_value); -const char *nm_setting_bond_get_option_by_name(NMSettingBond *setting, const char *name); -gboolean nm_setting_bond_add_option(NMSettingBond *setting, const char *name, const char *value); -gboolean nm_setting_bond_remove_option(NMSettingBond *setting, const char *name); - -gboolean nm_setting_bond_validate_option(const char *name, const char *value); - -const char **nm_setting_bond_get_valid_options(NMSettingBond *setting); - -const char *nm_setting_bond_get_option_default(NMSettingBond *setting, const char *name); - -NM_AVAILABLE_IN_1_24 -const char *nm_setting_bond_get_option_normalized(NMSettingBond *setting, const char *name); - -G_END_DECLS - -#endif /* __NM_SETTING_BOND_H__ */ diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c deleted file mode 100644 index 74c6384772..0000000000 --- a/libnm-core/nm-setting-bridge-port.c +++ /dev/null @@ -1,589 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2012 - 2013 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-bridge-port.h" - -#include -#include - -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-bridge.h" - -/** - * SECTION:nm-setting-bridge-port - * @short_description: Describes connection properties for bridge ports - * - * The #NMSettingBridgePort object is a #NMSetting subclass that describes - * optional properties that apply to bridge ports. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingBridgePort, - PROP_PRIORITY, - PROP_PATH_COST, - PROP_HAIRPIN_MODE, - PROP_VLANS, ); - -typedef struct { - GPtrArray *vlans; - guint16 priority; - guint16 path_cost; - bool hairpin_mode : 1; -} NMSettingBridgePortPrivate; - -G_DEFINE_TYPE(NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING) - -#define NM_SETTING_BRIDGE_PORT_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortPrivate)) - -static int -vlan_ptr_cmp(gconstpointer a, gconstpointer b) -{ - const NMBridgeVlan *vlan_a = *(const NMBridgeVlan **) a; - const NMBridgeVlan *vlan_b = *(const NMBridgeVlan **) b; - - return nm_bridge_vlan_cmp(vlan_a, vlan_b); -} - -gboolean -_nm_setting_bridge_port_sort_vlans(NMSettingBridgePort *setting) -{ - NMSettingBridgePortPrivate *priv; - gboolean need_sort = FALSE; - guint i; - - priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - for (i = 1; i < priv->vlans->len; i++) { - NMBridgeVlan *vlan_prev = priv->vlans->pdata[i - 1]; - NMBridgeVlan *vlan = priv->vlans->pdata[i]; - - if (nm_bridge_vlan_cmp(vlan_prev, vlan) > 0) { - need_sort = TRUE; - break; - } - } - - if (need_sort) { - g_ptr_array_sort(priv->vlans, vlan_ptr_cmp); - _notify(setting, PROP_VLANS); - } - - return need_sort; -} - -/*****************************************************************************/ - -/** - * nm_setting_bridge_port_get_priority: - * @setting: the #NMSettingBridgePort - * - * Returns: the #NMSettingBridgePort:priority property of the setting - **/ -guint16 -nm_setting_bridge_port_get_priority(NMSettingBridgePort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), 0); - - return NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting)->priority; -} - -/** - * nm_setting_bridge_port_get_path_cost: - * @setting: the #NMSettingBridgePort - * - * Returns: the #NMSettingBridgePort:path-cost property of the setting - **/ -guint16 -nm_setting_bridge_port_get_path_cost(NMSettingBridgePort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), 0); - - return NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting)->path_cost; -} - -/** - * nm_setting_bridge_port_get_hairpin_mode: - * @setting: the #NMSettingBridgePort - * - * Returns: the #NMSettingBridgePort:hairpin-mode property of the setting - **/ -gboolean -nm_setting_bridge_port_get_hairpin_mode(NMSettingBridgePort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), FALSE); - - return NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting)->hairpin_mode; -} - -/** - * nm_setting_bridge_port_add_vlan: - * @setting: the #NMSettingBridgePort - * @vlan: the vlan to add - * - * Appends a new vlan and associated information to the setting. The - * given vlan gets sealed and a reference to it is added. - * - * Since: 1.18 - **/ -void -nm_setting_bridge_port_add_vlan(NMSettingBridgePort *setting, NMBridgeVlan *vlan) -{ - NMSettingBridgePortPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting)); - g_return_if_fail(vlan); - - priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - nm_bridge_vlan_seal(vlan); - nm_bridge_vlan_ref(vlan); - - g_ptr_array_add(priv->vlans, vlan); - _notify(setting, PROP_VLANS); -} - -/** - * nm_setting_bridge_port_get_num_vlans: - * @setting: the #NMSettingBridgePort - * - * Returns: the number of VLANs - * - * Since: 1.18 - **/ -guint -nm_setting_bridge_port_get_num_vlans(NMSettingBridgePort *setting) -{ - NMSettingBridgePortPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), 0); - priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - return priv->vlans->len; -} - -/** - * nm_setting_bridge_port_get_vlan: - * @setting: the #NMSettingBridgePort - * @idx: index number of the VLAN to return - * - * Returns: (transfer none): the VLAN at index @idx - * - * Since: 1.18 - **/ -NMBridgeVlan * -nm_setting_bridge_port_get_vlan(NMSettingBridgePort *setting, guint idx) -{ - NMSettingBridgePortPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), NULL); - priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - g_return_val_if_fail(idx < priv->vlans->len, NULL); - - return priv->vlans->pdata[idx]; -} - -/** - * nm_setting_bridge_port_remove_vlan: - * @setting: the #NMSettingBridgePort - * @idx: index number of the VLAN. - * - * Removes the vlan at index @idx. - * - * Since: 1.18 - **/ -void -nm_setting_bridge_port_remove_vlan(NMSettingBridgePort *setting, guint idx) -{ - NMSettingBridgePortPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting)); - priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - g_return_if_fail(idx < priv->vlans->len); - - g_ptr_array_remove_index(priv->vlans, idx); - _notify(setting, PROP_VLANS); -} - -/** - * nm_setting_bridge_port_remove_vlan_by_vid: - * @setting: the #NMSettingBridgePort - * @vid_start: the vlan start index - * @vid_end: the vlan end index - * - * Remove the VLAN with range @vid_start to @vid_end. - * If @vid_end is zero, it is assumed to be equal to @vid_start - * and so the single-id VLAN with id @vid_start is removed. - * - * Returns: %TRUE if the vlan was found and removed; %FALSE otherwise - * - * Since: 1.18 - **/ -gboolean -nm_setting_bridge_port_remove_vlan_by_vid(NMSettingBridgePort *setting, - guint16 vid_start, - guint16 vid_end) -{ - NMSettingBridgePortPrivate *priv; - guint i; - - if (vid_end == 0) - vid_end = vid_start; - - g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), FALSE); - - priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - for (i = 0; i < priv->vlans->len; i++) { - NMBridgeVlan *vlan = priv->vlans->pdata[i]; - guint16 v_start = 0; - guint16 v_end = 0; - - nm_bridge_vlan_get_vid_range(vlan, &v_start, &v_end); - if (v_start == vid_start && v_end == vid_end) { - g_ptr_array_remove_index(priv->vlans, i); - _notify(setting, PROP_VLANS); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_bridge_port_clear_vlans: - * @setting: the #NMSettingBridgePort - * - * Removes all configured VLANs. - * - * Since: 1.18 - **/ -void -nm_setting_bridge_port_clear_vlans(NMSettingBridgePort *setting) -{ - NMSettingBridgePortPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting)); - priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - if (priv->vlans->len != 0) { - g_ptr_array_set_size(priv->vlans, 0); - _notify(setting, PROP_VLANS); - } -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingBridgePortPrivate *priv; - - priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - if (connection) { - NMSettingConnection *s_con; - const char * slave_type; - - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("missing setting")); - g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); - return FALSE; - } - - slave_type = nm_setting_connection_get_slave_type(s_con); - if (slave_type && strcmp(slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting must have the slave-type set to '%s'. " - "Instead it is '%s'"), - NM_SETTING_BRIDGE_PORT_SETTING_NAME, - NM_SETTING_BRIDGE_SETTING_NAME, - slave_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return FALSE; - } - } - - if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, - FALSE, - error, - NM_SETTING_BRIDGE_PORT_SETTING_NAME, - NM_SETTING_BRIDGE_PORT_VLANS)) - return FALSE; - - /* Failures from here on are NORMALIZABLE... */ - - if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, - TRUE, - error, - NM_SETTING_BRIDGE_PORT_SETTING_NAME, - NM_SETTING_BRIDGE_PORT_VLANS)) - return NM_SETTING_VERIFY_NORMALIZABLE; - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingBridgePortPrivate *priv_a; - NMSettingBridgePortPrivate *priv_b; - guint i; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_BRIDGE_PORT_VLANS)) { - if (set_b) { - priv_a = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(set_a); - priv_b = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(set_b); - - if (priv_a->vlans->len != priv_b->vlans->len) - return FALSE; - for (i = 0; i < priv_a->vlans->len; i++) { - if (nm_bridge_vlan_cmp(priv_a->vlans->pdata[i], priv_b->vlans->pdata[i])) - return FALSE; - } - } - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_bridge_port_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_PRIORITY: - g_value_set_uint(value, priv->priority); - break; - case PROP_PATH_COST: - g_value_set_uint(value, priv->path_cost); - break; - case PROP_HAIRPIN_MODE: - g_value_set_boolean(value, priv->hairpin_mode); - break; - case PROP_VLANS: - g_value_take_boxed(value, - _nm_utils_copy_array(priv->vlans, - (NMUtilsCopyFunc) nm_bridge_vlan_ref, - (GDestroyNotify) nm_bridge_vlan_unref)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_PRIORITY: - priv->priority = g_value_get_uint(value); - break; - case PROP_PATH_COST: - priv->path_cost = g_value_get_uint(value); - break; - case PROP_HAIRPIN_MODE: - priv->hairpin_mode = g_value_get_boolean(value); - break; - case PROP_VLANS: - g_ptr_array_unref(priv->vlans); - priv->vlans = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) _nm_bridge_vlan_dup_and_seal, - (GDestroyNotify) nm_bridge_vlan_unref); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_bridge_port_init(NMSettingBridgePort *setting) -{ - NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); - - priv->vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); - - priv->priority = NM_BRIDGE_PORT_PRIORITY_DEF; - priv->path_cost = NM_BRIDGE_PORT_PATH_COST_DEF; -} - -/** - * nm_setting_bridge_port_new: - * - * Creates a new #NMSettingBridgePort object with default values. - * - * Returns: (transfer full): the new empty #NMSettingBridgePort object - **/ -NMSetting * -nm_setting_bridge_port_new(void) -{ - return g_object_new(NM_TYPE_SETTING_BRIDGE_PORT, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(object); - - g_ptr_array_unref(priv->vlans); - - G_OBJECT_CLASS(nm_setting_bridge_port_parent_class)->finalize(object); -} - -static void -nm_setting_bridge_port_class_init(NMSettingBridgePortClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingBridgePortPrivate)); - - object_class->finalize = finalize; - object_class->get_property = get_property; - object_class->set_property = set_property; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - - /** - * NMSettingBridgePort:priority: - * - * The Spanning Tree Protocol (STP) priority of this bridge port. - **/ - /* ---ifcfg-rh--- - * property: priority - * variable: BRIDGING_OPTS: priority= - * values: 0 - 63 - * default: 32 - * description: STP priority. - * ---end--- - */ - obj_properties[PROP_PRIORITY] = - g_param_spec_uint(NM_SETTING_BRIDGE_PORT_PRIORITY, - "", - "", - NM_BRIDGE_PORT_PRIORITY_MIN, - NM_BRIDGE_PORT_PRIORITY_MAX, - NM_BRIDGE_PORT_PRIORITY_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridgePort:path-cost: - * - * The Spanning Tree Protocol (STP) port cost for destinations via this - * port. - **/ - /* ---ifcfg-rh--- - * property: path-cost - * variable: BRIDGING_OPTS: path_cost= - * values: 1 - 65535 - * default: 100 - * description: STP cost. - * ---end--- - */ - obj_properties[PROP_PATH_COST] = g_param_spec_uint(NM_SETTING_BRIDGE_PORT_PATH_COST, - "", - "", - NM_BRIDGE_PORT_PATH_COST_MIN, - NM_BRIDGE_PORT_PATH_COST_MAX, - NM_BRIDGE_PORT_PATH_COST_DEF, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridgePort:hairpin-mode: - * - * Enables or disables "hairpin mode" for the port, which allows frames to - * be sent back out through the port the frame was received on. - **/ - /* ---ifcfg-rh--- - * property: hairpin-mode - * variable: BRIDGING_OPTS: hairpin_mode= - * default: yes - * description: Hairpin mode of the bridge port. - * ---end--- - */ - obj_properties[PROP_HAIRPIN_MODE] = g_param_spec_boolean( - NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridgePort:vlans: (type GPtrArray(NMBridgeVlan)) - * - * Array of bridge VLAN objects. In addition to the VLANs - * specified here, the port will also have the default-pvid - * VLAN configured on the bridge by the bridge.vlan-default-pvid - * property. - * - * In nmcli the VLAN list can be specified with the following - * syntax: - * - * $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... - * - * where $vid is either a single id between 1 and 4094 or a - * range, represented as a couple of ids separated by a dash. - * - * Since: 1.18 - **/ - /* ---ifcfg-rh--- - * property: vlans - * variable: BRIDGE_PORT_VLANS - * description: List of VLANs on the bridge port - * example: BRIDGE_PORT_VLANS="1 pvid untagged,20,300-400 untagged" - * ---end--- - */ - obj_properties[PROP_VLANS] = g_param_spec_boxed(NM_SETTING_BRIDGE_PORT_VLANS, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_VLANS], - &nm_sett_info_propert_type_bridge_vlans); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_BRIDGE_PORT, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-bridge-port.h b/libnm-core/nm-setting-bridge-port.h deleted file mode 100644 index 679131d287..0000000000 --- a/libnm-core/nm-setting-bridge-port.h +++ /dev/null @@ -1,80 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2012 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_BRIDGE_PORT_H__ -#define __NM_SETTING_BRIDGE_PORT_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" -#include "nm-setting-bridge.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_BRIDGE_PORT (nm_setting_bridge_port_get_type()) -#define NM_SETTING_BRIDGE_PORT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePort)) -#define NM_SETTING_BRIDGE_PORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortClass)) -#define NM_IS_SETTING_BRIDGE_PORT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_BRIDGE_PORT)) -#define NM_IS_SETTING_BRIDGE_PORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_BRIDGE_PORT)) -#define NM_SETTING_BRIDGE_PORT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortClass)) - -#define NM_SETTING_BRIDGE_PORT_SETTING_NAME "bridge-port" - -#define NM_SETTING_BRIDGE_PORT_PRIORITY "priority" -#define NM_SETTING_BRIDGE_PORT_PATH_COST "path-cost" -#define NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE "hairpin-mode" -#define NM_SETTING_BRIDGE_PORT_VLANS "vlans" - -/** - * NMSettingBridgePort: - * - * Bridge Port Settings - */ -struct _NMSettingBridgePort { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingBridgePortClass; - -GType nm_setting_bridge_port_get_type(void); - -NMSetting *nm_setting_bridge_port_new(void); - -guint16 nm_setting_bridge_port_get_priority(NMSettingBridgePort *setting); - -guint16 nm_setting_bridge_port_get_path_cost(NMSettingBridgePort *setting); - -gboolean nm_setting_bridge_port_get_hairpin_mode(NMSettingBridgePort *setting); - -NM_AVAILABLE_IN_1_18 -void nm_setting_bridge_port_add_vlan(NMSettingBridgePort *setting, NMBridgeVlan *vlan); -NM_AVAILABLE_IN_1_18 -guint nm_setting_bridge_port_get_num_vlans(NMSettingBridgePort *setting); -NM_AVAILABLE_IN_1_18 -NMBridgeVlan *nm_setting_bridge_port_get_vlan(NMSettingBridgePort *setting, guint idx); -NM_AVAILABLE_IN_1_18 -void nm_setting_bridge_port_remove_vlan(NMSettingBridgePort *setting, guint idx); -NM_AVAILABLE_IN_1_18 -gboolean nm_setting_bridge_port_remove_vlan_by_vid(NMSettingBridgePort *setting, - guint16 vid_start, - guint16 vid_end); -NM_AVAILABLE_IN_1_18 -void nm_setting_bridge_port_clear_vlans(NMSettingBridgePort *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_BRIDGE_PORT_H__ */ diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c deleted file mode 100644 index 15d663db40..0000000000 --- a/libnm-core/nm-setting-bridge.c +++ /dev/null @@ -1,2292 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-bridge.h" - -#include -#include -#include - -#include "nm-glib-aux/nm-str-buf.h" -#include "nm-connection-private.h" -#include "nm-utils.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-bridge - * @short_description: Describes connection properties for bridges - * - * The #NMSettingBridge object is a #NMSetting subclass that describes properties - * necessary for bridging connections. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingBridge, - PROP_MAC_ADDRESS, - PROP_STP, - PROP_PRIORITY, - PROP_FORWARD_DELAY, - PROP_HELLO_TIME, - PROP_MAX_AGE, - PROP_AGEING_TIME, - PROP_GROUP_ADDRESS, - PROP_GROUP_FORWARD_MASK, - PROP_MULTICAST_HASH_MAX, - PROP_MULTICAST_LAST_MEMBER_COUNT, - PROP_MULTICAST_LAST_MEMBER_INTERVAL, - PROP_MULTICAST_MEMBERSHIP_INTERVAL, - PROP_MULTICAST_ROUTER, - PROP_MULTICAST_QUERIER, - PROP_MULTICAST_QUERIER_INTERVAL, - PROP_MULTICAST_QUERY_INTERVAL, - PROP_MULTICAST_QUERY_RESPONSE_INTERVAL, - PROP_MULTICAST_QUERY_USE_IFADDR, - PROP_MULTICAST_SNOOPING, - PROP_MULTICAST_STARTUP_QUERY_COUNT, - PROP_MULTICAST_STARTUP_QUERY_INTERVAL, - PROP_VLAN_FILTERING, - PROP_VLAN_DEFAULT_PVID, - PROP_VLAN_PROTOCOL, - PROP_VLAN_STATS_ENABLED, - PROP_VLANS, ); - -typedef struct { - GPtrArray *vlans; - char * mac_address; - char * multicast_router; - char * group_address; - char * vlan_protocol; - guint64 multicast_last_member_interval; - guint64 multicast_membership_interval; - guint64 multicast_querier_interval; - guint64 multicast_query_interval; - guint64 multicast_query_response_interval; - guint64 multicast_startup_query_interval; - guint32 ageing_time; - guint32 multicast_hash_max; - guint32 multicast_last_member_count; - guint32 multicast_startup_query_count; - guint16 priority; - guint16 forward_delay; - guint16 hello_time; - guint16 max_age; - guint16 vlan_default_pvid; - guint16 group_forward_mask; - bool multicast_snooping : 1; - bool vlan_filtering : 1; - bool stp : 1; - bool vlan_stats_enabled : 1; - bool multicast_query_use_ifaddr : 1; - bool multicast_querier : 1; -} NMSettingBridgePrivate; - -/** - * NMSettingBridge: - * - * Bridging Settings - */ -struct _NMSettingBridge { - NMSetting parent; - NMSettingBridgePrivate _priv; -}; - -struct _NMSettingBridgeClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING) - -#define NM_SETTING_BRIDGE_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMSettingBridge, NM_IS_SETTING_BRIDGE, NMSetting) - -/*****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMBridgeVlan, nm_bridge_vlan, _nm_bridge_vlan_dup, nm_bridge_vlan_unref) - -struct _NMBridgeVlan { - guint refcount; - guint16 vid_start; - guint16 vid_end; - bool untagged : 1; - bool pvid : 1; - bool sealed : 1; -}; - -static gboolean -NM_IS_BRIDGE_VLAN(const NMBridgeVlan *self, gboolean also_sealed) -{ - return self && self->refcount > 0 && (also_sealed || !self->sealed); -} - -/** - * nm_bridge_vlan_new: - * @vid_start: the start VLAN id, must be between 1 and 4094. - * @vid_end: the end VLAN id, must be 0 or between @vid_start and 4094. - * - * Creates a new #NMBridgeVlan object for the given VLAN id range. - * Setting @vid_end to 0 is equivalent to setting it to @vid_start - * and creates a single-id VLAN. - * - * Returns: (transfer full): the new #NMBridgeVlan object. - * - * Since: 1.18 - **/ -NMBridgeVlan * -nm_bridge_vlan_new(guint16 vid_start, guint16 vid_end) -{ - NMBridgeVlan *vlan; - - if (vid_end == 0) - vid_end = vid_start; - - g_return_val_if_fail(vid_start >= NM_BRIDGE_VLAN_VID_MIN, NULL); - g_return_val_if_fail(vid_end <= NM_BRIDGE_VLAN_VID_MAX, NULL); - g_return_val_if_fail(vid_start <= vid_end, NULL); - - vlan = g_slice_new0(NMBridgeVlan); - vlan->refcount = 1; - vlan->vid_start = vid_start; - vlan->vid_end = vid_end; - - return vlan; -} - -/** - * nm_bridge_vlan_ref: - * @vlan: the #NMBridgeVlan - * - * Increases the reference count of the object. - * - * Returns: the input argument @vlan object. - * - * Since: 1.18 - **/ -NMBridgeVlan * -nm_bridge_vlan_ref(NMBridgeVlan *vlan) -{ - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); - - nm_assert(vlan->refcount < G_MAXUINT); - - vlan->refcount++; - return vlan; -} - -/** - * nm_bridge_vlan_unref: - * @vlan: the #NMBridgeVlan - * - * Decreases the reference count of the object. If the reference count - * reaches zero the object will be destroyed. - * - * Since: 1.18 - **/ -void -nm_bridge_vlan_unref(NMBridgeVlan *vlan) -{ - g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE)); - - if (--vlan->refcount == 0) - g_slice_free(NMBridgeVlan, vlan); -} - -/** - * nm_bridge_vlan_cmp: - * @a: a #NMBridgeVlan - * @b: another #NMBridgeVlan - * - * Compare two bridge VLAN objects. - * - * Returns: zero of the two instances are equivalent or - * a non-zero integer otherwise. This defines a total ordering - * over the VLANs. Whether a VLAN is sealed or not does not - * affect the comparison. - * - * Since: 1.18 - **/ -int -nm_bridge_vlan_cmp(const NMBridgeVlan *a, const NMBridgeVlan *b) -{ - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(a, TRUE), 0); - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(b, TRUE), 0); - - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, vid_start); - NM_CMP_FIELD(a, b, vid_end); - NM_CMP_FIELD_BOOL(a, b, untagged); - NM_CMP_FIELD_BOOL(a, b, pvid); - - return 0; -} - -NMBridgeVlan * -_nm_bridge_vlan_dup(const NMBridgeVlan *vlan) -{ - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); - - if (vlan->sealed) { - nm_bridge_vlan_ref((NMBridgeVlan *) vlan); - return (NMBridgeVlan *) vlan; - } - - return nm_bridge_vlan_new_clone(vlan); -} - -NMBridgeVlan * -_nm_bridge_vlan_dup_and_seal(const NMBridgeVlan *vlan) -{ - NMBridgeVlan *new; - - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); - - new = _nm_bridge_vlan_dup(vlan); - nm_bridge_vlan_seal(new); - - return new; -} - -/** - * nm_bridge_vlan_get_vid_range: - * @vlan: the #NMBridgeVlan - * @vid_start: (out): location to store the VLAN id range start. - * @vid_end: (out): location to store the VLAN id range end - * - * Gets the VLAN id range. - * - * Returns: %TRUE is the VLAN specifies a range, %FALSE if it is - * a single-id VLAN. - * - * Since: 1.18 - **/ -gboolean -nm_bridge_vlan_get_vid_range(const NMBridgeVlan *vlan, guint16 *vid_start, guint16 *vid_end) -{ - /* with LTO and optimization, the compiler complains that the - * output variables are not initialized. In practice, the function - * only sets the output on success. But make the compiler happy. - */ - NM_SET_OUT(vid_start, 0); - NM_SET_OUT(vid_end, 0); - - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), 0); - - NM_SET_OUT(vid_start, vlan->vid_start); - NM_SET_OUT(vid_end, vlan->vid_end); - - return vlan->vid_start != vlan->vid_end; -} - -/** - * nm_bridge_vlan_is_untagged: - * @vlan: the #NMBridgeVlan - * - * Returns whether the VLAN is untagged. - * - * Returns: %TRUE if the VLAN is untagged, %FALSE otherwise - * - * Since: 1.18 - **/ -gboolean -nm_bridge_vlan_is_untagged(const NMBridgeVlan *vlan) -{ - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); - - return vlan->untagged; -} - -/** - * nm_bridge_vlan_is_pvid: - * @vlan: the #NMBridgeVlan - * - * Returns whether the VLAN is the PVID for the port. - * - * Returns: %TRUE if the VLAN is the PVID - * - * Since: 1.18 - **/ -gboolean -nm_bridge_vlan_is_pvid(const NMBridgeVlan *vlan) -{ - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); - - return vlan->pvid; -} - -/** - * nm_bridge_vlan_set_untagged: - * @vlan: the #NMBridgeVlan - * @value: the new value - * - * Change the value of the untagged property of the VLAN. - * - * Since: 1.18 - **/ -void -nm_bridge_vlan_set_untagged(NMBridgeVlan *vlan, gboolean value) -{ - g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, FALSE)); - - vlan->untagged = value; -} - -/** - * nm_bridge_vlan_set_pvid: - * @vlan: the #NMBridgeVlan - * @value: the new value - * - * Change the value of the PVID property of the VLAN. It - * is invalid to set the value to %TRUE for non-single-id - * VLANs. - * - * Since: 1.18 - **/ -void -nm_bridge_vlan_set_pvid(NMBridgeVlan *vlan, gboolean value) -{ - g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, FALSE)); - g_return_if_fail(!value || vlan->vid_start == vlan->vid_end); - - vlan->pvid = value; -} - -/** - * nm_bridge_vlan_is_sealed: - * @vlan: the #NMBridgeVlan instance - * - * Returns: whether @self is sealed or not. - * - * Since: 1.18 - */ -gboolean -nm_bridge_vlan_is_sealed(const NMBridgeVlan *vlan) -{ - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); - - return vlan->sealed; -} - -/** - * nm_bridge_vlan_seal: - * @vlan: the #NMBridgeVlan instance - * - * Seal the #NMBridgeVlan instance. Afterwards, it is a bug - * to call all functions that modify the instance (except ref/unref). - * A sealed instance cannot be unsealed again, but you can create - * an unsealed copy with nm_bridge_vlan_new_clone(). - * - * Since: 1.18 - */ -void -nm_bridge_vlan_seal(NMBridgeVlan *vlan) -{ - g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE)); - - vlan->sealed = TRUE; -} - -/** - * nm_bridge_vlan_new_clone: - * @vlan: the #NMBridgeVlan instance to copy - * - * Returns: (transfer full): a clone of @vlan. This instance - * is always unsealed. - * - * Since: 1.18 - */ -NMBridgeVlan * -nm_bridge_vlan_new_clone(const NMBridgeVlan *vlan) -{ - NMBridgeVlan *copy; - - g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); - - copy = nm_bridge_vlan_new(vlan->vid_start, vlan->vid_end); - copy->untagged = vlan->untagged; - copy->pvid = vlan->pvid; - - return copy; -} - -/** - * nm_bridge_vlan_to_str: - * @vlan: the %NMBridgeVlan - * @error: location of the error - * - * Convert a %NMBridgeVlan to a string. - * - * Returns: formatted string or %NULL - * - * Since: 1.18 - */ -char * -nm_bridge_vlan_to_str(const NMBridgeVlan *vlan, GError **error) -{ - NMStrBuf string; - - g_return_val_if_fail(vlan, NULL); - g_return_val_if_fail(!error || !*error, NULL); - - /* The function never fails at the moment, but it might in the - * future if more parameters are added to the object that could - * make it invalid. */ - - nm_str_buf_init(&string, NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE); - - if (vlan->vid_start == vlan->vid_end) - nm_str_buf_append_printf(&string, "%u", vlan->vid_start); - else - nm_str_buf_append_printf(&string, "%u-%u", vlan->vid_start, vlan->vid_end); - - if (nm_bridge_vlan_is_pvid(vlan)) - nm_str_buf_append(&string, " pvid"); - if (nm_bridge_vlan_is_untagged(vlan)) - nm_str_buf_append(&string, " untagged"); - - return nm_str_buf_finalize(&string, NULL); -} - -/** - * nm_bridge_vlan_from_str: - * @str: the string representation of a bridge VLAN - * @error: location of the error - * - * Parses the string representation of the queueing - * discipline to a %NMBridgeVlan instance. - * - * Returns: the %NMBridgeVlan or %NULL - * - * Since: 1.18 - */ -NMBridgeVlan * -nm_bridge_vlan_from_str(const char *str, GError **error) -{ - NMBridgeVlan * vlan = NULL; - gs_free const char **tokens = NULL; - guint i, vid_start, vid_end = 0; - gboolean pvid = FALSE; - gboolean untagged = FALSE; - char * c; - - g_return_val_if_fail(str, NULL); - g_return_val_if_fail(!error || !*error, NULL); - - tokens = nm_utils_escaped_tokens_split(str, NM_ASCII_SPACES); - if (!tokens || !tokens[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "missing VLAN id"); - return NULL; - } - - c = strchr(tokens[0], '-'); - if (c) - *c = '\0'; - - vid_start = _nm_utils_ascii_str_to_uint64(tokens[0], - 10, - NM_BRIDGE_VLAN_VID_MIN, - NM_BRIDGE_VLAN_VID_MAX, - G_MAXUINT); - if (vid_start == G_MAXUINT) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "invalid VLAN id range start '%s', must be in [1,4094]", - tokens[0]); - return NULL; - } - - if (c) { - vid_end = _nm_utils_ascii_str_to_uint64(c + 1, - 10, - NM_BRIDGE_VLAN_VID_MIN, - NM_BRIDGE_VLAN_VID_MAX, - G_MAXUINT); - if (vid_end == G_MAXUINT) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "invalid VLAN id range end '%s', must be in [1,4094]", - c + 1); - return NULL; - } - if (vid_end < vid_start) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "invalid VLAN id range %u-%u, start VLAN id must be less than end VLAN id", - vid_start, - vid_end); - return NULL; - } - } else - vid_end = vid_start; - - for (i = 1; tokens[i]; i++) { - if (nm_streq(tokens[i], "pvid")) { - if (vid_start != vid_end) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "a VLAN range can't be a PVID"); - return NULL; - } - pvid = TRUE; - } else if (nm_streq(tokens[i], "untagged")) - untagged = TRUE; - else { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "invalid option '%s'", - tokens[i]); - return NULL; - } - } - - vlan = nm_bridge_vlan_new(vid_start, vid_end); - nm_bridge_vlan_set_pvid(vlan, pvid); - nm_bridge_vlan_set_untagged(vlan, untagged); - - return vlan; -} - -/*****************************************************************************/ - -static int -vlan_ptr_cmp(gconstpointer a, gconstpointer b) -{ - const NMBridgeVlan *vlan_a = *(const NMBridgeVlan **) a; - const NMBridgeVlan *vlan_b = *(const NMBridgeVlan **) b; - - return nm_bridge_vlan_cmp(vlan_a, vlan_b); -} - -gboolean -_nm_setting_bridge_sort_vlans(NMSettingBridge *setting) -{ - NMSettingBridgePrivate *priv; - gboolean need_sort = FALSE; - guint i; - - priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - for (i = 1; i < priv->vlans->len; i++) { - NMBridgeVlan *vlan_prev = priv->vlans->pdata[i - 1]; - NMBridgeVlan *vlan = priv->vlans->pdata[i]; - - if (nm_bridge_vlan_cmp(vlan_prev, vlan) > 0) { - need_sort = TRUE; - break; - } - } - - if (need_sort) { - g_ptr_array_sort(priv->vlans, vlan_ptr_cmp); - _notify(setting, PROP_VLANS); - } - - return need_sort; -} - -/*****************************************************************************/ - -/** - * nm_setting_bridge_get_mac_address: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:mac-address property of the setting - **/ -const char * -nm_setting_bridge_get_mac_address(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->mac_address; -} - -/** - * nm_setting_bridge_get_stp: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:stp property of the setting - **/ -gboolean -nm_setting_bridge_get_stp(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->stp; -} - -/** - * nm_setting_bridge_get_priority: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:priority property of the setting - **/ -guint16 -nm_setting_bridge_get_priority(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->priority; -} - -/** - * nm_setting_bridge_get_forward_delay: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:forward-delay property of the setting - **/ -guint16 -nm_setting_bridge_get_forward_delay(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->forward_delay; -} - -/** - * nm_setting_bridge_get_hello_time: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:hello-time property of the setting - **/ -guint16 -nm_setting_bridge_get_hello_time(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->hello_time; -} - -/** - * nm_setting_bridge_get_max_age: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:max-age property of the setting - **/ -guint16 -nm_setting_bridge_get_max_age(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->max_age; -} - -/** - * nm_setting_bridge_get_ageing_time: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:ageing-time property of the setting - **/ -guint -nm_setting_bridge_get_ageing_time(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->ageing_time; -} - -/** - * nm_setting_bridge_get_group_forward_mask: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:group-forward-mask property of the setting - * - * Since: 1.10 - **/ -guint16 -nm_setting_bridge_get_group_forward_mask(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->group_forward_mask; -} - -/** - * nm_setting_bridge_get_multicast_snooping: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-snooping property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_bridge_get_multicast_snooping(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_snooping; -} - -/** - * nm_setting_bridge_get_vlan_filtering: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:vlan-filtering property of the setting - * - * Since: 1.18 - **/ -gboolean -nm_setting_bridge_get_vlan_filtering(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_filtering; -} - -/** - * nm_setting_bridge_get_vlan_default_pvid: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:vlan-default-pvid property of the setting - * - * Since: 1.18 - **/ -guint16 -nm_setting_bridge_get_vlan_default_pvid(NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 1); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_default_pvid; -} - -/** - * nm_setting_bridge_add_vlan: - * @setting: the #NMSettingBridge - * @vlan: the vlan to add - * - * Appends a new vlan and associated information to the setting. The - * given vlan gets sealed and a reference to it is added. - * - * Since: 1.18 - **/ -void -nm_setting_bridge_add_vlan(NMSettingBridge *setting, NMBridgeVlan *vlan) -{ - NMSettingBridgePrivate *priv; - - g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); - g_return_if_fail(vlan); - - priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - nm_bridge_vlan_seal(vlan); - nm_bridge_vlan_ref(vlan); - - g_ptr_array_add(priv->vlans, vlan); - _notify(setting, PROP_VLANS); -} - -/** - * nm_setting_bridge_get_num_vlans: - * @setting: the #NMSettingBridge - * - * Returns: the number of VLANs - * - * Since: 1.18 - **/ -guint -nm_setting_bridge_get_num_vlans(NMSettingBridge *setting) -{ - NMSettingBridgePrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - return priv->vlans->len; -} - -/** - * nm_setting_bridge_get_vlan: - * @setting: the #NMSettingBridge - * @idx: index number of the VLAN to return - * - * Returns: (transfer none): the VLAN at index @idx - * - * Since: 1.18 - **/ -NMBridgeVlan * -nm_setting_bridge_get_vlan(NMSettingBridge *setting, guint idx) -{ - NMSettingBridgePrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); - priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - g_return_val_if_fail(idx < priv->vlans->len, NULL); - - return priv->vlans->pdata[idx]; -} - -/** - * nm_setting_bridge_remove_vlan: - * @setting: the #NMSettingBridge - * @idx: index number of the VLAN. - * - * Removes the vlan at index @idx. - * - * Since: 1.18 - **/ -void -nm_setting_bridge_remove_vlan(NMSettingBridge *setting, guint idx) -{ - NMSettingBridgePrivate *priv; - - g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); - priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - g_return_if_fail(idx < priv->vlans->len); - - g_ptr_array_remove_index(priv->vlans, idx); - _notify(setting, PROP_VLANS); -} - -/** - * nm_setting_bridge_remove_vlan_by_vid: - * @setting: the #NMSettingBridge - * @vid_start: the vlan start index - * @vid_end: the vlan end index - * - * Remove the VLAN with range @vid_start to @vid_end. - * If @vid_end is zero, it is assumed to be equal to @vid_start - * and so the single-id VLAN with id @vid_start is removed. - * - * Returns: %TRUE if the vlan was found and removed; %FALSE otherwise - * - * Since: 1.18 - **/ -gboolean -nm_setting_bridge_remove_vlan_by_vid(NMSettingBridge *setting, guint16 vid_start, guint16 vid_end) -{ - NMSettingBridgePrivate *priv; - NMBridgeVlan * vlan; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); - priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - if (vid_end == 0) - vid_end = vid_start; - - for (i = 0; i < priv->vlans->len; i++) { - vlan = (NMBridgeVlan *) priv->vlans->pdata[i]; - if (vlan->vid_start == vid_start && vlan->vid_end == vid_end) { - g_ptr_array_remove_index(priv->vlans, i); - _notify(setting, PROP_VLANS); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_bridge_clear_vlans: - * @setting: the #NMSettingBridge - * - * Removes all configured VLANs. - * - * Since: 1.18 - **/ -void -nm_setting_bridge_clear_vlans(NMSettingBridge *setting) -{ - NMSettingBridgePrivate *priv; - - g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); - priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - if (priv->vlans->len != 0) { - g_ptr_array_set_size(priv->vlans, 0); - _notify(setting, PROP_VLANS); - } -} - -/** - * nm_setting_bridge_get_group_address: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:group-address property of the setting - * - * Since 1.24 - **/ -const char * -nm_setting_bridge_get_group_address(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->group_address; -} - -/** - * nm_setting_bridge_get_vlan_protocol: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:vlan-protocol property of the setting - * - * Since 1.24 - **/ -const char * -nm_setting_bridge_get_vlan_protocol(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_protocol; -} - -/** - * nm_setting_bridge_get_vlan_stats_enabled: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:vlan-stats-enabled property of the setting - * - * Since 1.24 - **/ -gboolean -nm_setting_bridge_get_vlan_stats_enabled(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_stats_enabled; -} - -/** - * nm_setting_bridge_get_multicast_router: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-router property of the setting - * - * Since 1.24 - **/ -const char * -nm_setting_bridge_get_multicast_router(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_router; -} - -/** - * nm_setting_bridge_get_multicast_query_use_ifaddr: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-query-use-ifaddr property of the setting - * - * Since 1.24 - **/ -gboolean -nm_setting_bridge_get_multicast_query_use_ifaddr(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_use_ifaddr; -} - -/** - * nm_setting_bridge_get_multicast_querier: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-querier property of the setting - * - * Since 1.24 - **/ -gboolean -nm_setting_bridge_get_multicast_querier(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_querier; -} - -/** - * nm_setting_bridge_get_multicast_hash_max: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-hash-max property of the setting - * - * Since 1.26 - **/ -guint32 -nm_setting_bridge_get_multicast_hash_max(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_hash_max; -} - -/** - * nm_setting_bridge_get_multicast_last_member_count: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-last-member-count property of the setting - * - * Since 1.26 - **/ -guint32 -nm_setting_bridge_get_multicast_last_member_count(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_last_member_count; -} - -/** - * nm_setting_bridge_get_multicast_last_member_interval: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-last-member-interval property of the setting - * - * Since 1.26 - **/ -guint64 -nm_setting_bridge_get_multicast_last_member_interval(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_last_member_interval; -} - -/** - * nm_setting_bridge_get_multicast_membership_interval: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-membership-interval property of the setting - * - * Since 1.26 - **/ -guint64 -nm_setting_bridge_get_multicast_membership_interval(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_membership_interval; -} - -/** - * nm_setting_bridge_get_multicast_querier_interval: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-querier-interval property of the setting - * - * Since 1.26 - **/ -guint64 -nm_setting_bridge_get_multicast_querier_interval(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_querier_interval; -} - -/** - * nm_setting_bridge_get_multicast_query_interval: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-query-interval property of the setting - * - * Since 1.26 - **/ -guint64 -nm_setting_bridge_get_multicast_query_interval(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_interval; -} - -/** - * nm_setting_bridge_get_multicast_query_response_interval: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-query-response-interval property of the setting - * - * Since 1.26 - **/ -guint64 -nm_setting_bridge_get_multicast_query_response_interval(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_response_interval; -} - -/** - * nm_setting_bridge_get_multicast_startup_query_count: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-query-response-interval property of the setting - * - * Since 1.26 - **/ -guint32 -nm_setting_bridge_get_multicast_startup_query_count(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_startup_query_count; -} - -/** - * nm_setting_bridge_get_multicast_startup_query_interval: - * @setting: the #NMSettingBridge - * - * Returns: the #NMSettingBridge:multicast-startup-query-interval property of the setting - * - * Since 1.26 - **/ -guint64 -nm_setting_bridge_get_multicast_startup_query_interval(const NMSettingBridge *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); - - return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_startup_query_interval; -} - -/*****************************************************************************/ - -static gboolean -check_range(guint32 val, guint32 min, guint32 max, gboolean zero, const char *prop, GError **error) -{ - if (zero && val == 0) - return TRUE; - - if (val < min || val > max) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value '%d' is out of range <%d-%d>"), - val, - min, - max); - g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, prop); - return FALSE; - } - return TRUE; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, ETH_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is not a valid MAC address")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_MAC_ADDRESS); - return FALSE; - } - - if (!check_range(priv->forward_delay, - NM_BRIDGE_FORWARD_DELAY_MIN, - NM_BRIDGE_FORWARD_DELAY_MAX, - !priv->stp, - NM_SETTING_BRIDGE_FORWARD_DELAY, - error)) - return FALSE; - - if (!check_range(priv->hello_time, - NM_BRIDGE_HELLO_TIME_MIN, - NM_BRIDGE_HELLO_TIME_MAX, - !priv->stp, - NM_SETTING_BRIDGE_HELLO_TIME, - error)) - return FALSE; - - if (!check_range(priv->max_age, - NM_BRIDGE_MAX_AGE_MIN, - NM_BRIDGE_MAX_AGE_MAX, - !priv->stp, - NM_SETTING_BRIDGE_MAX_AGE, - error)) - return FALSE; - - if (!check_range(priv->ageing_time, - NM_BRIDGE_AGEING_TIME_MIN, - NM_BRIDGE_AGEING_TIME_MAX, - !priv->stp, - NM_SETTING_BRIDGE_AGEING_TIME, - error)) - return FALSE; - - if (priv->group_forward_mask & 7) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the mask can't contain bits 0 (STP), 1 (MAC) or 2 (LACP)")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_GROUP_FORWARD_MASK); - return FALSE; - } - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, - FALSE, - error, - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_VLANS)) - return FALSE; - - if (priv->group_address && !_nm_utils_hwaddr_link_local_valid(priv->group_address)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is not a valid link local MAC address")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_GROUP_ADDRESS); - return FALSE; - } - - if (priv->vlan_protocol && !NM_IN_STRSET(priv->vlan_protocol, "802.1Q", "802.1ad")) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is not a valid VLAN filtering protocol")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_VLAN_PROTOCOL); - return FALSE; - } - - if (!NM_IN_STRSET(priv->multicast_router, NULL, "auto", "enabled", "disabled")) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is not a valid option")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_MULTICAST_ROUTER); - return FALSE; - } - - if (!nm_utils_is_power_of_two(priv->multicast_hash_max)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' option must be a power of 2"), - NM_SETTING_BRIDGE_MULTICAST_HASH_MAX); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_MULTICAST_HASH_MAX); - return FALSE; - } - - /* Failures from here on are NORMALIZABLE... */ - - if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, - TRUE, - error, - NM_SETTING_BRIDGE_SETTING_NAME, - NM_SETTING_BRIDGE_VLANS)) - return NM_SETTING_VERIFY_NORMALIZABLE; - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingBridgePrivate *priv_a; - NMSettingBridgePrivate *priv_b; - guint i; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_BRIDGE_VLANS)) { - if (set_b) { - priv_a = NM_SETTING_BRIDGE_GET_PRIVATE(set_a); - priv_b = NM_SETTING_BRIDGE_GET_PRIVATE(set_b); - - if (priv_a->vlans->len != priv_b->vlans->len) - return FALSE; - for (i = 0; i < priv_a->vlans->len; i++) { - if (nm_bridge_vlan_cmp(priv_a->vlans->pdata[i], priv_b->vlans->pdata[i])) - return FALSE; - } - } - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_bridge_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); - NMSettingBridge * setting = NM_SETTING_BRIDGE(object); - - switch (prop_id) { - case PROP_MAC_ADDRESS: - g_value_set_string(value, nm_setting_bridge_get_mac_address(setting)); - break; - case PROP_STP: - g_value_set_boolean(value, priv->stp); - break; - case PROP_PRIORITY: - g_value_set_uint(value, priv->priority); - break; - case PROP_FORWARD_DELAY: - g_value_set_uint(value, priv->forward_delay); - break; - case PROP_HELLO_TIME: - g_value_set_uint(value, priv->hello_time); - break; - case PROP_MAX_AGE: - g_value_set_uint(value, priv->max_age); - break; - case PROP_AGEING_TIME: - g_value_set_uint(value, priv->ageing_time); - break; - case PROP_GROUP_ADDRESS: - g_value_set_string(value, priv->group_address); - break; - case PROP_GROUP_FORWARD_MASK: - g_value_set_uint(value, priv->group_forward_mask); - break; - case PROP_MULTICAST_HASH_MAX: - g_value_set_uint(value, priv->multicast_hash_max); - break; - case PROP_MULTICAST_LAST_MEMBER_COUNT: - g_value_set_uint(value, priv->multicast_last_member_count); - break; - case PROP_MULTICAST_LAST_MEMBER_INTERVAL: - g_value_set_uint64(value, priv->multicast_last_member_interval); - break; - case PROP_MULTICAST_MEMBERSHIP_INTERVAL: - g_value_set_uint64(value, priv->multicast_membership_interval); - break; - case PROP_MULTICAST_SNOOPING: - g_value_set_boolean(value, priv->multicast_snooping); - break; - case PROP_MULTICAST_ROUTER: - g_value_set_string(value, priv->multicast_router); - break; - case PROP_MULTICAST_QUERIER: - g_value_set_boolean(value, priv->multicast_querier); - break; - case PROP_MULTICAST_QUERIER_INTERVAL: - g_value_set_uint64(value, priv->multicast_querier_interval); - break; - case PROP_MULTICAST_QUERY_INTERVAL: - g_value_set_uint64(value, priv->multicast_query_interval); - break; - case PROP_MULTICAST_QUERY_RESPONSE_INTERVAL: - g_value_set_uint64(value, priv->multicast_query_response_interval); - break; - case PROP_MULTICAST_QUERY_USE_IFADDR: - g_value_set_boolean(value, priv->multicast_query_use_ifaddr); - break; - case PROP_MULTICAST_STARTUP_QUERY_COUNT: - g_value_set_uint(value, priv->multicast_startup_query_count); - break; - case PROP_MULTICAST_STARTUP_QUERY_INTERVAL: - g_value_set_uint64(value, priv->multicast_startup_query_interval); - break; - case PROP_VLAN_FILTERING: - g_value_set_boolean(value, priv->vlan_filtering); - break; - case PROP_VLAN_DEFAULT_PVID: - g_value_set_uint(value, priv->vlan_default_pvid); - break; - case PROP_VLAN_PROTOCOL: - g_value_set_string(value, priv->vlan_protocol); - break; - case PROP_VLAN_STATS_ENABLED: - g_value_set_boolean(value, priv->vlan_stats_enabled); - break; - case PROP_VLANS: - g_value_take_boxed(value, - _nm_utils_copy_array(priv->vlans, - (NMUtilsCopyFunc) nm_bridge_vlan_ref, - (GDestroyNotify) nm_bridge_vlan_unref)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_MAC_ADDRESS: - g_free(priv->mac_address); - priv->mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); - break; - case PROP_STP: - priv->stp = g_value_get_boolean(value); - break; - case PROP_PRIORITY: - priv->priority = (guint16) g_value_get_uint(value); - break; - case PROP_FORWARD_DELAY: - priv->forward_delay = (guint16) g_value_get_uint(value); - break; - case PROP_HELLO_TIME: - priv->hello_time = (guint16) g_value_get_uint(value); - break; - case PROP_MAX_AGE: - priv->max_age = (guint16) g_value_get_uint(value); - break; - case PROP_AGEING_TIME: - priv->ageing_time = g_value_get_uint(value); - break; - case PROP_GROUP_ADDRESS: - g_free(priv->group_address); - priv->group_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); - break; - case PROP_GROUP_FORWARD_MASK: - priv->group_forward_mask = (guint16) g_value_get_uint(value); - break; - case PROP_MULTICAST_HASH_MAX: - priv->multicast_hash_max = g_value_get_uint(value); - break; - case PROP_MULTICAST_LAST_MEMBER_COUNT: - priv->multicast_last_member_count = g_value_get_uint(value); - break; - case PROP_MULTICAST_LAST_MEMBER_INTERVAL: - priv->multicast_last_member_interval = g_value_get_uint64(value); - break; - case PROP_MULTICAST_MEMBERSHIP_INTERVAL: - priv->multicast_membership_interval = g_value_get_uint64(value); - break; - case PROP_MULTICAST_SNOOPING: - priv->multicast_snooping = g_value_get_boolean(value); - break; - case PROP_MULTICAST_ROUTER: - g_free(priv->multicast_router); - priv->multicast_router = g_value_dup_string(value); - break; - case PROP_MULTICAST_QUERIER: - priv->multicast_querier = g_value_get_boolean(value); - break; - case PROP_MULTICAST_QUERIER_INTERVAL: - priv->multicast_querier_interval = g_value_get_uint64(value); - break; - case PROP_MULTICAST_QUERY_INTERVAL: - priv->multicast_query_interval = g_value_get_uint64(value); - break; - case PROP_MULTICAST_QUERY_RESPONSE_INTERVAL: - priv->multicast_query_response_interval = g_value_get_uint64(value); - break; - case PROP_MULTICAST_QUERY_USE_IFADDR: - priv->multicast_query_use_ifaddr = g_value_get_boolean(value); - break; - case PROP_MULTICAST_STARTUP_QUERY_COUNT: - priv->multicast_startup_query_count = g_value_get_uint(value); - break; - case PROP_MULTICAST_STARTUP_QUERY_INTERVAL: - priv->multicast_startup_query_interval = g_value_get_uint64(value); - break; - case PROP_VLAN_FILTERING: - priv->vlan_filtering = g_value_get_boolean(value); - break; - case PROP_VLAN_DEFAULT_PVID: - priv->vlan_default_pvid = g_value_get_uint(value); - break; - case PROP_VLAN_PROTOCOL: - g_free(priv->vlan_protocol); - priv->vlan_protocol = g_value_dup_string(value); - break; - case PROP_VLAN_STATS_ENABLED: - priv->vlan_stats_enabled = g_value_get_boolean(value); - break; - case PROP_VLANS: - g_ptr_array_unref(priv->vlans); - priv->vlans = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) _nm_bridge_vlan_dup_and_seal, - (GDestroyNotify) nm_bridge_vlan_unref); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_bridge_init(NMSettingBridge *setting) -{ - NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); - - priv->vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); - - priv->ageing_time = NM_BRIDGE_AGEING_TIME_DEF; - priv->forward_delay = NM_BRIDGE_FORWARD_DELAY_DEF; - priv->hello_time = NM_BRIDGE_HELLO_TIME_DEF; - priv->max_age = NM_BRIDGE_MAX_AGE_DEF; - priv->multicast_last_member_count = NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF; - priv->multicast_last_member_interval = NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF; - priv->multicast_membership_interval = NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF; - priv->multicast_hash_max = NM_BRIDGE_MULTICAST_HASH_MAX_DEF; - priv->multicast_snooping = NM_BRIDGE_MULTICAST_SNOOPING_DEF; - priv->priority = NM_BRIDGE_PRIORITY_DEF; - priv->stp = NM_BRIDGE_STP_DEF; - priv->vlan_default_pvid = NM_BRIDGE_VLAN_DEFAULT_PVID_DEF; - priv->multicast_query_interval = NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF; - priv->multicast_query_response_interval = NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF; - priv->multicast_querier_interval = NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF; - priv->multicast_startup_query_count = NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF; - priv->multicast_startup_query_interval = NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF; - - nm_assert(priv->multicast_querier == NM_BRIDGE_MULTICAST_QUERIER_DEF); - nm_assert(priv->multicast_query_use_ifaddr == NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF); - nm_assert(priv->vlan_stats_enabled == NM_BRIDGE_VLAN_STATS_ENABLED_DEF); -} - -/** - * nm_setting_bridge_new: - * - * Creates a new #NMSettingBridge object with default values. - * - * Returns: (transfer full): the new empty #NMSettingBridge object - **/ -NMSetting * -nm_setting_bridge_new(void) -{ - return g_object_new(NM_TYPE_SETTING_BRIDGE, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); - - g_free(priv->mac_address); - g_free(priv->multicast_router); - g_free(priv->group_address); - g_free(priv->vlan_protocol); - g_ptr_array_unref(priv->vlans); - - G_OBJECT_CLASS(nm_setting_bridge_parent_class)->finalize(object); -} - -static void -nm_setting_bridge_class_init(NMSettingBridgeClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - - /** - * NMSettingBridge:mac-address: - * - * If specified, the MAC address of bridge. When creating a new bridge, this - * MAC address will be set. - * - * If this field is left unspecified, the "ethernet.cloned-mac-address" is - * referred instead to generate the initial MAC address. Note that setting - * "ethernet.cloned-mac-address" anyway overwrites the MAC address of - * the bridge later while activating the bridge. Hence, this property - * is deprecated. - * - * Deprecated: 1.12: Use the ethernet.cloned-mac-address property instead. - **/ - /* ---keyfile--- - * property: mac-address - * format: usual hex-digits-and-colons notation - * description: MAC address in traditional hex-digits-and-colons notation, - * or semicolon separated list of 6 decimal bytes (obsolete) - * example: mac-address=00:22:68:12:79:A2 - * mac-address=0;34;104;18;121;162; - * ---end--- - * ---ifcfg-rh--- - * property: mac-address - * variable: BRIDGE_MACADDR(+) - * description: MAC address of the bridge. Note that this requires a recent - * kernel support, originally introduced in 3.15 upstream kernel) - * BRIDGE_MACADDR for bridges is an NM extension. - * ---end--- - */ - obj_properties[PROP_MAC_ADDRESS] = g_param_spec_string( - NM_SETTING_BRIDGE_MAC_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_MAC_ADDRESS], - &nm_sett_info_propert_type_mac_address); - - /** - * NMSettingBridge:stp: - * - * Controls whether Spanning Tree Protocol (STP) is enabled for this bridge. - **/ - /* ---ifcfg-rh--- - * property: stp - * variable: STP - * default: no - * description: Span tree protocol participation. - * ---end--- - */ - obj_properties[PROP_STP] = g_param_spec_boolean(NM_SETTING_BRIDGE_STP, - "", - "", - NM_BRIDGE_STP_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:priority: - * - * Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower - * values are "better"; the lowest priority bridge will be elected the root - * bridge. - **/ - /* ---ifcfg-rh--- - * property: priority - * variable: BRIDGING_OPTS: priority= - * values: 0 - 32768 - * default: 32768 - * description: STP priority. - * ---end--- - */ - obj_properties[PROP_PRIORITY] = - g_param_spec_uint(NM_SETTING_BRIDGE_PRIORITY, - "", - "", - NM_BRIDGE_PRIORITY_MIN, - NM_BRIDGE_PRIORITY_MAX, - NM_BRIDGE_PRIORITY_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:forward-delay: - * - * The Spanning Tree Protocol (STP) forwarding delay, in seconds. - **/ - /* ---ifcfg-rh--- - * property: forward-delay - * variable: DELAY - * values: 2 - 30 - * default: 15 - * description: STP forwarding delay. - * ---end--- - */ - obj_properties[PROP_FORWARD_DELAY] = - g_param_spec_uint(NM_SETTING_BRIDGE_FORWARD_DELAY, - "", - "", - 0, - NM_BRIDGE_FORWARD_DELAY_MAX, - NM_BRIDGE_FORWARD_DELAY_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:hello-time: - * - * The Spanning Tree Protocol (STP) hello time, in seconds. - **/ - /* ---ifcfg-rh--- - * property: hello-time - * variable: BRIDGING_OPTS: hello_time= - * values: 1 - 10 - * default: 2 - * description: STP hello time. - * ---end--- - */ - obj_properties[PROP_HELLO_TIME] = - g_param_spec_uint(NM_SETTING_BRIDGE_HELLO_TIME, - "", - "", - 0, - NM_BRIDGE_HELLO_TIME_MAX, - NM_BRIDGE_HELLO_TIME_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:max-age: - * - * The Spanning Tree Protocol (STP) maximum message age, in seconds. - **/ - /* ---ifcfg-rh--- - * property: max-age - * variable: BRIDGING_OPTS: max_age= - * values: 6 - 40 - * default: 20 - * description: STP maximum message age. - * ---end--- - */ - obj_properties[PROP_MAX_AGE] = - g_param_spec_uint(NM_SETTING_BRIDGE_MAX_AGE, - "", - "", - 0, - NM_BRIDGE_MAX_AGE_MAX, - NM_BRIDGE_MAX_AGE_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:ageing-time: - * - * The Ethernet MAC address aging time, in seconds. - **/ - /* ---ifcfg-rh--- - * property: ageing-time - * variable: BRIDGING_OPTS: ageing_time= - * values: 0 - 1000000 - * default: 300 - * description: Ethernet MAC ageing time. - * ---end--- - */ - obj_properties[PROP_AGEING_TIME] = - g_param_spec_uint(NM_SETTING_BRIDGE_AGEING_TIME, - "", - "", - NM_BRIDGE_AGEING_TIME_MIN, - NM_BRIDGE_AGEING_TIME_MAX, - NM_BRIDGE_AGEING_TIME_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:group-forward-mask: - * - * A mask of group addresses to forward. Usually, group addresses in - * the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not - * forwarded according to standards. This property is a mask of 16 bits, - * each corresponding to a group address in that range that must be - * forwarded. The mask can't have bits 0, 1 or 2 set because they are - * used for STP, MAC pause frames and LACP. - * - * Since: 1.10 - **/ - obj_properties[PROP_GROUP_FORWARD_MASK] = - g_param_spec_uint(NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, - "", - "", - 0, - 0xFFFF, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-snooping: - * - * Controls whether IGMP snooping is enabled for this bridge. - * Note that if snooping was automatically disabled due to hash collisions, - * the system may refuse to enable the feature until the collisions are - * resolved. - * - * Since: 1.2 - **/ - /* ---ifcfg-rh--- - * property: multicast-snooping - * variable: BRIDGING_OPTS: multicast_snooping= - * values: 0 or 1 - * default: 1 - * description: IGMP snooping support. - * ---end--- - */ - obj_properties[PROP_MULTICAST_SNOOPING] = g_param_spec_boolean( - NM_SETTING_BRIDGE_MULTICAST_SNOOPING, - "", - "", - NM_BRIDGE_MULTICAST_SNOOPING_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:vlan-filtering: - * - * Control whether VLAN filtering is enabled on the bridge. - * - * Since: 1.18 - **/ - /* ---ifcfg-rh--- - * property: vlan-filtering - * variable: BRIDGING_OPTS: vlan_filtering= - * values: 0 or 1 - * default: 0 - * description: VLAN filtering support. - * ---end--- - */ - obj_properties[PROP_VLAN_FILTERING] = g_param_spec_boolean( - NM_SETTING_BRIDGE_VLAN_FILTERING, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:vlan-default-pvid: - * - * The default PVID for the ports of the bridge, that is the VLAN id - * assigned to incoming untagged frames. - * - * Since: 1.18 - **/ - /* ---ifcfg-rh--- - * property: vlan-default-pvid - * variable: BRIDGING_OPTS: default_pvid= - * values: 0 - 4094 - * default: 1 - * description: default VLAN PVID. - * ---end--- - */ - obj_properties[PROP_VLAN_DEFAULT_PVID] = - g_param_spec_uint(NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, - "", - "", - 0, - NM_BRIDGE_VLAN_VID_MAX, - NM_BRIDGE_VLAN_DEFAULT_PVID_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:vlans: (type GPtrArray(NMBridgeVlan)) - * - * Array of bridge VLAN objects. In addition to the VLANs - * specified here, the bridge will also have the default-pvid - * VLAN configured by the bridge.vlan-default-pvid property. - * - * In nmcli the VLAN list can be specified with the following - * syntax: - * - * $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... - * - * where $vid is either a single id between 1 and 4094 or a - * range, represented as a couple of ids separated by a dash. - * - * Since: 1.18 - **/ - /* ---ifcfg-rh--- - * property: vlans - * variable: BRIDGE_VLANS - * description: List of VLANs on the bridge - * example: BRIDGE_VLANS="1 pvid untagged,20,300-400 untagged" - * ---end--- - */ - obj_properties[PROP_VLANS] = g_param_spec_boxed(NM_SETTING_BRIDGE_VLANS, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_VLANS], - &nm_sett_info_propert_type_bridge_vlans); - - /* ---dbus--- - * property: interface-name - * format: string - * description: Deprecated in favor of connection.interface-name, but can - * be used for backward-compatibility with older daemons, to set the - * bridge's interface name. - * ---end--- - */ - _nm_properties_override_dbus(properties_override, - "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); - - /** - * NMSettingBridge:group-address: - * - * If specified, The MAC address of the multicast group this bridge uses for STP. - * - * The address must be a link-local address in standard Ethernet MAC address format, - * ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. - * If not specified the default value is 01:80:C2:00:00:00. - * - * Since: 1.24 - **/ - /* ---ifcfg-rh--- - * property: group-address - * variable: BRIDGING_OPTS: group_address= - * description: STP group address. - * example: BRIDGING_OPTS="group_address=01:80:C2:00:00:0A" - * ---end--- - */ - obj_properties[PROP_GROUP_ADDRESS] = g_param_spec_string( - NM_SETTING_BRIDGE_GROUP_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_GROUP_ADDRESS], - &nm_sett_info_propert_type_mac_address); - - /** - * NMSettingBridge:vlan-protocol: - * - * If specified, the protocol used for VLAN filtering. - * - * Supported values are: '802.1Q', '802.1ad'. - * If not specified the default value is '802.1Q'. - * - * Since: 1.24 - **/ - /* ---ifcfg-rh--- - * property: vlan-protocol - * variable: BRIDGING_OPTS: vlan_protocol= - * description: VLAN filtering protocol. - * example: BRIDGING_OPTS="vlan_protocol=802.1Q" - * ---end--- - * - * Since: 1.24 - */ - obj_properties[PROP_VLAN_PROTOCOL] = g_param_spec_string( - NM_SETTING_BRIDGE_VLAN_PROTOCOL, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:vlan-stats-enabled: - * - * Controls whether per-VLAN stats accounting is enabled. - **/ - /* ---ifcfg-rh--- - * property: vlan-stats-enabled - * variable: BRIDGING_OPTS: vlan_stats_enabled= - * default: 0 - * example: BRIDGING_OPTS="vlan_stats_enabled=1" - * ---end--- - * - * Since: 1.24 - */ - obj_properties[PROP_VLAN_STATS_ENABLED] = g_param_spec_boolean( - NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, - "", - "", - NM_BRIDGE_VLAN_STATS_ENABLED_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-router: - * - * Sets bridge's multicast router. Multicast-snooping must be enabled - * for this option to work. - * - * Supported values are: 'auto', 'disabled', 'enabled' to which kernel - * assigns the numbers 1, 0, and 2, respectively. - * If not specified the default value is 'auto' (1). - **/ - /* ---ifcfg-rh--- - * property: multicast-router - * variable: BRIDGING_OPTS: multicast_router= - * values: auto, enabled, disabled - * default: auto - * example: BRIDGING_OPTS="multicast_router=enabled" - * ---end--- - * - * Since: 1.24 - */ - obj_properties[PROP_MULTICAST_ROUTER] = g_param_spec_string( - NM_SETTING_BRIDGE_MULTICAST_ROUTER, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-query-use-ifaddr: - * - * If enabled the bridge's own IP address is used as - * the source address for IGMP queries otherwise - * the default of 0.0.0.0 is used. - **/ - /* ---ifcfg-rh--- - * property: multicast-query-use-ifaddr - * variable: BRIDGING_OPTS: multicast_query_use_ifaddr= - * default: 0 - * example: BRIDGING_OPTS="multicast_query-use_ifaddr=1" - * ---end--- - * - * Since: 1.24 - */ - obj_properties[PROP_MULTICAST_QUERY_USE_IFADDR] = g_param_spec_boolean( - NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, - "", - "", - NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-querier: - * - * Enable or disable sending of multicast queries by the bridge. - * If not specified the option is disabled. - **/ - /* ---ifcfg-rh--- - * property: multicast-querier - * variable: BRIDGING_OPTS: multicast_querier= - * default: 0 - * example: BRIDGING_OPTS="multicast_querier=1" - * ---end--- - * - * Since: 1.24 - */ - obj_properties[PROP_MULTICAST_QUERIER] = g_param_spec_boolean( - NM_SETTING_BRIDGE_MULTICAST_QUERIER, - "", - "", - NM_BRIDGE_MULTICAST_QUERIER_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-hash-max: - * - * Set maximum size of multicast hash table (value must be a power of 2). - **/ - /* ---ifcfg-rh--- - * property: multicast-hash-max - * variable: BRIDGING_OPTS: multicast_hash_max= - * default: 4096 - * example: BRIDGING_OPTS="multicast_hash_max=8192" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_HASH_MAX] = - g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_HASH_MAX, - "", - "", - NM_BRIDGE_MULTICAST_HASH_MAX_MIN, - NM_BRIDGE_MULTICAST_HASH_MAX_MAX, - NM_BRIDGE_MULTICAST_HASH_MAX_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-last-member-count: - * - * Set the number of queries the bridge will send before - * stopping forwarding a multicast group after a "leave" - * message has been received. - **/ - /* ---ifcfg-rh--- - * property: multicast-last-member-count - * variable: BRIDGING_OPTS: multicast_last_member_count= - * default: 2 - * example: BRIDGING_OPTS="multicast_last_member_count=4" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_LAST_MEMBER_COUNT] = - g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_COUNT, - "", - "", - NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MIN, - NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MAX, - NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-last-member-interval: - * - * Set interval (in deciseconds) between queries to find remaining - * members of a group, after a "leave" message is received. - **/ - /* ---ifcfg-rh--- - * property: multicast-last-member-interval - * variable: BRIDGING_OPTS: multicast_last_member_interval= - * default: 100 - * example: BRIDGING_OPTS="multicast_last_member_interval=200" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_LAST_MEMBER_INTERVAL] = g_param_spec_uint64( - NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL, - "", - "", - NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MIN, - NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MAX, - NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-membership-interval: - * - * Set delay (in deciseconds) after which the bridge will - * leave a group, if no membership reports for this - * group are received. - **/ - /* ---ifcfg-rh--- - * property: multicast-membership-interval - * variable: BRIDGING_OPTS: multicast_membership_interval= - * default: 26000 - * example: BRIDGING_OPTS="multicast_membership_interval=16000" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_MEMBERSHIP_INTERVAL] = g_param_spec_uint64( - NM_SETTING_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL, - "", - "", - NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MIN, - NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MAX, - NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-querier-interval: - * - * If no queries are seen after this delay (in deciseconds) has passed, - * the bridge will start to send its own queries. - **/ - /* ---ifcfg-rh--- - * property: multicast-querier-interval - * variable: BRIDGING_OPTS: multicast_querier_interval= - * default: 25500 - * example: BRIDGING_OPTS="multicast_querier_interval=20000" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_QUERIER_INTERVAL] = g_param_spec_uint64( - NM_SETTING_BRIDGE_MULTICAST_QUERIER_INTERVAL, - "", - "", - NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MIN, - NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MAX, - NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-query-interval: - * - * Interval (in deciseconds) between queries sent - * by the bridge after the end of the startup phase. - **/ - /* ---ifcfg-rh--- - * property: multicast-query-interval - * variable: BRIDGING_OPTS: multicast_query_interval= - * default: 12500 - * example: BRIDGING_OPTS="multicast_query_interval=22500" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_QUERY_INTERVAL] = g_param_spec_uint64( - NM_SETTING_BRIDGE_MULTICAST_QUERY_INTERVAL, - "", - "", - NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MIN, - NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MAX, - NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-query-response-interval: - * - * Set the Max Response Time/Max Response Delay - * (in deciseconds) for IGMP/MLD queries sent by the bridge. - **/ - /* ---ifcfg-rh--- - * property: multicast-query-response-interval - * variable: BRIDGING_OPTS: multicast_query_response_interval= - * default: 1000 - * example: BRIDGING_OPTS="multicast_query_response_interval=2000" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_QUERY_RESPONSE_INTERVAL] = g_param_spec_uint64( - NM_SETTING_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL, - "", - "", - NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MIN, - NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MAX, - NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-startup-query-count: - * - * Set the number of IGMP queries to send during startup phase. - **/ - /* ---ifcfg-rh--- - * property: multicast-startup-query-count - * variable: BRIDGING_OPTS: multicast_startup_query_count= - * default: 2 - * example: BRIDGING_OPTS="multicast_startup_query_count=4" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_STARTUP_QUERY_COUNT] = - g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT, - "", - "", - NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MIN, - NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MAX, - NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingBridge:multicast-startup-query-interval: - * - * Sets the time (in deciseconds) between queries sent out - * at startup to determine membership information. - **/ - /* ---ifcfg-rh--- - * property: multicast-startup-query-interval - * variable: BRIDGING_OPTS: multicast_startup_query_interval= - * default: 3125 - * example: BRIDGING_OPTS="multicast_startup_query_interval=4000" - * ---end--- - * - * Since: 1.26 - */ - obj_properties[PROP_MULTICAST_STARTUP_QUERY_INTERVAL] = g_param_spec_uint64( - NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL, - "", - "", - NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MIN, - NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MAX, - NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_BRIDGE, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h deleted file mode 100644 index cda1861294..0000000000 --- a/libnm-core/nm-setting-bridge.h +++ /dev/null @@ -1,183 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2015 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_BRIDGE_H__ -#define __NM_SETTING_BRIDGE_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_BRIDGE (nm_setting_bridge_get_type()) -#define NM_SETTING_BRIDGE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_BRIDGE, NMSettingBridge)) -#define NM_SETTING_BRIDGE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_BRIDGE, NMSettingBridgeClass)) -#define NM_IS_SETTING_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_BRIDGE)) -#define NM_IS_SETTING_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_BRIDGE)) -#define NM_SETTING_BRIDGE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_BRIDGE, NMSettingBridgeClass)) - -#define NM_SETTING_BRIDGE_SETTING_NAME "bridge" - -#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address" -#define NM_SETTING_BRIDGE_STP "stp" -#define NM_SETTING_BRIDGE_PRIORITY "priority" -#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay" -#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" -#define NM_SETTING_BRIDGE_MAX_AGE "max-age" -#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" -#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" -#define NM_SETTING_BRIDGE_MULTICAST_HASH_MAX "multicast-hash-max" -#define NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_COUNT "multicast-last-member-count" -#define NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL "multicast-last-member-interval" -#define NM_SETTING_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL "multicast-membership-interval" -#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" -#define NM_SETTING_BRIDGE_MULTICAST_ROUTER "multicast-router" -#define NM_SETTING_BRIDGE_MULTICAST_QUERIER "multicast-querier" -#define NM_SETTING_BRIDGE_MULTICAST_QUERIER_INTERVAL "multicast-querier-interval" -#define NM_SETTING_BRIDGE_MULTICAST_QUERY_INTERVAL "multicast-query-interval" -#define NM_SETTING_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL "multicast-query-response-interval" -#define NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR "multicast-query-use-ifaddr" -#define NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT "multicast-startup-query-count" -#define NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL "multicast-startup-query-interval" -#define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" -#define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" -#define NM_SETTING_BRIDGE_VLANS "vlans" -#define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" -#define NM_SETTING_BRIDGE_VLAN_PROTOCOL "vlan-protocol" -#define NM_SETTING_BRIDGE_VLAN_STATS_ENABLED "vlan-stats-enabled" - -#define NM_BRIDGE_VLAN_VID_MIN 1 -#define NM_BRIDGE_VLAN_VID_MAX 4094 - -typedef struct _NMSettingBridgeClass NMSettingBridgeClass; - -typedef struct _NMBridgeVlan NMBridgeVlan; - -GType nm_setting_bridge_get_type(void); - -NMSetting *nm_setting_bridge_new(void); - -const char *nm_setting_bridge_get_mac_address(NMSettingBridge *setting); - -gboolean nm_setting_bridge_get_stp(NMSettingBridge *setting); - -guint16 nm_setting_bridge_get_priority(NMSettingBridge *setting); - -guint16 nm_setting_bridge_get_forward_delay(NMSettingBridge *setting); - -guint16 nm_setting_bridge_get_hello_time(NMSettingBridge *setting); - -guint16 nm_setting_bridge_get_max_age(NMSettingBridge *setting); - -guint32 nm_setting_bridge_get_ageing_time(NMSettingBridge *setting); -NM_AVAILABLE_IN_1_10 -guint16 nm_setting_bridge_get_group_forward_mask(NMSettingBridge *setting); - -gboolean nm_setting_bridge_get_multicast_snooping(NMSettingBridge *setting); -NM_AVAILABLE_IN_1_18 -gboolean nm_setting_bridge_get_vlan_filtering(NMSettingBridge *setting); -NM_AVAILABLE_IN_1_18 -guint16 nm_setting_bridge_get_vlan_default_pvid(NMSettingBridge *setting); -NM_AVAILABLE_IN_1_18 -void nm_setting_bridge_add_vlan(NMSettingBridge *setting, NMBridgeVlan *vlan); -NM_AVAILABLE_IN_1_18 -guint nm_setting_bridge_get_num_vlans(NMSettingBridge *setting); -NM_AVAILABLE_IN_1_18 -NMBridgeVlan *nm_setting_bridge_get_vlan(NMSettingBridge *setting, guint idx); -NM_AVAILABLE_IN_1_18 -void nm_setting_bridge_remove_vlan(NMSettingBridge *setting, guint idx); -NM_AVAILABLE_IN_1_18 -gboolean -nm_setting_bridge_remove_vlan_by_vid(NMSettingBridge *setting, guint16 vid_start, guint16 vid_end); -NM_AVAILABLE_IN_1_18 -void nm_setting_bridge_clear_vlans(NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_18 -GType nm_bridge_vlan_get_type(void); -NM_AVAILABLE_IN_1_18 -NMBridgeVlan *nm_bridge_vlan_new(guint16 vid_start, guint16 vid_end); -NM_AVAILABLE_IN_1_18 -NMBridgeVlan *nm_bridge_vlan_ref(NMBridgeVlan *vlan); -NM_AVAILABLE_IN_1_18 -void nm_bridge_vlan_unref(NMBridgeVlan *vlan); -NM_AVAILABLE_IN_1_18 -NMBridgeVlan *nm_bridge_vlan_new_clone(const NMBridgeVlan *vlan); -NM_AVAILABLE_IN_1_18 -int nm_bridge_vlan_cmp(const NMBridgeVlan *a, const NMBridgeVlan *b); -NM_AVAILABLE_IN_1_18 -void nm_bridge_vlan_seal(NMBridgeVlan *vlan); -NM_AVAILABLE_IN_1_18 -gboolean nm_bridge_vlan_is_sealed(const NMBridgeVlan *vlan); -NM_AVAILABLE_IN_1_18 -void nm_bridge_vlan_set_untagged(NMBridgeVlan *vlan, gboolean value); -NM_AVAILABLE_IN_1_18 -void nm_bridge_vlan_set_pvid(NMBridgeVlan *vlan, gboolean value); -NM_AVAILABLE_IN_1_18 -gboolean -nm_bridge_vlan_get_vid_range(const NMBridgeVlan *vlan, guint16 *vid_start, guint16 *vid_end); -NM_AVAILABLE_IN_1_18 -gboolean nm_bridge_vlan_is_untagged(const NMBridgeVlan *vlan); -NM_AVAILABLE_IN_1_18 -gboolean nm_bridge_vlan_is_pvid(const NMBridgeVlan *vlan); - -NM_AVAILABLE_IN_1_18 -char *nm_bridge_vlan_to_str(const NMBridgeVlan *vlan, GError **error); -NM_AVAILABLE_IN_1_18 -NMBridgeVlan *nm_bridge_vlan_from_str(const char *str, GError **error); - -NM_AVAILABLE_IN_1_24 -const char *nm_setting_bridge_get_group_address(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_24 -const char *nm_setting_bridge_get_vlan_protocol(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_24 -gboolean nm_setting_bridge_get_vlan_stats_enabled(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_24 -const char *nm_setting_bridge_get_multicast_router(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_24 -gboolean nm_setting_bridge_get_multicast_query_use_ifaddr(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_24 -gboolean nm_setting_bridge_get_multicast_querier(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint32 nm_setting_bridge_get_multicast_hash_max(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint32 nm_setting_bridge_get_multicast_last_member_count(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint64 nm_setting_bridge_get_multicast_last_member_interval(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint64 nm_setting_bridge_get_multicast_membership_interval(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint64 nm_setting_bridge_get_multicast_querier_interval(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint64 nm_setting_bridge_get_multicast_query_interval(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint64 nm_setting_bridge_get_multicast_query_response_interval(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint32 nm_setting_bridge_get_multicast_startup_query_count(const NMSettingBridge *setting); - -NM_AVAILABLE_IN_1_26 -guint64 nm_setting_bridge_get_multicast_startup_query_interval(const NMSettingBridge *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c deleted file mode 100644 index 42e77c6169..0000000000 --- a/libnm-core/nm-setting-cdma.c +++ /dev/null @@ -1,358 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-cdma.h" - -#include "nm-utils.h" -#include "nm-setting-private.h" -#include "nm-core-enum-types.h" - -/** - * SECTION:nm-setting-cdma - * @short_description: Describes CDMA-based mobile broadband properties - * - * The #NMSettingCdma object is a #NMSetting subclass that describes - * properties that allow connections to IS-95-based mobile broadband - * networks, including those using CDMA2000/EVDO technology. - */ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_NUMBER, - PROP_USERNAME, - PROP_PASSWORD, - PROP_PASSWORD_FLAGS, - PROP_MTU, ); - -typedef struct { - char * number; /* For dialing, duh */ - char * username; - char * password; - guint32 mtu; - NMSettingSecretFlags password_flags; -} NMSettingCdmaPrivate; - -G_DEFINE_TYPE(NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING) - -#define NM_SETTING_CDMA_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_CDMA, NMSettingCdmaPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_cdma_get_number: - * @setting: the #NMSettingCdma - * - * Returns: the #NMSettingCdma:number property of the setting - **/ -const char * -nm_setting_cdma_get_number(NMSettingCdma *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), NULL); - - return NM_SETTING_CDMA_GET_PRIVATE(setting)->number; -} - -/** - * nm_setting_cdma_get_username: - * @setting: the #NMSettingCdma - * - * Returns: the #NMSettingCdma:username property of the setting - **/ -const char * -nm_setting_cdma_get_username(NMSettingCdma *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), NULL); - - return NM_SETTING_CDMA_GET_PRIVATE(setting)->username; -} - -/** - * nm_setting_cdma_get_password: - * @setting: the #NMSettingCdma - * - * Returns: the #NMSettingCdma:password property of the setting - **/ -const char * -nm_setting_cdma_get_password(NMSettingCdma *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), NULL); - - return NM_SETTING_CDMA_GET_PRIVATE(setting)->password; -} - -/** - * nm_setting_cdma_get_password_flags: - * @setting: the #NMSettingCdma - * - * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingCdma:password - **/ -NMSettingSecretFlags -nm_setting_cdma_get_password_flags(NMSettingCdma *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_CDMA_GET_PRIVATE(setting)->password_flags; -} - -/** - * nm_setting_cdma_get_mtu: - * @setting: the #NMSettingCdma - * - * Returns: the #NMSettingCdma:mtu property of the setting - * - * Since: 1.8 - **/ -guint32 -nm_setting_cdma_get_mtu(NMSettingCdma *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), 0); - - return NM_SETTING_CDMA_GET_PRIVATE(setting)->mtu; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(setting); - - if (!priv->number) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_NUMBER); - return FALSE; - } else if (!strlen(priv->number)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_NUMBER); - return FALSE; - } - - if (priv->username && !strlen(priv->username)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_USERNAME); - return FALSE; - } - - return TRUE; -} - -static gboolean -verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) -{ - return _nm_setting_verify_secret_string(NM_SETTING_CDMA_GET_PRIVATE(setting)->password, - NM_SETTING_CDMA_SETTING_NAME, - NM_SETTING_CDMA_PASSWORD, - error); -} - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(setting); - GPtrArray * secrets = NULL; - - if (priv->password && *priv->password) - return NULL; - - if (priv->username) { - if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { - secrets = g_ptr_array_sized_new(1); - g_ptr_array_add(secrets, NM_SETTING_CDMA_PASSWORD); - } - } - - return secrets; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingCdma *setting = NM_SETTING_CDMA(object); - - switch (prop_id) { - case PROP_NUMBER: - g_value_set_string(value, nm_setting_cdma_get_number(setting)); - break; - case PROP_USERNAME: - g_value_set_string(value, nm_setting_cdma_get_username(setting)); - break; - case PROP_PASSWORD: - g_value_set_string(value, nm_setting_cdma_get_password(setting)); - break; - case PROP_PASSWORD_FLAGS: - g_value_set_flags(value, nm_setting_cdma_get_password_flags(setting)); - break; - case PROP_MTU: - g_value_set_uint(value, nm_setting_cdma_get_mtu(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_NUMBER: - g_free(priv->number); - priv->number = g_value_dup_string(value); - break; - case PROP_USERNAME: - g_free(priv->username); - priv->username = g_value_dup_string(value); - break; - case PROP_PASSWORD: - g_free(priv->password); - priv->password = g_value_dup_string(value); - break; - case PROP_PASSWORD_FLAGS: - priv->password_flags = g_value_get_flags(value); - break; - case PROP_MTU: - priv->mtu = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_cdma_init(NMSettingCdma *setting) -{} - -/** - * nm_setting_cdma_new: - * - * Creates a new #NMSettingCdma object with default values. - * - * Returns: the new empty #NMSettingCdma object - **/ -NMSetting * -nm_setting_cdma_new(void) -{ - return g_object_new(NM_TYPE_SETTING_CDMA, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(object); - - g_free(priv->number); - g_free(priv->username); - g_free(priv->password); - - G_OBJECT_CLASS(nm_setting_cdma_parent_class)->finalize(object); -} - -static void -nm_setting_cdma_class_init(NMSettingCdmaClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingCdmaPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->verify_secrets = verify_secrets; - setting_class->need_secrets = need_secrets; - - /** - * NMSettingCdma:number: - * - * The number to dial to establish the connection to the CDMA-based mobile - * broadband network, if any. If not specified, the default number (#777) - * is used when required. - **/ - obj_properties[PROP_NUMBER] = g_param_spec_string(NM_SETTING_CDMA_NUMBER, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingCdma:username: - * - * The username used to authenticate with the network, if required. Many - * providers do not require a username, or accept any username. But if a - * username is required, it is specified here. - **/ - obj_properties[PROP_USERNAME] = g_param_spec_string(NM_SETTING_CDMA_USERNAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingCdma:password: - * - * The password used to authenticate with the network, if required. Many - * providers do not require a password, or accept any password. But if a - * password is required, it is specified here. - **/ - obj_properties[PROP_PASSWORD] = - g_param_spec_string(NM_SETTING_CDMA_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingCdma:password-flags: - * - * Flags indicating how to handle the #NMSettingCdma:password property. - **/ - obj_properties[PROP_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_CDMA_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingCdma:mtu: - * - * If non-zero, only transmit packets of the specified size or smaller, - * breaking larger packets up into multiple frames. - * - * Since: 1.8 - **/ - obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_CDMA_MTU, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_CDMA); -} diff --git a/libnm-core/nm-setting-cdma.h b/libnm-core/nm-setting-cdma.h deleted file mode 100644 index 67784e8963..0000000000 --- a/libnm-core/nm-setting-cdma.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2011 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_CDMA_H__ -#define __NM_SETTING_CDMA_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_CDMA (nm_setting_cdma_get_type()) -#define NM_SETTING_CDMA(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_CDMA, NMSettingCdma)) -#define NM_SETTING_CDMA_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_CDMA, NMSettingCdmaClass)) -#define NM_IS_SETTING_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_CDMA)) -#define NM_IS_SETTING_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_CDMA)) -#define NM_SETTING_CDMA_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_CDMA, NMSettingCdmaClass)) - -#define NM_SETTING_CDMA_SETTING_NAME "cdma" - -#define NM_SETTING_CDMA_NUMBER "number" -#define NM_SETTING_CDMA_USERNAME "username" -#define NM_SETTING_CDMA_PASSWORD "password" -#define NM_SETTING_CDMA_PASSWORD_FLAGS "password-flags" -#define NM_SETTING_CDMA_MTU "mtu" - -/** - * NMSettingCdma: - * - * CDMA-based Mobile Broadband Settings - */ -struct _NMSettingCdma { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingCdmaClass; - -GType nm_setting_cdma_get_type(void); - -NMSetting * nm_setting_cdma_new(void); -const char * nm_setting_cdma_get_number(NMSettingCdma *setting); -const char * nm_setting_cdma_get_username(NMSettingCdma *setting); -const char * nm_setting_cdma_get_password(NMSettingCdma *setting); -NMSettingSecretFlags nm_setting_cdma_get_password_flags(NMSettingCdma *setting); - -NM_AVAILABLE_IN_1_8 -guint32 nm_setting_cdma_get_mtu(NMSettingCdma *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_CDMA_H__ */ diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c deleted file mode 100644 index d6626a4d5a..0000000000 --- a/libnm-core/nm-setting-connection.c +++ /dev/null @@ -1,2529 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-connection.h" - -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-core-enum-types.h" -#include "nm-connection-private.h" -#include "nm-setting-bond.h" -#include "nm-setting-bridge.h" -#include "nm-setting-team.h" -#include "nm-setting-vlan.h" -#include "systemd/nm-sd-utils-shared.h" - -/** - * SECTION:nm-setting-connection - * @short_description: Describes general connection properties - * - * The #NMSettingConnection object is a #NMSetting subclass that describes - * properties that apply to all #NMConnection objects, regardless of what type - * of network connection they describe. Each #NMConnection object must contain - * a #NMSettingConnection setting. - **/ - -/*****************************************************************************/ - -typedef enum _nm_packed { - PERM_TYPE_INVALID, - PERM_TYPE_USER, -} PermType; - -typedef struct { - PermType ptype; - char * item; -} Permission; - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingConnection, - PROP_ID, - PROP_UUID, - PROP_INTERFACE_NAME, - PROP_TYPE, - PROP_PERMISSIONS, - PROP_AUTOCONNECT, - PROP_AUTOCONNECT_PRIORITY, - PROP_AUTOCONNECT_RETRIES, - PROP_MULTI_CONNECT, - PROP_TIMESTAMP, - PROP_READ_ONLY, - PROP_ZONE, - PROP_MASTER, - PROP_SLAVE_TYPE, - PROP_AUTOCONNECT_SLAVES, - PROP_SECONDARIES, - PROP_GATEWAY_PING_TIMEOUT, - PROP_METERED, - PROP_LLDP, - PROP_MDNS, - PROP_LLMNR, - PROP_STABLE_ID, - PROP_AUTH_RETRIES, - PROP_WAIT_DEVICE_TIMEOUT, - PROP_MUD_URL, ); - -typedef struct { - GArray *permissions; - GSList *secondaries; /* secondary connections to activate with the base connection */ - char * id; - char * uuid; - char * stable_id; - char * interface_name; - char * type; - char * master; - char * slave_type; - char * zone; - char * mud_url; - guint64 timestamp; - int autoconnect_priority; - int autoconnect_retries; - int multi_connect; - int auth_retries; - int mdns; - int llmnr; - int wait_device_timeout; - guint gateway_ping_timeout; - NMSettingConnectionAutoconnectSlaves autoconnect_slaves; - NMMetered metered; - NMSettingConnectionLldp lldp; - bool read_only : 1; - bool autoconnect : 1; -} NMSettingConnectionPrivate; - -G_DEFINE_TYPE(NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING) - -#define NM_SETTING_CONNECTION_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate)) - -/*****************************************************************************/ - -static void -_permission_set_stale(Permission *permission, PermType ptype, char *item_take) -{ - nm_assert(permission); - nm_assert(NM_IN_SET(ptype, PERM_TYPE_INVALID, PERM_TYPE_USER)); - nm_assert(ptype != PERM_TYPE_USER - || nm_settings_connection_validate_permission_user(item_take, -1)); - - /* we don't inspect (clear) permission before setting. It takes a - * stale instance. */ - *permission = (Permission){ - .ptype = ptype, - .item = item_take, - }; -} - -static void -_permission_clear_stale(Permission *permission) -{ - g_free(permission->item); - /* We leave the permission instance with dangling pointers. - * It is "stale". */ -} - -static gboolean -_permission_set_stale_parse(Permission *permission, const char *str) -{ - const char *str0 = str; - const char *last_colon; - gsize ulen; - - nm_assert(str); - - if (!str) - goto invalid; - - if (!NM_STR_HAS_PREFIX(str, NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX)) - goto invalid; - - str += NM_STRLEN(NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX); - - last_colon = strrchr(str, ':'); - if (last_colon) { - /* Reject :[detail] for now */ - if (last_colon[1] != '\0') - goto invalid; - ulen = last_colon - str; - } else - ulen = strlen(str); - - if (!nm_settings_connection_validate_permission_user(str, ulen)) - goto invalid; - - /* Yay, valid... create the new permission */ - if (permission) - _permission_set_stale(permission, PERM_TYPE_USER, g_strndup(str, ulen)); - return TRUE; - -invalid: - if (permission) - _permission_set_stale(permission, PERM_TYPE_INVALID, g_strdup(str0)); - return FALSE; -} - -static char * -_permission_to_string(Permission *permission) -{ - nm_assert(permission); - - switch (permission->ptype) { - case PERM_TYPE_USER: - return g_strdup_printf(NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX "%s:", - permission->item); - case PERM_TYPE_INVALID: - nm_assert(permission->item); - return g_strdup(permission->item); - } - nm_assert_not_reached(); - return g_strdup(permission->item ?: ""); -} - -/*****************************************************************************/ - -/** - * nm_setting_connection_get_id: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:id property of the connection. - * - * Returns: the connection ID - **/ -const char * -nm_setting_connection_get_id(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->id; -} - -/** - * nm_setting_connection_get_uuid: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:uuid property of the connection. - * - * Returns: the connection UUID - **/ -const char * -nm_setting_connection_get_uuid(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->uuid; -} - -/** - * nm_setting_connection_get_stable_id: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:stable_id property of the connection. - * - * Returns: the stable-id for the connection - * - * Since: 1.4 - **/ -const char * -nm_setting_connection_get_stable_id(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->stable_id; -} - -/** - * nm_setting_connection_get_interface_name: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:interface-name property of the connection. - * - * Returns: the connection's interface name - **/ -const char * -nm_setting_connection_get_interface_name(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->interface_name; -} - -/** - * nm_setting_connection_get_connection_type: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:type property of the connection. - * - * Returns: the connection type - **/ -const char * -nm_setting_connection_get_connection_type(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->type; -} - -/** - * nm_setting_connection_get_num_permissions: - * @setting: the #NMSettingConnection - * - * Returns the number of entries in the #NMSettingConnection:permissions - * property of this setting. - * - * Returns: the number of permissions entries - */ -guint32 -nm_setting_connection_get_num_permissions(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); - - return nm_g_array_len(NM_SETTING_CONNECTION_GET_PRIVATE(setting)->permissions); -} - -/** - * nm_setting_connection_get_permission: - * @setting: the #NMSettingConnection - * @idx: the zero-based index of the permissions entry - * @out_ptype: on return, the permission type. This is currently always "user", - * unless the entry is invalid, in which case it returns "invalid". - * @out_pitem: on return, the permission item (formatted according to @ptype, see - * #NMSettingConnection:permissions for more detail - * @out_detail: on return, the permission detail (at this time, always %NULL) - * - * Retrieve one of the entries of the #NMSettingConnection:permissions property - * of this setting. - * - * Returns: %TRUE if a permission was returned, %FALSE if @idx was invalid - */ -gboolean -nm_setting_connection_get_permission(NMSettingConnection *setting, - guint32 idx, - const char ** out_ptype, - const char ** out_pitem, - const char ** out_detail) -{ - NMSettingConnectionPrivate *priv; - Permission * permission; - - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - - g_return_val_if_fail(idx < nm_g_array_len(priv->permissions), FALSE); - - permission = &g_array_index(priv->permissions, Permission, idx); - switch (permission->ptype) { - case PERM_TYPE_USER: - NM_SET_OUT(out_ptype, NM_SETTINGS_CONNECTION_PERMISSION_USER); - NM_SET_OUT(out_pitem, permission->item); - NM_SET_OUT(out_detail, NULL); - return TRUE; - case PERM_TYPE_INVALID: - goto invalid; - } - nm_assert_not_reached(); -invalid: - NM_SET_OUT(out_ptype, "invalid"); - NM_SET_OUT(out_pitem, permission->item); - NM_SET_OUT(out_detail, NULL); - return TRUE; -} - -/** - * nm_setting_connection_permissions_user_allowed: - * @setting: the #NMSettingConnection - * @uname: the user name to check permissions for - * - * Checks whether the given username is allowed to view/access this connection. - * - * Returns: %TRUE if the requested user is allowed to view this connection, - * %FALSE if the given user is not allowed to view this connection - */ -gboolean -nm_setting_connection_permissions_user_allowed(NMSettingConnection *setting, const char *uname) -{ - NMSettingConnectionPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); - g_return_val_if_fail(uname != NULL, FALSE); - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - - if (nm_g_array_len(priv->permissions) == 0) { - /* If no permissions, visible to all */ - return TRUE; - } - - for (i = 0; i < priv->permissions->len; i++) { - const Permission *permission = &g_array_index(priv->permissions, Permission, i); - - if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, uname)) - return TRUE; - } - - return FALSE; -} - -/** - * nm_setting_connection_add_permission: - * @setting: the #NMSettingConnection - * @ptype: the permission type; at this time only "user" is supported - * @pitem: the permission item formatted as required for @ptype - * @detail: (allow-none): unused at this time; must be %NULL - * - * Adds a permission to the connection's permission list. At this time, only - * the "user" permission type is supported, and @pitem must be a username. See - * #NMSettingConnection:permissions: for more details. - * - * Returns: %TRUE if the permission was unique and was successfully added to the - * list, %FALSE if @ptype or @pitem was invalid. - * If the permission was already present in the list, it will not be added - * a second time but %TRUE will be returned. Note that before 1.28, in this - * case %FALSE would be returned. - */ -gboolean -nm_setting_connection_add_permission(NMSettingConnection *setting, - const char * ptype, - const char * pitem, - const char * detail) -{ - NMSettingConnectionPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); - g_return_val_if_fail(ptype, FALSE); - g_return_val_if_fail(pitem, FALSE); - - if (!nm_streq0(ptype, NM_SETTINGS_CONNECTION_PERMISSION_USER)) - return FALSE; - - if (!nm_settings_connection_validate_permission_user(pitem, -1)) - return FALSE; - - if (detail) - return FALSE; - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - - if (!priv->permissions) { - priv->permissions = g_array_sized_new(FALSE, FALSE, sizeof(Permission), 1); - g_array_set_clear_func(priv->permissions, (GDestroyNotify) _permission_clear_stale); - } - - for (i = 0; i < priv->permissions->len; i++) { - const Permission *permission = &g_array_index(priv->permissions, Permission, i); - - if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, pitem)) - return TRUE; - } - - _permission_set_stale(nm_g_array_append_new(priv->permissions, Permission), - PERM_TYPE_USER, - g_strdup(pitem)); - _notify(setting, PROP_PERMISSIONS); - return TRUE; -} - -/** - * nm_setting_connection_remove_permission: - * @setting: the #NMSettingConnection - * @idx: the zero-based index of the permission to remove - * - * Removes the permission at index @idx from the connection. - */ -void -nm_setting_connection_remove_permission(NMSettingConnection *setting, guint32 idx) -{ - NMSettingConnectionPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_CONNECTION(setting)); - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - - g_return_if_fail(idx < nm_g_array_len(priv->permissions)); - - g_array_remove_index(priv->permissions, idx); - - _notify(setting, PROP_PERMISSIONS); -} - -/** - * nm_setting_connection_remove_permission_by_value: - * @setting: the #NMSettingConnection - * @ptype: the permission type; at this time only "user" is supported - * @pitem: the permission item formatted as required for @ptype - * @detail: (allow-none): unused at this time; must be %NULL - * - * Removes the permission from the connection. - * At this time, only the "user" permission type is supported, and @pitem must - * be a username. See #NMSettingConnection:permissions: for more details. - * - * Returns: %TRUE if the permission was found and removed; %FALSE if it was not. - */ -gboolean -nm_setting_connection_remove_permission_by_value(NMSettingConnection *setting, - const char * ptype, - const char * pitem, - const char * detail) -{ - NMSettingConnectionPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); - g_return_val_if_fail(ptype, FALSE); - g_return_val_if_fail(pitem, FALSE); - - if (!nm_streq0(ptype, NM_SETTINGS_CONNECTION_PERMISSION_USER)) - return FALSE; - - if (detail) - return FALSE; - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - if (priv->permissions) { - for (i = 0; i < priv->permissions->len; i++) { - const Permission *permission = &g_array_index(priv->permissions, Permission, i); - - if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, pitem)) { - g_array_remove_index(priv->permissions, i); - _notify(setting, PROP_PERMISSIONS); - return TRUE; - } - } - } - return FALSE; -} - -/** - * nm_setting_connection_get_autoconnect: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:autoconnect property of the connection. - * - * Returns: the connection's autoconnect behavior - **/ -gboolean -nm_setting_connection_get_autoconnect(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->autoconnect; -} - -/** - * nm_setting_connection_get_autoconnect_priority: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:autoconnect-priority property of the connection. - * The higher number, the higher priority. - * - * Returns: the connection's autoconnect priority - **/ -int -nm_setting_connection_get_autoconnect_priority(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->autoconnect_priority; -} - -/** - * nm_setting_connection_get_autoconnect_retries: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:autoconnect-retries property of the connection. - * Zero means infinite, -1 means the global default value. - * - * Returns: the connection's autoconnect retries - * - * Since: 1.6 - **/ -int -nm_setting_connection_get_autoconnect_retries(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), -1); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->autoconnect_retries; -} - -/** - * nm_setting_connection_get_multi_connect: - * @setting: the #NMSettingConnection - * - * Returns: the #NMSettingConnection:multi-connect property of the connection. - * - * Since: 1.14 - **/ -NMConnectionMultiConnect -nm_setting_connection_get_multi_connect(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), -1); - - return (NMConnectionMultiConnect) NM_SETTING_CONNECTION_GET_PRIVATE(setting)->multi_connect; -} - -/** - * nm_setting_connection_get_auth_retries: - * @setting: the #NMSettingConnection - * - * Returns the value contained in the #NMSettingConnection:auth-retries property. - * - * Returns: the configured authentication retries. Zero means - * infinity and -1 means a global default value. - * - * Since: 1.10 - **/ -int -nm_setting_connection_get_auth_retries(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), -1); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->auth_retries; -} - -/** - * nm_setting_connection_get_timestamp: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:timestamp property of the connection. - * - * Returns: the connection's timestamp - **/ -guint64 -nm_setting_connection_get_timestamp(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->timestamp; -} - -static GVariant * -_to_dbus_fcn_timestamp(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - guint64 v; - - v = options && options->timestamp.has ? options->timestamp.val - : NM_SETTING_CONNECTION_GET_PRIVATE(setting)->timestamp; - - if (v == 0u) - return NULL; - - return g_variant_new_uint64(v); -} - -/** - * nm_setting_connection_get_read_only: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:read-only property of the connection. - * - * Returns: %TRUE if the connection is read-only, %FALSE if it is not - **/ -gboolean -nm_setting_connection_get_read_only(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), TRUE); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->read_only; -} - -/** - * nm_setting_connection_get_zone: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:zone property of the connection. - * - * Returns: the trust level of a connection - **/ -const char * -nm_setting_connection_get_zone(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->zone; -} - -/** - * nm_setting_connection_get_master: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:master property of the connection. - * - * Returns: interface name of the master device or UUID of the master - * connection. - */ -const char * -nm_setting_connection_get_master(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->master; -} - -/** - * nm_setting_connection_get_slave_type: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:slave-type property of the connection. - * - * Returns: the type of slave this connection is, if any - */ -const char * -nm_setting_connection_get_slave_type(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->slave_type; -} - -/** - * nm_setting_connection_is_slave_type: - * @setting: the #NMSettingConnection - * @type: the setting name (ie #NM_SETTING_BOND_SETTING_NAME) to be matched - * against @setting's slave type - * - * Returns: %TRUE if connection is of the given slave @type - */ -gboolean -nm_setting_connection_is_slave_type(NMSettingConnection *setting, const char *type) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); - - return !g_strcmp0(NM_SETTING_CONNECTION_GET_PRIVATE(setting)->slave_type, type); -} - -/** - * nm_setting_connection_get_wait_device_timeout: - * @setting: the #NMSettingConnection - * - * Returns: the %NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT property with - * the timeout in milliseconds. -1 is the default. - * - * Since: 1.20 - */ -gint32 -nm_setting_connection_get_wait_device_timeout(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), -1); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->wait_device_timeout; -} - -/** - * nm_setting_connection_get_autoconnect_slaves: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:autoconnect-slaves property of the connection. - * - * Returns: whether slaves of the connection should be activated together - * with the connection. - * - * Since: 1.2 - **/ -NMSettingConnectionAutoconnectSlaves -nm_setting_connection_get_autoconnect_slaves(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), - NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->autoconnect_slaves; -} - -/** - * nm_setting_connection_get_num_secondaries: - * @setting: the #NMSettingConnection - * - * Returns: the number of configured secondary connection UUIDs - **/ -guint32 -nm_setting_connection_get_num_secondaries(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); - - return g_slist_length(NM_SETTING_CONNECTION_GET_PRIVATE(setting)->secondaries); -} - -/** - * nm_setting_connection_get_secondary: - * @setting: the #NMSettingConnection - * @idx: the zero-based index of the secondary connection UUID entry - * - * Returns: the secondary connection UUID at index @idx - **/ -const char * -nm_setting_connection_get_secondary(NMSettingConnection *setting, guint32 idx) -{ - NMSettingConnectionPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - g_return_val_if_fail(idx <= g_slist_length(priv->secondaries), NULL); - - return (const char *) g_slist_nth_data(priv->secondaries, idx); -} - -/** - * nm_setting_connection_get_mud_url: - * @setting: the #NMSettingConnection - * - * Returns the value contained in the #NMSettingConnection:mud-url - * property. - * - * Since: 1.26 - **/ -const char * -nm_setting_connection_get_mud_url(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->mud_url; -} - -/** - * nm_setting_connection_add_secondary: - * @setting: the #NMSettingConnection - * @sec_uuid: the secondary connection UUID to add - * - * Adds a new secondary connection UUID to the setting. - * - * Returns: %TRUE if the secondary connection UUID was added; %FALSE if the UUID - * was already present - **/ -gboolean -nm_setting_connection_add_secondary(NMSettingConnection *setting, const char *sec_uuid) -{ - NMSettingConnectionPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); - g_return_val_if_fail(sec_uuid != NULL, FALSE); - g_return_val_if_fail(sec_uuid[0] != '\0', FALSE); - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - for (iter = priv->secondaries; iter; iter = g_slist_next(iter)) { - if (!strcmp(sec_uuid, (char *) iter->data)) - return FALSE; - } - - priv->secondaries = g_slist_append(priv->secondaries, g_strdup(sec_uuid)); - _notify(setting, PROP_SECONDARIES); - return TRUE; -} - -/** - * nm_setting_connection_remove_secondary: - * @setting: the #NMSettingConnection - * @idx: index number of the secondary connection UUID - * - * Removes the secondary connection UUID at index @idx. - **/ -void -nm_setting_connection_remove_secondary(NMSettingConnection *setting, guint32 idx) -{ - NMSettingConnectionPrivate *priv; - GSList * elt; - - g_return_if_fail(NM_IS_SETTING_CONNECTION(setting)); - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - elt = g_slist_nth(priv->secondaries, idx); - g_return_if_fail(elt != NULL); - - g_free(elt->data); - priv->secondaries = g_slist_delete_link(priv->secondaries, elt); - _notify(setting, PROP_SECONDARIES); -} - -/** - * nm_setting_connection_remove_secondary_by_value: - * @setting: the #NMSettingConnection - * @sec_uuid: the secondary connection UUID to remove - * - * Removes the secondary connection UUID @sec_uuid. - * - * Returns: %TRUE if the secondary connection UUID was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_connection_remove_secondary_by_value(NMSettingConnection *setting, const char *sec_uuid) -{ - NMSettingConnectionPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); - g_return_val_if_fail(sec_uuid != NULL, FALSE); - g_return_val_if_fail(sec_uuid[0] != '\0', FALSE); - - priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - for (iter = priv->secondaries; iter; iter = g_slist_next(iter)) { - if (!strcmp(sec_uuid, (char *) iter->data)) { - priv->secondaries = g_slist_delete_link(priv->secondaries, iter); - _notify(setting, PROP_SECONDARIES); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_connection_get_gateway_ping_timeout: - * @setting: the #NMSettingConnection - * - * Returns: the value contained in the #NMSettingConnection:gateway-ping-timeout - * property. - **/ -guint32 -nm_setting_connection_get_gateway_ping_timeout(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->gateway_ping_timeout; -} - -/** - * nm_setting_connection_get_metered: - * @setting: the #NMSettingConnection - * - * Returns: the #NMSettingConnection:metered property of the setting. - * - * Since: 1.2 - **/ -NMMetered -nm_setting_connection_get_metered(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NM_METERED_UNKNOWN); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->metered; -} - -/** - * nm_setting_connection_get_lldp: - * @setting: the #NMSettingConnection - * - * Returns the #NMSettingConnection:lldp property of the connection. - * - * Returns: a %NMSettingConnectionLldp which indicates whether LLDP must be - * enabled for the connection. - * - * Since: 1.2 - **/ -NMSettingConnectionLldp -nm_setting_connection_get_lldp(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NM_SETTING_CONNECTION_LLDP_DEFAULT); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->lldp; -} - -/** - * nm_setting_connection_get_mdns: - * @setting: the #NMSettingConnection - * - * Returns: the #NMSettingConnection:mdns property of the setting. - * - * Since: 1.12 - **/ -NMSettingConnectionMdns -nm_setting_connection_get_mdns(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NM_SETTING_CONNECTION_MDNS_DEFAULT); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->mdns; -} - -/** - * nm_setting_connection_get_llmnr: - * @setting: the #NMSettingConnection - * - * Returns: the #NMSettingConnection:llmnr property of the setting. - * - * Since: 1.14 - **/ -NMSettingConnectionLlmnr -nm_setting_connection_get_llmnr(NMSettingConnection *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NM_SETTING_CONNECTION_LLMNR_DEFAULT); - - return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->llmnr; -} - -static void -_set_error_missing_base_setting(GError **error, const char *type) -{ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("setting required for connection of type '%s'"), - type); - g_prefix_error(error, "%s: ", type); -} - -gboolean -_nm_connection_detect_slave_type_full(NMSettingConnection *s_con, - NMConnection * connection, - const char ** out_slave_type, - const char ** out_normerr_slave_setting_type, - const char ** out_normerr_missing_slave_type, - const char ** out_normerr_missing_slave_type_port, - GError ** error) -{ - NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(s_con); - gboolean is_slave; - const char * slave_setting_type; - const char * slave_type; - const char * normerr_slave_setting_type = NULL; - const char * normerr_missing_slave_type = NULL; - const char * normerr_missing_slave_type_port = NULL; - - is_slave = FALSE; - slave_setting_type = NULL; - slave_type = priv->slave_type; - if (slave_type) { - is_slave = _nm_setting_slave_type_is_valid(slave_type, &slave_setting_type); - if (!is_slave) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Unknown slave type '%s'"), - slave_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return FALSE; - } - } - - if (is_slave) { - if (!priv->master) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("Slave connections need a valid '%s' property"), - NM_SETTING_CONNECTION_MASTER); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_MASTER); - return FALSE; - } - if (slave_setting_type && connection - && !nm_connection_get_setting_by_name(connection, slave_setting_type)) - normerr_slave_setting_type = slave_setting_type; - } else { - nm_assert(!slave_type); - if (priv->master) { - NMSetting *s_port; - - if (connection - && (slave_type = _nm_connection_detect_slave_type(connection, &s_port))) { - normerr_missing_slave_type = slave_type; - normerr_missing_slave_type_port = nm_setting_get_name(s_port); - } else { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("Cannot set '%s' without '%s'"), - NM_SETTING_CONNECTION_MASTER, - NM_SETTING_CONNECTION_SLAVE_TYPE); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return FALSE; - } - } - } - - NM_SET_OUT(out_slave_type, slave_type); - NM_SET_OUT(out_normerr_slave_setting_type, normerr_slave_setting_type); - NM_SET_OUT(out_normerr_missing_slave_type, normerr_missing_slave_type); - NM_SET_OUT(out_normerr_missing_slave_type_port, normerr_missing_slave_type_port); - return TRUE; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingConnection * self = NM_SETTING_CONNECTION(setting); - NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(self); - NMSetting * normerr_base_type = NULL; - const char * type; - const char * slave_type; - const char * normerr_slave_setting_type = NULL; - const char * normerr_missing_slave_type = NULL; - const char * normerr_missing_slave_type_port = NULL; - gboolean normerr_base_setting = FALSE; - - if (!priv->id) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_ID); - return FALSE; - } else if (!priv->id[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_ID); - return FALSE; - } - - if (priv->uuid && !nm_utils_is_uuid(priv->uuid)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid UUID"), - priv->uuid); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_UUID); - return FALSE; - } - - type = priv->type; - if (!type) { - if (!connection - || !(normerr_base_type = _nm_connection_find_base_type_setting(connection))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_TYPE); - return FALSE; - } - type = nm_setting_get_name(normerr_base_type); - } else { - GType base_type; - - if (!type[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_TYPE); - return FALSE; - } - - base_type = nm_setting_lookup_type(type); - if (base_type == G_TYPE_INVALID - || _nm_setting_type_get_base_type_priority(base_type) == NM_SETTING_PRIORITY_INVALID) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("connection type '%s' is not valid"), - type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_TYPE); - return FALSE; - } - - /* Make sure the corresponding 'type' item is present */ - if (connection && !nm_connection_get_setting_by_name(connection, type)) { - NMSetting * s_base; - NMConnection *connection2; - - s_base = g_object_new(base_type, NULL); - connection2 = nm_simple_connection_new_clone(connection); - nm_connection_add_setting(connection2, s_base); - - normerr_base_setting = nm_setting_verify(s_base, connection2, NULL); - - g_object_unref(connection2); - - if (!normerr_base_setting) { - _set_error_missing_base_setting(error, type); - return FALSE; - } - } - } - - if (priv->interface_name) { - GError * tmp_error = NULL; - NMUtilsIfaceType iface_type; - - if (NM_IN_STRSET(type, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME)) - iface_type = NMU_IFACE_OVS; - else if (nm_streq(type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) { - NMSettingOvsInterface *s_ovs_iface = NULL; - const char * ovs_iface_type; - - if (connection) - s_ovs_iface = nm_connection_get_setting_ovs_interface(connection); - _nm_setting_ovs_interface_verify_interface_type( - s_ovs_iface, - s_ovs_iface ? nm_setting_ovs_interface_get_interface_type(s_ovs_iface) : NULL, - connection, - FALSE, - NULL, - &ovs_iface_type, - NULL); - if (!ovs_iface_type) { - /* We cannot determine to OVS interface type. Consequently, we cannot - * fully validate the interface name. - * - * If we have a connection (and we do a full validation anyway), skip the - * check. The connection will fail validation when we validate the OVS setting. - * - * Otherwise, do the most basic validation. - */ - if (connection) - goto after_interface_name; - iface_type = NMU_IFACE_ANY; - } else if (NM_IN_STRSET(ovs_iface_type, "patch")) { - /* this interface type is internal to OVS. */ - iface_type = NMU_IFACE_OVS; - } else { - /* This interface type also requires a netdev. We need to validate - * for both OVS and KERNEL. */ - nm_assert(NM_IN_STRSET(ovs_iface_type, "internal", "system", "dpdk")); - iface_type = NMU_IFACE_OVS_AND_KERNEL; - } - } else - iface_type = NMU_IFACE_KERNEL; - - if (!nm_utils_ifname_valid(priv->interface_name, iface_type, &tmp_error)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - "'%s': %s", - priv->interface_name, - tmp_error->message); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_INTERFACE_NAME); - g_error_free(tmp_error); - return FALSE; - } - } -after_interface_name: - - if (!_nm_connection_detect_slave_type_full(self, - connection, - &slave_type, - &normerr_slave_setting_type, - &normerr_missing_slave_type, - &normerr_missing_slave_type_port, - error)) - return FALSE; - - if (nm_streq(type, NM_SETTING_OVS_PORT_SETTING_NAME) && slave_type - && !nm_streq(slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("'%s' connections must be enslaved to '%s', not '%s'"), - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - slave_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return FALSE; - } - - if (priv->metered != NM_METERED_UNKNOWN && priv->metered != NM_METERED_YES - && priv->metered != NM_METERED_NO) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("metered value %d is not valid"), - priv->metered); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_METERED); - return FALSE; - } - - if (priv->mdns < (int) NM_SETTING_CONNECTION_MDNS_DEFAULT - || priv->mdns > (int) NM_SETTING_CONNECTION_MDNS_YES) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value %d is not valid"), - priv->mdns); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_MDNS); - return FALSE; - } - - if (priv->llmnr < (int) NM_SETTING_CONNECTION_LLMNR_DEFAULT - || priv->llmnr > (int) NM_SETTING_CONNECTION_LLMNR_YES) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value %d is not valid"), - priv->llmnr); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_LLMNR); - return FALSE; - } - - if (!NM_IN_SET(priv->multi_connect, - (int) NM_CONNECTION_MULTI_CONNECT_DEFAULT, - (int) NM_CONNECTION_MULTI_CONNECT_SINGLE, - (int) NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE, - (int) NM_CONNECTION_MULTI_CONNECT_MULTIPLE)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value %d is not valid"), - priv->multi_connect); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_MULTI_CONNECT); - return FALSE; - } - - if (priv->mud_url) { - if (!priv->mud_url[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_CONNECTION_MUD_URL); - return FALSE; - } - if (nm_streq(priv->mud_url, NM_CONNECTION_MUD_URL_NONE)) { - /* pass */ - } else { - if (strlen(priv->mud_url) > 255) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("DHCP option cannot be longer than 255 characters")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_CONNECTION_MUD_URL); - return FALSE; - } - if (!nm_sd_http_url_is_valid_https(priv->mud_url)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("MUD URL is not a valid URL")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_CONNECTION_MUD_URL); - return FALSE; - } - } - } - - if (priv->permissions) { - guint i; - - for (i = 0; i < priv->permissions->len; i++) { - const Permission *permissions = &g_array_index(priv->permissions, Permission, i); - - if (permissions->ptype != PERM_TYPE_USER) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid permissions not in format \"user:$UNAME[:]\"")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_CONNECTION_PERMISSIONS); - return FALSE; - } - nm_assert(nm_settings_connection_validate_permission_user(permissions->item, -1)); - } - } - - /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ - - if (!priv->uuid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_UUID); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - if (normerr_base_type) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property type should be set to '%s'"), - nm_setting_get_name(normerr_base_type)); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_TYPE); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - if (normerr_base_setting) { - _set_error_missing_base_setting(error, priv->type); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - if (normerr_slave_setting_type) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("slave-type '%s' requires a '%s' setting in the connection"), - priv->slave_type, - normerr_slave_setting_type); - g_prefix_error(error, "%s: ", normerr_slave_setting_type); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - if (normerr_missing_slave_type) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("Detect a slave connection with '%s' set and a port type '%s'. '%s' should " - "be set to '%s'"), - NM_SETTING_CONNECTION_MASTER, - normerr_missing_slave_type_port, - NM_SETTING_CONNECTION_SLAVE_TYPE, - normerr_missing_slave_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - if (connection) { - gboolean has_bridge_port = FALSE; - - if ((!nm_streq0(priv->slave_type, NM_SETTING_BRIDGE_SETTING_NAME) - && (has_bridge_port = - !!nm_connection_get_setting_by_name(connection, - NM_SETTING_BRIDGE_PORT_SETTING_NAME))) - || (!nm_streq0(priv->slave_type, NM_SETTING_TEAM_SETTING_NAME) - && nm_connection_get_setting_by_name(connection, - NM_SETTING_TEAM_PORT_SETTING_NAME))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("A slave connection with '%s' set to '%s' cannot have a '%s' setting"), - NM_SETTING_CONNECTION_SLAVE_TYPE, - priv->slave_type ?: "", - has_bridge_port ? NM_SETTING_BRIDGE_PORT_SETTING_NAME - : NM_SETTING_TEAM_PORT_SETTING_NAME); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - } - - return TRUE; -} - -static const char * -find_virtual_interface_name(GVariant *connection_dict, GVariant **variant_to_free) -{ - GVariant * setting_dict; - const char *interface_name; - - nm_assert(variant_to_free && !*variant_to_free); - - setting_dict = g_variant_lookup_value(connection_dict, - NM_SETTING_BOND_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - if (!setting_dict) - setting_dict = g_variant_lookup_value(connection_dict, - NM_SETTING_BRIDGE_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - if (!setting_dict) - setting_dict = g_variant_lookup_value(connection_dict, - NM_SETTING_TEAM_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - if (!setting_dict) - setting_dict = g_variant_lookup_value(connection_dict, - NM_SETTING_VLAN_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - - if (!setting_dict) - return NULL; - - *variant_to_free = setting_dict; - - /* All of the deprecated virtual interface name properties were named "interface-name". */ - if (!g_variant_lookup(setting_dict, "interface-name", "&s", &interface_name)) - interface_name = NULL; - - return interface_name; -} - -static gboolean -nm_setting_connection_no_interface_name(NMSetting * setting, - GVariant * connection_dict, - const char * property, - NMSettingParseFlags parse_flags, - GError ** error) -{ - const char * virtual_interface_name; - gs_unref_variant GVariant *variant_to_free = NULL; - - virtual_interface_name = find_virtual_interface_name(connection_dict, &variant_to_free); - g_object_set(G_OBJECT(setting), - NM_SETTING_CONNECTION_INTERFACE_NAME, - virtual_interface_name, - NULL); - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_ID) - && nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_CONNECTION_ID)) - return NM_TERNARY_DEFAULT; - - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP) - && nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_CONNECTION_TIMESTAMP)) - return NM_TERNARY_DEFAULT; - - return NM_SETTING_CLASS(nm_setting_connection_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingConnection * setting = NM_SETTING_CONNECTION(object); - NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_ID: - g_value_set_string(value, nm_setting_connection_get_id(setting)); - break; - case PROP_UUID: - g_value_set_string(value, nm_setting_connection_get_uuid(setting)); - break; - case PROP_STABLE_ID: - g_value_set_string(value, nm_setting_connection_get_stable_id(setting)); - break; - case PROP_INTERFACE_NAME: - g_value_set_string(value, nm_setting_connection_get_interface_name(setting)); - break; - case PROP_TYPE: - g_value_set_string(value, nm_setting_connection_get_connection_type(setting)); - break; - case PROP_PERMISSIONS: - { - char **strv; - gsize i, l; - - l = nm_g_array_len(priv->permissions); - strv = g_new(char *, l + 1u); - - for (i = 0; i < l; i++) - strv[i] = _permission_to_string(&g_array_index(priv->permissions, Permission, i)); - strv[i] = NULL; - - g_value_take_boxed(value, strv); - break; - } - case PROP_AUTOCONNECT: - g_value_set_boolean(value, nm_setting_connection_get_autoconnect(setting)); - break; - case PROP_AUTOCONNECT_PRIORITY: - g_value_set_int(value, nm_setting_connection_get_autoconnect_priority(setting)); - break; - case PROP_AUTOCONNECT_RETRIES: - g_value_set_int(value, nm_setting_connection_get_autoconnect_retries(setting)); - break; - case PROP_MULTI_CONNECT: - g_value_set_int(value, priv->multi_connect); - break; - case PROP_TIMESTAMP: - g_value_set_uint64(value, nm_setting_connection_get_timestamp(setting)); - break; - case PROP_READ_ONLY: - g_value_set_boolean(value, nm_setting_connection_get_read_only(setting)); - break; - case PROP_ZONE: - g_value_set_string(value, nm_setting_connection_get_zone(setting)); - break; - case PROP_MASTER: - g_value_set_string(value, nm_setting_connection_get_master(setting)); - break; - case PROP_SLAVE_TYPE: - g_value_set_string(value, nm_setting_connection_get_slave_type(setting)); - break; - case PROP_AUTOCONNECT_SLAVES: - g_value_set_enum(value, nm_setting_connection_get_autoconnect_slaves(setting)); - break; - case PROP_SECONDARIES: - g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->secondaries, TRUE)); - break; - case PROP_GATEWAY_PING_TIMEOUT: - g_value_set_uint(value, priv->gateway_ping_timeout); - break; - case PROP_METERED: - g_value_set_enum(value, priv->metered); - break; - case PROP_LLDP: - g_value_set_int(value, priv->lldp); - break; - case PROP_AUTH_RETRIES: - g_value_set_int(value, priv->auth_retries); - break; - case PROP_MDNS: - g_value_set_int(value, priv->mdns); - break; - case PROP_LLMNR: - g_value_set_int(value, priv->llmnr); - break; - case PROP_WAIT_DEVICE_TIMEOUT: - g_value_set_int(value, priv->wait_device_timeout); - break; - case PROP_MUD_URL: - g_value_set_string(value, priv->mud_url); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_ID: - g_free(priv->id); - priv->id = g_value_dup_string(value); - break; - case PROP_UUID: - g_free(priv->uuid); - priv->uuid = g_value_dup_string(value); - break; - case PROP_STABLE_ID: - g_free(priv->stable_id); - priv->stable_id = g_value_dup_string(value); - break; - case PROP_INTERFACE_NAME: - g_free(priv->interface_name); - priv->interface_name = g_value_dup_string(value); - break; - case PROP_TYPE: - g_free(priv->type); - priv->type = g_value_dup_string(value); - break; - case PROP_PERMISSIONS: - { - const char *const *strv; - guint i; - - nm_clear_pointer(&priv->permissions, g_array_unref); - strv = g_value_get_boxed(value); - if (strv && strv[0]) { - priv->permissions = - g_array_sized_new(FALSE, FALSE, sizeof(Permission), NM_PTRARRAY_LEN(strv)); - g_array_set_clear_func(priv->permissions, (GDestroyNotify) _permission_clear_stale); - - for (i = 0; strv[i]; i++) { - Permission *permission = nm_g_array_append_new(priv->permissions, Permission); - - _permission_set_stale_parse(permission, strv[i]); - } - } - break; - } - case PROP_AUTOCONNECT: - priv->autoconnect = g_value_get_boolean(value); - break; - case PROP_AUTOCONNECT_PRIORITY: - priv->autoconnect_priority = g_value_get_int(value); - break; - case PROP_AUTOCONNECT_RETRIES: - priv->autoconnect_retries = g_value_get_int(value); - break; - case PROP_MULTI_CONNECT: - priv->multi_connect = g_value_get_int(value); - break; - case PROP_TIMESTAMP: - priv->timestamp = g_value_get_uint64(value); - break; - case PROP_READ_ONLY: - priv->read_only = g_value_get_boolean(value); - break; - case PROP_ZONE: - g_free(priv->zone); - priv->zone = g_value_dup_string(value); - break; - case PROP_MASTER: - g_free(priv->master); - priv->master = g_value_dup_string(value); - break; - case PROP_SLAVE_TYPE: - g_free(priv->slave_type); - priv->slave_type = g_value_dup_string(value); - break; - case PROP_AUTOCONNECT_SLAVES: - priv->autoconnect_slaves = g_value_get_enum(value); - break; - case PROP_SECONDARIES: - g_slist_free_full(priv->secondaries, g_free); - priv->secondaries = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); - break; - case PROP_GATEWAY_PING_TIMEOUT: - priv->gateway_ping_timeout = g_value_get_uint(value); - break; - case PROP_METERED: - priv->metered = g_value_get_enum(value); - break; - case PROP_LLDP: - priv->lldp = g_value_get_int(value); - break; - case PROP_AUTH_RETRIES: - priv->auth_retries = g_value_get_int(value); - break; - case PROP_MDNS: - priv->mdns = g_value_get_int(value); - break; - case PROP_LLMNR: - priv->llmnr = g_value_get_int(value); - break; - case PROP_WAIT_DEVICE_TIMEOUT: - priv->wait_device_timeout = g_value_get_int(value); - break; - case PROP_MUD_URL: - g_free(priv->mud_url); - priv->mud_url = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_connection_init(NMSettingConnection *setting) -{ - NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); - - priv->auth_retries = -1; - priv->autoconnect = TRUE; - priv->autoconnect_priority = NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT; - priv->autoconnect_retries = -1; - priv->autoconnect_slaves = NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT; - priv->lldp = NM_SETTING_CONNECTION_LLDP_DEFAULT; - priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; - priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; - priv->wait_device_timeout = -1; -} - -/** - * nm_setting_connection_new: - * - * Creates a new #NMSettingConnection object with default values. - * - * Returns: the new empty #NMSettingConnection object - **/ -NMSetting * -nm_setting_connection_new(void) -{ - return g_object_new(NM_TYPE_SETTING_CONNECTION, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(object); - - g_free(priv->id); - g_free(priv->uuid); - g_free(priv->stable_id); - g_free(priv->interface_name); - g_free(priv->type); - g_free(priv->zone); - g_free(priv->master); - g_free(priv->slave_type); - g_free(priv->mud_url); - nm_clear_pointer(&priv->permissions, g_array_unref); - g_slist_free_full(priv->secondaries, g_free); - - G_OBJECT_CLASS(nm_setting_connection_parent_class)->finalize(object); -} - -static void -nm_setting_connection_class_init(NMSettingConnectionClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingConnectionPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->compare_property = compare_property; - - /** - * NMSettingConnection:id: - * - * A human readable unique identifier for the connection, like "Work Wi-Fi" - * or "T-Mobile 3G". - **/ - /* ---ifcfg-rh--- - * property: id - * variable: NAME(+) - * description: User friendly name for the connection profile. - * ---end--- - */ - obj_properties[PROP_ID] = g_param_spec_string(NM_SETTING_CONNECTION_ID, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:uuid: - * - * A universally unique identifier for the connection, for example generated - * with libuuid. It should be assigned when the connection is created, and - * never changed as long as the connection still applies to the same - * network. For example, it should not be changed when the - * #NMSettingConnection:id property or #NMSettingIP4Config changes, but - * might need to be re-created when the Wi-Fi SSID, mobile broadband network - * provider, or #NMSettingConnection:type property changes. - * - * The UUID must be in the format "2815492f-7e56-435e-b2e9-246bd7cdc664" - * (ie, contains only hexadecimal characters and "-"). A suitable UUID may - * be generated by nm_utils_uuid_generate() or - * nm_utils_uuid_generate_from_string(). - **/ - /* ---ifcfg-rh--- - * property: uuid - * variable: UUID(+) - * description: UUID for the connection profile. When missing, NetworkManager - * creates the UUID itself (by hashing the filename). - * ---end--- - */ - obj_properties[PROP_UUID] = g_param_spec_string( - NM_SETTING_CONNECTION_UUID, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:stable-id: - * - * This represents the identity of the connection used for various purposes. - * It allows to configure multiple profiles to share the identity. Also, - * the stable-id can contain placeholders that are substituted dynamically and - * deterministically depending on the context. - * - * The stable-id is used for generating IPv6 stable private addresses - * with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the - * generated cloned MAC address for ethernet.cloned-mac-address=stable - * and wifi.cloned-mac-address=stable. It is also used as DHCP client - * identifier with ipv4.dhcp-client-id=stable and to derive the DHCP - * DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. - * - * Note that depending on the context where it is used, other parameters are - * also seeded into the generation algorithm. For example, a per-host key - * is commonly also included, so that different systems end up generating - * different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's - * name is included, so that different interfaces yield different addresses. - * The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret-key. - * - * The '$' character is treated special to perform dynamic substitutions - * at runtime. Currently, supported are "${CONNECTION}", "${DEVICE}", "${MAC}", - * "${BOOT}", "${RANDOM}". - * These effectively create unique IDs per-connection, per-device, per-boot, - * or every time. Note that "${DEVICE}" corresponds to the interface name of the - * device and "${MAC}" is the permanent MAC address of the device. - * Any unrecognized patterns following '$' are treated verbatim, however - * are reserved for future use. You are thus advised to avoid '$' or - * escape it as "$$". - * For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to create a unique id for - * this connection that changes with every reboot and differs depending on the - * interface where the profile activates. - * - * If the value is unset, a global connection default is consulted. If the - * value is still unset, the default is similar to "${CONNECTION}" and uses - * a unique, fixed ID for the connection. - * - * Since: 1.4 - **/ - /* ---ifcfg-rh--- - * property: stable-id - * variable: STABLE_ID(+) - * description: Token to generate stable IDs. - * ---end--- - */ - obj_properties[PROP_STABLE_ID] = g_param_spec_string( - NM_SETTING_CONNECTION_STABLE_ID, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:interface-name: - * - * The name of the network interface this connection is bound to. If not - * set, then the connection can be attached to any interface of the - * appropriate type (subject to restrictions imposed by other settings). - * - * For software devices this specifies the name of the created device. - * - * For connection types where interface names cannot easily be made - * persistent (e.g. mobile broadband or USB Ethernet), this property should - * not be used. Setting this property restricts the interfaces a connection - * can be used with, and if interface names change or are reordered the - * connection may be applied to the wrong interface. - **/ - /* ---ifcfg-rh--- - * property: interface-name - * variable: DEVICE - * description: Interface name of the device this profile is bound to. The variable - * can be left out when the profile should apply for more devices. Note that DEVICE - * can be required for some connection types. - * ---end--- - */ - obj_properties[PROP_INTERFACE_NAME] = g_param_spec_string( - NM_SETTING_CONNECTION_INTERFACE_NAME, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj( - properties_override, - obj_properties[PROP_INTERFACE_NAME], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING, - .missing_from_dbus_fcn = - nm_setting_connection_no_interface_name, )); - - /** - * NMSettingConnection:type: - * - * Base type of the connection. For hardware-dependent connections, should - * contain the setting name of the hardware-type specific setting (ie, - * "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for - * non-hardware dependent connections like VPN or otherwise, should contain - * the setting name of that setting type (ie, "vpn" or "bridge", etc). - **/ - /* ---ifcfg-rh--- - * property: type - * variable: TYPE (DEVICETYPE, DEVICE) - * values: Ethernet, Wireless, InfiniBand, Bridge, Bond, Vlan, Team, TeamPort - * description: Base type of the connection. DEVICETYPE is used for teaming - * connections. - * example: TYPE=Ethernet; TYPE=Bond; TYPE=Bridge; DEVICETYPE=TeamPort - * ---end--- - */ - obj_properties[PROP_TYPE] = g_param_spec_string(NM_SETTING_CONNECTION_TYPE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:permissions: - * - * An array of strings defining what access a given user has to this - * connection. If this is %NULL or empty, all users are allowed to access - * this connection; otherwise users are allowed if and only if they are in - * this list. When this is not empty, the connection can be active only when - * one of the specified users is logged into an active session. Each entry - * is of the form "[type]:[id]:[reserved]"; for example, "user:dcbw:blah". - * - * At this time only the "user" [type] is allowed. Any other values are - * ignored and reserved for future use. [id] is the username that this - * permission refers to, which may not contain the ":" character. Any - * [reserved] information present must be ignored and is reserved for future - * use. All of [type], [id], and [reserved] must be valid UTF-8. - */ - /* ---ifcfg-rh--- - * property: permissions - * variable: USERS(+) - * description: Restrict to certain users the access to this connection, and - * allow the connection to be active only when at least one of the - * specified users is logged into an active session. - * example: USERS="joe bob" - * ---end--- - */ - obj_properties[PROP_PERMISSIONS] = - g_param_spec_boxed(NM_SETTING_CONNECTION_PERMISSIONS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:autoconnect: - * - * Whether or not the connection should be automatically connected by - * NetworkManager when the resources for the connection are available. - * %TRUE to automatically activate the connection, %FALSE to require manual - * intervention to activate the connection. - * - * Note that autoconnect is not implemented for VPN profiles. See - * #NMSettingConnection:secondaries as an alternative to automatically - * connect VPN profiles. - **/ - /* ---ifcfg-rh--- - * property: autoconnect - * variable: ONBOOT - * default: yes - * description: Whether the connection should be autoconnected (not only while booting). - * ---end--- - */ - obj_properties[PROP_AUTOCONNECT] = g_param_spec_boolean( - NM_SETTING_CONNECTION_AUTOCONNECT, - "", - "", - TRUE, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:autoconnect-priority: - * - * The autoconnect priority. If the connection is set to autoconnect, - * connections with higher priority will be preferred. Defaults to 0. - * The higher number means higher priority. - **/ - /* ---ifcfg-rh--- - * property: autoconnect-priority - * variable: AUTOCONNECT_PRIORITY(+) - * values: -999 to 999 - * default: 0 - * description: Connection priority for automatic activation. Connections with - * higher numbers are preferred when selecting profiles for automatic activation. - * example: AUTOCONNECT_PRIORITY=20 - * ---end--- - */ - obj_properties[PROP_AUTOCONNECT_PRIORITY] = g_param_spec_int( - NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, - "", - "", - NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN, - NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX, - NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:autoconnect-retries: - * - * The number of times a connection should be tried when autoactivating before - * giving up. Zero means forever, -1 means the global default (4 times if not - * overridden). Setting this to 1 means to try activation only once before - * blocking autoconnect. Note that after a timeout, NetworkManager will try - * to autoconnect again. - */ - /* ---ifcfg-rh--- - * property: autoconnect-retries - * variable: AUTOCONNECT_RETRIES(+) - * description: The number of times a connection should be autoactivated - * before giving up and switching to the next one. - * values: -1 (use global default), 0 (forever) or a positive value - * example: AUTOCONNECT_RETRIES=1 - * ---end--- - */ - obj_properties[PROP_AUTOCONNECT_RETRIES] = g_param_spec_int( - NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, - "", - "", - -1, - G_MAXINT32, - -1, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:multi-connect: - * - * Specifies whether the profile can be active multiple times at a particular - * moment. The value is of type #NMConnectionMultiConnect. - * - * Since: 1.14 - */ - /* ---ifcfg-rh--- - * property: multi-connect - * variable: MULTI_CONNECT(+) - * description: whether the profile can be active on multiple devices at a given - * moment. The values are numbers corresponding to #NMConnectionMultiConnect enum. - * example: MULTI_CONNECT=3 - * ---end--- - */ - obj_properties[PROP_MULTI_CONNECT] = g_param_spec_int( - NM_SETTING_CONNECTION_MULTI_CONNECT, - "", - "", - G_MININT32, - G_MAXINT32, - NM_CONNECTION_MULTI_CONNECT_DEFAULT, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:timestamp: - * - * The time, in seconds since the Unix Epoch, that the connection was last - * _successfully_ fully activated. - * - * NetworkManager updates the connection timestamp periodically when the - * connection is active to ensure that an active connection has the latest - * timestamp. The property is only meant for reading (changes to this - * property will not be preserved). - **/ - obj_properties[PROP_TIMESTAMP] = g_param_spec_uint64( - NM_SETTING_CONNECTION_TIMESTAMP, - "", - "", - 0, - G_MAXUINT64, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj( - properties_override, - obj_properties[PROP_TIMESTAMP], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT64, - .to_dbus_fcn = _to_dbus_fcn_timestamp, )); - - /** - * NMSettingConnection:read-only: - * - * %FALSE if the connection can be modified using the provided settings - * service's D-Bus interface with the right privileges, or %TRUE if the - * connection is read-only and cannot be modified. - **/ - obj_properties[PROP_READ_ONLY] = g_param_spec_boolean( - NM_SETTING_CONNECTION_READ_ONLY, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:zone: - * - * The trust level of a the connection. Free form case-insensitive string - * (for example "Home", "Work", "Public"). %NULL or unspecified zone means - * the connection will be placed in the default zone as defined by the - * firewall. - * - * When updating this property on a currently activated connection, - * the change takes effect immediately. - **/ - /* ---ifcfg-rh--- - * property: zone - * variable: ZONE(+) - * description: Trust level of this connection. The string is usually used - * for a firewall. - * example: ZONE=Work - * ---end--- - */ - obj_properties[PROP_ZONE] = - g_param_spec_string(NM_SETTING_CONNECTION_ZONE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:master: - * - * Interface name of the master device or UUID of the master connection. - **/ - /* ---ifcfg-rh--- - * property: master - * variable: MASTER, MASTER_UUID, TEAM_MASTER, TEAM_MASTER_UUID, BRIDGE, BRIDGE_UUID - * description: Reference to master connection. The variable used depends on - * the connection type and the value. In general, if the *_UUID variant is present, - * the variant without *_UUID is ignored. NetworkManager attempts to write both - * for compatibility with legacy tooling. - * ---end--- - */ - obj_properties[PROP_MASTER] = - g_param_spec_string(NM_SETTING_CONNECTION_MASTER, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:slave-type: - * - * Setting name of the device type of this slave's master connection (eg, - * %NM_SETTING_BOND_SETTING_NAME), or %NULL if this connection is not a - * slave. - **/ - /* ---ifcfg-rh--- - * property: slave-type - * variable: MASTER, MASTER_UUID, TEAM_MASTER, TEAM_MASTER_UUID, DEVICETYPE, - * BRIDGE, BRIDGE_UUID - * description: Slave type doesn't map directly to a variable, but it is - * recognized using different variables. MASTER and MASTER_UUID for bonding, - * TEAM_MASTER, TEAM_MASTER_UUID and DEVICETYPE for teaming, BRIDGE - * and BRIDGE_UUID for bridging. - * ---end--- - */ - obj_properties[PROP_SLAVE_TYPE] = - g_param_spec_string(NM_SETTING_CONNECTION_SLAVE_TYPE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:autoconnect-slaves: - * - * Whether or not slaves of this connection should be automatically brought up - * when NetworkManager activates this connection. This only has a real effect - * for master connections. The properties #NMSettingConnection:autoconnect, - * #NMSettingConnection:autoconnect-priority and #NMSettingConnection:autoconnect-retries - * are unrelated to this setting. - * The permitted values are: 0: leave slave connections untouched, - * 1: activate all the slave connections with this connection, -1: default. - * If -1 (default) is set, global connection.autoconnect-slaves is read to - * determine the real value. If it is default as well, this fallbacks to 0. - * - * Since: 1.2 - **/ - /* ---ifcfg-rh--- - * property: autoconnect-slaves - * variable: AUTOCONNECT_SLAVES(+) - * default: missing variable means global default - * description: Whether slaves of this connection should be auto-connected - * when this connection is activated. - * ---end--- - */ - obj_properties[PROP_AUTOCONNECT_SLAVES] = g_param_spec_enum( - NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, - "", - "", - NM_TYPE_SETTING_CONNECTION_AUTOCONNECT_SLAVES, - NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:secondaries: - * - * List of connection UUIDs that should be activated when the base - * connection itself is activated. Currently, only VPN connections are - * supported. - **/ - /* ---ifcfg-rh--- - * property: secondaries - * variable: SECONDARY_UUIDS(+) - * description: UUID of VPN connections that should be activated - * together with this connection. - * ---end--- - */ - obj_properties[PROP_SECONDARIES] = g_param_spec_boxed( - NM_SETTING_CONNECTION_SECONDARIES, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:gateway-ping-timeout: - * - * If greater than zero, delay success of IP addressing until either the - * timeout is reached, or an IP gateway replies to a ping. - **/ - /* ---ifcfg-rh--- - * property: gateway-ping-timeout - * variable: GATEWAY_PING_TIMEOUT(+) - * default: 0 - * description: If greater than zero, the IP connectivity will be checked by - * pinging the gateway and waiting for the specified timeout (in seconds). - * example: GATEWAY_PING_TIMEOUT=5 - * ---end--- - */ - obj_properties[PROP_GATEWAY_PING_TIMEOUT] = - g_param_spec_uint(NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, - "", - "", - 0, - 600, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:metered: - * - * Whether the connection is metered. - * - * When updating this property on a currently activated connection, - * the change takes effect immediately. - * - * Since: 1.2 - **/ - /* ---ifcfg-rh--- - * property: metered - * variable: CONNECTION_METERED(+) - * values: yes,no,unknown - * description: Whether the device is metered - * example: CONNECTION_METERED=yes - * ---end--- - */ - obj_properties[PROP_METERED] = g_param_spec_enum( - NM_SETTING_CONNECTION_METERED, - "", - "", - NM_TYPE_METERED, - NM_METERED_UNKNOWN, - G_PARAM_READWRITE | NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:lldp: - * - * Whether LLDP is enabled for the connection. - * - * Since: 1.2 - **/ - /* ---ifcfg-rh--- - * property: lldp - * variable: LLDP(+) - * values: boolean value or 'rx' - * default: missing variable means global default - * description: whether LLDP is enabled for the connection - * example: LLDP=no - * ---end--- - */ - obj_properties[PROP_LLDP] = g_param_spec_int(NM_SETTING_CONNECTION_LLDP, - "", - "", - G_MININT32, - G_MAXINT32, - NM_SETTING_CONNECTION_LLDP_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:auth-retries: - * - * The number of retries for the authentication. Zero means to try indefinitely; -1 means - * to use a global default. If the global default is not set, the authentication - * retries for 3 times before failing the connection. - * - * Currently, this only applies to 802-1x authentication. - * - * Since: 1.10 - **/ - /* ---ifcfg-rh--- - * property: auth-retries - * variable: AUTH_RETRIES(+) - * default: 0 - * description: Number of retries for authentication. - * ---end--- - */ - obj_properties[PROP_AUTH_RETRIES] = g_param_spec_int( - NM_SETTING_CONNECTION_AUTH_RETRIES, - "", - "", - -1, - G_MAXINT32, - -1, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:mdns: - * - * Whether mDNS is enabled for the connection. - * - * The permitted values are: "yes" (2) register hostname and resolving - * for the connection, "no" (0) disable mDNS for the interface, "resolve" - * (1) do not register hostname but allow resolving of mDNS host names - * and "default" (-1) to allow lookup of a global default in NetworkManager.conf. - * If unspecified, "default" ultimately depends on the DNS plugin (which - * for systemd-resolved currently means "no"). - * - * This feature requires a plugin which supports mDNS. Otherwise, the - * setting has no effect. One such plugin is dns-systemd-resolved. -* - * Since: 1.12 - **/ - /* ---ifcfg-rh--- - * property: mdns - * variable: MDNS(+) - * values: yes,no,resolve - * default: missing variable means global default - * description: Whether or not mDNS is enabled for the connection - * example: MDNS=yes - * ---end--- - */ - obj_properties[PROP_MDNS] = g_param_spec_int(NM_SETTING_CONNECTION_MDNS, - "", - "", - G_MININT32, - G_MAXINT32, - NM_SETTING_CONNECTION_MDNS_DEFAULT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:llmnr: - * - * Whether Link-Local Multicast Name Resolution (LLMNR) is enabled - * for the connection. LLMNR is a protocol based on the Domain Name - * System (DNS) packet format that allows both IPv4 and IPv6 hosts - * to perform name resolution for hosts on the same local link. - * - * The permitted values are: "yes" (2) register hostname and resolving - * for the connection, "no" (0) disable LLMNR for the interface, "resolve" - * (1) do not register hostname but allow resolving of LLMNR host names - * If unspecified, "default" ultimately depends on the DNS plugin (which - * for systemd-resolved currently means "yes"). - * - * This feature requires a plugin which supports LLMNR. Otherwise, the - * setting has no effect. One such plugin is dns-systemd-resolved. - * - * Since: 1.14 - **/ - /* ---ifcfg-rh--- - * property: llmnr - * variable: LLMNR(+) - * values: yes,no,resolve - * default: missing variable means global default - * description: Whether or not LLMNR is enabled for the connection - * example: LLMNR=yes - * ---end--- - */ - obj_properties[PROP_LLMNR] = g_param_spec_int(NM_SETTING_CONNECTION_LLMNR, - "", - "", - G_MININT32, - G_MAXINT32, - NM_SETTING_CONNECTION_LLMNR_DEFAULT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:wait-device-timeout: - * - * Timeout in milliseconds to wait for device at startup. - * During boot, devices may take a while to be detected by the driver. - * This property will cause to delay NetworkManager-wait-online.service - * and nm-online to give the device a chance to appear. This works by - * waiting for the given timeout until a compatible device for the - * profile is available and managed. - * - * The value 0 means no wait time. The default value is -1, which - * currently has the same meaning as no wait time. - * - * Since: 1.20 - **/ - /* ---ifcfg-rh--- - * property: wait-device-timeout - * variable: DEVTIMEOUT(+) - * values: timeout in seconds. - * description: for initscripts compatibility, this variable must be - * a whole integer. If necessary, NetworkManager stores also a fractional - * component for the milliseconds. - * example: DEVTIMEOUT=5 - * ---end--- - */ - obj_properties[PROP_WAIT_DEVICE_TIMEOUT] = - g_param_spec_int(NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, - "", - "", - -1, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingConnection:mud-url: - * - * If configured, set to a Manufacturer Usage Description (MUD) URL that points - * to manufacturer-recommended network policies for IoT devices. It is transmitted - * as a DHCPv4 or DHCPv6 option. The value must be a valid URL starting with "https://". - * - * The special value "none" is allowed to indicate that no MUD URL is used. - * - * If the per-profile value is unspecified (the default), a global connection default gets - * consulted. If still unspecified, the ultimate default is "none". - * - * Since: 1.26 - **/ - /* ---ifcfg-rh--- - * property: mud-url - * variable: MUD_URL - * values: a valid URL that points to recommended policy for this device - * description: MUD_URL to be sent by device (See RFC 8520). - * example: https://yourdevice.example.com/model.json - * ---end--- - */ - obj_properties[PROP_MUD_URL] = g_param_spec_string(NM_SETTING_CONNECTION_MUD_URL, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_CONNECTION, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-connection.h b/libnm-core/nm-setting-connection.h deleted file mode 100644 index 34b40a4ff0..0000000000 --- a/libnm-core/nm-setting-connection.h +++ /dev/null @@ -1,219 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_CONNECTION_H__ -#define __NM_SETTING_CONNECTION_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_CONNECTION (nm_setting_connection_get_type()) -#define NM_SETTING_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_CONNECTION, NMSettingConnection)) -#define NM_SETTING_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionClass)) -#define NM_IS_SETTING_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_CONNECTION)) -#define NM_IS_SETTING_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_CONNECTION)) -#define NM_SETTING_CONNECTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionClass)) - -#define NM_SETTING_CONNECTION_SETTING_NAME "connection" - -#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN -999 -#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX 999 -#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT 0 - -#define NM_SETTING_CONNECTION_ID "id" -#define NM_SETTING_CONNECTION_UUID "uuid" -#define NM_SETTING_CONNECTION_STABLE_ID "stable-id" -#define NM_SETTING_CONNECTION_INTERFACE_NAME "interface-name" -#define NM_SETTING_CONNECTION_TYPE "type" -#define NM_SETTING_CONNECTION_AUTOCONNECT "autoconnect" -#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY "autoconnect-priority" -#define NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES "autoconnect-retries" -#define NM_SETTING_CONNECTION_MULTI_CONNECT "multi-connect" -#define NM_SETTING_CONNECTION_TIMESTAMP "timestamp" -#define NM_SETTING_CONNECTION_READ_ONLY "read-only" -#define NM_SETTING_CONNECTION_PERMISSIONS "permissions" -#define NM_SETTING_CONNECTION_ZONE "zone" -#define NM_SETTING_CONNECTION_MASTER "master" -#define NM_SETTING_CONNECTION_SLAVE_TYPE "slave-type" -#define NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES "autoconnect-slaves" -#define NM_SETTING_CONNECTION_SECONDARIES "secondaries" -#define NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT "gateway-ping-timeout" -#define NM_SETTING_CONNECTION_METERED "metered" -#define NM_SETTING_CONNECTION_LLDP "lldp" -#define NM_SETTING_CONNECTION_AUTH_RETRIES "auth-retries" -#define NM_SETTING_CONNECTION_MDNS "mdns" -#define NM_SETTING_CONNECTION_LLMNR "llmnr" -#define NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT "wait-device-timeout" -#define NM_SETTING_CONNECTION_MUD_URL "mud-url" - -/* Types for property values */ -/** - * NMSettingConnectionAutoconnectSlaves: - * @NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT: default value - * @NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO: slaves are not brought up when - * master is activated - * @NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES: slaves are brought up when - * master is activated - * - * #NMSettingConnectionAutoconnectSlaves values indicate whether slave connections - * should be activated when master is activated. - */ -typedef enum { - NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT = -1, - NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO = 0, - NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES = 1, -} NMSettingConnectionAutoconnectSlaves; - -/** - * NMSettingConnectionLldp: - * @NM_SETTING_CONNECTION_LLDP_DEFAULT: default value - * @NM_SETTING_CONNECTION_LLDP_DISABLE: disable LLDP - * @NM_SETTING_CONNECTION_LLDP_ENABLE_RX: enable reception of LLDP frames - * - * #NMSettingConnectionLldp values indicate whether LLDP should be enabled. - */ -typedef enum { - NM_SETTING_CONNECTION_LLDP_DEFAULT = -1, - NM_SETTING_CONNECTION_LLDP_DISABLE = 0, - NM_SETTING_CONNECTION_LLDP_ENABLE_RX = 1, -} NMSettingConnectionLldp; - -/** - * NMSettingConnectionMdns: - * @NM_SETTING_CONNECTION_MDNS_DEFAULT: default value - * @NM_SETTING_CONNECTION_MDNS_NO: disable mDNS - * @NM_SETTING_CONNECTION_MDNS_RESOLVE: support only resolving, do not register hostname - * @NM_SETTING_CONNECTION_MDNS_YES: enable mDNS - * - * #NMSettingConnectionMdns values indicate whether mDNS should be enabled. - * - * Since: 1.12 - */ -typedef enum { - NM_SETTING_CONNECTION_MDNS_DEFAULT = -1, - NM_SETTING_CONNECTION_MDNS_NO = 0, - NM_SETTING_CONNECTION_MDNS_RESOLVE = 1, - NM_SETTING_CONNECTION_MDNS_YES = 2, -} NMSettingConnectionMdns; - -/** - * NMSettingConnectionLlmnr: - * @NM_SETTING_CONNECTION_LLMNR_DEFAULT: default value - * @NM_SETTING_CONNECTION_LLMNR_NO: disable LLMNR - * @NM_SETTING_CONNECTION_LLMNR_RESOLVE: support only resolving, do not register hostname - * @NM_SETTING_CONNECTION_LLMNR_YES: enable LLMNR - * - * #NMSettingConnectionLlmnr values indicate whether LLMNR should be enabled. - * - * Since: 1.14 - */ -typedef enum { - NM_SETTING_CONNECTION_LLMNR_DEFAULT = -1, - NM_SETTING_CONNECTION_LLMNR_NO = 0, - NM_SETTING_CONNECTION_LLMNR_RESOLVE = 1, - NM_SETTING_CONNECTION_LLMNR_YES = 2, -} NMSettingConnectionLlmnr; - -/** - * NMSettingConnection: - * - * General Connection Profile Settings - */ -struct _NMSettingConnection { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingConnectionClass; - -GType nm_setting_connection_get_type(void); - -NMSetting * nm_setting_connection_new(void); -const char *nm_setting_connection_get_id(NMSettingConnection *setting); -const char *nm_setting_connection_get_uuid(NMSettingConnection *setting); -NM_AVAILABLE_IN_1_4 -const char *nm_setting_connection_get_stable_id(NMSettingConnection *setting); -const char *nm_setting_connection_get_interface_name(NMSettingConnection *setting); -const char *nm_setting_connection_get_connection_type(NMSettingConnection *setting); -gboolean nm_setting_connection_get_autoconnect(NMSettingConnection *setting); -int nm_setting_connection_get_autoconnect_priority(NMSettingConnection *setting); -NM_AVAILABLE_IN_1_6 -int nm_setting_connection_get_autoconnect_retries(NMSettingConnection *setting); -NM_AVAILABLE_IN_1_14 -NMConnectionMultiConnect nm_setting_connection_get_multi_connect(NMSettingConnection *setting); -guint64 nm_setting_connection_get_timestamp(NMSettingConnection *setting); -gboolean nm_setting_connection_get_read_only(NMSettingConnection *setting); - -guint32 nm_setting_connection_get_num_permissions(NMSettingConnection *setting); -gboolean nm_setting_connection_get_permission(NMSettingConnection *setting, - guint32 idx, - const char ** out_ptype, - const char ** out_pitem, - const char ** out_detail); -const char *nm_setting_connection_get_zone(NMSettingConnection *setting); -gboolean nm_setting_connection_permissions_user_allowed(NMSettingConnection *setting, - const char * uname); -gboolean nm_setting_connection_add_permission(NMSettingConnection *setting, - const char * ptype, - const char * pitem, - const char * detail); -void nm_setting_connection_remove_permission(NMSettingConnection *setting, guint32 idx); -gboolean nm_setting_connection_remove_permission_by_value(NMSettingConnection *setting, - const char * ptype, - const char * pitem, - const char * detail); - -const char *nm_setting_connection_get_master(NMSettingConnection *setting); -gboolean nm_setting_connection_is_slave_type(NMSettingConnection *setting, const char *type); -const char *nm_setting_connection_get_slave_type(NMSettingConnection *setting); -NM_AVAILABLE_IN_1_2 -NMSettingConnectionAutoconnectSlaves -nm_setting_connection_get_autoconnect_slaves(NMSettingConnection *setting); - -guint32 nm_setting_connection_get_num_secondaries(NMSettingConnection *setting); -const char *nm_setting_connection_get_secondary(NMSettingConnection *setting, guint32 idx); -gboolean nm_setting_connection_add_secondary(NMSettingConnection *setting, const char *sec_uuid); -void nm_setting_connection_remove_secondary(NMSettingConnection *setting, guint32 idx); -gboolean nm_setting_connection_remove_secondary_by_value(NMSettingConnection *setting, - const char * sec_uuid); - -guint32 nm_setting_connection_get_gateway_ping_timeout(NMSettingConnection *setting); -NM_AVAILABLE_IN_1_2 -NMMetered nm_setting_connection_get_metered(NMSettingConnection *setting); -NM_AVAILABLE_IN_1_2 -NMSettingConnectionLldp nm_setting_connection_get_lldp(NMSettingConnection *setting); - -NM_AVAILABLE_IN_1_10 -int nm_setting_connection_get_auth_retries(NMSettingConnection *setting); - -NM_AVAILABLE_IN_1_12 -NMSettingConnectionMdns nm_setting_connection_get_mdns(NMSettingConnection *setting); -NM_AVAILABLE_IN_1_14 -NMSettingConnectionLlmnr nm_setting_connection_get_llmnr(NMSettingConnection *setting); - -NM_AVAILABLE_IN_1_20 -gint32 nm_setting_connection_get_wait_device_timeout(NMSettingConnection *setting); - -NM_AVAILABLE_IN_1_26 -const char *nm_setting_connection_get_mud_url(NMSettingConnection *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_CONNECTION_H__ */ diff --git a/libnm-core/nm-setting-dcb.c b/libnm-core/nm-setting-dcb.c deleted file mode 100644 index 839d914674..0000000000 --- a/libnm-core/nm-setting-dcb.c +++ /dev/null @@ -1,1281 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2013 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-dcb.h" - -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" -#include "nm-core-enum-types.h" - -/** - * SECTION:nm-setting-dcb - * @short_description: Connection properties for Data Center Bridging - * - * The #NMSettingDcb object is a #NMSetting subclass that describes properties - * for enabling and using Data Center Bridging (DCB) on Ethernet networks. - * DCB is a set of protocols (including 802.1Qbb, 802.1Qaz, 802.1Qau, and - * 802.1AB) to eliminate packet loss in Ethernet networks and support the use - * of storage technologies like Fibre Channel over Ethernet (FCoE) and iSCSI. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingDcb, - - PROP_APP_FCOE_FLAGS, - PROP_APP_FCOE_PRIORITY, - PROP_APP_FCOE_MODE, - - PROP_APP_ISCSI_FLAGS, - PROP_APP_ISCSI_PRIORITY, - - PROP_APP_FIP_FLAGS, - PROP_APP_FIP_PRIORITY, - - PROP_PFC_FLAGS, - PROP_PRIORITY_FLOW_CONTROL, - - PROP_PRIORITY_GROUP_FLAGS, - PROP_PRIORITY_GROUP_ID, - PROP_PRIORITY_GROUP_BANDWIDTH, - PROP_PRIORITY_BANDWIDTH, - PROP_PRIORITY_STRICT_BANDWIDTH, - PROP_PRIORITY_TRAFFIC_CLASS, ); - -typedef struct { - char * app_fcoe_mode; - guint pfc[8]; - guint priority_group_id[8]; - guint priority_group_bandwidth[8]; - guint priority_bandwidth[8]; - guint priority_strict[8]; - guint priority_traffic_class[8]; - int app_fcoe_priority; - int app_iscsi_priority; - int app_fip_priority; - NMSettingDcbFlags app_fcoe_flags; - NMSettingDcbFlags app_iscsi_flags; - NMSettingDcbFlags app_fip_flags; - NMSettingDcbFlags pfc_flags; - NMSettingDcbFlags priority_group_flags; -} NMSettingDcbPrivate; - -G_DEFINE_TYPE(NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING) - -#define NM_SETTING_DCB_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_DCB, NMSettingDcbPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_dcb_get_app_fcoe_flags: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:app-fcoe-flags property of the setting - **/ -NMSettingDcbFlags -nm_setting_dcb_get_app_fcoe_flags(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fcoe_flags; -} - -/** - * nm_setting_dcb_get_app_fcoe_priority: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:app-fcoe-priority property of the setting - **/ -int -nm_setting_dcb_get_app_fcoe_priority(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fcoe_priority; -} - -/** - * nm_setting_dcb_get_app_fcoe_mode: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:app-fcoe-mode property of the setting - **/ -const char * -nm_setting_dcb_get_app_fcoe_mode(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), NULL); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fcoe_mode; -} - -/** - * nm_setting_dcb_get_app_iscsi_flags: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:app-iscsi-flags property of the setting - **/ -NMSettingDcbFlags -nm_setting_dcb_get_app_iscsi_flags(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->app_iscsi_flags; -} - -/** - * nm_setting_dcb_get_app_iscsi_priority: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:app-iscsi-priority property of the setting - **/ -int -nm_setting_dcb_get_app_iscsi_priority(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->app_iscsi_priority; -} - -/** - * nm_setting_dcb_get_app_fip_flags: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:app-fip-flags property of the setting - **/ -NMSettingDcbFlags -nm_setting_dcb_get_app_fip_flags(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fip_flags; -} - -/** - * nm_setting_dcb_get_app_fip_priority: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:app-fip-priority property of the setting - **/ -int -nm_setting_dcb_get_app_fip_priority(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fip_priority; -} - -/** - * nm_setting_dcb_get_priority_flow_control_flags: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:priority-flow-control-flags property of the setting - **/ -NMSettingDcbFlags -nm_setting_dcb_get_priority_flow_control_flags(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->pfc_flags; -} - -/** - * nm_setting_dcb_get_priority_flow_control: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to retrieve flow control for - * - * Returns: %TRUE if flow control is enabled for the given @user_priority, - * %FALSE if not enabled - **/ -gboolean -nm_setting_dcb_get_priority_flow_control(NMSettingDcb *setting, guint user_priority) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), FALSE); - g_return_val_if_fail(user_priority <= 7, FALSE); - - return !!NM_SETTING_DCB_GET_PRIVATE(setting)->pfc[user_priority]; -} - -/** - * nm_setting_dcb_set_priority_flow_control: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to set flow control for - * @enabled: %TRUE to enable flow control for this priority, %FALSE to disable it - * - * These values are only valid when #NMSettingDcb:priority-flow-control includes - * the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -void -nm_setting_dcb_set_priority_flow_control(NMSettingDcb *setting, - guint user_priority, - gboolean enabled) -{ - NMSettingDcbPrivate *priv; - guint uint_enabled = enabled ? 1 : 0; - - g_return_if_fail(NM_IS_SETTING_DCB(setting)); - g_return_if_fail(user_priority <= 7); - - priv = NM_SETTING_DCB_GET_PRIVATE(setting); - if (priv->pfc[user_priority] != uint_enabled) { - priv->pfc[user_priority] = uint_enabled; - _notify(setting, PROP_PRIORITY_FLOW_CONTROL); - } -} - -/** - * nm_setting_dcb_get_priority_group_flags: - * @setting: the #NMSettingDcb - * - * Returns: the #NMSettingDcb:priority-group-flags property of the setting - **/ -NMSettingDcbFlags -nm_setting_dcb_get_priority_group_flags(NMSettingDcb *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_group_flags; -} - -/** - * nm_setting_dcb_get_priority_group_id: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to retrieve the group ID for - * - * Returns: the group number @user_priority is assigned to. These values are - * only valid when #NMSettingDcb:priority-group-flags includes the - * %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -guint -nm_setting_dcb_get_priority_group_id(NMSettingDcb *setting, guint user_priority) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - g_return_val_if_fail(user_priority <= 7, 0); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_group_id[user_priority]; -} - -/** - * nm_setting_dcb_set_priority_group_id: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to set flow control for - * @group_id: the group (0 - 7) to assign @user_priority to, or 15 for the - * unrestricted group. - * - * These values are only valid when #NMSettingDcb:priority-group-flags includes - * the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -void -nm_setting_dcb_set_priority_group_id(NMSettingDcb *setting, guint user_priority, guint group_id) -{ - NMSettingDcbPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_DCB(setting)); - g_return_if_fail(user_priority <= 7); - g_return_if_fail(group_id <= 7 || group_id == 15); - - priv = NM_SETTING_DCB_GET_PRIVATE(setting); - if (priv->priority_group_id[user_priority] != group_id) { - priv->priority_group_id[user_priority] = group_id; - _notify(setting, PROP_PRIORITY_GROUP_ID); - } -} - -/** - * nm_setting_dcb_get_priority_group_bandwidth: - * @setting: the #NMSettingDcb - * @group_id: the priority group (0 - 7) to retrieve the bandwidth percentage for - * - * Returns: the bandwidth percentage assigned to @group_id. These values are - * only valid when #NMSettingDcb:priority-group-flags includes the - * %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -guint -nm_setting_dcb_get_priority_group_bandwidth(NMSettingDcb *setting, guint group_id) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - g_return_val_if_fail(group_id <= 7, FALSE); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_group_bandwidth[group_id]; -} - -/** - * nm_setting_dcb_set_priority_group_bandwidth: - * @setting: the #NMSettingDcb - * @group_id: the priority group (0 - 7) to set the bandwidth percentage for - * @bandwidth_percent: the bandwidth percentage (0 - 100) to assign to @group_id to - * - * These values are only valid when #NMSettingDcb:priority-group-flags includes - * the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -void -nm_setting_dcb_set_priority_group_bandwidth(NMSettingDcb *setting, - guint group_id, - guint bandwidth_percent) -{ - NMSettingDcbPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_DCB(setting)); - g_return_if_fail(group_id <= 7); - g_return_if_fail(bandwidth_percent <= 100); - - priv = NM_SETTING_DCB_GET_PRIVATE(setting); - if (priv->priority_group_bandwidth[group_id] != bandwidth_percent) { - priv->priority_group_bandwidth[group_id] = bandwidth_percent; - _notify(setting, PROP_PRIORITY_GROUP_BANDWIDTH); - } -} - -/** - * nm_setting_dcb_get_priority_bandwidth: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to retrieve the group bandwidth percentage for - * - * Returns: the allowed bandwidth percentage of @user_priority in its priority group. - * These values are only valid when #NMSettingDcb:priority-group-flags includes the - * %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -guint -nm_setting_dcb_get_priority_bandwidth(NMSettingDcb *setting, guint user_priority) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - g_return_val_if_fail(user_priority <= 7, FALSE); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_bandwidth[user_priority]; -} - -/** - * nm_setting_dcb_set_priority_bandwidth: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for - * @bandwidth_percent: the bandwidth percentage (0 - 100) that @user_priority is - * allowed to use within its priority group - * - * These values are only valid when #NMSettingDcb:priority-group-flags includes - * the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -void -nm_setting_dcb_set_priority_bandwidth(NMSettingDcb *setting, - guint user_priority, - guint bandwidth_percent) -{ - NMSettingDcbPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_DCB(setting)); - g_return_if_fail(user_priority <= 7); - g_return_if_fail(bandwidth_percent <= 100); - - priv = NM_SETTING_DCB_GET_PRIVATE(setting); - if (priv->priority_bandwidth[user_priority] != bandwidth_percent) { - priv->priority_bandwidth[user_priority] = bandwidth_percent; - _notify(setting, PROP_PRIORITY_BANDWIDTH); - } -} - -/** - * nm_setting_dcb_get_priority_strict_bandwidth: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to retrieve strict bandwidth for - * - * Returns: %TRUE if @user_priority may use all of the bandwidth allocated to its - * assigned group, or %FALSE if not. These values are only valid when - * #NMSettingDcb:priority-group-flags includes the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -gboolean -nm_setting_dcb_get_priority_strict_bandwidth(NMSettingDcb *setting, guint user_priority) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - g_return_val_if_fail(user_priority <= 7, FALSE); - - return !!NM_SETTING_DCB_GET_PRIVATE(setting)->priority_strict[user_priority]; -} - -/** - * nm_setting_dcb_set_priority_strict_bandwidth: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to set strict bandwidth for - * @strict: %TRUE to allow @user_priority to use all the bandwidth allocated to - * its priority group, or %FALSE if not - * - * These values are only valid when #NMSettingDcb:priority-group-flags includes - * the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -void -nm_setting_dcb_set_priority_strict_bandwidth(NMSettingDcb *setting, - guint user_priority, - gboolean strict) -{ - NMSettingDcbPrivate *priv; - guint uint_strict = strict ? 1 : 0; - - g_return_if_fail(NM_IS_SETTING_DCB(setting)); - g_return_if_fail(user_priority <= 7); - - priv = NM_SETTING_DCB_GET_PRIVATE(setting); - if (priv->priority_strict[user_priority] != uint_strict) { - priv->priority_strict[user_priority] = uint_strict; - _notify(setting, PROP_PRIORITY_STRICT_BANDWIDTH); - } -} - -/** - * nm_setting_dcb_get_priority_traffic_class: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to retrieve the traffic class for - * - * Returns: the traffic class assigned to @user_priority. These values are only - * valid when #NMSettingDcb:priority-group-flags includes the - * %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -guint -nm_setting_dcb_get_priority_traffic_class(NMSettingDcb *setting, guint user_priority) -{ - g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); - g_return_val_if_fail(user_priority <= 7, FALSE); - - return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_traffic_class[user_priority]; -} - -/** - * nm_setting_dcb_set_priority_traffic_clas: - * @setting: the #NMSettingDcb - * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for - * @traffic_class: the traffic_class (0 - 7) that @user_priority should map to - * - * These values are only valid when #NMSettingDcb:priority-group-flags includes - * the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ -void -nm_setting_dcb_set_priority_traffic_class(NMSettingDcb *setting, - guint user_priority, - guint traffic_class) -{ - NMSettingDcbPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_DCB(setting)); - g_return_if_fail(user_priority <= 7); - g_return_if_fail(traffic_class <= 7); - - priv = NM_SETTING_DCB_GET_PRIVATE(setting); - if (priv->priority_traffic_class[user_priority] != traffic_class) { - priv->priority_traffic_class[user_priority] = traffic_class; - _notify(setting, PROP_PRIORITY_TRAFFIC_CLASS); - } -} - -/*****************************************************************************/ - -#define DCB_FLAGS_ALL \ - (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) - -static gboolean -check_dcb_flags(NMSettingDcbFlags flags, const char *prop_name, GError **error) -{ - if (flags & ~DCB_FLAGS_ALL) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("flags invalid")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); - return FALSE; - } - - if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (flags & ~NM_SETTING_DCB_FLAG_ENABLE)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("flags invalid - disabled")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); - return FALSE; - } - - return TRUE; -} - -static gboolean -check_uint_array(const guint * array, - guint len, - NMSettingDcbFlags flags, - guint max, - guint extra, - gboolean sum_pct, - const char * prop_name, - GError ** error) -{ - guint i, sum = 0; - - /* Ensure each element is <= to max or equals extra */ - for (i = 0; i < len; i++) { - if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && array[i]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property invalid (not enabled)")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); - return FALSE; - } - - if ((array[i] > max) && (array[i] != extra)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("element invalid")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); - return FALSE; - } - sum += array[i]; - } - - /* Verify sum of percentages */ - if (sum_pct) { - if (flags & NM_SETTING_DCB_FLAG_ENABLE) { - /* If the feature is enabled, sum must equal 100% */ - if (sum != 100) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("sum not 100%")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); - return FALSE; - } - } else { - /* If the feature is disabled, sum must equal 0%, which was checked - * by the for() loop above. - */ - g_assert_cmpint(sum, ==, 0); - } - } - - return TRUE; -} - -static gboolean -check_priority(int val, NMSettingDcbFlags flags, const char *prop_name, GError **error) -{ - if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (val >= 0)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property invalid (not enabled)")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); - return FALSE; - } - - if (val < -1 || val > 7) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property invalid")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); - return FALSE; - } - return TRUE; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(setting); - - if (!check_dcb_flags(priv->app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_FLAGS, error)) - return FALSE; - - if (!check_priority(priv->app_fcoe_priority, - priv->app_fcoe_flags, - NM_SETTING_DCB_APP_FCOE_PRIORITY, - error)) - return FALSE; - - if (!priv->app_fcoe_mode) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property missing")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE); - return FALSE; - } - - if (strcmp(priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_FABRIC) - && strcmp(priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_VN2VN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property invalid")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE); - return FALSE; - } - - if (!check_dcb_flags(priv->app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_FLAGS, error)) - return FALSE; - - if (!check_priority(priv->app_iscsi_priority, - priv->app_iscsi_flags, - NM_SETTING_DCB_APP_ISCSI_PRIORITY, - error)) - return FALSE; - - if (!check_dcb_flags(priv->app_fip_flags, NM_SETTING_DCB_APP_FIP_FLAGS, error)) - return FALSE; - - if (!check_priority(priv->app_fip_priority, - priv->app_fip_flags, - NM_SETTING_DCB_APP_FIP_PRIORITY, - error)) - return FALSE; - - if (!check_dcb_flags(priv->pfc_flags, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, error)) - return FALSE; - - if (!check_uint_array(priv->pfc, - G_N_ELEMENTS(priv->pfc), - priv->pfc_flags, - 1, - 0, - FALSE, - NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, - error)) - return FALSE; - - if (!check_dcb_flags(priv->priority_group_flags, NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, error)) - return FALSE; - - if (!check_uint_array(priv->priority_group_id, - G_N_ELEMENTS(priv->priority_group_id), - priv->priority_group_flags, - 7, - 15, - FALSE, - NM_SETTING_DCB_PRIORITY_GROUP_ID, - error)) - return FALSE; - - if (!check_uint_array(priv->priority_group_bandwidth, - G_N_ELEMENTS(priv->priority_group_bandwidth), - priv->priority_group_flags, - 100, - 0, - TRUE, - NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, - error)) - return FALSE; - - /* FIXME: sum bandwidths in each group */ - if (!check_uint_array(priv->priority_bandwidth, - G_N_ELEMENTS(priv->priority_bandwidth), - priv->priority_group_flags, - 100, - 0, - FALSE, - NM_SETTING_DCB_PRIORITY_BANDWIDTH, - error)) - return FALSE; - - if (!check_uint_array(priv->priority_strict, - G_N_ELEMENTS(priv->priority_strict), - priv->priority_group_flags, - 1, - 0, - FALSE, - NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, - error)) - return FALSE; - - if (!check_uint_array(priv->priority_traffic_class, - G_N_ELEMENTS(priv->priority_traffic_class), - priv->priority_group_flags, - 7, - 0, - FALSE, - NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS, - error)) - return FALSE; - - return TRUE; -} - -/*****************************************************************************/ - -G_STATIC_ASSERT(sizeof(guint) == sizeof(gboolean)); - -static void -set_array_from_gvalue(const GValue *v, uint *a, size_t len) -{ - GArray * src = g_value_get_boxed(v); - const guint total_len = len * sizeof(a[0]); - - memset(a, 0, total_len); - if (src) { - g_return_if_fail(g_array_get_element_size(src) == sizeof(a[0])); - g_return_if_fail(src->len == len); - memcpy(a, src->data, total_len); - } -} -#define SET_ARRAY_FROM_GVALUE(v, a) set_array_from_gvalue(v, a, G_N_ELEMENTS(a)) - -static void -set_gvalue_from_array(GValue *v, uint *a, size_t len) -{ - GArray *src = g_array_sized_new(FALSE, TRUE, sizeof(guint), len); - - g_array_append_vals(src, a, len); - g_value_take_boxed(v, src); -} - -#define SET_GVALUE_FROM_ARRAY(v, a) set_gvalue_from_array(v, a, G_N_ELEMENTS(a)) - -static GVariant * -_nm_setting_dcb_uint_array_to_dbus(const GValue *prop_value) -{ - GArray *src = g_value_get_boxed(prop_value); - - return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, src->data, src->len, sizeof(guint32)); -} - -static void -_nm_setting_dcb_uint_array_from_dbus(GVariant *dbus_value, GValue *prop_value) -{ - gconstpointer array; - gsize length; - - array = g_variant_get_fixed_array(dbus_value, &length, sizeof(guint32)); - set_gvalue_from_array(prop_value, (guint *) array, length); -} - -static const NMSettInfoPropertType nm_sett_info_propert_type_dcb_au = { - .dbus_type = NM_G_VARIANT_TYPE("au"), - .gprop_to_dbus_fcn = _nm_setting_dcb_uint_array_to_dbus, - .gprop_from_dbus_fcn = _nm_setting_dcb_uint_array_from_dbus, -}; - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingDcb * setting = NM_SETTING_DCB(object); - NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_APP_FCOE_FLAGS: - g_value_set_flags(value, priv->app_fcoe_flags); - break; - case PROP_APP_FCOE_PRIORITY: - g_value_set_int(value, priv->app_fcoe_priority); - break; - case PROP_APP_FCOE_MODE: - g_value_set_string(value, priv->app_fcoe_mode); - break; - case PROP_APP_ISCSI_FLAGS: - g_value_set_flags(value, priv->app_iscsi_flags); - break; - case PROP_APP_ISCSI_PRIORITY: - g_value_set_int(value, priv->app_iscsi_priority); - break; - case PROP_APP_FIP_FLAGS: - g_value_set_flags(value, priv->app_fip_flags); - break; - case PROP_APP_FIP_PRIORITY: - g_value_set_int(value, priv->app_fip_priority); - break; - case PROP_PFC_FLAGS: - g_value_set_flags(value, priv->pfc_flags); - break; - case PROP_PRIORITY_FLOW_CONTROL: - SET_GVALUE_FROM_ARRAY(value, priv->pfc); - break; - case PROP_PRIORITY_GROUP_FLAGS: - g_value_set_flags(value, priv->priority_group_flags); - break; - case PROP_PRIORITY_GROUP_ID: - SET_GVALUE_FROM_ARRAY(value, priv->priority_group_id); - break; - case PROP_PRIORITY_GROUP_BANDWIDTH: - SET_GVALUE_FROM_ARRAY(value, priv->priority_group_bandwidth); - break; - case PROP_PRIORITY_BANDWIDTH: - SET_GVALUE_FROM_ARRAY(value, priv->priority_bandwidth); - break; - case PROP_PRIORITY_STRICT_BANDWIDTH: - SET_GVALUE_FROM_ARRAY(value, priv->priority_strict); - break; - case PROP_PRIORITY_TRAFFIC_CLASS: - SET_GVALUE_FROM_ARRAY(value, priv->priority_traffic_class); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_APP_FCOE_FLAGS: - priv->app_fcoe_flags = g_value_get_flags(value); - break; - case PROP_APP_FCOE_PRIORITY: - priv->app_fcoe_priority = g_value_get_int(value); - break; - case PROP_APP_FCOE_MODE: - g_free(priv->app_fcoe_mode); - priv->app_fcoe_mode = g_value_dup_string(value); - break; - case PROP_APP_ISCSI_FLAGS: - priv->app_iscsi_flags = g_value_get_flags(value); - break; - case PROP_APP_ISCSI_PRIORITY: - priv->app_iscsi_priority = g_value_get_int(value); - break; - case PROP_APP_FIP_FLAGS: - priv->app_fip_flags = g_value_get_flags(value); - break; - case PROP_APP_FIP_PRIORITY: - priv->app_fip_priority = g_value_get_int(value); - break; - case PROP_PFC_FLAGS: - priv->pfc_flags = g_value_get_flags(value); - break; - case PROP_PRIORITY_FLOW_CONTROL: - SET_ARRAY_FROM_GVALUE(value, priv->pfc); - break; - case PROP_PRIORITY_GROUP_FLAGS: - priv->priority_group_flags = g_value_get_flags(value); - break; - case PROP_PRIORITY_GROUP_ID: - SET_ARRAY_FROM_GVALUE(value, priv->priority_group_id); - break; - case PROP_PRIORITY_GROUP_BANDWIDTH: - SET_ARRAY_FROM_GVALUE(value, priv->priority_group_bandwidth); - break; - case PROP_PRIORITY_BANDWIDTH: - SET_ARRAY_FROM_GVALUE(value, priv->priority_bandwidth); - break; - case PROP_PRIORITY_STRICT_BANDWIDTH: - SET_ARRAY_FROM_GVALUE(value, priv->priority_strict); - break; - case PROP_PRIORITY_TRAFFIC_CLASS: - SET_ARRAY_FROM_GVALUE(value, priv->priority_traffic_class); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_dcb_init(NMSettingDcb *self) -{ - NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(self); - - priv->app_fcoe_mode = g_strdup(NM_SETTING_DCB_FCOE_MODE_FABRIC); - priv->app_fcoe_priority = -1; - priv->app_fip_priority = -1; - priv->app_iscsi_priority = -1; -} - -/** - * nm_setting_dcb_new: - * - * Creates a new #NMSettingDcb object with default values. - * - * Returns: (transfer full): the new empty #NMSettingDcb object - **/ -NMSetting * -nm_setting_dcb_new(void) -{ - return g_object_new(NM_TYPE_SETTING_DCB, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(object); - - g_free(priv->app_fcoe_mode); - - G_OBJECT_CLASS(nm_setting_dcb_parent_class)->finalize(object); -} - -static void -nm_setting_dcb_class_init(NMSettingDcbClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingDcbPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingDcb:app-fcoe-flags: - * - * Specifies the #NMSettingDcbFlags for the DCB FCoE application. Flags may - * be any combination of %NM_SETTING_DCB_FLAG_ENABLE, - * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. - **/ - /* ---ifcfg-rh--- - * property: app-fcoe-flags - * variable: DCB_APP_FCOE_ENABLE, DCB_APP_FCOE_ADVERTISE, DCB_APP_FCOE_WILLING - * description: FCOE flags. - * default: no - * example: DCB_APP_FCOE_ENABLE=yes DCB_APP_FCOE_ADVERTISE=yes - * ---end--- - */ - obj_properties[PROP_APP_FCOE_FLAGS] = - g_param_spec_flags(NM_SETTING_DCB_APP_FCOE_FLAGS, - "", - "", - NM_TYPE_SETTING_DCB_FLAGS, - NM_SETTING_DCB_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:app-fcoe-priority: - * - * The highest User Priority (0 - 7) which FCoE frames should use, or -1 for - * default priority. Only used when the #NMSettingDcb:app-fcoe-flags - * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ - /* ---ifcfg-rh--- - * property: app-fcoe-priority - * variable: DCB_APP_FCOE_PRIORITY - * values: 0 - 7 - * description: Priority of FCoE frames. - * ---end--- - */ - obj_properties[PROP_APP_FCOE_PRIORITY] = - g_param_spec_int(NM_SETTING_DCB_APP_FCOE_PRIORITY, - "", - "", - -1, - 7, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:app-fcoe-mode: - * - * The FCoE controller mode; either %NM_SETTING_DCB_FCOE_MODE_FABRIC - * (default) or %NM_SETTING_DCB_FCOE_MODE_VN2VN. - **/ - /* ---ifcfg-rh--- - * property: app-fcoe-mode - * variable: DCB_APP_FCOE_MODE - * values: fabric, vn2vn - * default: fabric - * description: FCoE controller mode. - * ---end--- - */ - obj_properties[PROP_APP_FCOE_MODE] = - g_param_spec_string(NM_SETTING_DCB_APP_FCOE_MODE, - "", - "", - NM_SETTING_DCB_FCOE_MODE_FABRIC, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:app-iscsi-flags: - * - * Specifies the #NMSettingDcbFlags for the DCB iSCSI application. Flags - * may be any combination of %NM_SETTING_DCB_FLAG_ENABLE, - * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. - **/ - /* ---ifcfg-rh--- - * property: app-iscsi-flags - * variable: DCB_APP_ISCSI_ENABLE, DCB_APP_ISCSI_ADVERTISE, DCB_APP_ISCSI_WILLING - * default: no - * description: iSCSI flags. - * ---end--- - */ - obj_properties[PROP_APP_ISCSI_FLAGS] = - g_param_spec_flags(NM_SETTING_DCB_APP_ISCSI_FLAGS, - "", - "", - NM_TYPE_SETTING_DCB_FLAGS, - NM_SETTING_DCB_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:app-iscsi-priority: - * - * The highest User Priority (0 - 7) which iSCSI frames should use, or -1 - * for default priority. Only used when the #NMSettingDcb:app-iscsi-flags - * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ - /* ---ifcfg-rh--- - * property: app-iscsi-priority - * variable: DCB_APP_ISCSI_PRIORITY - * values: 0 - 7 - * description: Priority of iSCSI frames. - * ---end--- - */ - obj_properties[PROP_APP_ISCSI_PRIORITY] = - g_param_spec_int(NM_SETTING_DCB_APP_ISCSI_PRIORITY, - "", - "", - -1, - 7, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:app-fip-flags: - * - * Specifies the #NMSettingDcbFlags for the DCB FIP application. Flags may - * be any combination of %NM_SETTING_DCB_FLAG_ENABLE, - * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. - **/ - /* ---ifcfg-rh--- - * property: app-fip-flags - * variable: DCB_APP_FIP_ENABLE, DCB_APP_FIP_ADVERTISE, DCB_APP_FIP_WILLING - * default: no - * description: FIP flags. - * ---end--- - */ - obj_properties[PROP_APP_FIP_FLAGS] = - g_param_spec_flags(NM_SETTING_DCB_APP_FIP_FLAGS, - "", - "", - NM_TYPE_SETTING_DCB_FLAGS, - NM_SETTING_DCB_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:app-fip-priority: - * - * The highest User Priority (0 - 7) which FIP frames should use, or -1 for - * default priority. Only used when the #NMSettingDcb:app-fip-flags - * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag. - **/ - /* ---ifcfg-rh--- - * property: app-fip-priority - * variable: DCB_APP_FIP_PRIORITY - * values: 0 - 7 - * description: Priority of FIP frames. - * ---end--- - */ - obj_properties[PROP_APP_FIP_PRIORITY] = - g_param_spec_int(NM_SETTING_DCB_APP_FIP_PRIORITY, - "", - "", - -1, - 7, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:priority-flow-control-flags: - * - * Specifies the #NMSettingDcbFlags for DCB Priority Flow Control (PFC). - * Flags may be any combination of %NM_SETTING_DCB_FLAG_ENABLE, - * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. - **/ - /* ---ifcfg-rh--- - * property: priority-flow-control-flags - * variable: DCB_PFC_ENABLE, DCB_PFC_ADVERTISE, DCB_PFC_WILLING - * default: no - * description: Priority flow control flags. - * ---end--- - */ - obj_properties[PROP_PFC_FLAGS] = g_param_spec_flags(NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, - "", - "", - NM_TYPE_SETTING_DCB_FLAGS, - NM_SETTING_DCB_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:priority-flow-control: (type GArray(gboolean)) - * - * An array of 8 boolean values, where the array index corresponds to the User - * Priority (0 - 7) and the value indicates whether or not the corresponding - * priority should transmit priority pause. - **/ - /* ---ifcfg-rh--- - * property: priority-flow-control - * variable: DCB_PFC_UP - * description: Priority flow control values. String of 8 "0" and "1", where "0". - * means "do not transmit priority pause", "1" means "transmit pause". - * example: DCB_PFC_UP=01101110 - * ---end--- - */ - obj_properties[PROP_PRIORITY_FLOW_CONTROL] = - g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, - "", - "", - G_TYPE_ARRAY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_PRIORITY_FLOW_CONTROL], - &nm_sett_info_propert_type_dcb_au); - - /** - * NMSettingDcb:priority-group-flags: - * - * Specifies the #NMSettingDcbFlags for DCB Priority Groups. Flags may be - * any combination of %NM_SETTING_DCB_FLAG_ENABLE, - * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. - **/ - /* ---ifcfg-rh--- - * property: priority-group-flags - * variable: DCB_PG_ENABLE, DCB_PG_ADVERTISE, DCB_PG_WILLING - * default: no - * description: Priority groups flags. - * ---end--- - */ - obj_properties[PROP_PRIORITY_GROUP_FLAGS] = - g_param_spec_flags(NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, - "", - "", - NM_TYPE_SETTING_DCB_FLAGS, - NM_SETTING_DCB_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingDcb:priority-group-id: (type GArray(guint)) - * - * An array of 8 uint values, where the array index corresponds to the User - * Priority (0 - 7) and the value indicates the Priority Group ID. Allowed - * Priority Group ID values are 0 - 7 or 15 for the unrestricted group. - **/ - /* ---ifcfg-rh--- - * property: priority-group-id - * variable: DCB_PG_ID - * description: Priority groups values. String of eight priorities (0 - 7) or "f" - * (unrestricted). - * example: DCB_PG_ID=1205f173 - * ---end--- - */ - obj_properties[PROP_PRIORITY_GROUP_ID] = - g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_GROUP_ID, - "", - "", - G_TYPE_ARRAY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_PRIORITY_GROUP_ID], - &nm_sett_info_propert_type_dcb_au); - - /** - * NMSettingDcb:priority-group-bandwidth: (type GArray(guint)) - * - * An array of 8 uint values, where the array index corresponds to the - * Priority Group ID (0 - 7) and the value indicates the percentage of link - * bandwidth allocated to that group. Allowed values are 0 - 100, and the - * sum of all values must total 100 percents. - **/ - /* ---ifcfg-rh--- - * property: priority-group-bandwidth - * variable: DCB_PG_PCT - * description: Priority groups values. Eight bandwidths (in percent), separated with commas. - * example: DCB_PG_PCT=10,5,10,15,10,10,10,30 - * ---end--- - */ - obj_properties[PROP_PRIORITY_GROUP_BANDWIDTH] = - g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, - "", - "", - G_TYPE_ARRAY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_PRIORITY_GROUP_BANDWIDTH], - &nm_sett_info_propert_type_dcb_au); - - /** - * NMSettingDcb:priority-bandwidth: (type GArray(guint)) - * - * An array of 8 uint values, where the array index corresponds to the User - * Priority (0 - 7) and the value indicates the percentage of bandwidth of - * the priority's assigned group that the priority may use. The sum of all - * percentages for priorities which belong to the same group must total 100 - * percents. - **/ - /* ---ifcfg-rh--- - * property: priority-bandwidth - * variable: DCB_PG_UPPCT - * description: Priority values. Eight bandwidths (in percent), separated with commas. - * The sum of the numbers must be 100. - * example: DCB_PG_UPPCT=7,13,10,10,15,15,10,20 - * ---end--- - */ - obj_properties[PROP_PRIORITY_BANDWIDTH] = - g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_BANDWIDTH, - "", - "", - G_TYPE_ARRAY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_PRIORITY_BANDWIDTH], - &nm_sett_info_propert_type_dcb_au); - - /** - * NMSettingDcb:priority-strict-bandwidth: (type GArray(gboolean)) - * - * An array of 8 boolean values, where the array index corresponds to the User - * Priority (0 - 7) and the value indicates whether or not the priority may - * use all of the bandwidth allocated to its assigned group. - **/ - /* ---ifcfg-rh--- - * property: priority-strict-bandwidth - * variable: DCB_PG_STRICT - * description: Priority values. String of eight "0" or "1", where "0" means - * "may not utilize all bandwidth", "1" means "may utilize all bandwidth". - * example: DCB_PG_STRICT=01101110 - * ---end--- - */ - obj_properties[PROP_PRIORITY_STRICT_BANDWIDTH] = - g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, - "", - "", - G_TYPE_ARRAY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_PRIORITY_STRICT_BANDWIDTH], - &nm_sett_info_propert_type_dcb_au); - - /** - * NMSettingDcb:priority-traffic-class: (type GArray(guint)) - * - * An array of 8 uint values, where the array index corresponds to the User - * Priority (0 - 7) and the value indicates the traffic class (0 - 7) to - * which the priority is mapped. - **/ - /* ---ifcfg-rh--- - * property: priority-traffic-class - * variable: DCB_PG_UP2TC - * description: Priority values. String of eight traffic class values (0 - 7). - * example: DCB_PG_UP2TC=01623701 - * ---end--- - */ - obj_properties[PROP_PRIORITY_TRAFFIC_CLASS] = - g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS, - "", - "", - G_TYPE_ARRAY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_PRIORITY_TRAFFIC_CLASS], - &nm_sett_info_propert_type_dcb_au); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_DCB, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-dcb.h b/libnm-core/nm-setting-dcb.h deleted file mode 100644 index a33c13ad99..0000000000 --- a/libnm-core/nm-setting-dcb.h +++ /dev/null @@ -1,146 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2013 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_DCB_H__ -#define __NM_SETTING_DCB_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_DCB (nm_setting_dcb_get_type()) -#define NM_SETTING_DCB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_DCB, NMSettingDcb)) -#define NM_SETTING_DCB_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_DCB, NMSettingDcbClass)) -#define NM_IS_SETTING_DCB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_DCB)) -#define NM_IS_SETTING_DCB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_DCB)) -#define NM_SETTING_DCB_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_DCB, NMSettingDcbClass)) - -#define NM_SETTING_DCB_SETTING_NAME "dcb" - -/** - * NMSettingDcbFlags: - * @NM_SETTING_DCB_FLAG_NONE: no flag - * @NM_SETTING_DCB_FLAG_ENABLE: the feature is enabled - * @NM_SETTING_DCB_FLAG_ADVERTISE: the feature is advertised - * @NM_SETTING_DCB_FLAG_WILLING: the feature is willing to change based on - * peer configuration advertisements - * - * DCB feature flags. - **/ -typedef enum { /*< flags >*/ - NM_SETTING_DCB_FLAG_NONE = 0x00000000, - NM_SETTING_DCB_FLAG_ENABLE = 0x00000001, - NM_SETTING_DCB_FLAG_ADVERTISE = 0x00000002, - NM_SETTING_DCB_FLAG_WILLING = 0x00000004 -} NMSettingDcbFlags; - -/** - * NM_SETTING_DCB_FCOE_MODE_FABRIC: - * - * Indicates that the FCoE controller should use "fabric" mode (default) - */ -#define NM_SETTING_DCB_FCOE_MODE_FABRIC "fabric" - -/** - * NM_SETTING_DCB_FCOE_MODE_VN2VN: - * - * Indicates that the FCoE controller should use "VN2VN" mode. - */ -#define NM_SETTING_DCB_FCOE_MODE_VN2VN "vn2vn" - -/* Properties */ -#define NM_SETTING_DCB_APP_FCOE_FLAGS "app-fcoe-flags" -#define NM_SETTING_DCB_APP_FCOE_PRIORITY "app-fcoe-priority" -#define NM_SETTING_DCB_APP_FCOE_MODE "app-fcoe-mode" - -#define NM_SETTING_DCB_APP_ISCSI_FLAGS "app-iscsi-flags" -#define NM_SETTING_DCB_APP_ISCSI_PRIORITY "app-iscsi-priority" - -#define NM_SETTING_DCB_APP_FIP_FLAGS "app-fip-flags" -#define NM_SETTING_DCB_APP_FIP_PRIORITY "app-fip-priority" - -#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS "priority-flow-control-flags" -#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL "priority-flow-control" - -#define NM_SETTING_DCB_PRIORITY_GROUP_FLAGS "priority-group-flags" -#define NM_SETTING_DCB_PRIORITY_GROUP_ID "priority-group-id" -#define NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH "priority-group-bandwidth" -#define NM_SETTING_DCB_PRIORITY_BANDWIDTH "priority-bandwidth" -#define NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH "priority-strict-bandwidth" -#define NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS "priority-traffic-class" - -/** - * NMSettingDcb: - * - * Data Center Bridging Settings - */ -struct _NMSettingDcb { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingDcbClass; - -GType nm_setting_dcb_get_type(void); - -NMSetting *nm_setting_dcb_new(void); - -NMSettingDcbFlags nm_setting_dcb_get_app_fcoe_flags(NMSettingDcb *setting); -int nm_setting_dcb_get_app_fcoe_priority(NMSettingDcb *setting); -const char * nm_setting_dcb_get_app_fcoe_mode(NMSettingDcb *setting); - -NMSettingDcbFlags nm_setting_dcb_get_app_iscsi_flags(NMSettingDcb *setting); -int nm_setting_dcb_get_app_iscsi_priority(NMSettingDcb *setting); - -NMSettingDcbFlags nm_setting_dcb_get_app_fip_flags(NMSettingDcb *setting); -int nm_setting_dcb_get_app_fip_priority(NMSettingDcb *setting); - -/* Priority Flow Control */ -NMSettingDcbFlags nm_setting_dcb_get_priority_flow_control_flags(NMSettingDcb *setting); -gboolean nm_setting_dcb_get_priority_flow_control(NMSettingDcb *setting, guint user_priority); -void nm_setting_dcb_set_priority_flow_control(NMSettingDcb *setting, - guint user_priority, - gboolean enabled); - -/* Priority Groups */ -NMSettingDcbFlags nm_setting_dcb_get_priority_group_flags(NMSettingDcb *setting); - -guint nm_setting_dcb_get_priority_group_id(NMSettingDcb *setting, guint user_priority); -void -nm_setting_dcb_set_priority_group_id(NMSettingDcb *setting, guint user_priority, guint group_id); - -guint nm_setting_dcb_get_priority_group_bandwidth(NMSettingDcb *setting, guint group_id); -void nm_setting_dcb_set_priority_group_bandwidth(NMSettingDcb *setting, - guint group_id, - guint bandwidth_percent); - -guint nm_setting_dcb_get_priority_bandwidth(NMSettingDcb *setting, guint user_priority); -void nm_setting_dcb_set_priority_bandwidth(NMSettingDcb *setting, - guint user_priority, - guint bandwidth_percent); - -gboolean nm_setting_dcb_get_priority_strict_bandwidth(NMSettingDcb *setting, guint user_priority); -void nm_setting_dcb_set_priority_strict_bandwidth(NMSettingDcb *setting, - guint user_priority, - gboolean strict); - -guint nm_setting_dcb_get_priority_traffic_class(NMSettingDcb *setting, guint user_priority); -void nm_setting_dcb_set_priority_traffic_class(NMSettingDcb *setting, - guint user_priority, - guint traffic_class); - -G_END_DECLS - -#endif /* __NM_SETTING_DCB_H__ */ diff --git a/libnm-core/nm-setting-dummy.c b/libnm-core/nm-setting-dummy.c deleted file mode 100644 index 9ba626dc82..0000000000 --- a/libnm-core/nm-setting-dummy.c +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-dummy.h" - -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-dummy - * @short_description: Describes connection properties for dummy interfaces - * - * The #NMSettingDummy object is a #NMSetting subclass that describes properties - * necessary for connection to dummy devices - **/ - -/*****************************************************************************/ - -G_DEFINE_TYPE(NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING) - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - return TRUE; -} - -/*****************************************************************************/ - -static void -nm_setting_dummy_init(NMSettingDummy *setting) -{} - -/** - * nm_setting_dummy_new: - * - * Creates a new #NMSettingDummy object with default values. - * - * Returns: (transfer full): the new empty #NMSettingDummy object - * - * Since: 1.8 - **/ -NMSetting * -nm_setting_dummy_new(void) -{ - return g_object_new(NM_TYPE_SETTING_DUMMY, NULL); -} - -static void -nm_setting_dummy_class_init(NMSettingDummyClass *klass) -{ - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - setting_class->verify = verify; - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_DUMMY); -} diff --git a/libnm-core/nm-setting-dummy.h b/libnm-core/nm-setting-dummy.h deleted file mode 100644 index 504428e717..0000000000 --- a/libnm-core/nm-setting-dummy.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_DUMMY_H__ -#define __NM_SETTING_DUMMY_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_DUMMY (nm_setting_dummy_get_type()) -#define NM_SETTING_DUMMY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_DUMMY, NMSettingDummy)) -#define NM_SETTING_DUMMY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_DUMMYCONFIG, NMSettingDummyClass)) -#define NM_IS_SETTING_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_DUMMY)) -#define NM_IS_SETTING_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_DUMMY)) -#define NM_SETTING_DUMMY_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_DUMMY, NMSettingDummyClass)) - -#define NM_SETTING_DUMMY_SETTING_NAME "dummy" - -/** - * NMSettingDummy: - * - * Dummy Link Settings - */ -struct _NMSettingDummy { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingDummyClass; - -NM_AVAILABLE_IN_1_8 -GType nm_setting_dummy_get_type(void); -NM_AVAILABLE_IN_1_8 -NMSetting *nm_setting_dummy_new(void); - -G_END_DECLS - -#endif /* __NM_SETTING_DUMMY_H__ */ diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c deleted file mode 100644 index f2c6d15e91..0000000000 --- a/libnm-core/nm-setting-ethtool.c +++ /dev/null @@ -1,378 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ethtool.h" - -#include "nm-setting-private.h" -#include "nm-base/nm-ethtool-base.h" - -/*****************************************************************************/ - -/** - * SECTION:nm-setting-ethtool - * @short_description: Describes connection properties for ethtool related options - * - * The #NMSettingEthtool object is a #NMSetting subclass that describes properties - * to control network driver and hardware settings. - **/ - -/*****************************************************************************/ - -static const GVariantType * -get_variant_type_from_ethtool_id(NMEthtoolID ethtool_id) -{ - if (nm_ethtool_id_is_feature(ethtool_id)) - return G_VARIANT_TYPE_BOOLEAN; - - if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id)) - return G_VARIANT_TYPE_UINT32; - - return NULL; -} - -/*****************************************************************************/ - -/** - * nm_ethtool_optname_is_feature: - * @optname: (allow-none): the option name to check - * - * Checks whether @optname is a valid option name for an offload feature. - * - * %Returns: %TRUE, if @optname is valid - * - * Since: 1.20 - * - * Note that nm_ethtool_optname_is_feature() was first added to the libnm header files - * in 1.14.0 but forgot to actually add to the library. This happened belatedly in 1.20.0 and - * the stable versions 1.18.2, 1.16.4 and 1.14.8 (with linker version "libnm_1_14_8"). - */ -gboolean -nm_ethtool_optname_is_feature(const char *optname) -{ - return optname && nm_ethtool_id_is_feature(nm_ethtool_id_get_by_name(optname)); -} - -/** - * nm_ethtool_optname_is_coalesce: - * @optname: (allow-none): the option name to check - * - * Checks whether @optname is a valid option name for a coalesce setting. - * - * %Returns: %TRUE, if @optname is valid - * - * Since: 1.26 - */ -gboolean -nm_ethtool_optname_is_coalesce(const char *optname) -{ - return optname && nm_ethtool_id_is_coalesce(nm_ethtool_id_get_by_name(optname)); -} - -/** - * nm_ethtool_optname_is_ring: - * @optname: (allow-none): the option name to check - * - * Checks whether @optname is a valid option name for a ring setting. - * - * %Returns: %TRUE, if @optname is valid - * - * Since: 1.26 - */ -gboolean -nm_ethtool_optname_is_ring(const char *optname) -{ - return optname && nm_ethtool_id_is_ring(nm_ethtool_id_get_by_name(optname)); -} - -/*****************************************************************************/ - -/** - * NMSettingEthtool: - * - * Ethtool Ethernet Settings - * - * Since: 1.14 - */ -struct _NMSettingEthtool { - NMSetting parent; -}; - -struct _NMSettingEthtoolClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingEthtool, nm_setting_ethtool, NM_TYPE_SETTING) - -#define NM_SETTING_ETHTOOL_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMSettingEthtool, NM_IS_SETTING_ETHTOOL, NMSetting) - -/*****************************************************************************/ - -/** - * nm_setting_ethtool_get_feature: - * @setting: the #NMSettingEthtool - * @optname: option name of the offload feature to get - * - * Gets and offload feature setting. Returns %NM_TERNARY_DEFAULT if the - * feature is not set. - * - * Note that @optname must be a valid name for a feature, according to - * nm_ethtool_optname_is_feature(). - * - * Returns: a #NMTernary value indicating whether the offload feature - * is enabled, disabled, or left untouched. - * - * Since: 1.14 - * - * Deprecated: 1.26: use nm_setting_option_get_boolean() instead. - */ -NMTernary -nm_setting_ethtool_get_feature(NMSettingEthtool *setting, const char *optname) -{ - gboolean v; - - g_return_val_if_fail(NM_IS_SETTING_ETHTOOL(setting), NM_TERNARY_DEFAULT); - g_return_val_if_fail(optname && nm_ethtool_optname_is_feature(optname), NM_TERNARY_DEFAULT); - - if (!nm_setting_option_get_boolean(NM_SETTING(setting), optname, &v)) - return NM_TERNARY_DEFAULT; - return v ? NM_TERNARY_TRUE : NM_TERNARY_FALSE; -} - -/** - * nm_setting_ethtool_set_feature: - * @setting: the #NMSettingEthtool - * @optname: option name of the offload feature to get - * @value: the new value to set. The special value %NM_TERNARY_DEFAULT - * means to clear the offload feature setting. - * - * Sets and offload feature setting. - * - * Note that @optname must be a valid name for a feature, according to - * nm_ethtool_optname_is_feature(). - * - * Since: 1.14 - * - * Deprecated: 1.26: use nm_setting_option_set() or nm_setting_option_set_boolean() instead. - */ -void -nm_setting_ethtool_set_feature(NMSettingEthtool *setting, const char *optname, NMTernary value) -{ - g_return_if_fail(NM_IS_SETTING_ETHTOOL(setting)); - g_return_if_fail(optname && nm_ethtool_optname_is_feature(optname)); - g_return_if_fail(NM_IN_SET(value, NM_TERNARY_DEFAULT, NM_TERNARY_FALSE, NM_TERNARY_TRUE)); - - if (value == NM_TERNARY_DEFAULT) - nm_setting_option_set(NM_SETTING(setting), optname, NULL); - else - nm_setting_option_set_boolean(NM_SETTING(setting), optname, (value != NM_TERNARY_FALSE)); -} - -/** - * nm_setting_ethtool_clear_features: - * @setting: the #NMSettingEthtool - * - * Clears all offload features settings - * - * Since: 1.14 - * - * Deprecated: 1.26: use nm_setting_option_clear_by_name() with nm_ethtool_optname_is_feature() predicate instead. - */ -void -nm_setting_ethtool_clear_features(NMSettingEthtool *setting) -{ - g_return_if_fail(NM_IS_SETTING_ETHTOOL(setting)); - - nm_setting_option_clear_by_name(NM_SETTING(setting), nm_ethtool_optname_is_feature); -} - -/*****************************************************************************/ - -guint -nm_setting_ethtool_init_features( - NMSettingEthtool *setting, - NMOptionBool * requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */) -{ - GHashTable * hash; - GHashTableIter iter; - guint i; - guint n_req = 0; - const char * name; - GVariant * variant; - - nm_assert(NM_IS_SETTING_ETHTOOL(setting)); - nm_assert(requested); - - for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) - requested[i] = NM_OPTION_BOOL_DEFAULT; - - hash = _nm_setting_option_hash(NM_SETTING(setting), FALSE); - if (!hash) - return 0; - - g_hash_table_iter_init(&iter, hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) { - NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name(name); - - if (!nm_ethtool_id_is_feature(ethtool_id)) - continue; - if (!g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) - continue; - - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(ethtool_id)] = - g_variant_get_boolean(variant) ? NM_OPTION_BOOL_TRUE : NM_OPTION_BOOL_FALSE; - n_req++; - } - - return n_req; -} - -/*****************************************************************************/ - -/** - * nm_setting_ethtool_get_optnames: - * @setting: the #NMSettingEthtool instance. - * @out_length: (out) (optional): return location for the number of keys returned, or %NULL - * - * This returns all options names that are set. This includes the feature names - * like %NM_ETHTOOL_OPTNAME_FEATURE_GRO. See nm_ethtool_optname_is_feature() to - * check whether the option name is valid for offload features. - * - * Returns: (array zero-terminated=1) (transfer container): list of set option - * names or %NULL if no options are set. The option names are still owned by - * @setting and may get invalidated when @setting gets modified. - * - * Since: 1.20 - * - * Deprecated: 1.26: use nm_setting_option_get_all_names() instead. - */ -const char ** -nm_setting_ethtool_get_optnames(NMSettingEthtool *setting, guint *out_length) -{ - const char *const *names; - guint len = 0; - - g_return_val_if_fail(NM_IS_SETTING_ETHTOOL(setting), NULL); - - names = nm_setting_option_get_all_names(NM_SETTING(setting), &len); - NM_SET_OUT(out_length, len); - return len > 0 ? nm_memdup(names, sizeof(names[0]) * (((gsize) len) + 1u)) : NULL; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - const char *const *optnames; - GVariant *const * variants; - guint len; - guint i; - - len = _nm_setting_option_get_all(setting, &optnames, &variants); - - for (i = 0; i < len; i++) { - const char * optname = optnames[i]; - GVariant * variant = variants[i]; - const GVariantType *variant_type; - NMEthtoolID ethtool_id; - - ethtool_id = nm_ethtool_id_get_by_name(optname); - variant_type = get_variant_type_from_ethtool_id(ethtool_id); - - if (!variant_type) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("unsupported ethtool setting")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); - return FALSE; - } - - if (!g_variant_is_of_type(variant, variant_type)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("setting has invalid variant type")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); - return FALSE; - } - - if (NM_IN_SET(ethtool_id, - NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX, - NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)) { - if (!NM_IN_SET(g_variant_get_uint32(variant), 0, 1)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("coalesce option must be either 0 or 1")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); - return FALSE; - } - } - } - - return TRUE; -} - -/*****************************************************************************/ - -static const GVariantType * -get_variant_type(const NMSettInfoSetting *sett_info, const char *name, GError **error) -{ - const GVariantType *variant_type; - - variant_type = get_variant_type_from_ethtool_id(nm_ethtool_id_get_by_name(name)); - - if (!variant_type) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("unknown ethtool option '%s'"), - name); - return NULL; - } - - return variant_type; -} - -/*****************************************************************************/ - -static void -nm_setting_ethtool_init(NMSettingEthtool *setting) -{} - -/** - * nm_setting_ethtool_new: - * - * Creates a new #NMSettingEthtool object with default values. - * - * Returns: (transfer full): the new empty #NMSettingEthtool object - * - * Since: 1.14 - **/ -NMSetting * -nm_setting_ethtool_new(void) -{ - return g_object_new(NM_TYPE_SETTING_ETHTOOL, NULL); -} - -static void -nm_setting_ethtool_class_init(NMSettingEthtoolClass *klass) -{ - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - setting_class->verify = verify; - - _nm_setting_class_commit_full( - setting_class, - NM_META_SETTING_TYPE_ETHTOOL, - NM_SETT_INFO_SETT_DETAIL(.gendata_info = - NM_SETT_INFO_SETT_GENDATA(.get_variant_type = - get_variant_type, ), ), - NULL); -} diff --git a/libnm-core/nm-setting-ethtool.h b/libnm-core/nm-setting-ethtool.h deleted file mode 100644 index d2310b408e..0000000000 --- a/libnm-core/nm-setting-ethtool.h +++ /dev/null @@ -1,70 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_ETHTOOL_H__ -#define __NM_SETTING_ETHTOOL_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -NM_AVAILABLE_IN_1_20 -gboolean nm_ethtool_optname_is_feature(const char *optname); - -NM_AVAILABLE_IN_1_26 -gboolean nm_ethtool_optname_is_coalesce(const char *optname); - -NM_AVAILABLE_IN_1_26 -gboolean nm_ethtool_optname_is_ring(const char *optname); - -/*****************************************************************************/ - -#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type()) -#define NM_SETTING_ETHTOOL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtool)) -#define NM_SETTING_ETHTOOL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass)) -#define NM_IS_SETTING_ETHTOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_ETHTOOL)) -#define NM_IS_SETTING_ETHTOOL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_ETHTOOL)) -#define NM_SETTING_ETHTOOL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass)) - -#define NM_SETTING_ETHTOOL_SETTING_NAME "ethtool" - -/*****************************************************************************/ - -typedef struct _NMSettingEthtoolClass NMSettingEthtoolClass; - -NM_AVAILABLE_IN_1_14 -GType nm_setting_ethtool_get_type(void); - -NM_AVAILABLE_IN_1_14 -NMSetting *nm_setting_ethtool_new(void); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_20 -NM_DEPRECATED_IN_1_26 -const char **nm_setting_ethtool_get_optnames(NMSettingEthtool *setting, guint *out_length); - -NM_AVAILABLE_IN_1_14 -NM_DEPRECATED_IN_1_26 -NMTernary nm_setting_ethtool_get_feature(NMSettingEthtool *setting, const char *optname); -NM_AVAILABLE_IN_1_14 -NM_DEPRECATED_IN_1_26 -void -nm_setting_ethtool_set_feature(NMSettingEthtool *setting, const char *optname, NMTernary value); -NM_AVAILABLE_IN_1_14 -NM_DEPRECATED_IN_1_26 -void nm_setting_ethtool_clear_features(NMSettingEthtool *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_ETHTOOL_H__ */ diff --git a/libnm-core/nm-setting-generic.c b/libnm-core/nm-setting-generic.c deleted file mode 100644 index 07dbd9b8f7..0000000000 --- a/libnm-core/nm-setting-generic.c +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2013 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-generic.h" - -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-generic - * @short_description: Describes connection properties for generic devices - * - * The #NMSettingGeneric object is a #NMSetting subclass that describes - * optional properties that apply to "generic" devices (ie, devices that - * NetworkManager does not specifically recognize). - * - * There are currently no properties on this object; it exists only to be - * the "connection type" setting on #NMConnections for generic devices. - **/ - -/*****************************************************************************/ - -typedef struct { - int dummy; -} NMSettingGenericPrivate; - -G_DEFINE_TYPE(NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING) - -#define NM_SETTING_GENERIC_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_GENERIC, NMSettingGenericPrivate)) - -/*****************************************************************************/ - -static void -nm_setting_generic_init(NMSettingGeneric *setting) -{} - -/** - * nm_setting_generic_new: - * - * Creates a new #NMSettingGeneric object with default values. - * - * Returns: (transfer full): the new empty #NMSettingGeneric object - **/ -NMSetting * -nm_setting_generic_new(void) -{ - return g_object_new(NM_TYPE_SETTING_GENERIC, NULL); -} - -static void -nm_setting_generic_class_init(NMSettingGenericClass *klass) -{ - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingGenericPrivate)); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_GENERIC); -} diff --git a/libnm-core/nm-setting-generic.h b/libnm-core/nm-setting-generic.h deleted file mode 100644 index 5c0195f2db..0000000000 --- a/libnm-core/nm-setting-generic.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2013 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_GENERIC_H__ -#define __NM_SETTING_GENERIC_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_GENERIC (nm_setting_generic_get_type()) -#define NM_SETTING_GENERIC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_GENERIC, NMSettingGeneric)) -#define NM_SETTING_GENERIC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_GENERIC, NMSettingGenericClass)) -#define NM_IS_SETTING_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_GENERIC)) -#define NM_IS_SETTING_GENERIC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_GENERIC)) -#define NM_SETTING_GENERIC_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_GENERIC, NMSettingGenericClass)) - -#define NM_SETTING_GENERIC_SETTING_NAME "generic" - -/** - * NMSettingGeneric: - * - * Generic Link Settings - */ -struct _NMSettingGeneric { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingGenericClass; - -GType nm_setting_generic_get_type(void); - -NMSetting *nm_setting_generic_new(void); - -G_END_DECLS - -#endif /* __NM_SETTING_GENERIC_H__ */ diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c deleted file mode 100644 index c4eda96918..0000000000 --- a/libnm-core/nm-setting-gsm.c +++ /dev/null @@ -1,868 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-gsm.h" - -#include "nm-utils.h" -#include "nm-setting-private.h" -#include "nm-core-enum-types.h" - -/** - * SECTION:nm-setting-gsm - * @short_description: Describes GSM/3GPP-based mobile broadband properties - * - * The #NMSettingGsm object is a #NMSetting subclass that describes - * properties that allow connections to 3GPP-based mobile broadband - * networks, including those using GPRS/EDGE and UMTS/HSPA technology. - */ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_AUTO_CONFIG, - PROP_NUMBER, - PROP_USERNAME, - PROP_PASSWORD, - PROP_PASSWORD_FLAGS, - PROP_APN, - PROP_NETWORK_ID, - PROP_PIN, - PROP_PIN_FLAGS, - PROP_HOME_ONLY, - PROP_DEVICE_ID, - PROP_SIM_ID, - PROP_SIM_OPERATOR_ID, - PROP_MTU, ); - -typedef struct { - char * number; /* For dialing, duh */ - char * username; - char * password; - char * device_id; - char * sim_id; - char * sim_operator_id; - char * apn; /* NULL for dynamic */ - char * network_id; /* for manual registration or NULL for automatic */ - char * pin; - NMSettingSecretFlags password_flags; - NMSettingSecretFlags pin_flags; - guint32 mtu; - bool auto_config : 1; - bool home_only : 1; -} NMSettingGsmPrivate; - -G_DEFINE_TYPE(NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING) - -#define NM_SETTING_GSM_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_GSM, NMSettingGsmPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_gsm_get_auto_config: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:auto-config property of the setting - * - * Since: 1.22 - **/ -gboolean -nm_setting_gsm_get_auto_config(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), FALSE); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->auto_config; -} - -/** - * nm_setting_gsm_get_number: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:number property of the setting - * - * Deprecated: 1.16: User-provided values for this setting are no longer used. - **/ -const char * -nm_setting_gsm_get_number(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->number; -} - -/** - * nm_setting_gsm_get_username: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:username property of the setting - **/ -const char * -nm_setting_gsm_get_username(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->username; -} - -/** - * nm_setting_gsm_get_password: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:password property of the setting - **/ -const char * -nm_setting_gsm_get_password(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->password; -} - -/** - * nm_setting_gsm_get_password_flags: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingGsm:password - **/ -NMSettingSecretFlags -nm_setting_gsm_get_password_flags(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->password_flags; -} - -/** - * nm_setting_gsm_get_apn: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:apn property of the setting - **/ -const char * -nm_setting_gsm_get_apn(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->apn; -} - -/** - * nm_setting_gsm_get_network_id: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:network-id property of the setting - **/ -const char * -nm_setting_gsm_get_network_id(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->network_id; -} - -/** - * nm_setting_gsm_get_pin: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:pin property of the setting - **/ -const char * -nm_setting_gsm_get_pin(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->pin; -} - -/** - * nm_setting_gsm_get_pin_flags: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingGsm:pin - **/ -NMSettingSecretFlags -nm_setting_gsm_get_pin_flags(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->pin_flags; -} - -/** - * nm_setting_gsm_get_home_only: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:home-only property of the setting - **/ -gboolean -nm_setting_gsm_get_home_only(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), FALSE); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->home_only; -} - -/** - * nm_setting_gsm_get_device_id: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:device-id property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_gsm_get_device_id(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->device_id; -} - -/** - * nm_setting_gsm_get_sim_id: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:sim-id property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_gsm_get_sim_id(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->sim_id; -} - -/** - * nm_setting_gsm_get_sim_operator_id: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:sim-operator-id property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_gsm_get_sim_operator_id(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->sim_operator_id; -} - -/** - * nm_setting_gsm_get_mtu: - * @setting: the #NMSettingGsm - * - * Returns: the #NMSettingGsm:mtu property of the setting - * - * Since: 1.8 - **/ -guint32 -nm_setting_gsm_get_mtu(NMSettingGsm *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_GSM(setting), 0); - - return NM_SETTING_GSM_GET_PRIVATE(setting)->mtu; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(setting); - - if (priv->number && !priv->number[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_NUMBER); - return FALSE; - } - - if (priv->apn) { - gsize apn_len = strlen(priv->apn); - gsize i; - - if (apn_len > 64) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property value '%s' is empty or too long (>64)"), - priv->apn); - g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_APN); - return FALSE; - } - - /* APNs roughly follow the same rules as DNS domain names. Allowed - * characters are a-z, 0-9, . and -. GSM 03.03 Section 9.1 states: - * - * The syntax of the APN shall follow the Name Syntax defined in - * RFC 2181 [14] and RFC 1035 [15]. The APN consists of one or - * more labels. Each label is coded as one octet length field - * followed by that number of octets coded as 8 bit ASCII characters. - * Following RFC 1035 [15] the labels should consist only of the - * alphabetic characters (A-Z and a-z), digits (0-9) and the - * dash (-). The case of alphabetic characters is not significant. - * - * A dot (.) is commonly used to separate parts of the APN, and - * apparently the underscore (_) is used as well. RFC 2181 indicates - * that no restrictions of any kind are placed on DNS labels, and thus - * it would appear that none are placed on APNs either, but many modems - * and networks will fail to accept APNs that include odd characters - * like space ( ) and such. - */ - for (i = 0; i < apn_len; i++) { - if (!g_ascii_isalnum(priv->apn[i]) && (priv->apn[i] != '.') && (priv->apn[i] != '_') - && (priv->apn[i] != '-')) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' contains invalid char(s) (use [A-Za-z._-])"), - priv->apn); - g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_APN); - return FALSE; - } - } - } - - if (priv->username && priv->username[0] == '\0') { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_USERNAME); - return FALSE; - } - - if (priv->network_id) { - gsize nid_len = strlen(priv->network_id); - gsize i; - - /* Accept both 5 and 6 digit MCC/MNC codes */ - if ((nid_len < 5) || (nid_len > 6)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' length is invalid (should be 5 or 6 digits)"), - priv->network_id); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_GSM_SETTING_NAME, - NM_SETTING_GSM_NETWORK_ID); - return FALSE; - } - - for (i = 0; i < nid_len; i++) { - if (!g_ascii_isdigit(priv->network_id[i])) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a number"), - priv->network_id); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_GSM_SETTING_NAME, - NM_SETTING_GSM_NETWORK_ID); - return FALSE; - } - } - } - - if (priv->device_id && !priv->device_id[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_DEVICE_ID); - return FALSE; - } - - if (priv->sim_id && !priv->sim_id[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_SIM_ID); - return FALSE; - } - - if (priv->sim_operator_id) { - size_t len = strlen(priv->sim_operator_id); - const char *p = priv->sim_operator_id; - - if (len == 0 || (len != 5 && len != 6)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty or wrong size")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_GSM_SETTING_NAME, - NM_SETTING_GSM_SIM_OPERATOR_ID); - return FALSE; - } - - while (p && *p) { - if (!g_ascii_isdigit(*p++)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property must contain only digits")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_GSM_SETTING_NAME, - NM_SETTING_GSM_SIM_OPERATOR_ID); - return FALSE; - } - } - } - - if (priv->auto_config && (priv->apn || priv->username || priv->password)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("can't be enabled when manual configuration is present")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_AUTO_CONFIG); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - return TRUE; -} - -static gboolean -verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) -{ - return _nm_setting_verify_secret_string(NM_SETTING_GSM_GET_PRIVATE(setting)->password, - NM_SETTING_GSM_SETTING_NAME, - NM_SETTING_GSM_PASSWORD, - error); -} - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(setting); - GPtrArray * secrets = NULL; - - if (priv->password && *priv->password) - return NULL; - - if (priv->username) { - if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { - secrets = g_ptr_array_sized_new(1); - g_ptr_array_add(secrets, NM_SETTING_GSM_PASSWORD); - } - } - - return secrets; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingGsm *setting = NM_SETTING_GSM(object); - - switch (prop_id) { - case PROP_AUTO_CONFIG: - g_value_set_boolean(value, nm_setting_gsm_get_auto_config(setting)); - break; - case PROP_NUMBER: - g_value_set_string(value, nm_setting_gsm_get_number(setting)); - break; - case PROP_USERNAME: - g_value_set_string(value, nm_setting_gsm_get_username(setting)); - break; - case PROP_PASSWORD: - g_value_set_string(value, nm_setting_gsm_get_password(setting)); - break; - case PROP_PASSWORD_FLAGS: - g_value_set_flags(value, nm_setting_gsm_get_password_flags(setting)); - break; - case PROP_APN: - g_value_set_string(value, nm_setting_gsm_get_apn(setting)); - break; - case PROP_NETWORK_ID: - g_value_set_string(value, nm_setting_gsm_get_network_id(setting)); - break; - case PROP_PIN: - g_value_set_string(value, nm_setting_gsm_get_pin(setting)); - break; - case PROP_PIN_FLAGS: - g_value_set_flags(value, nm_setting_gsm_get_pin_flags(setting)); - break; - case PROP_HOME_ONLY: - g_value_set_boolean(value, nm_setting_gsm_get_home_only(setting)); - break; - case PROP_DEVICE_ID: - g_value_set_string(value, nm_setting_gsm_get_device_id(setting)); - break; - case PROP_SIM_ID: - g_value_set_string(value, nm_setting_gsm_get_sim_id(setting)); - break; - case PROP_SIM_OPERATOR_ID: - g_value_set_string(value, nm_setting_gsm_get_sim_operator_id(setting)); - break; - case PROP_MTU: - g_value_set_uint(value, nm_setting_gsm_get_mtu(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(object); - char * tmp; - - switch (prop_id) { - case PROP_AUTO_CONFIG: - priv->auto_config = g_value_get_boolean(value); - break; - case PROP_NUMBER: - g_free(priv->number); - priv->number = g_value_dup_string(value); - break; - case PROP_USERNAME: - g_free(priv->username); - priv->username = g_value_dup_string(value); - break; - case PROP_PASSWORD: - g_free(priv->password); - priv->password = g_value_dup_string(value); - break; - case PROP_PASSWORD_FLAGS: - priv->password_flags = g_value_get_flags(value); - break; - case PROP_APN: - g_free(priv->apn); - priv->apn = NULL; - tmp = g_value_dup_string(value); - if (tmp) - priv->apn = g_strstrip(tmp); - break; - case PROP_NETWORK_ID: - g_free(priv->network_id); - priv->network_id = NULL; - tmp = g_value_dup_string(value); - if (tmp) - priv->network_id = g_strstrip(tmp); - break; - case PROP_PIN: - g_free(priv->pin); - priv->pin = g_value_dup_string(value); - break; - case PROP_PIN_FLAGS: - priv->pin_flags = g_value_get_flags(value); - break; - case PROP_HOME_ONLY: - priv->home_only = g_value_get_boolean(value); - break; - case PROP_DEVICE_ID: - g_free(priv->device_id); - priv->device_id = g_value_dup_string(value); - break; - case PROP_SIM_ID: - g_free(priv->sim_id); - priv->sim_id = g_value_dup_string(value); - break; - case PROP_SIM_OPERATOR_ID: - g_free(priv->sim_operator_id); - priv->sim_operator_id = g_value_dup_string(value); - break; - case PROP_MTU: - priv->mtu = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_gsm_init(NMSettingGsm *setting) -{} - -/** - * nm_setting_gsm_new: - * - * Creates a new #NMSettingGsm object with default values. - * - * Returns: the new empty #NMSettingGsm object - **/ -NMSetting * -nm_setting_gsm_new(void) -{ - return g_object_new(NM_TYPE_SETTING_GSM, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(object); - - g_free(priv->number); - g_free(priv->username); - g_free(priv->password); - g_free(priv->apn); - g_free(priv->network_id); - g_free(priv->pin); - g_free(priv->device_id); - g_free(priv->sim_id); - g_free(priv->sim_operator_id); - - G_OBJECT_CLASS(nm_setting_gsm_parent_class)->finalize(object); -} - -static void -nm_setting_gsm_class_init(NMSettingGsmClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingGsmPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->verify_secrets = verify_secrets; - setting_class->need_secrets = need_secrets; - - /** - * NMSettingGsm:auto-config: - * - * When %TRUE, the settings such as APN, username, or password will - * default to values that match the network the modem will register - * to in the Mobile Broadband Provider database. - * - * Since: 1.22 - **/ - obj_properties[PROP_AUTO_CONFIG] = - g_param_spec_boolean(NM_SETTING_GSM_AUTO_CONFIG, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:number: - * - * Legacy setting that used to help establishing PPP data sessions for - * GSM-based modems. - * - * Deprecated: 1.16: User-provided values for this setting are no longer used. - **/ - obj_properties[PROP_NUMBER] = g_param_spec_string(NM_SETTING_GSM_NUMBER, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:username: - * - * The username used to authenticate with the network, if required. Many - * providers do not require a username, or accept any username. But if a - * username is required, it is specified here. - **/ - obj_properties[PROP_USERNAME] = g_param_spec_string(NM_SETTING_GSM_USERNAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:password: - * - * The password used to authenticate with the network, if required. Many - * providers do not require a password, or accept any password. But if a - * password is required, it is specified here. - **/ - obj_properties[PROP_PASSWORD] = - g_param_spec_string(NM_SETTING_GSM_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:password-flags: - * - * Flags indicating how to handle the #NMSettingGsm:password property. - **/ - obj_properties[PROP_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_GSM_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:apn: - * - * The GPRS Access Point Name specifying the APN used when establishing a - * data session with the GSM-based network. The APN often determines how - * the user will be billed for their network usage and whether the user has - * access to the Internet or just a provider-specific walled-garden, so it - * is important to use the correct APN for the user's mobile broadband plan. - * The APN may only be composed of the characters a-z, 0-9, ., and - per GSM - * 03.60 Section 14.9. - **/ - obj_properties[PROP_APN] = g_param_spec_string(NM_SETTING_GSM_APN, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:network-id: - * - * The Network ID (GSM LAI format, ie MCC-MNC) to force specific network - * registration. If the Network ID is specified, NetworkManager will - * attempt to force the device to register only on the specified network. - * This can be used to ensure that the device does not roam when direct - * roaming control of the device is not otherwise possible. - **/ - obj_properties[PROP_NETWORK_ID] = - g_param_spec_string(NM_SETTING_GSM_NETWORK_ID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:pin: - * - * If the SIM is locked with a PIN it must be unlocked before any other - * operations are requested. Specify the PIN here to allow operation of the - * device. - **/ - obj_properties[PROP_PIN] = - g_param_spec_string(NM_SETTING_GSM_PIN, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:pin-flags: - * - * Flags indicating how to handle the #NMSettingGsm:pin property. - **/ - obj_properties[PROP_PIN_FLAGS] = g_param_spec_flags(NM_SETTING_GSM_PIN_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:home-only: - * - * When %TRUE, only connections to the home network will be allowed. - * Connections to roaming networks will not be made. - **/ - obj_properties[PROP_HOME_ONLY] = - g_param_spec_boolean(NM_SETTING_GSM_HOME_ONLY, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:device-id: - * - * The device unique identifier (as given by the WWAN management service) - * which this connection applies to. If given, the connection will only - * apply to the specified device. - * - * Since: 1.2 - **/ - obj_properties[PROP_DEVICE_ID] = - g_param_spec_string(NM_SETTING_GSM_DEVICE_ID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:sim-id: - * - * The SIM card unique identifier (as given by the WWAN management service) - * which this connection applies to. If given, the connection will apply - * to any device also allowed by #NMSettingGsm:device-id which contains a - * SIM card matching the given identifier. - * - * Since: 1.2 - **/ - obj_properties[PROP_SIM_ID] = g_param_spec_string(NM_SETTING_GSM_SIM_ID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:sim-operator-id: - * - * A MCC/MNC string like "310260" or "21601" identifying the specific - * mobile network operator which this connection applies to. If given, - * the connection will apply to any device also allowed by - * #NMSettingGsm:device-id and #NMSettingGsm:sim-id which contains a SIM - * card provisioned by the given operator. - * - * Since: 1.2 - **/ - obj_properties[PROP_SIM_OPERATOR_ID] = - g_param_spec_string(NM_SETTING_GSM_SIM_OPERATOR_ID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingGsm:mtu: - * - * If non-zero, only transmit packets of the specified size or smaller, - * breaking larger packets up into multiple frames. - * - * Since: 1.8 - **/ - obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_GSM_MTU, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /* Ignore incoming deprecated properties */ - _nm_properties_override_dbus(properties_override, - "allowed-bands", - &nm_sett_info_propert_type_deprecated_ignore_u); - _nm_properties_override_dbus(properties_override, - "network-type", - &nm_sett_info_propert_type_deprecated_ignore_i); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_GSM, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-gsm.h b/libnm-core/nm-setting-gsm.h deleted file mode 100644 index ed939e7cd2..0000000000 --- a/libnm-core/nm-setting-gsm.h +++ /dev/null @@ -1,93 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2011 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_GSM_H__ -#define __NM_SETTING_GSM_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_GSM (nm_setting_gsm_get_type()) -#define NM_SETTING_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_GSM, NMSettingGsm)) -#define NM_SETTING_GSM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_GSM, NMSettingGsmClass)) -#define NM_IS_SETTING_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_GSM)) -#define NM_IS_SETTING_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_GSM)) -#define NM_SETTING_GSM_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_GSM, NMSettingGsmClass)) - -#define NM_SETTING_GSM_SETTING_NAME "gsm" - -#define NM_SETTING_GSM_AUTO_CONFIG "auto-config" -#define NM_SETTING_GSM_USERNAME "username" -#define NM_SETTING_GSM_PASSWORD "password" -#define NM_SETTING_GSM_PASSWORD_FLAGS "password-flags" -#define NM_SETTING_GSM_APN "apn" -#define NM_SETTING_GSM_NETWORK_ID "network-id" -#define NM_SETTING_GSM_PIN "pin" -#define NM_SETTING_GSM_PIN_FLAGS "pin-flags" -#define NM_SETTING_GSM_HOME_ONLY "home-only" -#define NM_SETTING_GSM_DEVICE_ID "device-id" -#define NM_SETTING_GSM_SIM_ID "sim-id" -#define NM_SETTING_GSM_SIM_OPERATOR_ID "sim-operator-id" -#define NM_SETTING_GSM_MTU "mtu" - -/* Deprecated */ -#define NM_SETTING_GSM_NUMBER "number" - -/** - * NMSettingGsm: - * - * GSM-based Mobile Broadband Settings - */ -struct _NMSettingGsm { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingGsmClass; - -GType nm_setting_gsm_get_type(void); - -NMSetting *nm_setting_gsm_new(void); - -NM_AVAILABLE_IN_1_22 -gboolean nm_setting_gsm_get_auto_config(NMSettingGsm *setting); - -const char *nm_setting_gsm_get_username(NMSettingGsm *setting); -const char *nm_setting_gsm_get_password(NMSettingGsm *setting); -const char *nm_setting_gsm_get_apn(NMSettingGsm *setting); -const char *nm_setting_gsm_get_network_id(NMSettingGsm *setting); -const char *nm_setting_gsm_get_pin(NMSettingGsm *setting); -gboolean nm_setting_gsm_get_home_only(NMSettingGsm *setting); - -NM_AVAILABLE_IN_1_2 -const char *nm_setting_gsm_get_device_id(NMSettingGsm *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_gsm_get_sim_id(NMSettingGsm *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_gsm_get_sim_operator_id(NMSettingGsm *setting); -NM_AVAILABLE_IN_1_8 -guint32 nm_setting_gsm_get_mtu(NMSettingGsm *setting); - -NM_DEPRECATED_IN_1_16 -const char *nm_setting_gsm_get_number(NMSettingGsm *setting); - -NMSettingSecretFlags nm_setting_gsm_get_pin_flags(NMSettingGsm *setting); -NMSettingSecretFlags nm_setting_gsm_get_password_flags(NMSettingGsm *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_GSM_H__ */ diff --git a/libnm-core/nm-setting-hostname.c b/libnm-core/nm-setting-hostname.c deleted file mode 100644 index 2396b7bdd1..0000000000 --- a/libnm-core/nm-setting-hostname.c +++ /dev/null @@ -1,339 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2020 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-hostname.h" - -#include "nm-setting-private.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-hostname - * @short_description: Contains properties related to the hostname - * @include: nm-setting-hostname.h - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingHostname, - PROP_PRIORITY, - PROP_FROM_DHCP, - PROP_FROM_DNS_LOOKUP, - PROP_ONLY_FROM_DEFAULT, ); - -/** - * NMSettingHostname: - * - * Hostname settings - * - * Since: 1.30 - */ -struct _NMSettingHostname { - NMSetting parent; - int priority; - NMTernary from_dhcp; - NMTernary from_dns_lookup; - NMTernary only_from_default; -}; - -struct _NMSettingHostnameClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingHostname, nm_setting_hostname, NM_TYPE_SETTING) - -/** - * nm_setting_hostname_get_priority: - * @setting: the #NMSettingHostname - * - * Returns the value contained in the #NMSettingHostname:priority - * property. - * - * Returns: the 'priority' property value - * - * Since: 1.30 - **/ -int -nm_setting_hostname_get_priority(NMSettingHostname *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), 0); - - return setting->priority; -} - -/** - * nm_setting_hostname_get_from_dhcp: - * @setting: the #NMSettingHostname - * - * Returns the value contained in the #NMSettingHostname:from-dhcp - * property. - * - * Returns: the 'from-dhcp' property value - * - * Since: 1.30 - **/ -NMTernary -nm_setting_hostname_get_from_dhcp(NMSettingHostname *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT); - - return setting->from_dhcp; -} - -/** - * nm_setting_hostname_get_from_dns_lookup: - * @setting: the #NMSettingHostname - * - * Returns the value contained in the #NMSettingHostname:from-dns-lookup - * property. - * - * Returns: the 'from-dns-lookup' property value - * - * Since: 1.30 - **/ -NMTernary -nm_setting_hostname_get_from_dns_lookup(NMSettingHostname *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT); - - return setting->from_dns_lookup; -} - -/** - * nm_setting_hostname_get_only_from_default: - * @setting: the #NMSettingHostname - * - * Returns the value contained in the #NMSettingHostname:only-from-default - * property. - * - * Returns: the 'only-from-default' property value - * - * Since: 1.30 - **/ -NMTernary -nm_setting_hostname_get_only_from_default(NMSettingHostname *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT); - - return setting->only_from_default; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingHostname *self = NM_SETTING_HOSTNAME(object); - - switch (prop_id) { - case PROP_PRIORITY: - g_value_set_int(value, self->priority); - break; - case PROP_FROM_DHCP: - g_value_set_enum(value, self->from_dhcp); - break; - case PROP_FROM_DNS_LOOKUP: - g_value_set_enum(value, self->from_dns_lookup); - break; - case PROP_ONLY_FROM_DEFAULT: - g_value_set_enum(value, self->only_from_default); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingHostname *self = NM_SETTING_HOSTNAME(object); - - switch (prop_id) { - case PROP_PRIORITY: - self->priority = g_value_get_int(value); - break; - case PROP_FROM_DHCP: - self->from_dhcp = g_value_get_enum(value); - break; - case PROP_FROM_DNS_LOOKUP: - self->from_dns_lookup = g_value_get_enum(value); - break; - case PROP_ONLY_FROM_DEFAULT: - self->only_from_default = g_value_get_enum(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_hostname_init(NMSettingHostname *setting) -{ - setting->from_dhcp = NM_TERNARY_DEFAULT; - setting->from_dns_lookup = NM_TERNARY_DEFAULT; - setting->only_from_default = NM_TERNARY_DEFAULT; -} - -/** - * nm_setting_hostname_new: - * - * Creates a new #NMSettingHostname object with default values. - * - * Returns: (transfer full): the new empty #NMSettingHostname object - * - * Since: 1.30 - **/ -NMSetting * -nm_setting_hostname_new(void) -{ - return g_object_new(NM_TYPE_SETTING_HOSTNAME, NULL); -} - -static void -nm_setting_hostname_class_init(NMSettingHostnameClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - object_class->get_property = get_property; - object_class->set_property = set_property; - - /** - * NMSettingHostname:priority - * - * The relative priority of this connection to determine the - * system hostname. A lower numerical value is better (higher - * priority). A connection with higher priority is considered - * before connections with lower priority. - * - * If the value is zero, it can be overridden by a global value - * from NetworkManager configuration. If the property doesn't have - * a value in the global configuration, the value is assumed to be - * 100. - * - * Negative values have the special effect of excluding other - * connections with a greater numerical priority value; so in - * presence of at least one negative priority, only connections - * with the lowest priority value will be used to determine the - * hostname. - * - * Since: 1.30 - **/ - /* ---ifcfg-rh--- - * property: priority - * variable: HOSTNAME_PRIORITY(+) - * default: missing variable means global value or 100 - * description: hostname priority - * example: HOSTNAME_PRIORITY=50 - * ---end--- - */ - obj_properties[PROP_PRIORITY] = g_param_spec_int(NM_SETTING_HOSTNAME_PRIORITY, - "", - "", - G_MININT32, - G_MAXINT32, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingHostname:from-dhcp - * - * Whether the system hostname can be determined from DHCP on - * this connection. - * - * When set to %NM_TERNARY_DEFAULT, the value from global configuration - * is used. If the property doesn't have a value in the global - * configuration, NetworkManager assumes the value to be %NM_TERNARY_TRUE. - * - * Since: 1.30 - **/ - /* ---ifcfg-rh--- - * property: from-dhcp - * variable: HOSTNAME_FROM_DHCP(+) - * default: missing variable means global default or 1 - * description: whether the system hostname can be determined from DHCP - * example: HOSTNAME_FROM_DHCP=0,1 - * ---end--- - */ - obj_properties[PROP_FROM_DHCP] = g_param_spec_enum( - NM_SETTING_HOSTNAME_FROM_DHCP, - "", - "", - NM_TYPE_TERNARY, - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingHostname:from-dns-lookup - * - * Whether the system hostname can be determined from reverse - * DNS lookup of addresses on this device. - * - * When set to %NM_TERNARY_DEFAULT, the value from global configuration - * is used. If the property doesn't have a value in the global - * configuration, NetworkManager assumes the value to be %NM_TERNARY_TRUE. - * - * Since: 1.30 - **/ - /* ---ifcfg-rh--- - * property: from-dhcp - * variable: HOSTNAME_FROM_DNS_LOOKUP(+) - * default: missing variable means global default or 1 - * description: whether the system hostname can be determined from reverse - * DNS lookup - * example: HOSTNAME_FROM_DNS_LOOKUP=0,1 - * ---end--- - */ - obj_properties[PROP_FROM_DNS_LOOKUP] = g_param_spec_enum( - NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP, - "", - "", - NM_TYPE_TERNARY, - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingHostname:only-from-default - * - * If set to %NM_TERNARY_TRUE, NetworkManager attempts to get - * the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this - * device only when the device has the default route for the given - * address family (IPv4/IPv6). - * - * If set to %NM_TERNARY_FALSE, the hostname can be set from this - * device even if it doesn't have the default route. - * - * When set to %NM_TERNARY_DEFAULT, the value from global configuration - * is used. If the property doesn't have a value in the global - * configuration, NetworkManager assumes the value to be %NM_TERNARY_FALSE. - * - * Since: 1.30 - **/ - /* ---ifcfg-rh--- - * property: only-best-device - * variable: HOSTNAME_ONLY_FROM_DEFAULT(+) - * default: missing variable means global default or 1 - * description: whether the hostname can be determined only from - * devices with the default route - * example: HOSTNAME_ONLY_FROM_DEFAULT=0,1 - * ---end--- - */ - obj_properties[PROP_ONLY_FROM_DEFAULT] = g_param_spec_enum( - NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT, - "", - "", - NM_TYPE_TERNARY, - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_HOSTNAME); -} diff --git a/libnm-core/nm-setting-hostname.h b/libnm-core/nm-setting-hostname.h deleted file mode 100644 index 02b4e373e4..0000000000 --- a/libnm-core/nm-setting-hostname.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2020 Red Hat, Inc. - */ - -#ifndef NM_SETTING_HOSTNAME_H -#define NM_SETTING_HOSTNAME_H - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_HOSTNAME (nm_setting_hostname_get_type()) -#define NM_SETTING_HOSTNAME(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_HOSTNAME, NMSettingHostname)) -#define NM_SETTING_HOSTNAME_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_HOSTNAME, NMSettingHostnameClass)) -#define NM_IS_SETTING_HOSTNAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_HOSTNAME)) -#define NM_IS_SETTING_HOSTNAME_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_HOSTNAME)) -#define NM_SETTING_HOSTNAME_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_HOSTNAME, NMSettingHostnameClass)) - -#define NM_SETTING_HOSTNAME_SETTING_NAME "hostname" - -#define NM_SETTING_HOSTNAME_PRIORITY "priority" -#define NM_SETTING_HOSTNAME_FROM_DHCP "from-dhcp" -#define NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP "from-dns-lookup" -#define NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT "only-from-default" - -typedef struct _NMSettingHostnameClass NMSettingHostnameClass; - -NM_AVAILABLE_IN_1_30 -GType nm_setting_hostname_get_type(void); -NM_AVAILABLE_IN_1_30 -NMSetting *nm_setting_hostname_new(void); - -NM_AVAILABLE_IN_1_30 -int nm_setting_hostname_get_priority(NMSettingHostname *setting); -NM_AVAILABLE_IN_1_30 -NMTernary nm_setting_hostname_get_from_dhcp(NMSettingHostname *setting); -NM_AVAILABLE_IN_1_30 -NMTernary nm_setting_hostname_get_from_dns_lookup(NMSettingHostname *setting); -NM_AVAILABLE_IN_1_30 -NMTernary nm_setting_hostname_get_only_from_default(NMSettingHostname *setting); - -G_END_DECLS - -#endif /* NM_SETTING_HOSTNAME_H */ diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c deleted file mode 100644 index c315843c69..0000000000 --- a/libnm-core/nm-setting-infiniband.c +++ /dev/null @@ -1,521 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2013 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-infiniband.h" - -#include -#include - -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" -#include "nm-setting-connection.h" - -/** - * SECTION:nm-setting-infiniband - * @short_description: Describes connection properties for IP-over-InfiniBand networks - * - * The #NMSettingInfiniband object is a #NMSetting subclass that describes properties - * necessary for connection to IP-over-InfiniBand networks. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_MAC_ADDRESS, - PROP_MTU, - PROP_TRANSPORT_MODE, - PROP_P_KEY, - PROP_PARENT, ); - -typedef struct { - char * mac_address; - char * transport_mode; - char * parent; - char * virtual_iface_name; - int p_key; - guint32 mtu; -} NMSettingInfinibandPrivate; - -G_DEFINE_TYPE(NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING) - -#define NM_SETTING_INFINIBAND_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_infiniband_get_mac_address: - * @setting: the #NMSettingInfiniband - * - * Returns: the #NMSettingInfiniband:mac-address property of the setting - **/ -const char * -nm_setting_infiniband_get_mac_address(NMSettingInfiniband *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), NULL); - - return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->mac_address; -} - -/** - * nm_setting_infiniband_get_mtu: - * @setting: the #NMSettingInfiniband - * - * Returns: the #NMSettingInfiniband:mtu property of the setting - **/ -guint32 -nm_setting_infiniband_get_mtu(NMSettingInfiniband *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), 0); - - return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->mtu; -} - -/** - * nm_setting_infiniband_get_transport_mode: - * @setting: the #NMSettingInfiniband - * - * Returns the transport mode for this device. Either 'datagram' or - * 'connected'. - * - * Returns: the IPoIB transport mode - **/ -const char * -nm_setting_infiniband_get_transport_mode(NMSettingInfiniband *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), NULL); - - return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->transport_mode; -} - -/** - * nm_setting_infiniband_get_p_key: - * @setting: the #NMSettingInfiniband - * - * Returns the P_Key to use for this device. A value of -1 means to - * use the default P_Key (aka "the P_Key at index 0"). Otherwise, it is - * a 16-bit unsigned integer. - * - * Returns: the IPoIB P_Key - **/ -int -nm_setting_infiniband_get_p_key(NMSettingInfiniband *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), -1); - - return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->p_key; -} - -/** - * nm_setting_infiniband_get_parent: - * @setting: the #NMSettingInfiniband - * - * Returns the parent interface name for this device, if set. - * - * Returns: the parent interface name - **/ -const char * -nm_setting_infiniband_get_parent(NMSettingInfiniband *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), NULL); - - return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->parent; -} - -/** - * nm_setting_infiniband_get_virtual_interface_name: - * @setting: the #NMSettingInfiniband - * - * Returns the interface name created by combining #NMSettingInfiniband:parent - * and #NMSettingInfiniband:p-key. (If either property is unset, this will - * return %NULL.) - * - * Returns: the interface name, or %NULL - **/ -const char * -nm_setting_infiniband_get_virtual_interface_name(NMSettingInfiniband *setting) -{ - NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(setting); - - if (priv->p_key == -1 || !priv->parent) - return NULL; - - if (!priv->virtual_iface_name) - priv->virtual_iface_name = g_strdup_printf("%s.%04x", priv->parent, priv->p_key); - - return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->virtual_iface_name; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingConnection * s_con = NULL; - NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(setting); - - if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, INFINIBAND_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_INFINIBAND_SETTING_NAME, - NM_SETTING_INFINIBAND_MAC_ADDRESS); - return FALSE; - } - - if (!NM_IN_STRSET(priv->transport_mode, "datagram", "connected")) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_INFINIBAND_SETTING_NAME, - NM_SETTING_INFINIBAND_TRANSPORT_MODE); - return FALSE; - } - - if (priv->parent) { - GError *tmp_error = NULL; - - if (!nm_utils_ifname_valid_kernel(priv->parent, &tmp_error)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - "'%s': %s", - priv->parent, - tmp_error->message); - g_prefix_error(error, "%s: ", NM_SETTING_INFINIBAND_PARENT); - g_error_free(tmp_error); - return FALSE; - } - if (priv->p_key == -1) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Must specify a P_Key if specifying parent")); - g_prefix_error(error, "%s: ", NM_SETTING_INFINIBAND_PARENT); - } - } - - if (priv->p_key != -1) { - if (!priv->mac_address && !priv->parent) { - g_set_error_literal( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("InfiniBand P_Key connection did not specify parent interface name")); - g_prefix_error(error, "%s: ", NM_SETTING_INFINIBAND_PARENT); - return FALSE; - } - } - - if (connection) - s_con = nm_connection_get_setting_connection(connection); - if (s_con) { - const char *interface_name = nm_setting_connection_get_interface_name(s_con); - - if (interface_name && priv->p_key != -1) { - if (!priv->virtual_iface_name) - priv->virtual_iface_name = g_strdup_printf("%s.%04x", priv->parent, priv->p_key); - - if (strcmp(interface_name, priv->virtual_iface_name) != 0) { - /* We don't support renaming software infiniband devices. Later we might, but - * for now just reject such connections. - **/ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("interface name of software infiniband device must be '%s' or unset " - "(instead it is '%s')"), - priv->virtual_iface_name, - interface_name); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_INTERFACE_NAME); - return FALSE; - } - } - } - - /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ - - if (priv->mtu > NM_INFINIBAND_MAX_MTU) { - /* Traditionally, MTU for "datagram" mode was limited to 2044 - * and for "connected" mode it was 65520. - * - * This is no longer the case, and both transport modes use the same - * maximum of 65520 (NM_INFINIBAND_MAX_MTU). - * - * Note that this is the MTU in the connection profile. Whether - * we will be able to configure large MTUs later (during activation) - * is unknown at this point. */ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("mtu can be at most %u but it is %u"), - NM_INFINIBAND_MAX_MTU, - priv->mtu); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_INFINIBAND_SETTING_NAME, - NM_SETTING_INFINIBAND_MTU); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingInfiniband *setting = NM_SETTING_INFINIBAND(object); - - switch (prop_id) { - case PROP_MAC_ADDRESS: - g_value_set_string(value, nm_setting_infiniband_get_mac_address(setting)); - break; - case PROP_MTU: - g_value_set_uint(value, nm_setting_infiniband_get_mtu(setting)); - break; - case PROP_TRANSPORT_MODE: - g_value_set_string(value, nm_setting_infiniband_get_transport_mode(setting)); - break; - case PROP_P_KEY: - g_value_set_int(value, nm_setting_infiniband_get_p_key(setting)); - break; - case PROP_PARENT: - g_value_set_string(value, nm_setting_infiniband_get_parent(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_MAC_ADDRESS: - g_free(priv->mac_address); - priv->mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), INFINIBAND_ALEN); - break; - case PROP_MTU: - priv->mtu = g_value_get_uint(value); - break; - case PROP_TRANSPORT_MODE: - g_free(priv->transport_mode); - priv->transport_mode = g_value_dup_string(value); - break; - case PROP_P_KEY: - priv->p_key = g_value_get_int(value); - nm_clear_g_free(&priv->virtual_iface_name); - break; - case PROP_PARENT: - g_free(priv->parent); - priv->parent = g_value_dup_string(value); - nm_clear_g_free(&priv->virtual_iface_name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_infiniband_init(NMSettingInfiniband *self) -{ - NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(self); - - priv->p_key = -1; -} - -/** - * nm_setting_infiniband_new: - * - * Creates a new #NMSettingInfiniband object with default values. - * - * Returns: (transfer full): the new empty #NMSettingInfiniband object - **/ -NMSetting * -nm_setting_infiniband_new(void) -{ - return g_object_new(NM_TYPE_SETTING_INFINIBAND, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(object); - - g_free(priv->transport_mode); - g_free(priv->mac_address); - g_free(priv->parent); - g_free(priv->virtual_iface_name); - - G_OBJECT_CLASS(nm_setting_infiniband_parent_class)->finalize(object); -} - -static void -nm_setting_infiniband_class_init(NMSettingInfinibandClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingInfinibandPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingInfiniband:mac-address: - * - * If specified, this connection will only apply to the IPoIB device whose - * permanent MAC address matches. This property does not change the MAC - * address of the device (i.e. MAC spoofing). - **/ - /* ---keyfile--- - * property: mac-address - * format: usual hex-digits-and-colons notation - * description: MAC address in traditional hex-digits-and-colons notation, or - * or semicolon separated list of 20 decimal bytes (obsolete) - * example: mac-address= 80:00:00:6d:fe:80:00:00:00:00:00:00:00:02:55:00:70:33:cf:01 - * ---end--- - * ---ifcfg-rh--- - * property: mac-address - * variable: HWADDR - * description: IBoIP 20-byte hardware address of the device (in traditional - * hex-digits-and-colons notation). - * Note that for initscripts this is the current MAC address of the device as found - * during ifup. For NetworkManager this is the permanent MAC address. Or in case no - * permanent MAC address exists, the MAC address initially configured on the device. - * example: HWADDR=01:02:03:04:05:06:07:08:09:0A:01:02:03:04:05:06:07:08:09:11 - * ---end--- - */ - obj_properties[PROP_MAC_ADDRESS] = g_param_spec_string( - NM_SETTING_INFINIBAND_MAC_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_MAC_ADDRESS], - &nm_sett_info_propert_type_mac_address); - - /** - * NMSettingInfiniband:mtu: - * - * If non-zero, only transmit packets of the specified size or smaller, - * breaking larger packets up into multiple frames. - **/ - /* ---ifcfg-rh--- - * property: mtu - * variable: MTU - * description: MTU of the interface. - * ---end--- - */ - obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_INFINIBAND_MTU, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingInfiniband:transport-mode: - * - * The IP-over-InfiniBand transport mode. Either "datagram" or - * "connected". - **/ - /* ---ifcfg-rh--- - * property: transport-mode - * variable: CONNECTED_MODE - * default: CONNECTED_MODE=no - * description: CONNECTED_MODE=yes for "connected" mode, CONNECTED_MODE=no for - * "datagram" mode - * ---end--- - */ - obj_properties[PROP_TRANSPORT_MODE] = g_param_spec_string( - NM_SETTING_INFINIBAND_TRANSPORT_MODE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingInfiniband:p-key: - * - * The InfiniBand P_Key to use for this device. A value of -1 means to use - * the default P_Key (aka "the P_Key at index 0"). Otherwise, it is a 16-bit - * unsigned integer, whose high bit is set if it is a "full membership" - * P_Key. - **/ - /* ---ifcfg-rh--- - * property: p-key - * variable: PKEY_ID (and PKEY=yes) - * default: PKEY=no - * description: InfiniBand P_Key. The value can be a hex number prefixed with "0x" - * or a decimal number. - * When PKEY_ID is specified, PHYSDEV and DEVICE also must be specified. - * example: PKEY=yes PKEY_ID=2 PHYSDEV=mlx4_ib0 DEVICE=mlx4_ib0.8002 - * ---end--- - */ - obj_properties[PROP_P_KEY] = - g_param_spec_int(NM_SETTING_INFINIBAND_P_KEY, - "", - "", - -1, - 0xFFFF, - -1, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingInfiniband:parent: - * - * The interface name of the parent device of this device. Normally %NULL, - * but if the #NMSettingInfiniband:p_key property is set, then you must - * specify the base device by setting either this property or - * #NMSettingInfiniband:mac-address. - **/ - /* ---ifcfg-rh--- - * property: parent - * variable: PHYSDEV (PKEY=yes) - * default: PKEY=no - * description: InfiniBand parent device. - * example: PHYSDEV=ib0 - * ---end--- - */ - obj_properties[PROP_PARENT] = g_param_spec_string( - NM_SETTING_INFINIBAND_PARENT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_INFINIBAND, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-infiniband.h b/libnm-core/nm-setting-infiniband.h deleted file mode 100644 index 4a771aef9e..0000000000 --- a/libnm-core/nm-setting-infiniband.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_INFINIBAND_H__ -#define __NM_SETTING_INFINIBAND_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_INFINIBAND (nm_setting_infiniband_get_type()) -#define NM_SETTING_INFINIBAND(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_INFINIBAND, NMSettingInfiniband)) -#define NM_SETTING_INFINIBAND_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandClass)) -#define NM_IS_SETTING_INFINIBAND(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_INFINIBAND)) -#define NM_IS_SETTING_INFINIBAND_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_INFINIBAND)) -#define NM_SETTING_INFINIBAND_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandClass)) - -#define NM_SETTING_INFINIBAND_SETTING_NAME "infiniband" - -#define NM_SETTING_INFINIBAND_MAC_ADDRESS "mac-address" -#define NM_SETTING_INFINIBAND_MTU "mtu" -#define NM_SETTING_INFINIBAND_TRANSPORT_MODE "transport-mode" -#define NM_SETTING_INFINIBAND_P_KEY "p-key" -#define NM_SETTING_INFINIBAND_PARENT "parent" - -/** - * NMSettingInfiniband: - * - * Infiniband Settings - */ -struct _NMSettingInfiniband { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingInfinibandClass; - -GType nm_setting_infiniband_get_type(void); - -NMSetting * nm_setting_infiniband_new(void); -const char *nm_setting_infiniband_get_mac_address(NMSettingInfiniband *setting); -guint32 nm_setting_infiniband_get_mtu(NMSettingInfiniband *setting); -const char *nm_setting_infiniband_get_transport_mode(NMSettingInfiniband *setting); -int nm_setting_infiniband_get_p_key(NMSettingInfiniband *setting); -const char *nm_setting_infiniband_get_parent(NMSettingInfiniband *setting); - -const char *nm_setting_infiniband_get_virtual_interface_name(NMSettingInfiniband *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_INFINIBAND_H__ */ diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c deleted file mode 100644 index 45ecbd8868..0000000000 --- a/libnm-core/nm-setting-ip-config.c +++ /dev/null @@ -1,6284 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2017 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ip-config.h" - -#include -#include - -#include "nm-glib-aux/nm-str-buf.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-utils.h" -#include "nm-setting-private.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-ip-config - * @short_description: Abstract base class for IPv4 and IPv6 - * addressing, routing, and name service properties - * @include: nm-setting-ip-config.h - * @see_also: #NMSettingIP4Config, #NMSettingIP6Config - * - * #NMSettingIPConfig is the abstract base class of - * #NMSettingIP4Config and #NMSettingIP6Config, providing properties - * related to IP addressing, routing, and Domain Name Service. - **/ - -/*****************************************************************************/ - -const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[] = { - {NM_SETTING_DNS_OPTION_DEBUG, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_NDOTS, TRUE, FALSE}, - {NM_SETTING_DNS_OPTION_TIMEOUT, TRUE, FALSE}, - {NM_SETTING_DNS_OPTION_ATTEMPTS, TRUE, FALSE}, - {NM_SETTING_DNS_OPTION_ROTATE, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_NO_CHECK_NAMES, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_INET6, FALSE, TRUE}, - {NM_SETTING_DNS_OPTION_IP6_BYTESTRING, FALSE, TRUE}, - {NM_SETTING_DNS_OPTION_IP6_DOTINT, FALSE, TRUE}, - {NM_SETTING_DNS_OPTION_NO_IP6_DOTINT, FALSE, TRUE}, - {NM_SETTING_DNS_OPTION_EDNS0, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_SINGLE_REQUEST, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_SINGLE_REQUEST_REOPEN, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_NO_TLD_QUERY, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_USE_VC, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_NO_RELOAD, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_TRUST_AD, FALSE, FALSE}, - {NULL, FALSE, FALSE}}; - -static char * -canonicalize_ip(int family, const char *ip, gboolean null_any) -{ - guint8 addr_bytes[sizeof(struct in6_addr)]; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - int ret; - - if (!ip) { - if (null_any) - return NULL; - if (family == AF_INET) - return g_strdup("0.0.0.0"); - if (family == AF_INET6) - return g_strdup("::"); - g_return_val_if_reached(NULL); - } - - ret = inet_pton(family, ip, addr_bytes); - g_return_val_if_fail(ret == 1, NULL); - - if (null_any) { - if (!memcmp(addr_bytes, &in6addr_any, nm_utils_addr_family_to_size(family))) - return NULL; - } - - return g_strdup(inet_ntop(family, addr_bytes, addr_str, sizeof(addr_str))); -} - -static char * -canonicalize_ip_binary(int family, gconstpointer ip, gboolean null_any) -{ - char string[NM_UTILS_INET_ADDRSTRLEN]; - - if (!ip) { - if (null_any) - return NULL; - if (family == AF_INET) - return g_strdup("0.0.0.0"); - if (family == AF_INET6) - return g_strdup("::"); - g_return_val_if_reached(NULL); - } - if (null_any) { - if (!memcmp(ip, &in6addr_any, nm_utils_addr_family_to_size(family))) - return NULL; - } - return g_strdup(inet_ntop(family, ip, string, sizeof(string))); -} - -static gboolean -valid_ip(int family, const char *ip, GError **error) -{ - if (!ip) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("Missing IPv4 address") : _("Missing IPv6 address")); - return FALSE; - } - if (!nm_utils_ipaddr_is_valid(family, ip)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("Invalid IPv4 address '%s'") - : _("Invalid IPv6 address '%s'"), - ip); - return FALSE; - } else - return TRUE; -} - -static gboolean -valid_prefix(int family, guint prefix, GError **error) -{ - if ((family == AF_INET && prefix <= 32) || (family == AF_INET6 && prefix <= 128)) - return TRUE; - - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("Invalid IPv4 address prefix '%u'") - : _("Invalid IPv6 address prefix '%u'"), - prefix); - return FALSE; -} - -static gboolean -valid_metric(gint64 metric, GError **error) -{ - if (metric < -1 || metric > G_MAXUINT32) { - if (error) { - char buf[64]; - - /* We can't concatenate G_GINT64_FORMAT into a translatable string */ - g_snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT, metric); - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Invalid routing metric '%s'"), - buf); - } - return FALSE; - } - - return TRUE; -} - -/***************************************************************************** - * NMIPAddress - *****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMIPAddress, nm_ip_address, nm_ip_address_dup, nm_ip_address_unref) - -struct NMIPAddress { - guint refcount; - - char *address; - int prefix, family; - - GHashTable *attributes; -}; - -/** - * nm_ip_address_new: - * @family: the IP address family (AF_INET or - * AF_INET6) - * @addr: the IP address - * @prefix: the address prefix length - * @error: location to store error, or %NULL - * - * Creates a new #NMIPAddress object. - * - * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error - **/ -NMIPAddress * -nm_ip_address_new(int family, const char *addr, guint prefix, GError **error) -{ - NMIPAddress *address; - - g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); - g_return_val_if_fail(addr != NULL, NULL); - - if (!valid_ip(family, addr, error)) - return NULL; - if (!valid_prefix(family, prefix, error)) - return NULL; - - address = g_slice_new0(NMIPAddress); - address->refcount = 1; - - address->family = family; - address->address = canonicalize_ip(family, addr, FALSE); - address->prefix = prefix; - - return address; -} - -/** - * nm_ip_address_new_binary: - * @family: the IP address family (AF_INET or - * AF_INET6) - * @addr: the IP address - * @prefix: the address prefix length - * @error: location to store error, or %NULL - * - * Creates a new #NMIPAddress object. @addr must point to a buffer of the - * correct size for @family. - * - * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error - **/ -NMIPAddress * -nm_ip_address_new_binary(int family, gconstpointer addr, guint prefix, GError **error) -{ - NMIPAddress *address; - char string[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); - g_return_val_if_fail(addr != NULL, NULL); - - if (!valid_prefix(family, prefix, error)) - return NULL; - - address = g_slice_new0(NMIPAddress); - address->refcount = 1; - - address->family = family; - address->address = g_strdup(inet_ntop(family, addr, string, sizeof(string))); - address->prefix = prefix; - - return address; -} - -/** - * nm_ip_address_ref: - * @address: the #NMIPAddress - * - * Increases the reference count of the object. - **/ -void -nm_ip_address_ref(NMIPAddress *address) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(address->refcount > 0); - - address->refcount++; -} - -/** - * nm_ip_address_unref: - * @address: the #NMIPAddress - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - **/ -void -nm_ip_address_unref(NMIPAddress *address) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(address->refcount > 0); - - address->refcount--; - if (address->refcount == 0) { - g_free(address->address); - if (address->attributes) - g_hash_table_unref(address->attributes); - g_slice_free(NMIPAddress, address); - } -} - -/** - * nm_ip_address_cmp_full: - * @a: the #NMIPAddress - * @b: the #NMIPAddress to compare @address to. - * @cmp_flags: the #NMIPAddressCmpFlags that indicate what to compare. - * - * Note that with @cmp_flags #NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS, there - * is no total order for comparing GVariant. That means, if the two addresses - * only differ by their attributes, the sort order is undefined and the return - * value only indicates equality. - * - * Returns: 0 if the two objects have the same values (according to their flags) - * or a integer indicating the compare order. - **/ -int -nm_ip_address_cmp_full(const NMIPAddress *a, const NMIPAddress *b, NMIPAddressCmpFlags cmp_flags) -{ - g_return_val_if_fail(!a || a->refcount > 0, 0); - g_return_val_if_fail(!b || b->refcount > 0, 0); - g_return_val_if_fail(!NM_FLAGS_ANY(cmp_flags, ~NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS), 0); - - NM_CMP_SELF(a, b); - - NM_CMP_FIELD(a, b, family); - NM_CMP_FIELD(a, b, prefix); - NM_CMP_FIELD_STR(a, b, address); - - if (NM_FLAGS_HAS(cmp_flags, NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS)) { - GHashTableIter iter; - const char * key; - GVariant * value, *value2; - guint n; - - n = a->attributes ? g_hash_table_size(a->attributes) : 0u; - NM_CMP_DIRECT(n, (b->attributes ? g_hash_table_size(b->attributes) : 0u)); - - if (n > 0) { - g_hash_table_iter_init(&iter, a->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { - value2 = g_hash_table_lookup(b->attributes, key); - /* We cannot really compare GVariants, because g_variant_compare() does - * not work in general. So, don't bother. NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS is - * documented to not provide a total order for the attribute contents. - * - * Theoretically, we can implement also a total order. However we should - * not do that by default because it would require us to sort the keys - * first. Most callers don't care about total order, so they shouldn't - * pay the overhead. */ - if (!value2) - return -2; - if (!g_variant_equal(value, value2)) - return -2; - } - } - } - - return 0; -} - -/** - * nm_ip_address_equal: - * @address: the #NMIPAddress - * @other: the #NMIPAddress to compare @address to. - * - * Determines if two #NMIPAddress objects contain the same address and prefix - * (attributes are not compared). - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - **/ -gboolean -nm_ip_address_equal(NMIPAddress *address, NMIPAddress *other) -{ - return nm_ip_address_cmp_full(address, other, NM_IP_ADDRESS_CMP_FLAGS_NONE) == 0; -} - -/** - * nm_ip_address_dup: - * @address: the #NMIPAddress - * - * Creates a copy of @address - * - * Returns: (transfer full): a copy of @address - **/ -NMIPAddress * -nm_ip_address_dup(NMIPAddress *address) -{ - NMIPAddress *copy; - - g_return_val_if_fail(address != NULL, NULL); - g_return_val_if_fail(address->refcount > 0, NULL); - - copy = nm_ip_address_new(address->family, address->address, address->prefix, NULL); - if (address->attributes) { - GHashTableIter iter; - const char * key; - GVariant * value; - - g_hash_table_iter_init(&iter, address->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) - nm_ip_address_set_attribute(copy, key, value); - } - - return copy; -} - -/** - * nm_ip_address_get_family: - * @address: the #NMIPAddress - * - * Gets the IP address family (eg, AF_INET) property of this address - * object. - * - * Returns: the IP address family - **/ -int -nm_ip_address_get_family(NMIPAddress *address) -{ - g_return_val_if_fail(address != NULL, 0); - g_return_val_if_fail(address->refcount > 0, 0); - - return address->family; -} - -/** - * nm_ip_address_get_address: - * @address: the #NMIPAddress - * - * Gets the IP address property of this address object. - * - * Returns: the IP address - **/ -const char * -nm_ip_address_get_address(NMIPAddress *address) -{ - g_return_val_if_fail(address != NULL, NULL); - g_return_val_if_fail(address->refcount > 0, NULL); - - return address->address; -} - -/** - * nm_ip_address_set_address: - * @address: the #NMIPAddress - * @addr: the IP address, as a string - * - * Sets the IP address property of this address object. - * - * @addr must be a valid address of @address's family. If you aren't sure you - * have a valid address, use nm_utils_ipaddr_valid() to check it. - **/ -void -nm_ip_address_set_address(NMIPAddress *address, const char *addr) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(addr != NULL); - g_return_if_fail(nm_utils_ipaddr_is_valid(address->family, addr)); - - g_free(address->address); - address->address = canonicalize_ip(address->family, addr, FALSE); -} - -/** - * nm_ip_address_get_address_binary: (skip) - * @address: the #NMIPAddress - * @addr: a buffer in which to store the address in binary format. - * - * Gets the IP address property of this address object. - * - * @addr must point to a buffer that is the correct size for @address's family. - **/ -void -nm_ip_address_get_address_binary(NMIPAddress *address, gpointer addr) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(addr != NULL); - - inet_pton(address->family, address->address, addr); -} - -/** - * nm_ip_address_set_address_binary: (skip) - * @address: the #NMIPAddress - * @addr: the address, in binary format - * - * Sets the IP address property of this address object. - * - * @addr must point to a buffer that is the correct size for @address's family. - **/ -void -nm_ip_address_set_address_binary(NMIPAddress *address, gconstpointer addr) -{ - char string[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_if_fail(address != NULL); - g_return_if_fail(addr != NULL); - - g_free(address->address); - address->address = g_strdup(inet_ntop(address->family, addr, string, sizeof(string))); -} - -/** - * nm_ip_address_get_prefix: - * @address: the #NMIPAddress - * - * Gets the IP address prefix (ie "24" or "30" etc) property of this address - * object. - * - * Returns: the IP address prefix - **/ -guint -nm_ip_address_get_prefix(NMIPAddress *address) -{ - g_return_val_if_fail(address != NULL, 0); - g_return_val_if_fail(address->refcount > 0, 0); - - return address->prefix; -} - -/** - * nm_ip_address_set_prefix: - * @address: the #NMIPAddress - * @prefix: the IP address prefix - * - * Sets the IP address prefix property of this address object. - **/ -void -nm_ip_address_set_prefix(NMIPAddress *address, guint prefix) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(valid_prefix(address->family, prefix, NULL)); - - address->prefix = prefix; -} - -const char ** -_nm_ip_address_get_attribute_names(const NMIPAddress *address, gboolean sorted, guint *out_length) -{ - nm_assert(address); - - return nm_utils_strdict_get_keys(address->attributes, sorted, out_length); -} - -/** - * nm_ip_address_get_attribute_names: - * @address: the #NMIPAddress - * - * Gets an array of attribute names defined on @address. - * - * Returns: (transfer full): a %NULL-terminated array of attribute names, - **/ -char ** -nm_ip_address_get_attribute_names(NMIPAddress *address) -{ - const char **names; - - g_return_val_if_fail(address, NULL); - - names = _nm_ip_address_get_attribute_names(address, TRUE, NULL); - return nm_utils_strv_make_deep_copied_nonnull(names); -} - -/** - * nm_ip_address_get_attribute: - * @address: the #NMIPAddress - * @name: the name of an address attribute - * - * Gets the value of the attribute with name @name on @address - * - * Returns: (transfer none): the value of the attribute with name @name on - * @address, or %NULL if @address has no such attribute. - **/ -GVariant * -nm_ip_address_get_attribute(NMIPAddress *address, const char *name) -{ - g_return_val_if_fail(address != NULL, NULL); - g_return_val_if_fail(name != NULL && *name != '\0', NULL); - - if (address->attributes) - return g_hash_table_lookup(address->attributes, name); - else - return NULL; -} - -/** - * nm_ip_address_set_attribute: - * @address: the #NMIPAddress - * @name: the name of an address attribute - * @value: (transfer none) (allow-none): the value - * - * Sets or clears the named attribute on @address to the given value. - **/ -void -nm_ip_address_set_attribute(NMIPAddress *address, const char *name, GVariant *value) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(name != NULL && *name != '\0'); - g_return_if_fail(strcmp(name, "address") != 0 && strcmp(name, "prefix") != 0); - - if (!address->attributes) { - address->attributes = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref); - } - - if (value) - g_hash_table_insert(address->attributes, g_strdup(name), g_variant_ref_sink(value)); - else - g_hash_table_remove(address->attributes, name); -} - -/***************************************************************************** - * NMIPRoute - *****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMIPRoute, nm_ip_route, nm_ip_route_dup, nm_ip_route_unref) - -struct NMIPRoute { - guint refcount; - - int family; - char * dest; - guint prefix; - char * next_hop; - gint64 metric; - - GHashTable *attributes; -}; - -/** - * nm_ip_route_new: - * @family: the IP address family (AF_INET or - * AF_INET6) - * @dest: the IP address of the route's destination - * @prefix: the address prefix length - * @next_hop: (allow-none): the IP address of the next hop (or %NULL) - * @metric: the route metric (or -1 for "default") - * @error: location to store error, or %NULL - * - * Creates a new #NMIPRoute object. - * - * Returns: (transfer full): the new #NMIPRoute object, or %NULL on error - **/ -NMIPRoute * -nm_ip_route_new(int family, - const char *dest, - guint prefix, - const char *next_hop, - gint64 metric, - GError ** error) -{ - NMIPRoute *route; - - g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); - g_return_val_if_fail(dest, NULL); - - if (!valid_ip(family, dest, error)) - return NULL; - if (!valid_prefix(family, prefix, error)) - return NULL; - if (next_hop && !valid_ip(family, next_hop, error)) - return NULL; - if (!valid_metric(metric, error)) - return NULL; - - route = g_slice_new0(NMIPRoute); - route->refcount = 1; - - route->family = family; - route->dest = canonicalize_ip(family, dest, FALSE); - route->prefix = prefix; - route->next_hop = canonicalize_ip(family, next_hop, TRUE); - route->metric = metric; - - return route; -} - -/** - * nm_ip_route_new_binary: - * @family: the IP address family (AF_INET or - * AF_INET6) - * @dest: the IP address of the route's destination - * @prefix: the address prefix length - * @next_hop: (allow-none): the IP address of the next hop (or %NULL) - * @metric: the route metric (or -1 for "default") - * @error: location to store error, or %NULL - * - * Creates a new #NMIPRoute object. @dest and @next_hop (if non-%NULL) must - * point to buffers of the correct size for @family. - * - * Returns: (transfer full): the new #NMIPRoute object, or %NULL on error - **/ -NMIPRoute * -nm_ip_route_new_binary(int family, - gconstpointer dest, - guint prefix, - gconstpointer next_hop, - gint64 metric, - GError ** error) -{ - NMIPRoute *route; - - g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); - g_return_val_if_fail(dest, NULL); - - if (!valid_prefix(family, prefix, error)) - return NULL; - if (!valid_metric(metric, error)) - return NULL; - - route = g_slice_new0(NMIPRoute); - route->refcount = 1; - - route->family = family; - route->dest = canonicalize_ip_binary(family, dest, FALSE); - route->prefix = prefix; - route->next_hop = canonicalize_ip_binary(family, next_hop, TRUE); - route->metric = metric; - - return route; -} - -/** - * nm_ip_route_ref: - * @route: the #NMIPRoute - * - * Increases the reference count of the object. - **/ -void -nm_ip_route_ref(NMIPRoute *route) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(route->refcount > 0); - - route->refcount++; -} - -/** - * nm_ip_route_unref: - * @route: the #NMIPRoute - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - **/ -void -nm_ip_route_unref(NMIPRoute *route) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(route->refcount > 0); - - route->refcount--; - if (route->refcount == 0) { - g_free(route->dest); - g_free(route->next_hop); - if (route->attributes) - g_hash_table_unref(route->attributes); - g_slice_free(NMIPRoute, route); - } -} - -/** - * nm_ip_route_equal_full: - * @route: the #NMIPRoute - * @other: the #NMIPRoute to compare @route to. - * @cmp_flags: tune how to compare attributes. Currently, only - * NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE (0) and NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS (1) - * is supported. - * - * Determines if two #NMIPRoute objects contain the same destination, prefix, - * next hop, and metric. - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - * - * Since: 1.10 - **/ -gboolean -nm_ip_route_equal_full(NMIPRoute *route, NMIPRoute *other, guint cmp_flags) -{ - g_return_val_if_fail(route != NULL, FALSE); - g_return_val_if_fail(route->refcount > 0, FALSE); - - g_return_val_if_fail(other != NULL, FALSE); - g_return_val_if_fail(other->refcount > 0, FALSE); - - g_return_val_if_fail(NM_IN_SET(cmp_flags, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS), - FALSE); - - if (route->prefix != other->prefix || route->metric != other->metric - || strcmp(route->dest, other->dest) != 0 - || g_strcmp0(route->next_hop, other->next_hop) != 0) - return FALSE; - if (cmp_flags == NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS) { - GHashTableIter iter; - const char * key; - GVariant * value, *value2; - guint n; - - n = route->attributes ? g_hash_table_size(route->attributes) : 0u; - if (n != (other->attributes ? g_hash_table_size(other->attributes) : 0u)) - return FALSE; - if (n) { - g_hash_table_iter_init(&iter, route->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { - value2 = g_hash_table_lookup(other->attributes, key); - if (!value2) - return FALSE; - if (!g_variant_equal(value, value2)) - return FALSE; - } - } - } - return TRUE; -} - -/** - * nm_ip_route_equal: - * @route: the #NMIPRoute - * @other: the #NMIPRoute to compare @route to. - * - * Determines if two #NMIPRoute objects contain the same destination, prefix, - * next hop, and metric. (Attributes are not compared.) - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - **/ -gboolean -nm_ip_route_equal(NMIPRoute *route, NMIPRoute *other) -{ - return nm_ip_route_equal_full(route, other, NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE); -} - -/** - * nm_ip_route_dup: - * @route: the #NMIPRoute - * - * Creates a copy of @route - * - * Returns: (transfer full): a copy of @route - **/ -NMIPRoute * -nm_ip_route_dup(NMIPRoute *route) -{ - NMIPRoute *copy; - - g_return_val_if_fail(route != NULL, NULL); - g_return_val_if_fail(route->refcount > 0, NULL); - - copy = nm_ip_route_new(route->family, - route->dest, - route->prefix, - route->next_hop, - route->metric, - NULL); - if (route->attributes) { - GHashTableIter iter; - const char * key; - GVariant * value; - - g_hash_table_iter_init(&iter, route->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) - nm_ip_route_set_attribute(copy, key, value); - } - - return copy; -} - -/** - * nm_ip_route_get_family: - * @route: the #NMIPRoute - * - * Gets the IP address family (eg, AF_INET) property of this route - * object. - * - * Returns: the IP address family - **/ -int -nm_ip_route_get_family(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, 0); - g_return_val_if_fail(route->refcount > 0, 0); - - return route->family; -} - -/** - * nm_ip_route_get_dest: - * @route: the #NMIPRoute - * - * Gets the IP destination address property of this route object. - * - * Returns: the IP address of the route's destination - **/ -const char * -nm_ip_route_get_dest(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, NULL); - g_return_val_if_fail(route->refcount > 0, NULL); - - return route->dest; -} - -/** - * nm_ip_route_set_dest: - * @route: the #NMIPRoute - * @dest: the route's destination, as a string - * - * Sets the destination property of this route object. - * - * @dest must be a valid address of @route's family. If you aren't sure you - * have a valid address, use nm_utils_ipaddr_is_valid() to check it. - **/ -void -nm_ip_route_set_dest(NMIPRoute *route, const char *dest) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(nm_utils_ipaddr_is_valid(route->family, dest)); - - g_free(route->dest); - route->dest = canonicalize_ip(route->family, dest, FALSE); -} - -/** - * nm_ip_route_get_dest_binary: (skip) - * @route: the #NMIPRoute - * @dest: a buffer in which to store the destination in binary format. - * - * Gets the destination property of this route object. - * - * @dest must point to a buffer that is the correct size for @route's family. - **/ -void -nm_ip_route_get_dest_binary(NMIPRoute *route, gpointer dest) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(dest != NULL); - - inet_pton(route->family, route->dest, dest); -} - -/** - * nm_ip_route_set_dest_binary: (skip) - * @route: the #NMIPRoute - * @dest: the route's destination, in binary format - * - * Sets the destination property of this route object. - * - * @dest must point to a buffer that is the correct size for @route's family. - **/ -void -nm_ip_route_set_dest_binary(NMIPRoute *route, gconstpointer dest) -{ - char string[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_if_fail(route != NULL); - g_return_if_fail(dest != NULL); - - g_free(route->dest); - route->dest = g_strdup(inet_ntop(route->family, dest, string, sizeof(string))); -} - -/** - * nm_ip_route_get_prefix: - * @route: the #NMIPRoute - * - * Gets the IP prefix (ie "24" or "30" etc) of this route. - * - * Returns: the IP prefix - **/ -guint -nm_ip_route_get_prefix(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, 0); - g_return_val_if_fail(route->refcount > 0, 0); - - return route->prefix; -} - -/** - * nm_ip_route_set_prefix: - * @route: the #NMIPRoute - * @prefix: the route prefix - * - * Sets the prefix property of this route object. - **/ -void -nm_ip_route_set_prefix(NMIPRoute *route, guint prefix) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(valid_prefix(route->family, prefix, NULL)); - - route->prefix = prefix; -} - -/** - * nm_ip_route_get_next_hop: - * @route: the #NMIPRoute - * - * Gets the IP address of the next hop of this route; this will be %NULL if the - * route has no next hop. - * - * Returns: the IP address of the next hop, or %NULL if this is a device route. - **/ -const char * -nm_ip_route_get_next_hop(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, NULL); - g_return_val_if_fail(route->refcount > 0, NULL); - - return route->next_hop; -} - -/** - * nm_ip_route_set_next_hop: - * @route: the #NMIPRoute - * @next_hop: (allow-none): the route's next hop, as a string - * - * Sets the next-hop property of this route object. - * - * @next_hop (if non-%NULL) must be a valid address of @route's family. If you - * aren't sure you have a valid address, use nm_utils_ipaddr_valid() to check - * it. - **/ -void -nm_ip_route_set_next_hop(NMIPRoute *route, const char *next_hop) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(!next_hop || nm_utils_ipaddr_is_valid(route->family, next_hop)); - - g_free(route->next_hop); - route->next_hop = canonicalize_ip(route->family, next_hop, TRUE); -} - -/** - * nm_ip_route_get_next_hop_binary: (skip) - * @route: the #NMIPRoute - * @next_hop: a buffer in which to store the next hop in binary format. - * - * Gets the next hop property of this route object. - * - * @next_hop must point to a buffer that is the correct size for @route's family. - * - * Returns: %TRUE if @route has a next hop, %FALSE if not (in which case - * @next_hop will be zeroed out) - **/ -gboolean -nm_ip_route_get_next_hop_binary(NMIPRoute *route, gpointer next_hop) -{ - g_return_val_if_fail(route != NULL, FALSE); - g_return_val_if_fail(next_hop != NULL, FALSE); - - if (route->next_hop) { - inet_pton(route->family, route->next_hop, next_hop); - return TRUE; - } else { - memset(next_hop, 0, nm_utils_addr_family_to_size(route->family)); - return FALSE; - } -} - -/** - * nm_ip_route_set_next_hop_binary: (skip) - * @route: the #NMIPRoute - * @next_hop: the route's next hop, in binary format - * - * Sets the destination property of this route object. - * - * @next_hop (if non-%NULL) must point to a buffer that is the correct size for - * @route's family. - **/ -void -nm_ip_route_set_next_hop_binary(NMIPRoute *route, gconstpointer next_hop) -{ - g_return_if_fail(route != NULL); - - g_free(route->next_hop); - route->next_hop = canonicalize_ip_binary(route->family, next_hop, TRUE); -} - -/** - * nm_ip_route_get_metric: - * @route: the #NMIPRoute - * - * Gets the route metric property of this route object; lower values - * indicate "better" or more preferred routes; -1 indicates "default" - * (meaning NetworkManager will set it appropriately). - * - * Returns: the route metric - **/ -gint64 -nm_ip_route_get_metric(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, 0); - g_return_val_if_fail(route->refcount > 0, 0); - - return route->metric; -} - -/** - * nm_ip_route_set_metric: - * @route: the #NMIPRoute - * @metric: the route metric (or -1 for "default") - * - * Sets the metric property of this route object. - **/ -void -nm_ip_route_set_metric(NMIPRoute *route, gint64 metric) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(valid_metric(metric, NULL)); - - route->metric = metric; -} - -GHashTable * -_nm_ip_route_get_attributes(NMIPRoute *route) -{ - nm_assert(route); - - return route->attributes; -} - -/** - * _nm_ip_route_get_attribute_names: - * @route: the #NMIPRoute - * @sorted: whether to sort the names. Otherwise, their order is - * undefined and unstable. - * @out_length: (allow-none) (out): the number of elements - * - * Gets an array of attribute names defined on @route. - * - * Returns: (array length=out_length) (transfer container): a %NULL-terminated array - * of attribute names or %NULL if there are no attributes. The order of the returned - * names depends on @sorted. - **/ -const char ** -_nm_ip_route_get_attribute_names(const NMIPRoute *route, gboolean sorted, guint *out_length) -{ - nm_assert(route); - - return nm_utils_strdict_get_keys(route->attributes, sorted, out_length); -} - -/** - * nm_ip_route_get_attribute_names: - * @route: the #NMIPRoute - * - * Gets an array of attribute names defined on @route. - * - * Returns: (transfer full): a %NULL-terminated array of attribute names - **/ -char ** -nm_ip_route_get_attribute_names(NMIPRoute *route) -{ - const char **names; - - g_return_val_if_fail(route != NULL, NULL); - - names = _nm_ip_route_get_attribute_names(route, TRUE, NULL); - return nm_utils_strv_make_deep_copied_nonnull(names); -} - -/** - * nm_ip_route_get_attribute: - * @route: the #NMIPRoute - * @name: the name of an route attribute - * - * Gets the value of the attribute with name @name on @route - * - * Returns: (transfer none): the value of the attribute with name @name on - * @route, or %NULL if @route has no such attribute. - **/ -GVariant * -nm_ip_route_get_attribute(NMIPRoute *route, const char *name) -{ - g_return_val_if_fail(route != NULL, NULL); - g_return_val_if_fail(name != NULL && *name != '\0', NULL); - - if (route->attributes) - return g_hash_table_lookup(route->attributes, name); - else - return NULL; -} - -/** - * nm_ip_route_set_attribute: - * @route: the #NMIPRoute - * @name: the name of a route attribute - * @value: (transfer none) (allow-none): the value - * - * Sets the named attribute on @route to the given value. - **/ -void -nm_ip_route_set_attribute(NMIPRoute *route, const char *name, GVariant *value) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(name != NULL && *name != '\0'); - g_return_if_fail(strcmp(name, "dest") != 0 && strcmp(name, "prefix") != 0 - && strcmp(name, "next-hop") != 0 && strcmp(name, "metric") != 0); - - if (!route->attributes) { - route->attributes = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref); - } - - if (value) - g_hash_table_insert(route->attributes, g_strdup(name), g_variant_ref_sink(value)); - else - g_hash_table_remove(route->attributes, name); -} - -static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_CWND, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_FROM, - G_VARIANT_TYPE_STRING, - .v6 = TRUE, - .str_type = 'p', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_INITCWND, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_INITRWND, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_MTU, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_ONLINK, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_SCOPE, - G_VARIANT_TYPE_BYTE, - .v4 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_SRC, - G_VARIANT_TYPE_STRING, - .v4 = TRUE, - .v6 = TRUE, - .str_type = 'a', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TABLE, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TYPE, - G_VARIANT_TYPE_STRING, - .v4 = TRUE, - .v6 = TRUE, - .str_type = 'T', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_WINDOW, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NULL, -}; - -/** - * nm_ip_route_get_variant_attribute_spec: - * - * Returns: the specifiers for route attributes - * - * Since: 1.8 - */ -const NMVariantAttributeSpec *const * -nm_ip_route_get_variant_attribute_spec(void) -{ - return ip_route_attribute_spec; -} - -/** - * nm_ip_route_attribute_validate: - * @name: the attribute name - * @value: the attribute value - * @family: IP address family of the route - * @known: (out): on return, whether the attribute name is a known one - * @error: (allow-none): return location for a #GError, or %NULL - * - * Validates a route attribute, i.e. checks that the attribute is a known one - * and the value is of the correct type and well-formed. - * - * Returns: %TRUE if the attribute is valid, %FALSE otherwise - * - * Since: 1.8 - */ -gboolean -nm_ip_route_attribute_validate(const char *name, - GVariant * value, - int family, - gboolean * known, - GError ** error) -{ - const NMVariantAttributeSpec *spec; - - g_return_val_if_fail(name, FALSE); - g_return_val_if_fail(value, FALSE); - g_return_val_if_fail(family == AF_INET || family == AF_INET6, FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - spec = _nm_variant_attribute_spec_find_binary_search(ip_route_attribute_spec, - G_N_ELEMENTS(ip_route_attribute_spec) - 1, - name); - if (!spec) { - NM_SET_OUT(known, FALSE); - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unknown attribute")); - return FALSE; - } - - NM_SET_OUT(known, TRUE); - - if (!g_variant_is_of_type(value, spec->type)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid attribute type '%s'"), - g_variant_get_type_string(value)); - return FALSE; - } - - if ((family == AF_INET && !spec->v4) || (family == AF_INET6 && !spec->v6)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("attribute is not valid for a IPv4 route") - : _("attribute is not valid for a IPv6 route")); - return FALSE; - } - - if (g_variant_type_equal(spec->type, G_VARIANT_TYPE_STRING)) { - const char *string = g_variant_get_string(value, NULL); - - switch (spec->str_type) { - case 'a': /* IP address */ - if (!nm_utils_ipaddr_is_valid(family, string)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("'%s' is not a valid IPv4 address") - : _("'%s' is not a valid IPv6 address"), - string); - return FALSE; - } - break; - case 'p': /* IP address + optional prefix */ - { - gs_free char *addr_free = NULL; - const char * addr = string; - const char * str; - - str = strchr(addr, '/'); - if (str) { - addr = nm_strndup_a(200, addr, str - addr, &addr_free); - str++; - if (_nm_utils_ascii_str_to_int64(str, 10, 0, family == AF_INET ? 32 : 128, -1) - < 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid prefix %s"), - str); - return FALSE; - } - } - if (!nm_utils_ipaddr_is_valid(family, addr)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("'%s' is not a valid IPv4 address") - : _("'%s' is not a valid IPv6 address"), - string); - return FALSE; - } - break; - } - case 'T': /* route type. */ - if (!NM_IN_SET(nm_utils_route_type_by_name(string), RTN_UNICAST, RTN_LOCAL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%s is not a valid route type"), - string); - return FALSE; - } - break; - default: - break; - } - } - - return TRUE; -} - -gboolean -_nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error) -{ - NMUtilsNamedValue attrs_static[G_N_ELEMENTS(ip_route_attribute_spec)]; - gs_free NMUtilsNamedValue *attrs_free = NULL; - const NMUtilsNamedValue * attrs; - guint attrs_len; - GVariant * val; - guint i; - guint8 u8; - - g_return_val_if_fail(route, FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - if (!route->attributes) - return TRUE; - - attrs = nm_utils_named_values_from_strdict(route->attributes, - &attrs_len, - attrs_static, - &attrs_free); - for (i = 0; i < attrs_len; i++) { - const char *key = attrs[i].name; - GVariant * val2 = attrs[i].value_ptr; - - if (!nm_ip_route_attribute_validate(key, val2, route->family, NULL, NULL)) - return FALSE; - } - - if ((val = g_hash_table_lookup(route->attributes, NM_IP_ROUTE_ATTRIBUTE_TYPE))) { - nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_STRING)); - u8 = nm_utils_route_type_by_name(g_variant_get_string(val, NULL)); - - if (u8 == RTN_LOCAL && route->family == AF_INET - && (val = g_hash_table_lookup(route->attributes, NM_IP_ROUTE_ATTRIBUTE_SCOPE))) { - nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_BYTE)); - u8 = g_variant_get_byte(val); - - if (!NM_IN_SET(u8, RT_SCOPE_HOST, RT_SCOPE_NOWHERE)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("route scope is invalid")); - return FALSE; - } - } - } - - return TRUE; -} - -/*****************************************************************************/ - -struct NMIPRoutingRule { - NMIPAddr from_bin; - NMIPAddr to_bin; - char * from_str; - char * to_str; - char * iifname; - char * oifname; - guint ref_count; - guint32 priority; - guint32 table; - gint32 suppress_prefixlength; - guint32 fwmark; - guint32 fwmask; - guint16 sport_start; - guint16 sport_end; - guint16 dport_start; - guint16 dport_end; - guint8 action; - guint8 from_len; - guint8 to_len; - guint8 tos; - guint8 ipproto; - bool is_v4 : 1; - bool sealed : 1; - bool priority_has : 1; - bool from_has : 1; - bool from_valid : 1; - bool to_has : 1; - bool to_valid : 1; - bool invert : 1; -}; - -static NMIPRoutingRule *_ip_routing_rule_dup(const NMIPRoutingRule *rule); - -G_DEFINE_BOXED_TYPE(NMIPRoutingRule, - nm_ip_routing_rule, - _ip_routing_rule_dup, - nm_ip_routing_rule_unref) - -static gboolean -NM_IS_IP_ROUTING_RULE(const NMIPRoutingRule *self, gboolean also_sealed) -{ - return self && self->ref_count > 0 && (also_sealed || !self->sealed); -} - -static int -_ip_routing_rule_get_addr_family(const NMIPRoutingRule *self) -{ - nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); - - return self->is_v4 ? AF_INET : AF_INET6; -} - -static int -_ip_routing_rule_get_addr_size(const NMIPRoutingRule *self) -{ - nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); - - return self->is_v4 ? sizeof(struct in_addr) : sizeof(struct in6_addr); -} - -static NMIPRoutingRule * -_ip_routing_rule_dup(const NMIPRoutingRule *rule) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), NULL); - - if (rule->sealed) - return nm_ip_routing_rule_ref((NMIPRoutingRule *) rule); - return nm_ip_routing_rule_new_clone(rule); -} - -/** - * nm_ip_routing_rule_new: - * @addr_family: the address family of the routing rule. Must be either - * %AF_INET (2) or %AF_INET6 (10). - * - * Returns: (transfer full): a newly created rule instance with the - * provided address family. The instance is unsealed. - * - * Since: 1.18 - */ -NMIPRoutingRule * -nm_ip_routing_rule_new(int addr_family) -{ - NMIPRoutingRule *self; - - g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NULL); - - self = g_slice_new(NMIPRoutingRule); - *self = (NMIPRoutingRule){ - .ref_count = 1, - .is_v4 = (addr_family == AF_INET), - .action = FR_ACT_TO_TBL, - .table = RT_TABLE_MAIN, - .suppress_prefixlength = -1, - }; - return self; -} - -/** - * nm_ip_routing_rule_new_clone: - * @rule: the #NMIPRoutingRule to clone. - * - * Returns: (transfer full): a newly created rule instance with - * the same settings as @rule. Note that the instance will - * always be unsealred. - * - * Since: 1.18 - */ -NMIPRoutingRule * -nm_ip_routing_rule_new_clone(const NMIPRoutingRule *rule) -{ - NMIPRoutingRule *self; - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), NULL); - - self = g_slice_new(NMIPRoutingRule); - *self = (NMIPRoutingRule){ - .ref_count = 1, - .sealed = FALSE, - .is_v4 = rule->is_v4, - - .priority = rule->priority, - .priority_has = rule->priority_has, - - .invert = rule->invert, - - .tos = rule->tos, - - .fwmark = rule->fwmark, - .fwmask = rule->fwmask, - - .sport_start = rule->sport_start, - .sport_end = rule->sport_end, - .dport_start = rule->dport_start, - .dport_end = rule->dport_end, - - .ipproto = rule->ipproto, - - .from_len = rule->from_len, - .from_bin = rule->from_bin, - .from_str = (rule->from_has && !rule->from_valid) ? g_strdup(rule->from_str) : NULL, - .from_has = rule->from_has, - .from_valid = rule->from_valid, - - .to_len = rule->to_len, - .to_bin = rule->to_bin, - .to_str = (rule->to_has && !rule->to_valid) ? g_strdup(rule->to_str) : NULL, - .to_has = rule->to_has, - .to_valid = rule->to_valid, - - .iifname = g_strdup(rule->iifname), - .oifname = g_strdup(rule->oifname), - - .action = rule->action, - .table = rule->table, - - .suppress_prefixlength = rule->suppress_prefixlength, - }; - return self; -} - -/** - * nm_ip_routing_rule_ref: - * @self: (allow-none): the #NMIPRoutingRule instance - * - * Increases the reference count of the instance. - * This is not thread-safe. - * - * Returns: (transfer full): the @self argument with incremented - * reference count. - * - * Since: 1.18 - */ -NMIPRoutingRule * -nm_ip_routing_rule_ref(NMIPRoutingRule *self) -{ - if (!self) - return NULL; - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - nm_assert(self->ref_count < G_MAXUINT); - self->ref_count++; - return self; -} - -/** - * nm_ip_routing_rule_unref: - * @self: (allow-none): the #NMIPRoutingRule instance - * - * Decreases the reference count of the instance and destroys - * the instance if the reference count reaches zero. - * This is not thread-safe. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_unref(NMIPRoutingRule *self) -{ - if (!self) - return; - - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE)); - - if (--self->ref_count > 0) - return; - - g_free(self->from_str); - g_free(self->to_str); - g_free(self->iifname); - g_free(self->oifname); - - g_slice_free(NMIPRoutingRule, self); -} - -/** - * nm_ip_routing_rule_is_sealed: - * @self: the #NMIPRoutingRule instance - * - * Returns: whether @self is sealed. Once sealed, an instance - * cannot be modified nor unsealed. - * - * Since: 1.18 - */ -gboolean -nm_ip_routing_rule_is_sealed(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); - - return self->sealed; -} - -/** - * nm_ip_routing_rule_seal: - * @self: the #NMIPRoutingRule instance - * - * Seals the routing rule. Afterwards, the instance can no longer be - * modified, and it is a bug to call any of the accessors that would - * modify the rule. If @self was already sealed, this has no effect. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_seal(NMIPRoutingRule *self) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE)); - - self->sealed = TRUE; -} - -/** - * nm_ip_routing_rule_get_addr_family: - * @self: the #NMIPRoutingRule instance - * - * Returns: the address family of the rule. Either %AF_INET or %AF_INET6. - * - * Since: 1.18 - */ -int -nm_ip_routing_rule_get_addr_family(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), AF_UNSPEC); - - return _ip_routing_rule_get_addr_family(self); -} - -/** - * nm_ip_routing_rule_get_priority: - * @self: the #NMIPRoutingRule instance - * - * Returns: the priority. A valid priority is in the range from - * 0 to %G_MAXUINT32. If unset, -1 is returned. - * - * Since: 1.18 - */ -gint64 -nm_ip_routing_rule_get_priority(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), -1); - - return self->priority_has ? (gint64) self->priority : (gint64) -1; -} - -/** - * nm_ip_routing_rule_set_priority: - * @self: the #NMIPRoutingRule instance - * @priority: the priority to set - * - * A valid priority ranges from 0 to %G_MAXUINT32. "-1" is also allowed - * to reset the priority. It is a bug calling this function with any - * other value. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_priority(NMIPRoutingRule *self, gint64 priority) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - if (priority >= 0 && priority <= (gint64) G_MAXUINT32) { - self->priority = (guint32) priority; - self->priority_has = TRUE; - } else { - g_return_if_fail(priority == -1); - self->priority = 0; - self->priority_has = FALSE; - } -} - -/** - * nm_ip_routing_rule_get_invert: - * @self: the #NMIPRoutingRule instance - * - * Returns: the "invert" setting of the rule. - * - * Since: 1.18 - */ -gboolean -nm_ip_routing_rule_get_invert(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); - - return self->invert; -} - -/** - * nm_ip_routing_rule_set_invert: - * @self: the #NMIPRoutingRule instance - * @invert: the new value to set - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_invert(NMIPRoutingRule *self, gboolean invert) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->invert = invert; -} - -/** - * nm_ip_routing_rule_get_from_len: - * @self: the #NMIPRoutingRule instance - * - * Returns: the set prefix length for the from/src parameter. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_from_len(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->from_len; -} - -/** - * nm_ip_routing_rule_get_from: - * @self: the #NMIPRoutingRule instance - * - * Returns: (transfer none): the set from/src parameter or - * %NULL, if no value is set. - * - * Since: 1.18 - */ -const char * -nm_ip_routing_rule_get_from(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - if (!self->from_has) - return NULL; - if (!self->from_str) { - nm_assert(self->from_valid); - ((NMIPRoutingRule *) self)->from_str = - nm_utils_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->from_bin); - } - return self->from_str; -} - -const NMIPAddr * -nm_ip_routing_rule_get_from_bin(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - return (self->from_has && self->from_valid) ? &self->from_bin : NULL; -} - -void -nm_ip_routing_rule_set_from_bin(NMIPRoutingRule *self, gconstpointer from, guint8 len) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - nm_clear_g_free(&self->from_str); - - if (!from) { - self->from_has = FALSE; - self->from_len = len; - return; - } - - self->from_has = TRUE; - self->from_len = len; - self->from_valid = TRUE; - nm_ip_addr_set(_ip_routing_rule_get_addr_family(self), &self->from_bin, from); -} - -/** - * nm_ip_routing_rule_set_from: - * @self: the #NMIPRoutingRule instance - * @from: (allow-none): the from/src address to set. - * The address family must match. - * @len: the corresponding prefix length of the address. - * - * Setting invalid values is accepted, but will later fail - * during nm_ip_routing_rule_validate(). - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_from(NMIPRoutingRule *self, const char *from, guint8 len) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - if (!from) { - nm_clear_g_free(&self->from_str); - self->from_has = FALSE; - self->from_len = len; - return; - } - - nm_clear_g_free(&self->from_str); - self->from_has = TRUE; - self->from_len = len; - self->from_valid = nm_utils_parse_inaddr_bin(_ip_routing_rule_get_addr_family(self), - from, - NULL, - &self->from_bin); - if (!self->from_valid) - self->from_str = g_strdup(from); -} - -/** - * nm_ip_routing_rule_get_to_len: - * @self: the #NMIPRoutingRule instance - * - * Returns: the set prefix length for the to/dst parameter. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_to_len(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->to_len; -} - -/** - * nm_ip_routing_rule_get_to: - * @self: the #NMIPRoutingRule instance - * - * Returns: (transfer none): the set to/dst parameter or - * %NULL, if no value is set. - * - * Since: 1.18 - */ -const char * -nm_ip_routing_rule_get_to(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - if (!self->to_has) - return NULL; - if (!self->to_str) { - nm_assert(self->to_valid); - ((NMIPRoutingRule *) self)->to_str = - nm_utils_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->to_bin); - } - return self->to_str; -} - -const NMIPAddr * -nm_ip_routing_rule_get_to_bin(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - return (self->to_has && self->to_valid) ? &self->to_bin : NULL; -} - -void -nm_ip_routing_rule_set_to_bin(NMIPRoutingRule *self, gconstpointer to, guint8 len) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - nm_clear_g_free(&self->to_str); - - if (!to) { - self->to_has = FALSE; - self->to_len = len; - return; - } - - self->to_has = TRUE; - self->to_len = len; - self->to_valid = TRUE; - nm_ip_addr_set(_ip_routing_rule_get_addr_family(self), &self->to_bin, to); -} - -/** - * nm_ip_routing_rule_set_to: - * @self: the #NMIPRoutingRule instance - * @to: (allow-none): the to/dst address to set. - * The address family must match. - * @len: the corresponding prefix length of the address. - * If @to is %NULL, this valid is ignored. - * - * Setting invalid values is accepted, but will later fail - * during nm_ip_routing_rule_validate(). - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_to(NMIPRoutingRule *self, const char *to, guint8 len) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - if (!to) { - nm_clear_g_free(&self->to_str); - self->to_has = FALSE; - self->to_len = len; - return; - } - - nm_clear_g_free(&self->to_str); - self->to_has = TRUE; - self->to_len = len; - self->to_valid = - nm_utils_parse_inaddr_bin(_ip_routing_rule_get_addr_family(self), to, NULL, &self->to_bin); - if (!self->to_valid) - self->to_str = g_strdup(to); -} - -/** - * nm_ip_routing_rule_get_tos: - * @self: the #NMIPRoutingRule instance - * - * Returns: the tos of the rule. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_tos(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->tos; -} - -/** - * nm_ip_routing_rule_set_tos: - * @self: the #NMIPRoutingRule instance - * @tos: the tos to set - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_tos(NMIPRoutingRule *self, guint8 tos) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->tos = tos; -} - -/** - * nm_ip_routing_rule_get_ipproto: - * @self: the #NMIPRoutingRule instance - * - * Returns: the ipproto of the rule. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_ipproto(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->ipproto; -} - -/** - * nm_ip_routing_rule_set_ipproto: - * @self: the #NMIPRoutingRule instance - * @ipproto: the ipproto to set - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_ipproto(NMIPRoutingRule *self, guint8 ipproto) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->ipproto = ipproto; -} - -/** - * nm_ip_routing_rule_get_source_port_start: - * @self: the #NMIPRoutingRule instance - * - * Returns: the source port start setting. - * - * Since: 1.18 - */ -guint16 -nm_ip_routing_rule_get_source_port_start(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->sport_start; -} - -/** - * nm_ip_routing_rule_get_source_port_end: - * @self: the #NMIPRoutingRule instance - * - * Returns: the source port end setting. - * - * Since: 1.18 - */ -guint16 -nm_ip_routing_rule_get_source_port_end(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->sport_end; -} - -/** - * nm_ip_routing_rule_set_source_port: - * @self: the #NMIPRoutingRule instance - * @start: the start port to set. - * @end: the end port to set. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_source_port(NMIPRoutingRule *self, guint16 start, guint16 end) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->sport_start = start; - self->sport_end = end; -} - -/** - * nm_ip_routing_rule_get_destination_port_start: - * @self: the #NMIPRoutingRule instance - * - * Returns: the destination port start setting. - * - * Since: 1.18 - */ -guint16 -nm_ip_routing_rule_get_destination_port_start(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->dport_start; -} - -/** - * nm_ip_routing_rule_get_destination_port_end: - * @self: the #NMIPRoutingRule instance - * - * Returns: the destination port end setting. - * - * Since: 1.18 - */ -guint16 -nm_ip_routing_rule_get_destination_port_end(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->dport_end; -} - -/** - * nm_ip_routing_rule_set_destination_port: - * @self: the #NMIPRoutingRule instance - * @start: the start port to set. - * @end: the end port to set. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_destination_port(NMIPRoutingRule *self, guint16 start, guint16 end) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->dport_start = start; - self->dport_end = end; -} - -/** - * nm_ip_routing_rule_get_fwmark: - * @self: the #NMIPRoutingRule instance - * - * Returns: the fwmark setting. - * - * Since: 1.18 - */ -guint32 -nm_ip_routing_rule_get_fwmark(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->fwmark; -} - -/** - * nm_ip_routing_rule_get_fwmask: - * @self: the #NMIPRoutingRule instance - * - * Returns: the fwmask setting. - * - * Since: 1.18 - */ -guint32 -nm_ip_routing_rule_get_fwmask(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->fwmask; -} - -/** - * nm_ip_routing_rule_set_fwmark: - * @self: the #NMIPRoutingRule instance - * @fwmark: the fwmark - * @fwmask: the fwmask - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_fwmark(NMIPRoutingRule *self, guint32 fwmark, guint32 fwmask) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->fwmark = fwmark; - self->fwmask = fwmask; -} - -/** - * nm_ip_routing_rule_get_iifname: - * @self: the #NMIPRoutingRule instance. - * - * Returns: (transfer none): the set iifname or %NULL if unset. - * - * Since: 1.18 - */ -const char * -nm_ip_routing_rule_get_iifname(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - return self->iifname; -} - -gboolean -nm_ip_routing_rule_get_xifname_bin(const NMIPRoutingRule *self, - gboolean iif /* or else oif */, - char out_xifname[static 16 /* IFNAMSIZ */]) -{ - gs_free gpointer bin_to_free = NULL; - const char * xifname; - gconstpointer bin; - gsize len; - - nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); - nm_assert(out_xifname); - - xifname = iif ? self->iifname : self->oifname; - - if (!xifname) - return FALSE; - - bin = nm_utils_buf_utf8safe_unescape(xifname, - NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, - &len, - &bin_to_free); - - strncpy(out_xifname, bin, 16 /* IFNAMSIZ */); - out_xifname[15] = '\0'; - return TRUE; -} - -/** - * nm_ip_routing_rule_set_iifname: - * @self: the #NMIPRoutingRule instance. - * @iifname: (allow-none): the iifname to set or %NULL to unset. - * - * The name supports C backslash escaping for non-UTF-8 characters. - * Note that nm_ip_routing_rule_from_string() too uses backslash - * escaping when tokenizing the words by whitespace. So, in string - * representation you'd get double backslashes. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_iifname(NMIPRoutingRule *self, const char *iifname) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - g_free(self->iifname); - self->iifname = g_strdup(iifname); -} - -/** - * nm_ip_routing_rule_get_oifname: - * @self: the #NMIPRoutingRule instance. - * - * Returns: (transfer none): the set oifname or %NULL if unset. - * - * Since: 1.18 - */ -const char * -nm_ip_routing_rule_get_oifname(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - return self->oifname; -} - -/** - * nm_ip_routing_rule_set_oifname: - * @self: the #NMIPRoutingRule instance. - * @oifname: (allow-none): the oifname to set or %NULL to unset. - * - * The name supports C backslash escaping for non-UTF-8 characters. - * Note that nm_ip_routing_rule_from_string() too uses backslash - * escaping when tokenizing the words by whitespace. So, in string - * representation you'd get double backslashes. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_oifname(NMIPRoutingRule *self, const char *oifname) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - g_free(self->oifname); - self->oifname = g_strdup(oifname); -} - -/** - * nm_ip_routing_rule_get_action: - * @self: the #NMIPRoutingRule instance - * - * Returns: the set action. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_action(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->action; -} - -/** - * nm_ip_routing_rule_set_action: - * @self: the #NMIPRoutingRule instance - * @action: the action to set - * - * Note that currently only certain actions are allowed. nm_ip_routing_rule_validate() - * will reject unsupported actions as invalid. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_action(NMIPRoutingRule *self, guint8 action) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->action = action; -} - -/** - * nm_ip_routing_rule_get_table: - * @self: the #NMIPRoutingRule instance - * - * Returns: the set table. - * - * Since: 1.18 - */ -guint32 -nm_ip_routing_rule_get_table(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->table; -} - -/** - * nm_ip_routing_rule_set_table: - * @self: the #NMIPRoutingRule instance - * @table: the table to set - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_table(NMIPRoutingRule *self, guint32 table) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->table = table; -} - -/** - * nm_ip_routing_rule_get_suppress_prefixlength: - * @self: the #NMIPRoutingRule instance - * - * Returns: the suppress_prefixlength of the rule. -1 means that the value is unset. - * - * Since: 1.20 - */ -gint32 -nm_ip_routing_rule_get_suppress_prefixlength(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), -1); - - return self->suppress_prefixlength; -} - -/** - * nm_ip_routing_rule_set_suppress_prefixlength: - * @self: the #NMIPRoutingRule instance - * @suppress_prefixlength: the suppress_prefixlength to set. The value -1 means - * unset. - * - * Since: 1.20 - */ -void -nm_ip_routing_rule_set_suppress_prefixlength(NMIPRoutingRule *self, gint32 suppress_prefixlength) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->suppress_prefixlength = suppress_prefixlength; -} - -/** - * nm_ip_routing_rule_cmp: - * @rule: (allow-none): the #NMIPRoutingRule instance to compare - * @other: (allow-none): the other #NMIPRoutingRule instance to compare - * - * Returns: zero, a positive, or a negative integer to indicate - * equality or how the arguments compare. - * - * Since: 1.18 - */ -int -nm_ip_routing_rule_cmp(const NMIPRoutingRule *rule, const NMIPRoutingRule *other) -{ - NM_CMP_SELF(rule, other); - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), 0); - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(other, TRUE), 0); - - NM_CMP_FIELD_UNSAFE(rule, other, priority_has); - if (rule->priority_has) - NM_CMP_FIELD(rule, other, priority); - - NM_CMP_FIELD_UNSAFE(rule, other, is_v4); - - NM_CMP_FIELD_UNSAFE(rule, other, invert); - - NM_CMP_FIELD(rule, other, tos); - - NM_CMP_FIELD(rule, other, fwmark); - NM_CMP_FIELD(rule, other, fwmask); - - NM_CMP_FIELD(rule, other, action); - - NM_CMP_FIELD(rule, other, table); - - NM_CMP_FIELD(rule, other, suppress_prefixlength); - - NM_CMP_FIELD(rule, other, sport_start); - NM_CMP_FIELD(rule, other, sport_end); - NM_CMP_FIELD(rule, other, dport_start); - NM_CMP_FIELD(rule, other, dport_end); - - NM_CMP_FIELD(rule, other, ipproto); - - /* We compare the plain strings, not the binary values after utf8safe unescaping. - * - * The reason is, that the rules differ already when the direct strings differ, not - * only when the unescaped names differ. */ - NM_CMP_FIELD_STR0(rule, other, iifname); - NM_CMP_FIELD_STR0(rule, other, oifname); - - NM_CMP_FIELD(rule, other, from_len); - - NM_CMP_FIELD_UNSAFE(rule, other, from_has); - if (rule->from_has) { - NM_CMP_FIELD_UNSAFE(rule, other, from_valid); - if (rule->from_valid) { - NM_CMP_RETURN( - memcmp(&rule->from_bin, &other->from_bin, _ip_routing_rule_get_addr_size(rule))); - } else - NM_CMP_FIELD_STR(rule, other, from_str); - } - - NM_CMP_FIELD(rule, other, to_len); - - NM_CMP_FIELD_UNSAFE(rule, other, to_has); - if (rule->to_has) { - NM_CMP_FIELD_UNSAFE(rule, other, to_valid); - if (rule->to_valid) { - NM_CMP_RETURN( - memcmp(&rule->to_bin, &other->to_bin, _ip_routing_rule_get_addr_size(rule))); - } else - NM_CMP_FIELD_STR(rule, other, to_str); - } - - return 0; -} - -static gboolean -_rr_xport_range_valid(guint16 xport_start, guint16 xport_end) -{ - if (xport_start == 0) - return (xport_end == 0); - - return xport_start <= xport_end && xport_end < 0xFFFFu; -} - -static gboolean -_rr_xport_range_parse(char *str, gint64 *out_start, guint16 *out_end) -{ - guint16 start, end; - gint64 i64; - char * s; - - s = strchr(str, '-'); - if (s) - *(s++) = '\0'; - - i64 = _nm_utils_ascii_str_to_int64(str, 10, 0, 0xFFFF, -1); - if (i64 == -1) - return FALSE; - - start = i64; - if (s) { - i64 = _nm_utils_ascii_str_to_int64(s, 10, 0, 0xFFFF, -1); - if (i64 == -1) - return FALSE; - end = i64; - } else - end = start; - - *out_start = start; - *out_end = end; - return TRUE; -} - -/** - * nm_ip_routing_rule_validate: - * @self: the #NMIPRoutingRule instance to validate - * @error: (allow-none) (out): the error result if validation fails. - * - * Returns: %TRUE if the rule validates. - * - * Since: 1.18 - */ -gboolean -nm_ip_routing_rule_validate(const NMIPRoutingRule *self, GError **error) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - /* Kernel may be more flexible about validating. We do a strict validation - * here and reject certain settings eagerly. We can always relax it later. */ - - if (!self->priority_has) { - /* iproute2 accepts not specifying the priority, in which case kernel will select - * an unused priority. We don't allow for that, and will always require the user to - * select a priority. - * - * Note that if the user selects priority 0 or a non-unique priority, this is problematic - * due to kernel bugs rh#1685816 and rh#1685816. It may result in NetworkManager wrongly being - * unable to add a rule or deleting the wrong rule. - * This problem is not at all specific to the priority, it affects all rules that - * have default values which confuse kernel. But setting a unique priority avoids - * this problem nicely. */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid priority")); - return FALSE; - } - - if (NM_IN_SET(self->action, FR_ACT_TO_TBL)) { - if (self->table == 0) { - /* with IPv4, kernel allows a table (in RTM_NEWRULE) of zero to automatically select - * an unused table. We don't. The user needs to specify the table. - * - * For IPv6, kernel doesn't allow a table of zero, so we are consistent here. */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing table")); - return FALSE; - } - } else { - /* whitelist the actions that we currently. */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid action")); - return FALSE; - } - - if (self->from_len == 0) { - if (self->from_has) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("has from/src but the prefix-length is zero")); - return FALSE; - } - } else if (self->from_len > 0 && self->from_len <= 8 * _ip_routing_rule_get_addr_size(self)) { - if (!self->from_has) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing from/src for a non zero prefix-length")); - return FALSE; - } - if (!self->from_valid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid from/src")); - return FALSE; - } - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid prefix length for from/src")); - return FALSE; - } - - if (self->to_len == 0) { - if (self->to_has) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("has to/dst but the prefix-length is zero")); - return FALSE; - } - } else if (self->to_len > 0 && self->to_len <= 8 * _ip_routing_rule_get_addr_size(self)) { - if (!self->to_has) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing to/dst for a non zero prefix-length")); - return FALSE; - } - if (!self->to_valid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid to/dst")); - return FALSE; - } - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid prefix length for to/dst")); - return FALSE; - } - - if (self->iifname - && (!g_utf8_validate(self->iifname, -1, NULL) - || !nm_utils_is_valid_iface_name_utf8safe(self->iifname))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid iifname")); - return FALSE; - } - - if (self->oifname - && (!g_utf8_validate(self->oifname, -1, NULL) - || !nm_utils_is_valid_iface_name_utf8safe(self->oifname))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid oifname")); - return FALSE; - } - - if (!_rr_xport_range_valid(self->sport_start, self->sport_end)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid source port range")); - return FALSE; - } - - if (!_rr_xport_range_valid(self->dport_start, self->dport_end)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid destination port range")); - return FALSE; - } - - if (self->suppress_prefixlength != -1) { - if (self->suppress_prefixlength < -1 - || self->suppress_prefixlength > (self->is_v4 ? 32 : 128)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("suppress_prefixlength out of range")); - return FALSE; - } - if (self->action != FR_ACT_TO_TBL) { - g_set_error_literal( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("suppress_prefixlength is only allowed with the to-table action")); - return FALSE; - } - } - - return TRUE; -} - -/*****************************************************************************/ - -typedef enum { - RR_DBUS_ATTR_ACTION, - RR_DBUS_ATTR_DPORT_END, - RR_DBUS_ATTR_DPORT_START, - RR_DBUS_ATTR_FAMILY, - RR_DBUS_ATTR_FROM, - RR_DBUS_ATTR_FROM_LEN, - RR_DBUS_ATTR_FWMARK, - RR_DBUS_ATTR_FWMASK, - RR_DBUS_ATTR_IIFNAME, - RR_DBUS_ATTR_INVERT, - RR_DBUS_ATTR_IPPROTO, - RR_DBUS_ATTR_OIFNAME, - RR_DBUS_ATTR_PRIORITY, - RR_DBUS_ATTR_SPORT_END, - RR_DBUS_ATTR_SPORT_START, - RR_DBUS_ATTR_TABLE, - RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, - RR_DBUS_ATTR_TO, - RR_DBUS_ATTR_TOS, - RR_DBUS_ATTR_TO_LEN, - - _RR_DBUS_ATTR_NUM, -} RRDbusAttr; - -typedef struct { - const char * name; - const GVariantType *dbus_type; -} RRDbusData; - -static const RRDbusData rr_dbus_data[_RR_DBUS_ATTR_NUM] = { -#define _D(attr, _name, type) \ - [attr] = { \ - .name = _name, \ - .dbus_type = type, \ - } - _D(RR_DBUS_ATTR_ACTION, NM_IP_ROUTING_RULE_ATTR_ACTION, G_VARIANT_TYPE_BYTE), - _D(RR_DBUS_ATTR_DPORT_END, NM_IP_ROUTING_RULE_ATTR_DPORT_END, G_VARIANT_TYPE_UINT16), - _D(RR_DBUS_ATTR_DPORT_START, NM_IP_ROUTING_RULE_ATTR_DPORT_START, G_VARIANT_TYPE_UINT16), - _D(RR_DBUS_ATTR_FAMILY, NM_IP_ROUTING_RULE_ATTR_FAMILY, G_VARIANT_TYPE_INT32), - _D(RR_DBUS_ATTR_FROM, NM_IP_ROUTING_RULE_ATTR_FROM, G_VARIANT_TYPE_STRING), - _D(RR_DBUS_ATTR_FROM_LEN, NM_IP_ROUTING_RULE_ATTR_FROM_LEN, G_VARIANT_TYPE_BYTE), - _D(RR_DBUS_ATTR_FWMARK, NM_IP_ROUTING_RULE_ATTR_FWMARK, G_VARIANT_TYPE_UINT32), - _D(RR_DBUS_ATTR_FWMASK, NM_IP_ROUTING_RULE_ATTR_FWMASK, G_VARIANT_TYPE_UINT32), - _D(RR_DBUS_ATTR_IIFNAME, NM_IP_ROUTING_RULE_ATTR_IIFNAME, G_VARIANT_TYPE_STRING), - _D(RR_DBUS_ATTR_INVERT, NM_IP_ROUTING_RULE_ATTR_INVERT, G_VARIANT_TYPE_BOOLEAN), - _D(RR_DBUS_ATTR_IPPROTO, NM_IP_ROUTING_RULE_ATTR_IPPROTO, G_VARIANT_TYPE_BYTE), - _D(RR_DBUS_ATTR_OIFNAME, NM_IP_ROUTING_RULE_ATTR_OIFNAME, G_VARIANT_TYPE_STRING), - _D(RR_DBUS_ATTR_PRIORITY, NM_IP_ROUTING_RULE_ATTR_PRIORITY, G_VARIANT_TYPE_UINT32), - _D(RR_DBUS_ATTR_SPORT_END, NM_IP_ROUTING_RULE_ATTR_SPORT_END, G_VARIANT_TYPE_UINT16), - _D(RR_DBUS_ATTR_SPORT_START, NM_IP_ROUTING_RULE_ATTR_SPORT_START, G_VARIANT_TYPE_UINT16), - _D(RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, - NM_IP_ROUTING_RULE_ATTR_SUPPRESS_PREFIXLENGTH, - G_VARIANT_TYPE_INT32), - _D(RR_DBUS_ATTR_TABLE, NM_IP_ROUTING_RULE_ATTR_TABLE, G_VARIANT_TYPE_UINT32), - _D(RR_DBUS_ATTR_TO, NM_IP_ROUTING_RULE_ATTR_TO, G_VARIANT_TYPE_STRING), - _D(RR_DBUS_ATTR_TOS, NM_IP_ROUTING_RULE_ATTR_TOS, G_VARIANT_TYPE_BYTE), - _D(RR_DBUS_ATTR_TO_LEN, NM_IP_ROUTING_RULE_ATTR_TO_LEN, G_VARIANT_TYPE_BYTE), -#undef _D -}; - -static void -_rr_variants_free(GVariant *(*p_variants)[]) -{ - int i; - - for (i = 0; i < _RR_DBUS_ATTR_NUM; i++) { - if ((*p_variants)[i]) - g_variant_unref((*p_variants)[i]); - } -} - -NMIPRoutingRule * -nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error) -{ - nm_auto(_rr_variants_free) GVariant *variants[_RR_DBUS_ATTR_NUM] = {}; - nm_auto_unref_ip_routing_rule NMIPRoutingRule *self = NULL; - RRDbusAttr attr; - GVariantIter iter; - const char * iter_key; - GVariant * iter_val; - int addr_family; - int i; - - g_variant_iter_init(&iter, variant); - -#if NM_MORE_ASSERTS > 10 - for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { - nm_assert(rr_dbus_data[attr].name); - nm_assert(g_variant_type_string_is_valid((const char *) rr_dbus_data[attr].dbus_type)); - } -#endif - - while (g_variant_iter_next(&iter, "{&sv}", &iter_key, &iter_val)) { - gs_unref_variant GVariant *iter_val2 = iter_val; - - for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { - if (nm_streq(iter_key, rr_dbus_data[attr].name)) { - if (variants[attr]) { - if (strict) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("duplicate key %s"), - iter_key); - return NULL; - } - g_variant_unref(variants[attr]); - } - variants[attr] = g_steal_pointer(&iter_val2); - break; - } - } - - if (attr >= _RR_DBUS_ATTR_NUM && strict) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid key \"%s\""), - iter_key); - return NULL; - } - } - - for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { - if (!variants[attr]) - continue; - if (!g_variant_is_of_type(variants[attr], rr_dbus_data[attr].dbus_type)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid variant type '%s' for \"%s\""), - (const char *) rr_dbus_data[attr].dbus_type, - rr_dbus_data[attr].name); - return NULL; - } - } - - if (!variants[RR_DBUS_ATTR_FAMILY]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing \"" NM_IP_ROUTING_RULE_ATTR_FAMILY "\"")); - return NULL; - } - addr_family = g_variant_get_int32(variants[RR_DBUS_ATTR_FAMILY]); - if (!NM_IN_SET(addr_family, AF_INET, AF_INET6)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid \"" NM_IP_ROUTING_RULE_ATTR_FAMILY "\"")); - return NULL; - } - - self = nm_ip_routing_rule_new(addr_family); - - if (variants[RR_DBUS_ATTR_PRIORITY]) - nm_ip_routing_rule_set_priority(self, - g_variant_get_uint32(variants[RR_DBUS_ATTR_PRIORITY])); - - if (variants[RR_DBUS_ATTR_INVERT]) - nm_ip_routing_rule_set_invert(self, g_variant_get_boolean(variants[RR_DBUS_ATTR_INVERT])); - - if (variants[RR_DBUS_ATTR_TOS]) - nm_ip_routing_rule_set_tos(self, g_variant_get_byte(variants[RR_DBUS_ATTR_TOS])); - - if (variants[RR_DBUS_ATTR_IPPROTO]) - nm_ip_routing_rule_set_ipproto(self, g_variant_get_byte(variants[RR_DBUS_ATTR_IPPROTO])); - - for (i = 0; i < 2; i++) { - GVariant *v_start = variants[i ? RR_DBUS_ATTR_SPORT_START : RR_DBUS_ATTR_DPORT_START]; - GVariant *v_end = variants[i ? RR_DBUS_ATTR_SPORT_END : RR_DBUS_ATTR_DPORT_END]; - guint16 start, end; - - if (!v_start && !v_end) - continue; - - /* if start or end is missing, it defaults to the other parameter, respectively. */ - if (v_start) - start = g_variant_get_uint16(v_start); - else - start = g_variant_get_uint16(v_end); - if (v_end) - end = g_variant_get_uint16(v_end); - else - end = g_variant_get_uint16(v_start); - - if (i) - nm_ip_routing_rule_set_source_port(self, start, end); - else - nm_ip_routing_rule_set_destination_port(self, start, end); - } - - if (variants[RR_DBUS_ATTR_FWMARK] || variants[RR_DBUS_ATTR_FWMASK]) { - nm_ip_routing_rule_set_fwmark( - self, - variants[RR_DBUS_ATTR_FWMARK] ? g_variant_get_uint32(variants[RR_DBUS_ATTR_FWMARK]) - : 0u, - variants[RR_DBUS_ATTR_FWMASK] ? g_variant_get_uint32(variants[RR_DBUS_ATTR_FWMASK]) - : 0u); - } - - if (variants[RR_DBUS_ATTR_FROM] || variants[RR_DBUS_ATTR_FROM_LEN]) { - nm_ip_routing_rule_set_from( - self, - variants[RR_DBUS_ATTR_FROM] ? g_variant_get_string(variants[RR_DBUS_ATTR_FROM], NULL) - : NULL, - variants[RR_DBUS_ATTR_FROM_LEN] ? g_variant_get_byte(variants[RR_DBUS_ATTR_FROM_LEN]) - : 0u); - } - - if (variants[RR_DBUS_ATTR_TO] || variants[RR_DBUS_ATTR_TO_LEN]) { - nm_ip_routing_rule_set_to( - self, - variants[RR_DBUS_ATTR_TO] ? g_variant_get_string(variants[RR_DBUS_ATTR_TO], NULL) - : NULL, - variants[RR_DBUS_ATTR_TO_LEN] ? g_variant_get_byte(variants[RR_DBUS_ATTR_TO_LEN]) : 0u); - } - - if (variants[RR_DBUS_ATTR_IIFNAME]) - nm_ip_routing_rule_set_iifname(self, - g_variant_get_string(variants[RR_DBUS_ATTR_IIFNAME], NULL)); - - if (variants[RR_DBUS_ATTR_OIFNAME]) - nm_ip_routing_rule_set_oifname(self, - g_variant_get_string(variants[RR_DBUS_ATTR_OIFNAME], NULL)); - - if (variants[RR_DBUS_ATTR_ACTION]) - nm_ip_routing_rule_set_action(self, g_variant_get_byte(variants[RR_DBUS_ATTR_ACTION])); - - if (variants[RR_DBUS_ATTR_TABLE]) - nm_ip_routing_rule_set_table(self, g_variant_get_uint32(variants[RR_DBUS_ATTR_TABLE])); - - if (variants[RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH]) - nm_ip_routing_rule_set_suppress_prefixlength( - self, - g_variant_get_int32(variants[RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH])); - - if (strict && !nm_ip_routing_rule_validate(self, error)) - return NULL; - - return g_steal_pointer(&self); -} - -static void -_rr_to_dbus_add(GVariantBuilder *builder, RRDbusAttr attr, GVariant *value) -{ - nm_assert(builder); - nm_assert(value); - nm_assert(g_variant_is_floating(value)); - nm_assert(g_variant_is_of_type(value, rr_dbus_data[attr].dbus_type)); - - g_variant_builder_add(builder, "{sv}", rr_dbus_data[attr].name, value); -} - -GVariant * -nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self) -{ - GVariantBuilder builder; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_FAMILY, - g_variant_new_int32(_ip_routing_rule_get_addr_family(self))); - - if (self->invert) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_INVERT, g_variant_new_boolean(TRUE)); - - if (self->priority_has) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_PRIORITY, g_variant_new_uint32(self->priority)); - - if (self->tos != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TOS, g_variant_new_byte(self->tos)); - - if (self->ipproto != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_IPPROTO, g_variant_new_byte(self->ipproto)); - - if (self->fwmark != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FWMARK, g_variant_new_uint32(self->fwmark)); - - if (self->fwmask != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FWMASK, g_variant_new_uint32(self->fwmask)); - - if (self->sport_start != 0 || self->sport_end != 0) { - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_SPORT_START, - g_variant_new_uint16(self->sport_start)); - if (self->sport_start != self->sport_end) - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_SPORT_END, - g_variant_new_uint16(self->sport_end)); - } - - if (self->dport_start != 0 || self->dport_end != 0) { - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_DPORT_START, - g_variant_new_uint16(self->dport_start)); - if (self->dport_start != self->dport_end) - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_DPORT_END, - g_variant_new_uint16(self->dport_end)); - } - - if (self->from_has || self->from_len != 0) { - _rr_to_dbus_add( - &builder, - RR_DBUS_ATTR_FROM, - g_variant_new_string(self->from_str - ?: nm_utils_inet_ntop(_ip_routing_rule_get_addr_family(self), - &self->from_bin, - addr_str))); - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FROM_LEN, g_variant_new_byte(self->from_len)); - } - - if (self->to_has || self->to_len != 0) { - _rr_to_dbus_add( - &builder, - RR_DBUS_ATTR_TO, - g_variant_new_string(self->to_str - ?: nm_utils_inet_ntop(_ip_routing_rule_get_addr_family(self), - &self->to_bin, - addr_str))); - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TO_LEN, g_variant_new_byte(self->to_len)); - } - - if (self->iifname) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_IIFNAME, g_variant_new_string(self->iifname)); - - if (self->oifname) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_OIFNAME, g_variant_new_string(self->oifname)); - - if (self->action != FR_ACT_TO_TBL) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_ACTION, g_variant_new_byte(self->action)); - - if (self->table != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TABLE, g_variant_new_uint32(self->table)); - - if (self->suppress_prefixlength != -1) - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, - g_variant_new_int32(self->suppress_prefixlength)); - - return g_variant_builder_end(&builder); -} - -/*****************************************************************************/ - -static gboolean -_rr_string_validate(gboolean for_from /* or else to-string */, - NMIPRoutingRuleAsStringFlags to_string_flags, - GHashTable * extra_args, - GError ** error) -{ - if (NM_FLAGS_ANY(to_string_flags, - ~(NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET - | NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 - | NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Unsupported to-string-flags argument")); - return FALSE; - } - - if (extra_args && g_hash_table_size(extra_args) > 0) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Unsupported extra-argument")); - return FALSE; - } - - return TRUE; -} - -static int -_rr_string_addr_family_from_flags(NMIPRoutingRuleAsStringFlags to_string_flags) -{ - if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET)) { - if (!NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6)) - return AF_INET; - } else if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6)) - return AF_INET6; - return AF_UNSPEC; -} - -/** - * nm_ip_routing_rule_from_string: - * @str: the string representation to convert to an #NMIPRoutingRule - * @to_string_flags: #NMIPRoutingRuleAsStringFlags for controlling the - * string conversion. - * @extra_args: (allow-none): extra arguments for controlling the string - * conversion. Currently, not extra arguments are supported. - * @error: (allow-none) (out): the error reason. - * - * Returns: (transfer full): the new #NMIPRoutingRule or %NULL on error. - * - * Since: 1.18 - */ -NMIPRoutingRule * -nm_ip_routing_rule_from_string(const char * str, - NMIPRoutingRuleAsStringFlags to_string_flags, - GHashTable * extra_args, - GError ** error) -{ - nm_auto_unref_ip_routing_rule NMIPRoutingRule *self = NULL; - gs_free const char ** tokens = NULL; - gsize i_token; - gboolean any_words = FALSE; - char * word0 = NULL; - char * word1 = NULL; - char * word_from = NULL; - char * word_to = NULL; - char * word_iifname = NULL; - char * word_oifname = NULL; - gint64 i64_priority = -1; - gint64 i64_table = -1; - gint64 i64_tos = -1; - gint64 i64_fwmark = -1; - gint64 i64_fwmask = -1; - gint64 i64_sport_start = -1; - gint64 i64_ipproto = -1; - gint64 i64_suppress_prefixlength = -1; - guint16 sport_end = 0; - gint64 i64_dport_start = -1; - guint16 dport_end = 0; - gboolean val_invert = FALSE; - int addr_family = AF_UNSPEC; - NMIPAddr val_from = {}; - NMIPAddr val_to = {}; - int val_from_len = -1; - int val_to_len = -1; - char * s; - - g_return_val_if_fail(str, NULL); - - if (!_rr_string_validate(TRUE, to_string_flags, extra_args, error)) - return NULL; - - /* NM_IP_ROUTING_RULE_TO_STRING_TYPE_IPROUTE gives a string representation that is - * partly compatibly with iproute2. That is, the part after `ip -[46] rule add $ARGS`. - * There are differences though: - * - * - trying to convert an invalid rule to string may not be possible. The reason is for - * example that an invalid rule can have nm_ip_routing_rule_get_from() like "bogus", - * but we don't write that as "from bogus". In general, if you try to convert an invalid - * rule to string, the operation may fail or the result may itself not be parsable. - * Of course, valid rules can be converted to string and read back the same (round-trip). - * - * - iproute2 in may regards is flexible about the command lines. For example - * - for tables it accepts table names from /etc/iproute2/rt_tables. We only - * accept the special aliases "main", "local", and "default". - * - key names like "preference" can be abbreviated to "pref", we don't do that. - * - the "preference"/"priority" may be unspecified, in which kernel automatically - * chooses an unused priority (during `ip rule add`). We don't allow for that, the - * priority must be explicitly set. - * - * - iproute2 does not support any escaping. Well, it's the shell that supports quoting - * and escaping and splits the command line. We need to split the command line ourself, - * but we don't support full shell quotation. - * from-string tokenizes words at (ASCII) whitespaces (removing the whitespaces). - * It also supports backslash escaping (e.g. to contain whitespace), but it does - * not support special escape sequences. Values are taken literally, meaning - * "\n\ \111" gives results in "n 111". - * The strings really shouldn't contain any special characters that require escaping, - * but that's the rule. - * This also goes together with the @allow_escaping parameter of nm_utils_strsplit_set(). - * If you concatenate multiple rule expressions with a delimiter, the delimiter inside - * each word can be backslash escaped, and nm_utils_strsplit_set(allow_escaping=TRUE) will - * properly split the words, preserving the backslashes, which then will be removed by - * nm_ip_routing_rule_from_string(). - */ - - addr_family = _rr_string_addr_family_from_flags(to_string_flags); - - tokens = nm_utils_escaped_tokens_split(str, NM_ASCII_SPACES); - for (i_token = 0; tokens && tokens[i_token]; i_token++) { - char *str_word = (char *) tokens[i_token]; - - any_words = TRUE; - if (!word0) - word0 = str_word; - else { - nm_assert(!word1); - word1 = str_word; - } - - /* iproute2 matches keywords with any partial prefix. We don't allow - * for that flexibility. */ - - if (NM_IN_STRSET(word0, "from")) { - if (!word1) - continue; - if (word_from) - goto next_fail_word0_duplicate_key; - word_from = word1; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "to")) { - if (!word1) - continue; - if (word_to) - goto next_fail_word0_duplicate_key; - word_to = word1; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "not")) { - /* we accept multiple "not" specifiers. "not not" still means - * not. */ - val_invert = TRUE; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "priority", "order", "pref", "preference")) { - if (!word1) - continue; - if (i64_priority != -1) - goto next_fail_word0_duplicate_key; - i64_priority = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXUINT32, -1); - if (i64_priority == -1) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "table", "lookup")) { - if (!word1) - continue; - if (i64_table != -1) - goto next_fail_word0_duplicate_key; - i64_table = _nm_utils_ascii_str_to_int64(word1, 0, 1, G_MAXUINT32, -1); - if (i64_table == -1) { - if (nm_streq(word1, "main")) - i64_table = RT_TABLE_MAIN; - else if (nm_streq(word1, "local")) - i64_table = RT_TABLE_LOCAL; - else if (nm_streq(word1, "default")) - i64_table = RT_TABLE_DEFAULT; - else - goto next_fail_word1_invalid_value; - } - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "tos", "dsfield")) { - if (!word1) - continue; - if (i64_tos != -1) - goto next_fail_word0_duplicate_key; - i64_tos = _nm_utils_ascii_str_to_int64(word1, 16, 0, G_MAXUINT8, -1); - if (i64_tos == -1) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "ipproto")) { - if (!word1) - continue; - if (i64_ipproto != -1) - goto next_fail_word0_duplicate_key; - i64_ipproto = _nm_utils_ascii_str_to_int64(word1, 10, 0, G_MAXUINT8, -1); - if (i64_ipproto == -1) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "sport")) { - if (!word1) - continue; - if (i64_sport_start != -1) - goto next_fail_word0_duplicate_key; - if (!_rr_xport_range_parse(word1, &i64_sport_start, &sport_end)) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "dport")) { - if (!word1) - continue; - if (i64_dport_start != -1) - goto next_fail_word0_duplicate_key; - if (!_rr_xport_range_parse(word1, &i64_dport_start, &dport_end)) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "fwmark")) { - if (!word1) - continue; - if (i64_fwmark != -1) - goto next_fail_word0_duplicate_key; - s = strchr(word1, '/'); - if (s) - *(s++) = '\0'; - i64_fwmark = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXUINT32, -1); - if (i64_fwmark == -1) - goto next_fail_word1_invalid_value; - if (s) { - i64_fwmask = _nm_utils_ascii_str_to_int64(s, 0, 0, G_MAXUINT32, -1); - if (i64_fwmask == -1) - goto next_fail_word1_invalid_value; - } else - i64_fwmask = 0xFFFFFFFFu; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "iif", "dev")) { - if (!word1) - continue; - if (word_iifname) - goto next_fail_word0_duplicate_key; - word_iifname = word1; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "oif")) { - if (!word1) - continue; - if (word_oifname) - goto next_fail_word0_duplicate_key; - word_oifname = word1; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "suppress_prefixlength", "sup_pl")) { - if (!word1) - continue; - if (i64_suppress_prefixlength != -1) - goto next_fail_word0_duplicate_key; - i64_suppress_prefixlength = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXINT32, -1); - if (i64_suppress_prefixlength == -1) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - - /* also the action is still unsupported. For the moment, we only support - * FR_ACT_TO_TBL, which is the default (by not expressing it on the command - * line). */ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unsupported key \"%s\""), - word0); - return FALSE; -next_fail_word0_duplicate_key: - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("duplicate key \"%s\""), - word0); - return FALSE; -next_fail_word1_invalid_value: - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid value for \"%s\""), - word0); - return FALSE; -next_words_consumed: - word0 = NULL; - word1 = NULL; - } - - if (!any_words) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("empty text does not describe a rule")); - return FALSE; - } - - if (word0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("missing argument for \"%s\""), - word0); - return FALSE; - } - - if (!NM_IN_STRSET(word_from, NULL, "all")) { - if (!nm_utils_parse_inaddr_prefix_bin(addr_family, - word_from, - &addr_family, - &val_from, - &val_from_len)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid \"from\" part")); - return FALSE; - } - if (val_from_len == -1) - val_from_len = nm_utils_addr_family_to_size(addr_family) * 8; - } - - if (!NM_IN_STRSET(word_to, NULL, "all")) { - if (!nm_utils_parse_inaddr_prefix_bin(addr_family, - word_to, - &addr_family, - &val_to, - &val_to_len)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid \"to\" part")); - return FALSE; - } - if (val_to_len == -1) - val_to_len = nm_utils_addr_family_to_size(addr_family) * 8; - } - - if (!NM_IN_SET(addr_family, AF_INET, AF_INET6)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("cannot detect address family for rule")); - return FALSE; - } - - self = nm_ip_routing_rule_new(addr_family); - - if (val_invert) - self->invert = TRUE; - - if (i64_priority != -1) - nm_ip_routing_rule_set_priority(self, i64_priority); - - if (i64_tos != -1) - nm_ip_routing_rule_set_tos(self, i64_tos); - - if (i64_ipproto != -1) - nm_ip_routing_rule_set_ipproto(self, i64_ipproto); - - if (i64_fwmark != -1) - nm_ip_routing_rule_set_fwmark(self, i64_fwmark, i64_fwmask); - - if (i64_sport_start != -1) - nm_ip_routing_rule_set_source_port(self, i64_sport_start, sport_end); - - if (i64_dport_start != -1) - nm_ip_routing_rule_set_destination_port(self, i64_dport_start, dport_end); - - if (i64_suppress_prefixlength != -1) - nm_ip_routing_rule_set_suppress_prefixlength(self, i64_suppress_prefixlength); - - if (val_from_len > 0 || (val_from_len == 0 && !nm_ip_addr_is_null(addr_family, &val_from))) { - nm_ip_routing_rule_set_from_bin(self, &val_from, val_from_len); - } - - if (val_to_len > 0 || (val_to_len == 0 && !nm_ip_addr_is_null(addr_family, &val_to))) { - nm_ip_routing_rule_set_to_bin(self, &val_to, val_to_len); - } - - if (word_iifname) - nm_ip_routing_rule_set_iifname(self, word_iifname); - - if (word_oifname) - nm_ip_routing_rule_set_oifname(self, word_oifname); - - if (i64_table != -1) - nm_ip_routing_rule_set_table(self, i64_table); - - if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE)) { - gs_free_error GError *local = NULL; - - if (!nm_ip_routing_rule_validate(self, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("rule is invalid: %s"), - local->message); - return NULL; - } - } - - return g_steal_pointer(&self); -} - -static void -_rr_string_append_inet_addr(NMStrBuf * str, - gboolean is_from /* or else is-to */, - gboolean required, - int addr_family, - const NMIPAddr *addr_bin, - guint8 addr_len) -{ - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - - if (addr_len == 0) { - if (required) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(str, ' '), - "%s %s/0", - is_from ? "from" : "to", - (addr_family == AF_INET) ? "0.0.0.0" : "::"); - } - return; - } - - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(str, ' '), - "%s %s", - is_from ? "from" : "to", - nm_utils_inet_ntop(addr_family, addr_bin, addr_str)); - if (addr_len != nm_utils_addr_family_to_size(addr_family) * 8) { - nm_str_buf_append_printf(str, "/%u", addr_len); - } -} - -/** - * nm_ip_routing_rule_to_string: - * @self: the #NMIPRoutingRule instance to convert to string. - * @to_string_flags: #NMIPRoutingRuleAsStringFlags for controlling the - * string conversion. - * @extra_args: (allow-none): extra arguments for controlling the string - * conversion. Currently, not extra arguments are supported. - * @error: (allow-none) (out): the error reason. - * - * Returns: (transfer full): the string representation or %NULL on error. - * - * Since: 1.18 - */ -char * -nm_ip_routing_rule_to_string(const NMIPRoutingRule * self, - NMIPRoutingRuleAsStringFlags to_string_flags, - GHashTable * extra_args, - GError ** error) -{ - int addr_family; - NMStrBuf str; - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - if (!_rr_string_validate(FALSE, to_string_flags, extra_args, error)) - return NULL; - - addr_family = nm_ip_routing_rule_get_addr_family(self); - - if (!NM_IN_SET(_rr_string_addr_family_from_flags(to_string_flags), AF_UNSPEC, addr_family)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid address family")); - return NULL; - } - - /* It is only guaranteed that valid rules can be expressed as string. - * - * Still, unless requested proceed to convert to string without validating and - * hope for the best. - * - * That is, because self->from_str might contain an invalid IP address (indicated - * by self->from_valid). But we don't support serializing such arbitrary strings - * as "from %s". */ - if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE)) { - gs_free_error GError *local = NULL; - - if (!nm_ip_routing_rule_validate(self, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("rule is invalid: %s"), - local->message); - return NULL; - } - } - - nm_str_buf_init(&str, NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE); - - if (self->priority_has) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "priority %u", - (guint) self->priority); - } - - if (self->invert) - nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "not"); - - _rr_string_append_inet_addr(&str, - TRUE, - (!self->to_has || !self->to_valid), - addr_family, - &self->from_bin, - (self->from_has && self->from_valid) ? self->from_len : 0); - - _rr_string_append_inet_addr(&str, - FALSE, - FALSE, - addr_family, - &self->to_bin, - (self->to_has && self->to_valid) ? self->to_len : 0); - - if (self->tos != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "tos 0x%02x", - (guint) self->tos); - } - - if (self->ipproto != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "ipproto %u", - (guint) self->ipproto); - } - - if (self->fwmark != 0 || self->fwmask != 0) { - if (self->fwmark != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "fwmark 0x%x", - self->fwmark); - } else { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), "fwmark 0"); - } - if (self->fwmask != 0xFFFFFFFFu) { - if (self->fwmask != 0) - nm_str_buf_append_printf(&str, "/0x%x", self->fwmask); - else - nm_str_buf_append_printf(&str, "/0"); - } - } - - if (self->sport_start != 0 || self->sport_end != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "sport %u", - self->sport_start); - if (self->sport_start != self->sport_end) { - nm_str_buf_append_printf(&str, "-%u", self->sport_end); - } - } - - if (self->dport_start != 0 || self->dport_end != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "dport %u", - self->dport_start); - if (self->dport_start != self->dport_end) { - nm_str_buf_append_printf(&str, "-%u", self->dport_end); - } - } - - if (self->iifname) { - nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "iif "); - nm_utils_escaped_tokens_escape_strbuf(self->iifname, NM_ASCII_SPACES, &str); - } - - if (self->oifname) { - nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "oif "); - nm_utils_escaped_tokens_escape_strbuf(self->oifname, NM_ASCII_SPACES, &str); - } - - if (self->table != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "table %u", - (guint) self->table); - } - - if (self->suppress_prefixlength != -1) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "suppress_prefixlength %d", - (int) self->suppress_prefixlength); - } - - return nm_str_buf_finalize(&str, NULL); -} - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingIPConfig, - PROP_METHOD, - PROP_DNS, - PROP_DNS_SEARCH, - PROP_DNS_OPTIONS, - PROP_DNS_PRIORITY, - PROP_ADDRESSES, - PROP_GATEWAY, - PROP_ROUTES, - PROP_ROUTE_METRIC, - PROP_ROUTE_TABLE, - PROP_IGNORE_AUTO_ROUTES, - PROP_IGNORE_AUTO_DNS, - PROP_DHCP_HOSTNAME, - PROP_DHCP_HOSTNAME_FLAGS, - PROP_DHCP_SEND_HOSTNAME, - PROP_NEVER_DEFAULT, - PROP_MAY_FAIL, - PROP_DAD_TIMEOUT, - PROP_DHCP_TIMEOUT, - PROP_DHCP_IAID, - PROP_DHCP_REJECT_SERVERS, ); - -typedef struct { - GPtrArray *dns; /* array of IP address strings */ - GPtrArray *dns_search; /* array of domain name strings */ - GPtrArray *dns_options; /* array of DNS options */ - GPtrArray *addresses; /* array of NMIPAddress */ - GPtrArray *routes; /* array of NMIPRoute */ - GPtrArray *routing_rules; - GArray * dhcp_reject_servers; - char * method; - char * gateway; - char * dhcp_hostname; - char * dhcp_iaid; - gint64 route_metric; - guint dhcp_hostname_flags; - int dns_priority; - int dad_timeout; - int dhcp_timeout; - guint32 route_table; - bool ignore_auto_routes : 1; - bool ignore_auto_dns : 1; - bool dhcp_send_hostname : 1; - bool never_default : 1; - bool may_fail : 1; -} NMSettingIPConfigPrivate; - -G_DEFINE_ABSTRACT_TYPE(NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING) - -#define NM_SETTING_IP_CONFIG_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfigPrivate)) - -/*****************************************************************************/ - -#define NM_SETTING_IP_CONFIG_GET_FAMILY(setting) \ - (NM_IS_SETTING_IP4_CONFIG(setting) ? AF_INET : AF_INET6) - -/** - * nm_setting_ip_config_get_method: - * @setting: the #NMSettingIPConfig - * - * Returns: the #NMSettingIPConfig:method property of the setting; see - * #NMSettingIP4Config and #NMSettingIP6Config for details of the - * methods available with each type. - **/ -const char * -nm_setting_ip_config_get_method(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->method; -} - -/** - * nm_setting_ip_config_get_num_dns: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured DNS servers - **/ -guint -nm_setting_ip_config_get_num_dns(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns->len; -} - -/** - * nm_setting_ip_config_get_dns: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS server to return - * - * Returns: the IP address of the DNS server at index @idx - **/ -const char * -nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->dns->len, NULL); - - return priv->dns->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_dns: - * @setting: the #NMSettingIPConfig - * @dns: the IP address of the DNS server to add - * - * Adds a new DNS server to the setting. - * - * Returns: %TRUE if the DNS server was added; %FALSE if the server was already - * known - **/ -gboolean -nm_setting_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns) -{ - NMSettingIPConfigPrivate *priv; - char * dns_canonical; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns != NULL, FALSE); - g_return_val_if_fail(nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns), - FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - dns_canonical = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns, FALSE); - for (i = 0; i < priv->dns->len; i++) { - if (!strcmp(dns_canonical, priv->dns->pdata[i])) { - g_free(dns_canonical); - return FALSE; - } - } - - g_ptr_array_add(priv->dns, dns_canonical); - _notify(setting, PROP_DNS); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_dns: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS server to remove - * - * Removes the DNS server at index @idx. - **/ -void -nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->dns->len); - - g_ptr_array_remove_index(priv->dns, idx); - _notify(setting, PROP_DNS); -} - -/** - * nm_setting_ip_config_remove_dns_by_value: - * @setting: the #NMSettingIPConfig - * @dns: the DNS server to remove - * - * Removes the DNS server @dns. - * - * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char *dns) -{ - NMSettingIPConfigPrivate *priv; - char * dns_canonical; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns != NULL, FALSE); - g_return_val_if_fail(nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns), - FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - dns_canonical = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns, FALSE); - for (i = 0; i < priv->dns->len; i++) { - if (!strcmp(dns_canonical, priv->dns->pdata[i])) { - g_ptr_array_remove_index(priv->dns, i); - _notify(setting, PROP_DNS); - g_free(dns_canonical); - return TRUE; - } - } - g_free(dns_canonical); - return FALSE; -} - -/** - * nm_setting_ip_config_clear_dns: - * @setting: the #NMSettingIPConfig - * - * Removes all configured DNS servers. - **/ -void -nm_setting_ip_config_clear_dns(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - if (priv->dns->len != 0) { - g_ptr_array_set_size(priv->dns, 0); - _notify(setting, PROP_DNS); - } -} - -/** - * nm_setting_ip_config_get_num_dns_searches: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured DNS search domains - **/ -guint -nm_setting_ip_config_get_num_dns_searches(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_search->len; -} - -/** - * nm_setting_ip_config_get_dns_search: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS search domain to return - * - * Returns: the DNS search domain at index @idx - **/ -const char * -nm_setting_ip_config_get_dns_search(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->dns_search->len, NULL); - - return priv->dns_search->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_dns_search: - * @setting: the #NMSettingIPConfig - * @dns_search: the search domain to add - * - * Adds a new DNS search domain to the setting. - * - * Returns: %TRUE if the DNS search domain was added; %FALSE if the search - * domain was already known - **/ -gboolean -nm_setting_ip_config_add_dns_search(NMSettingIPConfig *setting, const char *dns_search) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns_search != NULL, FALSE); - g_return_val_if_fail(dns_search[0] != '\0', FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->dns_search->len; i++) { - if (!strcmp(dns_search, priv->dns_search->pdata[i])) - return FALSE; - } - - g_ptr_array_add(priv->dns_search, g_strdup(dns_search)); - _notify(setting, PROP_DNS_SEARCH); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_dns_search: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS search domain - * - * Removes the DNS search domain at index @idx. - **/ -void -nm_setting_ip_config_remove_dns_search(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->dns_search->len); - - g_ptr_array_remove_index(priv->dns_search, idx); - _notify(setting, PROP_DNS_SEARCH); -} - -/** - * nm_setting_ip_config_remove_dns_search_by_value: - * @setting: the #NMSettingIPConfig - * @dns_search: the search domain to remove - * - * Removes the DNS search domain @dns_search. - * - * Returns: %TRUE if the DNS search domain was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_ip_config_remove_dns_search_by_value(NMSettingIPConfig *setting, const char *dns_search) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns_search != NULL, FALSE); - g_return_val_if_fail(dns_search[0] != '\0', FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->dns_search->len; i++) { - if (!strcmp(dns_search, priv->dns_search->pdata[i])) { - g_ptr_array_remove_index(priv->dns_search, i); - _notify(setting, PROP_DNS_SEARCH); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_ip_config_clear_dns_searches: - * @setting: the #NMSettingIPConfig - * - * Removes all configured DNS search domains. - **/ -void -nm_setting_ip_config_clear_dns_searches(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - if (priv->dns_search->len != 0) { - g_ptr_array_set_size(priv->dns_search, 0); - _notify(setting, PROP_DNS_SEARCH); - } -} - -/** - * nm_setting_ip_config_get_num_dns_options: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured DNS options - * - * Since: 1.2 - **/ -guint -nm_setting_ip_config_get_num_dns_options(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - return priv->dns_options ? priv->dns_options->len : 0; -} - -/** - * nm_setting_ip_config_has_dns_options: - * @setting: the #NMSettingIPConfig - * - * NMSettingIPConfig can have a list of dns-options. If the list - * is empty, there are two similar (but differentiated) states. - * Either the options are explicitly set to have no values, - * or the options are left undefined. The latter means to use - * a default configuration, while the former explicitly means "no-options". - * - * Returns: whether DNS options are initialized or left unset (the default). - **/ -gboolean -nm_setting_ip_config_has_dns_options(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return !!NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_options; -} - -/** - * nm_setting_ip_config_get_dns_option: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS option - * - * Returns: the DNS option at index @idx - * - * Since: 1.2 - **/ -const char * -nm_setting_ip_config_get_dns_option(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(priv->dns_options, NULL); - g_return_val_if_fail(idx < priv->dns_options->len, NULL); - - return priv->dns_options->pdata[idx]; -} - -/** - * nm_setting_ip_config_next_valid_dns_option: - * @setting: the #NMSettingIPConfig - * @idx: index to start the search from - * - * Returns: the index, greater or equal than @idx, of the first valid - * DNS option, or -1 if no valid option is found - **/ -int -nm_setting_ip_config_next_valid_dns_option(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), -1); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - if (!priv->dns_options) - return -1; - - for (; idx < priv->dns_options->len; idx++) { - if (_nm_utils_dns_option_validate(priv->dns_options->pdata[idx], - NULL, - NULL, - NM_IS_SETTING_IP6_CONFIG(setting), - _nm_utils_dns_option_descs)) - return idx; - } - - return -1; -} - -/** - * nm_setting_ip_config_add_dns_option: - * @setting: the #NMSettingIPConfig - * @dns_option: the DNS option to add - * - * Adds a new DNS option to the setting. - * - * Returns: %TRUE if the DNS option was added; %FALSE otherwise - * - * Since: 1.2 - **/ -gboolean -nm_setting_ip_config_add_dns_option(NMSettingIPConfig *setting, const char *dns_option) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns_option != NULL, FALSE); - g_return_val_if_fail(dns_option[0] != '\0', FALSE); - - if (!_nm_utils_dns_option_validate(dns_option, NULL, NULL, FALSE, NULL)) - return FALSE; - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (!priv->dns_options) - priv->dns_options = g_ptr_array_new_with_free_func(g_free); - else { - if (_nm_utils_dns_option_find_idx(priv->dns_options, dns_option) >= 0) - return FALSE; - } - - g_ptr_array_add(priv->dns_options, g_strdup(dns_option)); - _notify(setting, PROP_DNS_OPTIONS); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_dns_option: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS option - * - * Removes the DNS option at index @idx. - * - * Since: 1.2 - **/ -void -nm_setting_ip_config_remove_dns_option(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(priv->dns_options); - g_return_if_fail(idx >= 0 && idx < priv->dns_options->len); - - g_ptr_array_remove_index(priv->dns_options, idx); - _notify(setting, PROP_DNS_OPTIONS); -} - -/** - * nm_setting_ip_config_remove_dns_option_by_value: - * @setting: the #NMSettingIPConfig - * @dns_option: the DNS option to remove - * - * Removes the DNS option @dns_option. - * - * Returns: %TRUE if the DNS option was found and removed; %FALSE if it was not. - * - * Since: 1.2 - **/ -gboolean -nm_setting_ip_config_remove_dns_option_by_value(NMSettingIPConfig *setting, const char *dns_option) -{ - NMSettingIPConfigPrivate *priv; - gssize i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns_option != NULL, FALSE); - g_return_val_if_fail(dns_option[0] != '\0', FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (!priv->dns_options) - return FALSE; - - i = _nm_utils_dns_option_find_idx(priv->dns_options, dns_option); - if (i >= 0) { - g_ptr_array_remove_index(priv->dns_options, i); - _notify(setting, PROP_DNS_OPTIONS); - return TRUE; - } - - return FALSE; -} - -/** - * nm_setting_ip_config_clear_dns_options: - * @setting: the #NMSettingIPConfig - * @is_set: the dns-options can be either empty or unset (default). - * Specify how to clear the options. - * - * Removes all configured DNS options. - * - * Since: 1.2 - **/ -void -nm_setting_ip_config_clear_dns_options(NMSettingIPConfig *setting, gboolean is_set) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (!priv->dns_options) { - if (!is_set) - return; - priv->dns_options = g_ptr_array_new_with_free_func(g_free); - } else { - if (!is_set) { - g_ptr_array_unref(priv->dns_options); - priv->dns_options = NULL; - } else { - if (priv->dns_options->len == 0) - return; - g_ptr_array_set_size(priv->dns_options, 0); - } - } - _notify(setting, PROP_DNS_OPTIONS); -} - -/** - * nm_setting_ip_config_get_dns_priority: - * @setting: the #NMSettingIPConfig - * - * Returns: the priority of DNS servers - * - * Since: 1.4 - **/ -int -nm_setting_ip_config_get_dns_priority(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_priority; -} - -/** - * nm_setting_ip_config_get_num_addresses: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured addresses - **/ -guint -nm_setting_ip_config_get_num_addresses(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->addresses->len; -} - -/** - * nm_setting_ip_config_get_address: - * @setting: the #NMSettingIPConfig - * @idx: index number of the address to return - * - * Returns: (transfer none): the address at index @idx - **/ -NMIPAddress * -nm_setting_ip_config_get_address(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->addresses->len, NULL); - - return priv->addresses->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_address: - * @setting: the #NMSettingIPConfig - * @address: the new address to add - * - * Adds a new IP address and associated information to the setting. The - * given address is duplicated internally and is not changed by this function. - * - * Returns: %TRUE if the address was added; %FALSE if the address was already - * known. - **/ -gboolean -nm_setting_ip_config_add_address(NMSettingIPConfig *setting, NMIPAddress *address) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(address != NULL, FALSE); - g_return_val_if_fail(address->family == NM_SETTING_IP_CONFIG_GET_FAMILY(setting), FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->addresses->len; i++) { - if (nm_ip_address_equal(priv->addresses->pdata[i], address)) - return FALSE; - } - - g_ptr_array_add(priv->addresses, nm_ip_address_dup(address)); - - _notify(setting, PROP_ADDRESSES); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_address: - * @setting: the #NMSettingIPConfig - * @idx: index number of the address to remove - * - * Removes the address at index @idx. - **/ -void -nm_setting_ip_config_remove_address(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->addresses->len); - - g_ptr_array_remove_index(priv->addresses, idx); - - _notify(setting, PROP_ADDRESSES); -} - -/** - * nm_setting_ip_config_remove_address_by_value: - * @setting: the #NMSettingIPConfig - * @address: the IP address to remove - * - * Removes the address @address. - * - * Returns: %TRUE if the address was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_ip_config_remove_address_by_value(NMSettingIPConfig *setting, NMIPAddress *address) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(address != NULL, FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->addresses->len; i++) { - if (nm_ip_address_equal(priv->addresses->pdata[i], address)) { - g_ptr_array_remove_index(priv->addresses, i); - _notify(setting, PROP_ADDRESSES); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_ip_config_clear_addresses: - * @setting: the #NMSettingIPConfig - * - * Removes all configured addresses. - **/ -void -nm_setting_ip_config_clear_addresses(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - if (priv->addresses->len != 0) { - g_ptr_array_set_size(priv->addresses, 0); - _notify(setting, PROP_ADDRESSES); - } -} - -/** - * nm_setting_ip_config_get_gateway: - * @setting: the #NMSettingIPConfig - * - * Returns: the IP address of the gateway associated with this configuration, or - * %NULL. - **/ -const char * -nm_setting_ip_config_get_gateway(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->gateway; -} - -/** - * nm_setting_ip_config_get_num_routes: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured routes - **/ -guint -nm_setting_ip_config_get_num_routes(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->routes->len; -} - -/** - * nm_setting_ip_config_get_route: - * @setting: the #NMSettingIPConfig - * @idx: index number of the route to return - * - * Returns: (transfer none): the route at index @idx - **/ -NMIPRoute * -nm_setting_ip_config_get_route(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->routes->len, NULL); - - return priv->routes->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_route: - * @setting: the #NMSettingIPConfig - * @route: the route to add - * - * Appends a new route and associated information to the setting. The - * given route is duplicated internally and is not changed by this function. - * If an identical route (considering attributes as well) already exists, the - * route is not added and the function returns %FALSE. - * - * Note that before 1.10, this function would not consider route attributes - * and not add a route that has an existing route with same dest/prefix,next_hop,metric - * parameters. - * - * Returns: %TRUE if the route was added; %FALSE if the route was already known. - **/ -gboolean -nm_setting_ip_config_add_route(NMSettingIPConfig *setting, NMIPRoute *route) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(route != NULL, FALSE); - g_return_val_if_fail(route->family == NM_SETTING_IP_CONFIG_GET_FAMILY(setting), FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->routes->len; i++) { - if (nm_ip_route_equal_full(priv->routes->pdata[i], - route, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) - return FALSE; - } - - g_ptr_array_add(priv->routes, nm_ip_route_dup(route)); - _notify(setting, PROP_ROUTES); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_route: - * @setting: the #NMSettingIPConfig - * @idx: index number of the route - * - * Removes the route at index @idx. - **/ -void -nm_setting_ip_config_remove_route(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->routes->len); - - g_ptr_array_remove_index(priv->routes, idx); - _notify(setting, PROP_ROUTES); -} - -/** - * nm_setting_ip_config_remove_route_by_value: - * @setting: the #NMSettingIPConfig - * @route: the route to remove - * - * Removes the first matching route that matches @route. - * Note that before 1.10, this function would only compare dest/prefix,next_hop,metric - * and ignore route attributes. Now, @route must match exactly. - * - * Returns: %TRUE if the route was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_ip_config_remove_route_by_value(NMSettingIPConfig *setting, NMIPRoute *route) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(route != NULL, FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->routes->len; i++) { - if (nm_ip_route_equal_full(priv->routes->pdata[i], - route, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) { - g_ptr_array_remove_index(priv->routes, i); - _notify(setting, PROP_ROUTES); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_ip_config_clear_routes: - * @setting: the #NMSettingIPConfig - * - * Removes all configured routes. - **/ -void -nm_setting_ip_config_clear_routes(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - if (priv->routes->len != 0) { - g_ptr_array_set_size(priv->routes, 0); - _notify(setting, PROP_ROUTES); - } -} - -/** - * nm_setting_ip_config_get_route_metric: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:route-metric - * property. - * - * Returns: the route metric that is used for routes that don't explicitly - * specify a metric. See #NMSettingIPConfig:route-metric for more details. - **/ -gint64 -nm_setting_ip_config_get_route_metric(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), -1); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->route_metric; -} - -/** - * nm_setting_ip_config_get_route_table: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:route-table - * property. - * - * Returns: the configured route-table. - * - * Since: 1.10 - **/ -guint32 -nm_setting_ip_config_get_route_table(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->route_table; -} - -/*****************************************************************************/ - -static void -_routing_rules_notify(NMSettingIPConfig *setting) -{ - _nm_setting_emit_property_changed(NM_SETTING(setting)); -} - -/** - * nm_setting_ip_config_get_num_routing_rules: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured routing rules - * - * Since: 1.18 - **/ -guint -nm_setting_ip_config_get_num_routing_rules(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - return priv->routing_rules ? priv->routing_rules->len : 0u; -} - -/** - * nm_setting_ip_config_get_routing_rule: - * @setting: the #NMSettingIPConfig - * @idx: index number of the routing_rule to return - * - * Returns: (transfer none): the routing rule at index @idx - * - * Since: 1.18 - **/ -NMIPRoutingRule * -nm_setting_ip_config_get_routing_rule(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - g_return_val_if_fail(priv->routing_rules && idx < priv->routing_rules->len, NULL); - - return priv->routing_rules->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_routing_rule: - * @setting: the #NMSettingIPConfig - * @routing_rule: the #NMIPRoutingRule to add. The address family - * of the added rule must be compatible with the setting. - * - * Appends a new routing-rule and associated information to the setting. The - * given routing rules gets sealed and the reference count is incremented. - * The function does not check whether an identical rule already exists - * and always appends the rule to the end of the list. - * - * Since: 1.18 - **/ -void -nm_setting_ip_config_add_routing_rule(NMSettingIPConfig *setting, NMIPRoutingRule *routing_rule) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - g_return_if_fail(NM_IS_IP_ROUTING_RULE(routing_rule, TRUE)); - g_return_if_fail(_ip_routing_rule_get_addr_family(routing_rule) - == NM_SETTING_IP_CONFIG_GET_FAMILY(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - if (!priv->routing_rules) - priv->routing_rules = - g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); - - nm_ip_routing_rule_seal(routing_rule); - g_ptr_array_add(priv->routing_rules, nm_ip_routing_rule_ref(routing_rule)); - _routing_rules_notify(setting); -} - -/** - * nm_setting_ip_config_remove_routing_rule: - * @setting: the #NMSettingIPConfig - * @idx: index number of the routing_rule - * - * Removes the routing_rule at index @idx. - * - * Since: 1.18 - **/ -void -nm_setting_ip_config_remove_routing_rule(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(priv->routing_rules && idx < priv->routing_rules->len); - - g_ptr_array_remove_index(priv->routing_rules, idx); - _routing_rules_notify(setting); -} - -/** - * nm_setting_ip_config_clear_routing_rules: - * @setting: the #NMSettingIPConfig - * - * Removes all configured routing rules. - * - * Since: 1.18 - **/ -void -nm_setting_ip_config_clear_routing_rules(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - if (priv->routing_rules && priv->routing_rules->len > 0) { - g_ptr_array_set_size(priv->routing_rules, 0); - _routing_rules_notify(setting); - } -} - -static GVariant * -_routing_rules_dbus_only_synth(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMSettingIPConfig * self = NM_SETTING_IP_CONFIG(setting); - NMSettingIPConfigPrivate *priv; - GVariantBuilder builder; - gboolean any = FALSE; - guint i; - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(self); - - if (!priv->routing_rules || priv->routing_rules->len == 0) - return NULL; - - for (i = 0; i < priv->routing_rules->len; i++) { - GVariant *variant; - - variant = nm_ip_routing_rule_to_dbus(priv->routing_rules->pdata[i]); - if (!variant) - continue; - - if (!any) { - any = TRUE; - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - } - g_variant_builder_add(&builder, "@a{sv}", variant); - } - - return any ? g_variant_builder_end(&builder) : NULL; -} - -static gboolean -_routing_rules_dbus_only_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GVariantIter iter_rules; - GVariant * rule_var; - guint i_rule; - gboolean success = FALSE; - gboolean rules_changed = FALSE; - - nm_assert(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}"))); - - g_variant_iter_init(&iter_rules, value); - - i_rule = 0; - while (g_variant_iter_next(&iter_rules, "@a{sv}", &rule_var)) { - _nm_unused gs_unref_variant GVariant *rule_var_unref = rule_var; - nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL; - gs_free_error GError *local = NULL; - - i_rule++; - - rule = - nm_ip_routing_rule_from_dbus(rule_var, - NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT), - &local); - if (!rule) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("rule #%u is invalid: %s"), - i_rule, - local->message); - goto out; - } - continue; - } - - nm_setting_ip_config_add_routing_rule(NM_SETTING_IP_CONFIG(setting), rule); - rules_changed = TRUE; - } - - success = TRUE; - -out: - if (rules_changed) - _routing_rules_notify(NM_SETTING_IP_CONFIG(setting)); - return success; -} - -/*****************************************************************************/ - -/** - * nm_setting_ip_config_get_ignore_auto_routes: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:ignore-auto-routes - * property. - * - * Returns: %TRUE if automatically configured (ie via DHCP) routes should be - * ignored. - **/ -gboolean -nm_setting_ip_config_get_ignore_auto_routes(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->ignore_auto_routes; -} - -/** - * nm_setting_ip_config_get_ignore_auto_dns: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:ignore-auto-dns - * property. - * - * Returns: %TRUE if automatically configured (ie via DHCP) DNS information - * should be ignored. - **/ -gboolean -nm_setting_ip_config_get_ignore_auto_dns(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->ignore_auto_dns; -} - -/** - * nm_setting_ip_config_get_dhcp_hostname: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-hostname - * property. - * - * Returns: the configured hostname to send to the DHCP server - **/ -const char * -nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_hostname; -} - -/** - * nm_setting_ip_config_get_dhcp_send_hostname: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-send-hostname - * property. - * - * Returns: %TRUE if NetworkManager should send the machine hostname to the - * DHCP server when requesting addresses to allow the server to automatically - * update DNS information for this machine. - **/ -gboolean -nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_send_hostname; -} - -/** - * nm_setting_ip_config_get_never_default: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:never-default - * property. - * - * Returns: %TRUE if this connection should never be the default - * connection - **/ -gboolean -nm_setting_ip_config_get_never_default(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->never_default; -} - -/** - * nm_setting_ip_config_get_may_fail: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:may-fail - * property. - * - * Returns: %TRUE if this connection doesn't require this type of IP - * addressing to complete for the connection to succeed. - **/ -gboolean -nm_setting_ip_config_get_may_fail(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->may_fail; -} - -/** - * nm_setting_ip_config_get_dad_timeout: - * @setting: the #NMSettingIPConfig - * - * Returns: the #NMSettingIPConfig:dad-timeout property. - * - * Since: 1.2 - **/ -int -nm_setting_ip_config_get_dad_timeout(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dad_timeout; -} - -/** - * nm_setting_ip_config_get_dhcp_hostname_flags: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-hostname-flags - * property. - * - * Returns: flags for the DHCP hostname and FQDN - * - * Since: 1.22 - */ -NMDhcpHostnameFlags -nm_setting_ip_config_get_dhcp_hostname_flags(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NM_DHCP_HOSTNAME_FLAG_NONE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_hostname_flags; -} - -/** - * nm_setting_ip_config_get_dhcp_timeout: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-timeout - * property. - * - * Returns: the configured DHCP timeout in seconds. 0 = default for - * the particular kind of device. - * - * Since: 1.2 - **/ -int -nm_setting_ip_config_get_dhcp_timeout(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_timeout; -} - -/** - * nm_setting_ip_config_get_dhcp_iaid: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-iaid - * property. - * - * Returns: the configured DHCP IAID (Identity Association Identifier) - * - * Since: 1.22 - **/ -const char * -nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_iaid; -} - -/** - * nm_setting_ip_config_get_dhcp_reject_servers: - * @setting: the #NMSettingIPConfig - * @out_len: (allow-none) (out): the number of returned elements - * - * Returns: (array length=out_len zero-terminated=1) (transfer none): - * A %NULL terminated array of DHCP reject servers. Even if no reject - * servers are configured, this always returns a non %NULL value. - * - * Since: 1.28 - */ -const char *const * -nm_setting_ip_config_get_dhcp_reject_servers(NMSettingIPConfig *setting, guint *out_len) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - return nm_strvarray_get_strv(&NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_reject_servers, - out_len); -} - -/** - * nm_setting_ip_config_add_dhcp_reject_server: - * @setting: the #NMSettingIPConfig - * @server: the DHCP reject server to add - * - * Adds a new DHCP reject server to the setting. - * - * Since: 1.28 - **/ -void -nm_setting_ip_config_add_dhcp_reject_server(NMSettingIPConfig *setting, const char *server) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - g_return_if_fail(server != NULL); - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - nm_strvarray_add(nm_strvarray_ensure(&priv->dhcp_reject_servers), server); - _notify(setting, PROP_DHCP_REJECT_SERVERS); -} - -/** - * nm_setting_ip_config_remove_dhcp_reject_server: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DHCP reject server - * - * Removes the DHCP reject server at index @idx. - * - * Since: 1.28 - **/ -void -nm_setting_ip_config_remove_dhcp_reject_server(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(priv->dhcp_reject_servers && idx < priv->dhcp_reject_servers->len); - - g_array_remove_index(priv->dhcp_reject_servers, idx); - _notify(setting, PROP_DHCP_REJECT_SERVERS); -} - -/** - * nm_setting_ip_config_clear_dhcp_reject_servers: - * @setting: the #NMSettingIPConfig - * - * Removes all configured DHCP reject servers. - * - * Since: 1.28 - **/ -void -nm_setting_ip_config_clear_dhcp_reject_servers(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (nm_g_array_len(priv->dhcp_reject_servers) != 0) { - nm_clear_pointer(&priv->dhcp_reject_servers, g_array_unref); - _notify(setting, PROP_DHCP_REJECT_SERVERS); - } -} - -static gboolean -verify_label(const char *label) -{ - const char *p; - char * iface; - - p = strchr(label, ':'); - if (!p) - return FALSE; - iface = g_strndup(label, p - label); - if (!nm_utils_ifname_valid_kernel(iface, NULL)) { - g_free(iface); - return FALSE; - } - g_free(iface); - - for (p++; *p; p++) { - if (!g_ascii_isalnum(*p) && *p != '_') - return FALSE; - } - - return TRUE; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - guint i; - - if (!priv->method) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), NM_SETTING_IP_CONFIG_METHOD); - return FALSE; - } - - if (priv->dhcp_hostname && !*priv->dhcp_hostname) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME); - return FALSE; - } - - /* Validate DNS */ - for (i = 0; i < priv->dns->len; i++) { - const char *dns = priv->dns->pdata[i]; - - if (!nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. DNS server address is invalid"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DNS); - return FALSE; - } - } - - /* Validate addresses */ - for (i = 0; i < priv->addresses->len; i++) { - NMIPAddress *addr = (NMIPAddress *) priv->addresses->pdata[i]; - GVariant * label; - - if (nm_ip_address_get_family(addr) != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. IP address is invalid"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - if (label) { - if (!g_variant_is_of_type(label, G_VARIANT_TYPE_STRING)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. IP address has 'label' property with invalid type"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - if (!verify_label(g_variant_get_string(label, NULL))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. IP address has invalid label '%s'"), - (int) (i + 1), - g_variant_get_string(label, NULL)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - } - } - - /* Validate gateway */ - if (priv->gateway) { - if (!priv->addresses->len) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("gateway cannot be set if there are no addresses configured")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_GATEWAY); - return FALSE; - } - - if (!nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), priv->gateway)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("gateway is invalid")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_GATEWAY); - return FALSE; - } - } - - /* Validate routes */ - for (i = 0; i < priv->routes->len; i++) { - gs_free_error GError *local = NULL; - NMIPRoute * route = (NMIPRoute *) priv->routes->pdata[i]; - - if (nm_ip_route_get_family(route) != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. route is invalid"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ROUTES); - return FALSE; - } - - if (!_nm_ip_route_attribute_validate_all(route, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid attribute: %s"), - local->message); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ROUTES); - return FALSE; - } - } - - if (priv->routing_rules) { - for (i = 0; i < priv->routing_rules->len; i++) { - NMIPRoutingRule *rule = priv->routing_rules->pdata[i]; - gs_free_error GError *local = NULL; - - if (_ip_routing_rule_get_addr_family(rule) - != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%u. rule has wrong address-family"), - i + 1); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ROUTING_RULES); - return FALSE; - } - if (!nm_ip_routing_rule_validate(rule, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%u. rule is invalid: %s"), - i + 1, - local->message); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ROUTES); - return FALSE; - } - } - } - - if (priv->dhcp_iaid && !_nm_utils_iaid_verify(priv->dhcp_iaid, NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IAID"), - priv->dhcp_iaid); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_IAID); - return FALSE; - } - - /* Validate DHCP hostname flags */ - if (priv->dhcp_hostname_flags != NM_DHCP_HOSTNAME_FLAG_NONE && !priv->dhcp_send_hostname) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the property cannot be set when '%s' is disabled"), - NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS); - return FALSE; - } - - if (!_nm_utils_validate_dhcp_hostname_flags(priv->dhcp_hostname_flags, - NM_SETTING_IP_CONFIG_GET_FAMILY(setting), - error)) { - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS); - return FALSE; - } - - /* Validate reject servers */ - if (priv->dhcp_reject_servers && priv->dhcp_reject_servers->len != 0) { - if (NM_SETTING_IP_CONFIG_GET_FAMILY(setting) != AF_INET) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the property is currently supported only for DHCPv4")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS); - return FALSE; - } - - for (i = 0; i < priv->dhcp_reject_servers->len; i++) { - if (!nm_utils_parse_inaddr_prefix( - NM_SETTING_IP_CONFIG_GET_FAMILY(setting), - g_array_index(priv->dhcp_reject_servers, const char *, i), - NULL, - NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IP or subnet"), - g_array_index(priv->dhcp_reject_servers, const char *, i)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS); - return FALSE; - } - } - } - - /* Normalizable errors */ - if (priv->gateway && priv->never_default) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("a gateway is incompatible with '%s'"), - NM_SETTING_IP_CONFIG_NEVER_DEFAULT); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_GATEWAY); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingIPConfigPrivate *a_priv; - NMSettingIPConfigPrivate *b_priv; - guint i; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ADDRESSES)) { - if (set_b) { - a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); - b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); - - if (a_priv->addresses->len != b_priv->addresses->len) - return FALSE; - for (i = 0; i < a_priv->addresses->len; i++) { - if (nm_ip_address_cmp_full(a_priv->addresses->pdata[i], - b_priv->addresses->pdata[i], - NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS) - != 0) - return FALSE; - } - } - return TRUE; - } - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ROUTES)) { - if (set_b) { - a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); - b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); - - if (a_priv->routes->len != b_priv->routes->len) - return FALSE; - for (i = 0; i < a_priv->routes->len; i++) { - if (!nm_ip_route_equal_full(a_priv->routes->pdata[i], - b_priv->routes->pdata[i], - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) - return FALSE; - } - } - return TRUE; - } - - if (nm_streq(sett_info->property_infos[property_idx].name, - NM_SETTING_IP_CONFIG_ROUTING_RULES)) { - if (set_b) { - guint n; - - a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); - b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); - - n = (a_priv->routing_rules) ? a_priv->routing_rules->len : 0u; - if (n != (b_priv->routing_rules ? b_priv->routing_rules->len : 0u)) - return FALSE; - for (i = 0; i < n; i++) { - if (nm_ip_routing_rule_cmp(a_priv->routing_rules->pdata[i], - b_priv->routing_rules->pdata[i]) - != 0) - return FALSE; - } - } - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_ip_config_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -static void -duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) -{ - NMSettingIPConfigPrivate *priv_src = NM_SETTING_IP_CONFIG_GET_PRIVATE(src); - NMSettingIPConfigPrivate *priv_dst = NM_SETTING_IP_CONFIG_GET_PRIVATE(dst); - guint i; - gboolean changed = FALSE; - - NM_SETTING_CLASS(nm_setting_ip_config_parent_class) - ->duplicate_copy_properties(sett_info, src, dst); - - if (priv_dst->routing_rules && priv_dst->routing_rules->len > 0) { - changed = TRUE; - g_ptr_array_set_size(priv_dst->routing_rules, 0); - } - if (priv_src->routing_rules && priv_src->routing_rules->len > 0) { - changed = TRUE; - if (!priv_dst->routing_rules) - priv_dst->routing_rules = - g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); - for (i = 0; i < priv_src->routing_rules->len; i++) { - g_ptr_array_add(priv_dst->routing_rules, - nm_ip_routing_rule_ref(priv_src->routing_rules->pdata[i])); - } - } - if (changed) - _routing_rules_notify(NM_SETTING_IP_CONFIG(dst)); -} - -static void -enumerate_values(const NMSettInfoProperty *property_info, - NMSetting * setting, - NMSettingValueIterFn func, - gpointer user_data) -{ - if (nm_streq(property_info->name, NM_SETTING_IP_CONFIG_ROUTING_RULES)) { - NMSettingIPConfigPrivate * priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - nm_auto_unset_gvalue GValue value = G_VALUE_INIT; - GPtrArray * ptr = NULL; - guint i; - - if (priv->routing_rules && priv->routing_rules->len > 0) { - ptr = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); - for (i = 0; i < priv->routing_rules->len; i++) - g_ptr_array_add(ptr, nm_ip_routing_rule_ref(priv->routing_rules->pdata[i])); - } - g_value_init(&value, G_TYPE_PTR_ARRAY); - g_value_take_boxed(&value, ptr); - func(setting, property_info->name, &value, 0, user_data); - return; - } - - NM_SETTING_CLASS(nm_setting_ip_config_parent_class) - ->enumerate_values(property_info, setting, func, user_data); -} - -/*****************************************************************************/ - -static gboolean -ip_gateway_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - /* FIXME: properly handle errors */ - - /* Don't set from 'gateway' if we're going to use the gateway in 'addresses' */ - if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "gateway")) - return TRUE; - - g_object_set(setting, property, g_variant_get_string(value, NULL), NULL); - return TRUE; -} - -GArray * -_nm_sett_info_property_override_create_array_ip_config(void) -{ - GArray *properties_override = _nm_sett_info_property_override_create_array(); - - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_GATEWAY], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING, - .from_dbus_fcn = ip_gateway_set, )); - - /* ---dbus--- - * property: routing-rules - * format: array of 'a{sv}' - * description: Array of dictionaries for routing rules. - * ---end--- - */ - _nm_properties_override_dbus( - properties_override, - NM_SETTING_IP_CONFIG_ROUTING_RULES, - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _routing_rules_dbus_only_synth, - .from_dbus_fcn = _routing_rules_dbus_only_set, )); - - return properties_override; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingIPConfig * setting = NM_SETTING_IP_CONFIG(object); - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_METHOD: - g_value_set_string(value, nm_setting_ip_config_get_method(setting)); - break; - case PROP_DNS: - g_value_take_boxed(value, _nm_utils_ptrarray_to_strv(priv->dns)); - break; - case PROP_DNS_SEARCH: - g_value_take_boxed(value, _nm_utils_ptrarray_to_strv(priv->dns_search)); - break; - case PROP_DNS_OPTIONS: - g_value_take_boxed(value, - priv->dns_options ? _nm_utils_ptrarray_to_strv(priv->dns_options) - : NULL); - break; - case PROP_DNS_PRIORITY: - g_value_set_int(value, priv->dns_priority); - break; - case PROP_ADDRESSES: - g_value_take_boxed(value, - _nm_utils_copy_array(priv->addresses, - (NMUtilsCopyFunc) nm_ip_address_dup, - (GDestroyNotify) nm_ip_address_unref)); - break; - case PROP_GATEWAY: - g_value_set_string(value, nm_setting_ip_config_get_gateway(setting)); - break; - case PROP_ROUTES: - g_value_take_boxed(value, - _nm_utils_copy_array(priv->routes, - (NMUtilsCopyFunc) nm_ip_route_dup, - (GDestroyNotify) nm_ip_route_unref)); - break; - case PROP_ROUTE_METRIC: - g_value_set_int64(value, priv->route_metric); - break; - case PROP_ROUTE_TABLE: - g_value_set_uint(value, priv->route_table); - break; - case PROP_IGNORE_AUTO_ROUTES: - g_value_set_boolean(value, nm_setting_ip_config_get_ignore_auto_routes(setting)); - break; - case PROP_IGNORE_AUTO_DNS: - g_value_set_boolean(value, nm_setting_ip_config_get_ignore_auto_dns(setting)); - break; - case PROP_DHCP_HOSTNAME: - g_value_set_string(value, nm_setting_ip_config_get_dhcp_hostname(setting)); - break; - case PROP_DHCP_SEND_HOSTNAME: - g_value_set_boolean(value, nm_setting_ip_config_get_dhcp_send_hostname(setting)); - break; - case PROP_NEVER_DEFAULT: - g_value_set_boolean(value, priv->never_default); - break; - case PROP_MAY_FAIL: - g_value_set_boolean(value, priv->may_fail); - break; - case PROP_DAD_TIMEOUT: - g_value_set_int(value, nm_setting_ip_config_get_dad_timeout(setting)); - break; - case PROP_DHCP_TIMEOUT: - g_value_set_int(value, nm_setting_ip_config_get_dhcp_timeout(setting)); - break; - case PROP_DHCP_IAID: - g_value_set_string(value, nm_setting_ip_config_get_dhcp_iaid(setting)); - break; - case PROP_DHCP_HOSTNAME_FLAGS: - g_value_set_uint(value, nm_setting_ip_config_get_dhcp_hostname_flags(setting)); - break; - case PROP_DHCP_REJECT_SERVERS: - g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(priv->dhcp_reject_servers, NULL)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingIPConfig * setting = NM_SETTING_IP_CONFIG(object); - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - const char * gateway; - char ** strv; - guint i; - - switch (prop_id) { - case PROP_METHOD: - g_free(priv->method); - priv->method = g_value_dup_string(value); - break; - case PROP_DNS: - g_ptr_array_unref(priv->dns); - priv->dns = _nm_utils_strv_to_ptrarray(g_value_get_boxed(value)); - break; - case PROP_DNS_SEARCH: - g_ptr_array_unref(priv->dns_search); - priv->dns_search = _nm_utils_strv_to_ptrarray(g_value_get_boxed(value)); - break; - case PROP_DNS_OPTIONS: - strv = g_value_get_boxed(value); - if (!strv) { - if (priv->dns_options) { - g_ptr_array_unref(priv->dns_options); - priv->dns_options = NULL; - } - } else { - if (priv->dns_options) - g_ptr_array_set_size(priv->dns_options, 0); - else - priv->dns_options = g_ptr_array_new_with_free_func(g_free); - for (i = 0; strv[i]; i++) { - if (_nm_utils_dns_option_validate(strv[i], NULL, NULL, FALSE, NULL) - && _nm_utils_dns_option_find_idx(priv->dns_options, strv[i]) < 0) - g_ptr_array_add(priv->dns_options, g_strdup(strv[i])); - } - } - break; - case PROP_DNS_PRIORITY: - priv->dns_priority = g_value_get_int(value); - break; - case PROP_ADDRESSES: - g_ptr_array_unref(priv->addresses); - priv->addresses = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) nm_ip_address_dup, - (GDestroyNotify) nm_ip_address_unref); - break; - case PROP_GATEWAY: - gateway = g_value_get_string(value); - g_return_if_fail( - !gateway - || nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), gateway)); - g_free(priv->gateway); - priv->gateway = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), gateway, TRUE); - break; - case PROP_ROUTES: - g_ptr_array_unref(priv->routes); - priv->routes = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) nm_ip_route_dup, - (GDestroyNotify) nm_ip_route_unref); - break; - case PROP_ROUTE_METRIC: - priv->route_metric = g_value_get_int64(value); - break; - case PROP_ROUTE_TABLE: - priv->route_table = g_value_get_uint(value); - break; - case PROP_IGNORE_AUTO_ROUTES: - priv->ignore_auto_routes = g_value_get_boolean(value); - break; - case PROP_IGNORE_AUTO_DNS: - priv->ignore_auto_dns = g_value_get_boolean(value); - break; - case PROP_DHCP_HOSTNAME: - g_free(priv->dhcp_hostname); - priv->dhcp_hostname = g_value_dup_string(value); - break; - case PROP_DHCP_SEND_HOSTNAME: - priv->dhcp_send_hostname = g_value_get_boolean(value); - break; - case PROP_NEVER_DEFAULT: - priv->never_default = g_value_get_boolean(value); - break; - case PROP_MAY_FAIL: - priv->may_fail = g_value_get_boolean(value); - break; - case PROP_DAD_TIMEOUT: - priv->dad_timeout = g_value_get_int(value); - break; - case PROP_DHCP_TIMEOUT: - priv->dhcp_timeout = g_value_get_int(value); - break; - case PROP_DHCP_IAID: - priv->dhcp_iaid = g_value_dup_string(value); - break; - case PROP_DHCP_HOSTNAME_FLAGS: - priv->dhcp_hostname_flags = g_value_get_uint(value); - break; - case PROP_DHCP_REJECT_SERVERS: - nm_strvarray_set_strv(&priv->dhcp_reject_servers, g_value_get_boxed(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ip_config_init(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - priv->dns = g_ptr_array_new_with_free_func(g_free); - priv->dns_search = g_ptr_array_new_with_free_func(g_free); - priv->addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); - priv->routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); - priv->route_metric = -1; - priv->dhcp_send_hostname = TRUE; - priv->may_fail = TRUE; - priv->dad_timeout = -1; -} - -static void -finalize(GObject *object) -{ - NMSettingIPConfig * self = NM_SETTING_IP_CONFIG(object); - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(self); - - g_free(priv->method); - g_free(priv->gateway); - g_free(priv->dhcp_hostname); - g_free(priv->dhcp_iaid); - - g_ptr_array_unref(priv->dns); - g_ptr_array_unref(priv->dns_search); - if (priv->dns_options) - g_ptr_array_unref(priv->dns_options); - g_ptr_array_unref(priv->addresses); - g_ptr_array_unref(priv->routes); - if (priv->routing_rules) - g_ptr_array_unref(priv->routing_rules); - nm_clear_pointer(&priv->dhcp_reject_servers, g_array_unref); - - G_OBJECT_CLASS(nm_setting_ip_config_parent_class)->finalize(object); -} - -static void -nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingIPConfigPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->compare_property = compare_property; - setting_class->duplicate_copy_properties = duplicate_copy_properties; - setting_class->enumerate_values = enumerate_values; - - /** - * NMSettingIPConfig:method: - * - * IP configuration method. - * - * #NMSettingIP4Config and #NMSettingIP6Config both support "disabled", - * "auto", "manual", and "link-local". See the subclass-specific - * documentation for other values. - * - * In general, for the "auto" method, properties such as - * #NMSettingIPConfig:dns and #NMSettingIPConfig:routes specify information - * that is added on to the information returned from automatic - * configuration. The #NMSettingIPConfig:ignore-auto-routes and - * #NMSettingIPConfig:ignore-auto-dns properties modify this behavior. - * - * For methods that imply no upstream network, such as "shared" or - * "link-local", these properties must be empty. - * - * For IPv4 method "shared", the IP subnet can be configured by adding one - * manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the - * shared method must be configured on the interface which shares the internet - * to a subnet, not on the uplink which is shared. - **/ - obj_properties[PROP_METHOD] = g_param_spec_string( - NM_SETTING_IP_CONFIG_METHOD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dns: - * - * Array of IP addresses of DNS servers. - **/ - obj_properties[PROP_DNS] = g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dns-search: - * - * Array of DNS search domains. Domains starting with a tilde ('~') - * are considered 'routing' domains and are used only to decide the - * interface over which a query must be forwarded; they are not used - * to complete unqualified host names. - * - * When using a DNS plugin that supports Conditional Forwarding or - * Split DNS, then the search domains specify which name servers to - * query. This makes the behavior different from running with plain - * /etc/resolv.conf. For more information see also the dns-priority setting. - **/ - obj_properties[PROP_DNS_SEARCH] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS_SEARCH, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dns-options: - * - * Array of DNS options as described in man 5 resolv.conf. - * - * %NULL means that the options are unset and left at the default. - * In this case NetworkManager will use default options. This is - * distinct from an empty list of properties. - * - * The currently supported options are "attempts", "debug", "edns0", - * "inet6", "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", - * "no-ip6-dotint", "no-reload", "no-tld-query", "rotate", "single-request", - * "single-request-reopen", "timeout", "trust-ad", "use-vc". - * - * The "trust-ad" setting is only honored if the profile contributes - * name servers to resolv.conf, and if all contributing profiles have - * "trust-ad" enabled. - * - * When using a caching DNS plugin (dnsmasq or systemd-resolved in - * NetworkManager.conf) then "edns0" and "trust-ad" are automatically - * added. - * - * Since: 1.2 - **/ - obj_properties[PROP_DNS_OPTIONS] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS_OPTIONS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dns-priority: - * - * DNS servers priority. - * - * The relative priority for DNS servers specified by this setting. A lower - * numerical value is better (higher priority). - * - * Negative values have the special effect of excluding other configurations - * with a greater numerical priority value; so in presence of at least one negative - * priority, only DNS servers from connections with the lowest priority value will be used. - * To avoid all DNS leaks, set the priority of the profile that should be used - * to the most negative value of all active connections profiles. - * - * Zero selects a globally configured default value. If the latter is missing - * or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for - * other connections. - * - * Note that the priority is to order DNS settings for multiple active - * connections. It does not disambiguate multiple DNS servers within the - * same connection profile. - * - * When multiple devices have configurations with the same priority, VPNs will be - * considered first, then devices with the best (lowest metric) default - * route and then all other devices. - * - * When using dns=default, servers with higher priority will be on top of - * resolv.conf. To prioritize a given server over another one within the - * same connection, just specify them in the desired order. - * Note that commonly the resolver tries name servers in /etc/resolv.conf - * in the order listed, proceeding with the next server in the list - * on failure. See for example the "rotate" option of the dns-options setting. - * If there are any negative DNS priorities, then only name servers from - * the devices with that lowest priority will be considered. - * - * When using a DNS resolver that supports Conditional Forwarding or - * Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection - * is used to query domains in its search list. The search domains determine which - * name servers to ask, and the DNS priority is used to prioritize - * name servers based on the domain. Queries for domains not present in any - * search list are routed through connections having the '~.' special wildcard - * domain, which is added automatically to connections with the default route - * (or can be added manually). When multiple connections specify the same domain, the - * one with the best priority (lowest numerical value) wins. If a sub domain - * is configured on another interface it will be accepted regardless the priority, - * unless parent domain on the other interface has a negative priority, which causes - * the sub domain to be shadowed. - * With Split DNS one can avoid undesired DNS leaks by properly configuring - * DNS priorities and the search domains, so that only name servers of the desired - * interface are configured. - * - * Since: 1.4 - **/ - obj_properties[PROP_DNS_PRIORITY] = - g_param_spec_int(NM_SETTING_IP_CONFIG_DNS_PRIORITY, - "", - "", - G_MININT32, - G_MAXINT32, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:addresses: (type GPtrArray(NMIPAddress)) - * - * Array of IP addresses. - **/ - obj_properties[PROP_ADDRESSES] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_ADDRESSES, - "", - "", - G_TYPE_PTR_ARRAY, - /* "addresses" is a legacy D-Bus property, because the - * "addresses" GObject property normally gets set from - * the "address-data" D-Bus property... - */ - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | NM_SETTING_PARAM_LEGACY - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:gateway: - * - * The gateway associated with this configuration. This is only meaningful - * if #NMSettingIPConfig:addresses is also set. - * - * The gateway's main purpose is to control the next hop of the standard default route on the device. - * Hence, the gateway property conflicts with #NMSettingIPConfig:never-default and will be - * automatically dropped if the IP configuration is set to never-default. - * - * As an alternative to set the gateway, configure a static default route with /0 as prefix - * length. - **/ - obj_properties[PROP_GATEWAY] = g_param_spec_string( - NM_SETTING_IP_CONFIG_GATEWAY, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:routes: (type GPtrArray(NMIPRoute)) - * - * Array of IP routes. - **/ - obj_properties[PROP_ROUTES] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_ROUTES, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | - /* See :addresses above Re: LEGACY */ - NM_SETTING_PARAM_LEGACY | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:route-metric: - * - * The default metric for routes that don't explicitly specify a metric. - * The default value -1 means that the metric is chosen automatically - * based on the device type. - * The metric applies to dynamic routes, manual (static) routes that - * don't have an explicit metric setting, address prefix routes, and - * the default route. - * Note that for IPv6, the kernel accepts zero (0) but coerces it to - * 1024 (user default). Hence, setting this property to zero effectively - * mean setting it to 1024. - * For IPv4, zero is a regular value for the metric. - **/ - obj_properties[PROP_ROUTE_METRIC] = - g_param_spec_int64(NM_SETTING_IP_CONFIG_ROUTE_METRIC, - "", - "", - -1, - G_MAXUINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:route-table: - * - * Enable policy routing (source routing) and set the routing table used when adding routes. - * - * This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes - * and static routes. But note that static routes can individually overwrite the setting - * by explicitly specifying a non-zero routing table. - * - * If the table setting is left at zero, it is eligible to be overwritten via global - * configuration. If the property is zero even after applying the global configuration - * value, policy routing is disabled for the address family of this connection. - * - * Policy routing disabled means that NetworkManager will add all routes to the main - * table (except static routes that explicitly configure a different table). Additionally, - * NetworkManager will not delete any extraneous routes from tables except the main table. - * This is to preserve backward compatibility for users who manage routing tables outside - * of NetworkManager. - * - * Since: 1.10 - **/ - obj_properties[PROP_ROUTE_TABLE] = g_param_spec_uint( - NM_SETTING_IP_CONFIG_ROUTE_TABLE, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - /** - * NMSettingIPConfig:ignore-auto-routes: - * - * When #NMSettingIPConfig:method is set to "auto" and this property to - * %TRUE, automatically configured routes are ignored and only routes - * specified in the #NMSettingIPConfig:routes property, if any, are used. - **/ - obj_properties[PROP_IGNORE_AUTO_ROUTES] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:ignore-auto-dns: - * - * When #NMSettingIPConfig:method is set to "auto" and this property to - * %TRUE, automatically configured name servers and search domains are - * ignored and only name servers and search domains specified in the - * #NMSettingIPConfig:dns and #NMSettingIPConfig:dns-search properties, if - * any, are used. - **/ - obj_properties[PROP_IGNORE_AUTO_DNS] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-hostname: - * - * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the - * specified name will be sent to the DHCP server when acquiring a lease. - * This property and #NMSettingIP4Config:dhcp-fqdn are mutually exclusive and - * cannot be set at the same time. - **/ - obj_properties[PROP_DHCP_HOSTNAME] = - g_param_spec_string(NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-send-hostname: - * - * If %TRUE, a hostname is sent to the DHCP server when acquiring a lease. - * Some DHCP servers use this hostname to update DNS databases, essentially - * providing a static hostname for the computer. If the - * #NMSettingIPConfig:dhcp-hostname property is %NULL and this property is - * %TRUE, the current persistent hostname of the computer is sent. - **/ - obj_properties[PROP_DHCP_SEND_HOSTNAME] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, - "", - "", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:never-default: - * - * If %TRUE, this connection will never be the default connection for this - * IP type, meaning it will never be assigned the default route by - * NetworkManager. - **/ - obj_properties[PROP_NEVER_DEFAULT] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_NEVER_DEFAULT, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:may-fail: - * - * If %TRUE, allow overall network configuration to proceed even if the - * configuration specified by this property times out. Note that at least - * one IP configuration must succeed or overall network configuration will - * still fail. For example, in IPv6-only networks, setting this property to - * %TRUE on the #NMSettingIP4Config allows the overall network configuration - * to succeed if IPv4 configuration fails but IPv6 configuration completes - * successfully. - **/ - obj_properties[PROP_MAY_FAIL] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_MAY_FAIL, - "", - "", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dad-timeout: - * - * Timeout in milliseconds used to check for the presence of duplicate IP - * addresses on the network. If an address conflict is detected, the - * activation will fail. A zero value means that no duplicate address - * detection is performed, -1 means the default value (either configuration - * ipvx.dad-timeout override or zero). A value greater than zero is a - * timeout in milliseconds. - * - * The property is currently implemented only for IPv4. - * - * Since: 1.2 - **/ - obj_properties[PROP_DAD_TIMEOUT] = g_param_spec_int( - NM_SETTING_IP_CONFIG_DAD_TIMEOUT, - "", - "", - -1, - NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX, - -1, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-timeout: - * - * A timeout for a DHCP transaction in seconds. If zero (the default), a - * globally configured default is used. If still unspecified, a device specific - * timeout is used (usually 45 seconds). - * - * Set to 2147483647 (MAXINT32) for infinity. - **/ - obj_properties[PROP_DHCP_TIMEOUT] = g_param_spec_int( - NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, - "", - "", - 0, - G_MAXINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-iaid: - * - * A string containing the "Identity Association Identifier" (IAID) used - * by the DHCP client. The property is a 32-bit decimal value or a - * special value among "mac", "perm-mac", "ifname" and "stable". When - * set to "mac" (or "perm-mac"), the last 4 bytes of the current (or - * permanent) MAC address are used as IAID. When set to "ifname", the - * IAID is computed by hashing the interface name. The special value - * "stable" can be used to generate an IAID based on the stable-id (see - * connection.stable-id), a per-host key and the interface name. When - * the property is unset, the value from global configuration is used; - * if no global default is set then the IAID is assumed to be - * "ifname". Note that at the moment this property is ignored for IPv6 - * by dhclient, which always derives the IAID from the MAC address. - * - * Since: 1.22 - **/ - obj_properties[PROP_DHCP_IAID] = - g_param_spec_string(NM_SETTING_IP_CONFIG_DHCP_IAID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-hostname-flags: - * - * Flags for the DHCP hostname and FQDN. - * - * Currently, this property only includes flags to control the FQDN flags - * set in the DHCP FQDN option. Supported FQDN flags are - * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, - * %NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE. When no FQDN flag is set and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS is set, the DHCP FQDN option will - * contain no flag. Otherwise, if no FQDN flag is set and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS is not set, the standard FQDN flags - * are set in the request: - * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, - * %NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED for IPv4 and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE for IPv6. - * - * When this property is set to the default value %NM_DHCP_HOSTNAME_FLAG_NONE, - * a global default is looked up in NetworkManager configuration. If that value - * is unset or also %NM_DHCP_HOSTNAME_FLAG_NONE, then the standard FQDN flags - * described above are sent in the DHCP requests. - * - * Since: 1.22 - */ - obj_properties[PROP_DHCP_HOSTNAME_FLAGS] = - g_param_spec_uint(NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, - "", - "", - 0, - G_MAXUINT32, - NM_DHCP_HOSTNAME_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-reject-servers: - * - * Array of servers from which DHCP offers must be rejected. This property - * is useful to avoid getting a lease from misconfigured or rogue servers. - * - * For DHCPv4, each element must be an IPv4 address, optionally - * followed by a slash and a prefix length (e.g. "192.168.122.0/24"). - * - * This property is currently not implemented for DHCPv6. - * - * Since: 1.28 - **/ - obj_properties[PROP_DHCP_REJECT_SERVERS] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); -} diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h deleted file mode 100644 index 1cb1671714..0000000000 --- a/libnm-core/nm-setting-ip-config.h +++ /dev/null @@ -1,494 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef NM_SETTING_IP_CONFIG_H -#define NM_SETTING_IP_CONFIG_H - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" -#include "nm-utils.h" - -G_BEGIN_DECLS - -#define NM_IP_ADDRESS_ATTRIBUTE_LABEL "label" - -/** - * NMIPAddressCmpFlags: - * @NM_IP_ADDRESS_CMP_FLAGS_NONE: no flags. - * @NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS: when comparing two addresses, - * also consider their attributes. Warning: note that attributes are GVariants - * and they don't have a total order. In other words, if the address differs only - * by their attributes, the returned compare order is not total. In that case, - * the return value merely indicates equality (zero) or inequality. - * - * Compare flags for nm_ip_address_cmp_full(). - * - * Since: 1.22 - */ -typedef enum { /*< flags >*/ - NM_IP_ADDRESS_CMP_FLAGS_NONE = 0, - NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS = 0x1, -} NMIPAddressCmpFlags; - -typedef struct NMIPAddress NMIPAddress; - -GType nm_ip_address_get_type(void); - -NMIPAddress *nm_ip_address_new(int family, const char *addr, guint prefix, GError **error); -NMIPAddress *nm_ip_address_new_binary(int family, gconstpointer addr, guint prefix, GError **error); - -void nm_ip_address_ref(NMIPAddress *address); -void nm_ip_address_unref(NMIPAddress *address); -gboolean nm_ip_address_equal(NMIPAddress *address, NMIPAddress *other); -NM_AVAILABLE_IN_1_22 -int -nm_ip_address_cmp_full(const NMIPAddress *a, const NMIPAddress *b, NMIPAddressCmpFlags cmp_flags); -NMIPAddress *nm_ip_address_dup(NMIPAddress *address); - -int nm_ip_address_get_family(NMIPAddress *address); -const char *nm_ip_address_get_address(NMIPAddress *address); -void nm_ip_address_set_address(NMIPAddress *address, const char *addr); -void nm_ip_address_get_address_binary(NMIPAddress *address, gpointer addr); -void nm_ip_address_set_address_binary(NMIPAddress *address, gconstpointer addr); -guint nm_ip_address_get_prefix(NMIPAddress *address); -void nm_ip_address_set_prefix(NMIPAddress *address, guint prefix); - -char ** nm_ip_address_get_attribute_names(NMIPAddress *address); -GVariant *nm_ip_address_get_attribute(NMIPAddress *address, const char *name); -void nm_ip_address_set_attribute(NMIPAddress *address, const char *name, GVariant *value); - -typedef struct NMIPRoute NMIPRoute; - -GType nm_ip_route_get_type(void); - -NMIPRoute *nm_ip_route_new(int family, - const char *dest, - guint prefix, - const char *next_hop, - gint64 metric, - GError ** error); -NMIPRoute *nm_ip_route_new_binary(int family, - gconstpointer dest, - guint prefix, - gconstpointer next_hop, - gint64 metric, - GError ** error); - -void nm_ip_route_ref(NMIPRoute *route); -void nm_ip_route_unref(NMIPRoute *route); -gboolean nm_ip_route_equal(NMIPRoute *route, NMIPRoute *other); - -enum { /*< flags >*/ - NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE = 0, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS = 0x1, -}; - -NM_AVAILABLE_IN_1_10 -gboolean nm_ip_route_equal_full(NMIPRoute *route, NMIPRoute *other, guint cmp_flags); - -NMIPRoute *nm_ip_route_dup(NMIPRoute *route); - -int nm_ip_route_get_family(NMIPRoute *route); -const char *nm_ip_route_get_dest(NMIPRoute *route); -void nm_ip_route_set_dest(NMIPRoute *route, const char *dest); -void nm_ip_route_get_dest_binary(NMIPRoute *route, gpointer dest); -void nm_ip_route_set_dest_binary(NMIPRoute *route, gconstpointer dest); -guint nm_ip_route_get_prefix(NMIPRoute *route); -void nm_ip_route_set_prefix(NMIPRoute *route, guint prefix); -const char *nm_ip_route_get_next_hop(NMIPRoute *route); -void nm_ip_route_set_next_hop(NMIPRoute *route, const char *next_hop); -gboolean nm_ip_route_get_next_hop_binary(NMIPRoute *route, gpointer next_hop); -void nm_ip_route_set_next_hop_binary(NMIPRoute *route, gconstpointer next_hop); -gint64 nm_ip_route_get_metric(NMIPRoute *route); -void nm_ip_route_set_metric(NMIPRoute *route, gint64 metric); - -char ** nm_ip_route_get_attribute_names(NMIPRoute *route); -GVariant *nm_ip_route_get_attribute(NMIPRoute *route, const char *name); -void nm_ip_route_set_attribute(NMIPRoute *route, const char *name, GVariant *value); -NM_AVAILABLE_IN_1_8 -const NMVariantAttributeSpec *const *nm_ip_route_get_variant_attribute_spec(void); -NM_AVAILABLE_IN_1_8 -gboolean nm_ip_route_attribute_validate(const char *name, - GVariant * value, - int family, - gboolean * known, - GError ** error); - -#define NM_IP_ROUTE_ATTRIBUTE_CWND "cwnd" -#define NM_IP_ROUTE_ATTRIBUTE_FROM "from" -#define NM_IP_ROUTE_ATTRIBUTE_INITCWND "initcwnd" -#define NM_IP_ROUTE_ATTRIBUTE_INITRWND "initrwnd" -#define NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND "lock-cwnd" -#define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND "lock-initcwnd" -#define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND "lock-initrwnd" -#define NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU "lock-mtu" -#define NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW "lock-window" -#define NM_IP_ROUTE_ATTRIBUTE_MTU "mtu" -#define NM_IP_ROUTE_ATTRIBUTE_ONLINK "onlink" -#define NM_IP_ROUTE_ATTRIBUTE_SCOPE "scope" -#define NM_IP_ROUTE_ATTRIBUTE_SRC "src" -#define NM_IP_ROUTE_ATTRIBUTE_TABLE "table" -#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos" -#define NM_IP_ROUTE_ATTRIBUTE_TYPE "type" -#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window" - -/*****************************************************************************/ - -typedef struct NMIPRoutingRule NMIPRoutingRule; - -NM_AVAILABLE_IN_1_18 -GType nm_ip_routing_rule_get_type(void); - -NM_AVAILABLE_IN_1_18 -NMIPRoutingRule *nm_ip_routing_rule_new(int addr_family); - -NM_AVAILABLE_IN_1_18 -NMIPRoutingRule *nm_ip_routing_rule_new_clone(const NMIPRoutingRule *rule); - -NM_AVAILABLE_IN_1_18 -NMIPRoutingRule *nm_ip_routing_rule_ref(NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_unref(NMIPRoutingRule *self); - -NM_AVAILABLE_IN_1_18 -gboolean nm_ip_routing_rule_is_sealed(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_seal(NMIPRoutingRule *self); - -NM_AVAILABLE_IN_1_18 -int nm_ip_routing_rule_get_addr_family(const NMIPRoutingRule *self); - -NM_AVAILABLE_IN_1_18 -gboolean nm_ip_routing_rule_get_invert(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_invert(NMIPRoutingRule *self, gboolean invert); - -NM_AVAILABLE_IN_1_18 -gint64 nm_ip_routing_rule_get_priority(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_priority(NMIPRoutingRule *self, gint64 priority); - -NM_AVAILABLE_IN_1_18 -guint8 nm_ip_routing_rule_get_tos(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_tos(NMIPRoutingRule *self, guint8 tos); - -NM_AVAILABLE_IN_1_18 -guint8 nm_ip_routing_rule_get_ipproto(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_ipproto(NMIPRoutingRule *self, guint8 ipproto); - -NM_AVAILABLE_IN_1_18 -guint16 nm_ip_routing_rule_get_source_port_start(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -guint16 nm_ip_routing_rule_get_source_port_end(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_source_port(NMIPRoutingRule *self, guint16 start, guint16 end); - -NM_AVAILABLE_IN_1_18 -guint16 nm_ip_routing_rule_get_destination_port_start(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -guint16 nm_ip_routing_rule_get_destination_port_end(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_destination_port(NMIPRoutingRule *self, guint16 start, guint16 end); - -NM_AVAILABLE_IN_1_18 -guint32 nm_ip_routing_rule_get_fwmark(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -guint32 nm_ip_routing_rule_get_fwmask(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_fwmark(NMIPRoutingRule *self, guint32 fwmark, guint32 fwmask); - -NM_AVAILABLE_IN_1_18 -guint8 nm_ip_routing_rule_get_from_len(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -const char *nm_ip_routing_rule_get_from(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_from(NMIPRoutingRule *self, const char *from, guint8 len); - -NM_AVAILABLE_IN_1_18 -guint8 nm_ip_routing_rule_get_to_len(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -const char *nm_ip_routing_rule_get_to(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_to(NMIPRoutingRule *self, const char *to, guint8 len); - -NM_AVAILABLE_IN_1_18 -const char *nm_ip_routing_rule_get_iifname(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_iifname(NMIPRoutingRule *self, const char *iifname); - -NM_AVAILABLE_IN_1_18 -const char *nm_ip_routing_rule_get_oifname(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_oifname(NMIPRoutingRule *self, const char *oifname); - -NM_AVAILABLE_IN_1_18 -guint8 nm_ip_routing_rule_get_action(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_action(NMIPRoutingRule *self, guint8 action); - -NM_AVAILABLE_IN_1_18 -guint32 nm_ip_routing_rule_get_table(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_18 -void nm_ip_routing_rule_set_table(NMIPRoutingRule *self, guint32 table); - -NM_AVAILABLE_IN_1_20 -gint32 nm_ip_routing_rule_get_suppress_prefixlength(const NMIPRoutingRule *self); -NM_AVAILABLE_IN_1_20 -void nm_ip_routing_rule_set_suppress_prefixlength(NMIPRoutingRule *self, - gint32 suppress_prefixlength); - -NM_AVAILABLE_IN_1_18 -int nm_ip_routing_rule_cmp(const NMIPRoutingRule *rule, const NMIPRoutingRule *other); - -NM_AVAILABLE_IN_1_18 -gboolean nm_ip_routing_rule_validate(const NMIPRoutingRule *self, GError **error); - -/** - * NMIPRoutingRuleAsStringFlags: - * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE: no flags selected. - * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET: whether to allow parsing - * IPv4 addresses. - * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6: whether to allow parsing - * IPv6 addresses. If both @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET and - * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 are unset, it's the same - * as setting them both. - * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE: if set, ensure that the - * rule verfies or fail. - * - * Since: 1.18 - */ -typedef enum { /*< flags >*/ - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE = 0, - - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET = 0x1, - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 = 0x2, - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE = 0x4, -} NMIPRoutingRuleAsStringFlags; - -NM_AVAILABLE_IN_1_18 -NMIPRoutingRule *nm_ip_routing_rule_from_string(const char * str, - NMIPRoutingRuleAsStringFlags to_string_flags, - GHashTable * extra_args, - GError ** error); - -NM_AVAILABLE_IN_1_18 -char *nm_ip_routing_rule_to_string(const NMIPRoutingRule * self, - NMIPRoutingRuleAsStringFlags to_string_flags, - GHashTable * extra_args, - GError ** error); - -/*****************************************************************************/ - -#define NM_TYPE_SETTING_IP_CONFIG (nm_setting_ip_config_get_type()) -#define NM_SETTING_IP_CONFIG(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfig)) -#define NM_SETTING_IP_CONFIG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_IPCONFIG, NMSettingIPConfigClass)) -#define NM_IS_SETTING_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_IP_CONFIG)) -#define NM_IS_SETTING_IP_CONFIG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_IP_CONFIG)) -#define NM_SETTING_IP_CONFIG_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfigClass)) - -#define NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX 30000 - -#define NM_SETTING_IP_CONFIG_METHOD "method" -#define NM_SETTING_IP_CONFIG_DNS "dns" -#define NM_SETTING_IP_CONFIG_DNS_SEARCH "dns-search" -#define NM_SETTING_IP_CONFIG_DNS_OPTIONS "dns-options" -#define NM_SETTING_IP_CONFIG_DNS_PRIORITY "dns-priority" -#define NM_SETTING_IP_CONFIG_ADDRESSES "addresses" -#define NM_SETTING_IP_CONFIG_GATEWAY "gateway" -#define NM_SETTING_IP_CONFIG_ROUTES "routes" -#define NM_SETTING_IP_CONFIG_ROUTE_METRIC "route-metric" -#define NM_SETTING_IP_CONFIG_ROUTE_TABLE "route-table" -#define NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes" -#define NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns" -#define NM_SETTING_IP_CONFIG_DHCP_HOSTNAME "dhcp-hostname" -#define NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME "dhcp-send-hostname" -#define NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS "dhcp-hostname-flags" -#define NM_SETTING_IP_CONFIG_NEVER_DEFAULT "never-default" -#define NM_SETTING_IP_CONFIG_MAY_FAIL "may-fail" -#define NM_SETTING_IP_CONFIG_DAD_TIMEOUT "dad-timeout" -#define NM_SETTING_IP_CONFIG_DHCP_TIMEOUT "dhcp-timeout" -#define NM_SETTING_IP_CONFIG_DHCP_IAID "dhcp-iaid" -#define NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS "dhcp-reject-servers" - -/* these are not real GObject properties. */ -#define NM_SETTING_IP_CONFIG_ROUTING_RULES "routing-rules" - -#define NM_SETTING_DNS_OPTION_DEBUG "debug" -#define NM_SETTING_DNS_OPTION_NDOTS "ndots" -#define NM_SETTING_DNS_OPTION_TIMEOUT "timeout" -#define NM_SETTING_DNS_OPTION_ATTEMPTS "attempts" -#define NM_SETTING_DNS_OPTION_ROTATE "rotate" -#define NM_SETTING_DNS_OPTION_NO_CHECK_NAMES "no-check-names" -#define NM_SETTING_DNS_OPTION_INET6 "inet6" -#define NM_SETTING_DNS_OPTION_IP6_BYTESTRING "ip6-bytestring" -#define NM_SETTING_DNS_OPTION_IP6_DOTINT "ip6-dotint" -#define NM_SETTING_DNS_OPTION_NO_IP6_DOTINT "no-ip6-dotint" -#define NM_SETTING_DNS_OPTION_EDNS0 "edns0" -#define NM_SETTING_DNS_OPTION_SINGLE_REQUEST "single-request" -#define NM_SETTING_DNS_OPTION_SINGLE_REQUEST_REOPEN "single-request-reopen" -#define NM_SETTING_DNS_OPTION_NO_TLD_QUERY "no-tld-query" -#define NM_SETTING_DNS_OPTION_USE_VC "use-vc" -#define NM_SETTING_DNS_OPTION_NO_RELOAD "no-reload" -#define NM_SETTING_DNS_OPTION_TRUST_AD "trust-ad" - -/** - * NMSettingIPConfig: - */ -struct _NMSettingIPConfig { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /* Padding for future expansion */ - gpointer padding[8]; -} NMSettingIPConfigClass; - -/** - * NMDhcpHostnameFlags: - * @NM_DHCP_HOSTNAME_FLAG_NONE: no flag set. The default value from - * Networkmanager global configuration is used. If such value is unset - * or still zero, the DHCP request will use standard FQDN flags, i.e. - * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED for IPv4 and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE for IPv6. - * @NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE: whether the server should - * do the A RR (FQDN-to-address) DNS updates. - * @NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED: if set, the FQDN is encoded - * using canonical wire format. Otherwise it uses the deprecated - * ASCII encoding. This flag is allowed only for DHCPv4. - * @NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE: when not set, request the - * server to perform updates (the PTR RR and possibly the A RR - * based on the %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE flag). If - * this is set, the %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE flag - * should be cleared. - * @NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS: when set, no FQDN flags are - * sent in the DHCP FQDN option. When cleared and all other FQDN - * flags are zero, standard FQDN flags are sent. This flag is - * incompatible with any other FQDN flag. - * - * #NMDhcpHostnameFlags describe flags related to the DHCP hostname and - * FQDN. - * - * Since: 1.22 - */ -typedef enum { /*< flags >*/ - NM_DHCP_HOSTNAME_FLAG_NONE = 0x0, - - NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE = 0x1, - NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED = 0x2, - NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE = 0x4, - - NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS = 0x8, - -} NMDhcpHostnameFlags; - -GType nm_setting_ip_config_get_type(void); - -const char *nm_setting_ip_config_get_method(NMSettingIPConfig *setting); - -guint nm_setting_ip_config_get_num_dns(NMSettingIPConfig *setting); -const char *nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns); -void nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char *dns); -void nm_setting_ip_config_clear_dns(NMSettingIPConfig *setting); - -guint nm_setting_ip_config_get_num_dns_searches(NMSettingIPConfig *setting); -const char *nm_setting_ip_config_get_dns_search(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_add_dns_search(NMSettingIPConfig *setting, const char *dns_search); -void nm_setting_ip_config_remove_dns_search(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_remove_dns_search_by_value(NMSettingIPConfig *setting, - const char * dns_search); -void nm_setting_ip_config_clear_dns_searches(NMSettingIPConfig *setting); - -guint nm_setting_ip_config_get_num_dns_options(NMSettingIPConfig *setting); -gboolean nm_setting_ip_config_has_dns_options(NMSettingIPConfig *setting); -const char *nm_setting_ip_config_get_dns_option(NMSettingIPConfig *setting, guint idx); -gboolean nm_setting_ip_config_add_dns_option(NMSettingIPConfig *setting, const char *dns_option); -void nm_setting_ip_config_remove_dns_option(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_remove_dns_option_by_value(NMSettingIPConfig *setting, - const char * dns_option); -void nm_setting_ip_config_clear_dns_options(NMSettingIPConfig *setting, gboolean is_set); - -NM_AVAILABLE_IN_1_4 -int nm_setting_ip_config_get_dns_priority(NMSettingIPConfig *setting); - -guint nm_setting_ip_config_get_num_addresses(NMSettingIPConfig *setting); -NMIPAddress *nm_setting_ip_config_get_address(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_add_address(NMSettingIPConfig *setting, NMIPAddress *address); -void nm_setting_ip_config_remove_address(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_remove_address_by_value(NMSettingIPConfig *setting, - NMIPAddress * address); -void nm_setting_ip_config_clear_addresses(NMSettingIPConfig *setting); - -const char *nm_setting_ip_config_get_gateway(NMSettingIPConfig *setting); - -guint nm_setting_ip_config_get_num_routes(NMSettingIPConfig *setting); -NMIPRoute *nm_setting_ip_config_get_route(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_add_route(NMSettingIPConfig *setting, NMIPRoute *route); -void nm_setting_ip_config_remove_route(NMSettingIPConfig *setting, int idx); -gboolean nm_setting_ip_config_remove_route_by_value(NMSettingIPConfig *setting, NMIPRoute *route); -void nm_setting_ip_config_clear_routes(NMSettingIPConfig *setting); - -gint64 nm_setting_ip_config_get_route_metric(NMSettingIPConfig *setting); - -NM_AVAILABLE_IN_1_10 -guint32 nm_setting_ip_config_get_route_table(NMSettingIPConfig *setting); - -NM_AVAILABLE_IN_1_18 -guint nm_setting_ip_config_get_num_routing_rules(NMSettingIPConfig *setting); -NM_AVAILABLE_IN_1_18 -NMIPRoutingRule *nm_setting_ip_config_get_routing_rule(NMSettingIPConfig *setting, guint idx); -NM_AVAILABLE_IN_1_18 -void nm_setting_ip_config_add_routing_rule(NMSettingIPConfig *setting, - NMIPRoutingRule * routing_rule); -NM_AVAILABLE_IN_1_18 -void nm_setting_ip_config_remove_routing_rule(NMSettingIPConfig *setting, guint idx); -NM_AVAILABLE_IN_1_18 -void nm_setting_ip_config_clear_routing_rules(NMSettingIPConfig *setting); - -gboolean nm_setting_ip_config_get_ignore_auto_routes(NMSettingIPConfig *setting); -gboolean nm_setting_ip_config_get_ignore_auto_dns(NMSettingIPConfig *setting); - -const char *nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting); -gboolean nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting); - -gboolean nm_setting_ip_config_get_never_default(NMSettingIPConfig *setting); -gboolean nm_setting_ip_config_get_may_fail(NMSettingIPConfig *setting); -NM_AVAILABLE_IN_1_2 -int nm_setting_ip_config_get_dad_timeout(NMSettingIPConfig *setting); -NM_AVAILABLE_IN_1_2 -int nm_setting_ip_config_get_dhcp_timeout(NMSettingIPConfig *setting); -NM_AVAILABLE_IN_1_22 -const char *nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting); - -NM_AVAILABLE_IN_1_22 -NMDhcpHostnameFlags nm_setting_ip_config_get_dhcp_hostname_flags(NMSettingIPConfig *setting); - -NM_AVAILABLE_IN_1_28 -const char *const *nm_setting_ip_config_get_dhcp_reject_servers(NMSettingIPConfig *setting, - guint * out_len); -NM_AVAILABLE_IN_1_28 -void nm_setting_ip_config_add_dhcp_reject_server(NMSettingIPConfig *setting, const char *server); -NM_AVAILABLE_IN_1_28 -void nm_setting_ip_config_remove_dhcp_reject_server(NMSettingIPConfig *setting, guint idx); -NM_AVAILABLE_IN_1_28 -void nm_setting_ip_config_clear_dhcp_reject_servers(NMSettingIPConfig *setting); - -G_END_DECLS - -#endif /* NM_SETTING_IP_CONFIG_H */ diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c deleted file mode 100644 index 998b816bd3..0000000000 --- a/libnm-core/nm-setting-ip-tunnel.c +++ /dev/null @@ -1,867 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ip-tunnel.h" - -#include "nm-setting-private.h" -#include "nm-utils.h" - -/** - * SECTION:nm-setting-ip-tunnel - * @short_description: Describes connection properties for IP tunnel devices - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, - PROP_MODE, - PROP_LOCAL, - PROP_REMOTE, - PROP_TTL, - PROP_TOS, - PROP_PATH_MTU_DISCOVERY, - PROP_INPUT_KEY, - PROP_OUTPUT_KEY, - PROP_ENCAPSULATION_LIMIT, - PROP_FLOW_LABEL, - PROP_MTU, - PROP_FLAGS, ); - -typedef struct { - char * parent; - char * local; - char * remote; - char * input_key; - char * output_key; - guint ttl; - guint tos; - guint encapsulation_limit; - guint flow_label; - NMIPTunnelMode mode; - guint32 mtu; - guint32 flags; - bool path_mtu_discovery : 1; -} NMSettingIPTunnelPrivate; - -G_DEFINE_TYPE(NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING) - -#define NM_SETTING_IP_TUNNEL_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_ip_tunnel_get_parent: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:parent property of the setting - * - * Returns: the parent device - * - * Since: 1.2 - **/ -const char * -nm_setting_ip_tunnel_get_parent(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->parent; -} - -/** - * nm_setting_ip_tunnel_get_mode: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:mode property of the setting. - * - * Returns: the tunnel mode - * - * Since: 1.2 - **/ -NMIPTunnelMode -nm_setting_ip_tunnel_get_mode(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->mode; -} - -/** - * nm_setting_ip_tunnel_get_local: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:local property of the setting. - * - * Returns: the local endpoint - * - * Since: 1.2 - **/ -const char * -nm_setting_ip_tunnel_get_local(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->local; -} - -/** - * nm_setting_ip_tunnel_get_remote: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:remote property of the setting. - * - * Returns: the remote endpoint - * - * Since: 1.2 - **/ -const char * -nm_setting_ip_tunnel_get_remote(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->remote; -} - -/** - * nm_setting_ip_tunnel_get_ttl: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:ttl property of the setting. - * - * Returns: the Time-to-live value - * - * Since: 1.2 - **/ - -guint -nm_setting_ip_tunnel_get_ttl(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->ttl; -} - -/** - * nm_setting_ip_tunnel_get_tos: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:tos property of the setting. - * - * Returns: the TOS value - * - * Since: 1.2 - **/ -guint -nm_setting_ip_tunnel_get_tos(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->tos; -} - -/** - * nm_setting_ip_tunnel_get_path_mtu_discovery: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:path-mtu-discovery property of the setting. - * - * Returns: whether path MTU discovery is enabled - * - * Since: 1.2 - **/ -gboolean -nm_setting_ip_tunnel_get_path_mtu_discovery(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), TRUE); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->path_mtu_discovery; -} - -/** - * nm_setting_ip_tunnel_get_input_key: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:input-key property of the setting. - * - * Returns: the input key - * - * Since: 1.2 - **/ -const char * -nm_setting_ip_tunnel_get_input_key(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->input_key; -} - -/** - * nm_setting_ip_tunnel_get_output_key: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:output-key property of the setting. - * - * Returns: the output key - * - * Since: 1.2 - **/ -const char * -nm_setting_ip_tunnel_get_output_key(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->output_key; -} - -/** - * nm_setting_ip_tunnel_get_encapsulation_limit: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:encapsulation-limit property of the setting. - * - * Returns: the encapsulation limit value - * - * Since: 1.2 - **/ -guint -nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->encapsulation_limit; -} - -/** - * nm_setting_ip_tunnel_get_flow_label: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:flow-label property of the setting. - * - * Returns: the flow label value - * - * Since: 1.2 - **/ -guint -nm_setting_ip_tunnel_get_flow_label(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->flow_label; -} - -/** - * nm_setting_ip_tunnel_get_mtu: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:mtu property of the setting. - * - * Returns: the MTU - * - * Since: 1.2 - **/ -guint -nm_setting_ip_tunnel_get_mtu(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->mtu; -} - -/* - * nm_setting_ip_tunnel_get_flags: - * @setting: the #NMSettingIPTunnel - * - * Returns the #NMSettingIPTunnel:flags property of the setting. - * - * Returns: the tunnel flags - * - * Since: 1.12 - **/ -NMIPTunnelFlags -nm_setting_ip_tunnel_get_flags(NMSettingIPTunnel *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NM_IP_TUNNEL_FLAG_NONE); - - return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->flags; -} - -/*****************************************************************************/ - -gboolean -_nm_ip_tunnel_mode_is_layer2(NMIPTunnelMode mode) -{ - return NM_IN_SET(mode, NM_IP_TUNNEL_MODE_GRETAP, NM_IP_TUNNEL_MODE_IP6GRETAP); -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting); - int family = AF_UNSPEC; - guint32 flags; - - switch (priv->mode) { - case NM_IP_TUNNEL_MODE_IPIP: - case NM_IP_TUNNEL_MODE_SIT: - case NM_IP_TUNNEL_MODE_ISATAP: - case NM_IP_TUNNEL_MODE_GRE: - case NM_IP_TUNNEL_MODE_VTI: - case NM_IP_TUNNEL_MODE_GRETAP: - family = AF_INET; - break; - case NM_IP_TUNNEL_MODE_IP6IP6: - case NM_IP_TUNNEL_MODE_IPIP6: - case NM_IP_TUNNEL_MODE_IP6GRE: - case NM_IP_TUNNEL_MODE_VTI6: - case NM_IP_TUNNEL_MODE_IP6GRETAP: - family = AF_INET6; - break; - case NM_IP_TUNNEL_MODE_UNKNOWN: - break; - } - - if (family == AF_UNSPEC) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%d' is not a valid tunnel mode"), - (int) priv->mode); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_MODE); - return FALSE; - } - - if (priv->parent && !nm_utils_ifname_valid_kernel(priv->parent, NULL) - && !nm_utils_is_uuid(priv->parent)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is neither an UUID nor an interface name"), - priv->parent); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_PARENT); - return FALSE; - } - - if (priv->local && !nm_utils_ipaddr_is_valid(family, priv->local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IPv%c address"), - priv->local, - family == AF_INET ? '4' : '6'); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_LOCAL); - return FALSE; - } - - if (!priv->remote) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_REMOTE); - return FALSE; - } - - if (!nm_utils_ipaddr_is_valid(family, priv->remote)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IPv%c address"), - priv->remote, - family == AF_INET ? '4' : '6'); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_REMOTE); - return FALSE; - } - - if ((priv->input_key && priv->input_key[0]) || (priv->output_key && priv->output_key[0])) { - if (!NM_IN_SET(priv->mode, - NM_IP_TUNNEL_MODE_GRE, - NM_IP_TUNNEL_MODE_GRETAP, - NM_IP_TUNNEL_MODE_IP6GRE, - NM_IP_TUNNEL_MODE_IP6GRETAP)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("tunnel keys can only be specified for GRE tunnels")); - return FALSE; - } - } - - if (priv->input_key && priv->input_key[0]) { - gint64 val; - - val = _nm_utils_ascii_str_to_int64(priv->input_key, 10, 0, G_MAXUINT32, -1); - if (val == -1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid tunnel key"), - priv->input_key); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_INPUT_KEY); - return FALSE; - } - } - - if (priv->output_key && priv->output_key[0]) { - gint64 val; - - val = _nm_utils_ascii_str_to_int64(priv->output_key, 10, 0, G_MAXUINT32, -1); - if (val == -1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid tunnel key"), - priv->output_key); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_OUTPUT_KEY); - return FALSE; - } - } - - if (!priv->path_mtu_discovery && priv->ttl != 0) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("a fixed TTL is allowed only when path MTU discovery is enabled")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_TTL); - return FALSE; - } - - flags = priv->flags; - if (NM_IN_SET(priv->mode, NM_IP_TUNNEL_MODE_IPIP6, NM_IP_TUNNEL_MODE_IP6IP6)) - flags &= (guint32)(~_NM_IP_TUNNEL_FLAG_ALL_IP6TNL); - if (flags) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("some flags are invalid for the select mode: %s"), - nm_utils_enum_to_str(nm_ip_tunnel_flags_get_type(), flags)); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_FLAGS); - return FALSE; - } - - if (nm_connection_get_setting_wired(connection) && !_nm_ip_tunnel_mode_is_layer2(priv->mode)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("wired setting not allowed for mode %s"), - nm_utils_enum_to_str(nm_ip_tunnel_mode_get_type(), priv->mode)); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP_TUNNEL_SETTING_NAME, - NM_SETTING_IP_TUNNEL_MODE); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingIPTunnel * setting = NM_SETTING_IP_TUNNEL(object); - NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_value_set_string(value, priv->parent); - break; - case PROP_MODE: - g_value_set_uint(value, priv->mode); - break; - case PROP_LOCAL: - g_value_set_string(value, priv->local); - break; - case PROP_REMOTE: - g_value_set_string(value, priv->remote); - break; - case PROP_TTL: - g_value_set_uint(value, priv->ttl); - break; - case PROP_TOS: - g_value_set_uint(value, priv->tos); - break; - case PROP_PATH_MTU_DISCOVERY: - g_value_set_boolean(value, priv->path_mtu_discovery); - break; - case PROP_INPUT_KEY: - g_value_set_string(value, priv->input_key); - break; - case PROP_OUTPUT_KEY: - g_value_set_string(value, priv->output_key); - break; - case PROP_ENCAPSULATION_LIMIT: - g_value_set_uint(value, priv->encapsulation_limit); - break; - case PROP_FLOW_LABEL: - g_value_set_uint(value, priv->flow_label); - break; - case PROP_MTU: - g_value_set_uint(value, priv->mtu); - break; - case PROP_FLAGS: - g_value_set_uint(value, priv->flags); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingIPTunnel * setting = NM_SETTING_IP_TUNNEL(object); - NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_free(priv->parent); - priv->parent = g_value_dup_string(value); - break; - case PROP_MODE: - priv->mode = g_value_get_uint(value); - break; - case PROP_LOCAL: - g_free(priv->local); - priv->local = g_value_dup_string(value); - break; - case PROP_REMOTE: - g_free(priv->remote); - priv->remote = g_value_dup_string(value); - break; - case PROP_TTL: - priv->ttl = g_value_get_uint(value); - break; - case PROP_TOS: - priv->tos = g_value_get_uint(value); - break; - case PROP_PATH_MTU_DISCOVERY: - priv->path_mtu_discovery = g_value_get_boolean(value); - break; - case PROP_INPUT_KEY: - g_free(priv->input_key); - priv->input_key = g_value_dup_string(value); - break; - case PROP_OUTPUT_KEY: - g_free(priv->output_key); - priv->output_key = g_value_dup_string(value); - break; - case PROP_ENCAPSULATION_LIMIT: - priv->encapsulation_limit = g_value_get_uint(value); - break; - case PROP_FLOW_LABEL: - priv->flow_label = g_value_get_uint(value); - break; - case PROP_MTU: - priv->mtu = g_value_get_uint(value); - break; - case PROP_FLAGS: - priv->flags = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ip_tunnel_init(NMSettingIPTunnel *self) -{ - NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(self); - - priv->path_mtu_discovery = TRUE; -} - -/** - * nm_setting_ip_tunnel_new: - * - * Creates a new #NMSettingIPTunnel object with default values. - * - * Returns: (transfer full): the new empty #NMSettingIPTunnel object - * - * Since: 1.2 - **/ -NMSetting * -nm_setting_ip_tunnel_new(void) -{ - return g_object_new(NM_TYPE_SETTING_IP_TUNNEL, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingIPTunnel * setting = NM_SETTING_IP_TUNNEL(object); - NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting); - - g_free(priv->parent); - g_free(priv->local); - g_free(priv->remote); - g_free(priv->input_key); - g_free(priv->output_key); - - G_OBJECT_CLASS(nm_setting_ip_tunnel_parent_class)->finalize(object); -} - -static void -nm_setting_ip_tunnel_class_init(NMSettingIPTunnelClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingIPTunnelPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingIPTunnel:parent: - * - * If given, specifies the parent interface name or parent connection UUID - * the new device will be bound to so that tunneled packets will only be - * routed via that interface. - * - * Since: 1.2 - **/ - obj_properties[PROP_PARENT] = g_param_spec_string( - NM_SETTING_IP_TUNNEL_PARENT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:mode: - * - * The tunneling mode, for example %NM_IP_TUNNEL_MODE_IPIP or - * %NM_IP_TUNNEL_MODE_GRE. - * - * Since: 1.2 - **/ - obj_properties[PROP_MODE] = - g_param_spec_uint(NM_SETTING_IP_TUNNEL_MODE, - "", - "", - 0, - G_MAXUINT, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:local: - * - * The local endpoint of the tunnel; the value can be empty, otherwise it - * must contain an IPv4 or IPv6 address. - * - * Since: 1.2 - **/ - obj_properties[PROP_LOCAL] = g_param_spec_string(NM_SETTING_IP_TUNNEL_LOCAL, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:remote: - * - * The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 - * address. - * - * Since: 1.2 - **/ - obj_properties[PROP_REMOTE] = g_param_spec_string( - NM_SETTING_IP_TUNNEL_REMOTE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:ttl - * - * The TTL to assign to tunneled packets. 0 is a special value meaning that - * packets inherit the TTL value. - * - * Since: 1.2 - **/ - obj_properties[PROP_TTL] = - g_param_spec_uint(NM_SETTING_IP_TUNNEL_TTL, - "", - "", - 0, - 255, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:tos - * - * The type of service (IPv4) or traffic class (IPv6) field to be set on - * tunneled packets. - * - * Since: 1.2 - **/ - obj_properties[PROP_TOS] = - g_param_spec_uint(NM_SETTING_IP_TUNNEL_TOS, - "", - "", - 0, - 255, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:path-mtu-discovery - * - * Whether to enable Path MTU Discovery on this tunnel. - * - * Since: 1.2 - **/ - obj_properties[PROP_PATH_MTU_DISCOVERY] = g_param_spec_boolean( - NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, - "", - "", - TRUE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:input-key: - * - * The key used for tunnel input packets; the property is valid only for - * certain tunnel modes (GRE, IP6GRE). If empty, no key is used. - * - * Since: 1.2 - **/ - obj_properties[PROP_INPUT_KEY] = g_param_spec_string( - NM_SETTING_IP_TUNNEL_INPUT_KEY, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:output-key: - * - * The key used for tunnel output packets; the property is valid only for - * certain tunnel modes (GRE, IP6GRE). If empty, no key is used. - * - * Since: 1.2 - **/ - obj_properties[PROP_OUTPUT_KEY] = g_param_spec_string( - NM_SETTING_IP_TUNNEL_OUTPUT_KEY, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:encapsulation-limit: - * - * How many additional levels of encapsulation are permitted to be prepended - * to packets. This property applies only to IPv6 tunnels. - * - * Since: 1.2 - **/ - obj_properties[PROP_ENCAPSULATION_LIMIT] = - g_param_spec_uint(NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, - "", - "", - 0, - 255, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:flow-label: - * - * The flow label to assign to tunnel packets. This property applies only to - * IPv6 tunnels. - * - * Since: 1.2 - **/ - obj_properties[PROP_FLOW_LABEL] = - g_param_spec_uint(NM_SETTING_IP_TUNNEL_FLOW_LABEL, - "", - "", - 0, - (1 << 20) - 1, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:mtu: - * - * If non-zero, only transmit packets of the specified size or smaller, - * breaking larger packets up into multiple fragments. - * - * Since: 1.2 - **/ - obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_IP_TUNNEL_MTU, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPTunnel:flags: - * - * Tunnel flags. Currently, the following values are supported: - * %NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT, %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS, - * %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL, %NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV, - * %NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY, %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK. - * They are valid only for IPv6 tunnels. - * - * Since: 1.12 - **/ - obj_properties[PROP_FLAGS] = g_param_spec_uint(NM_SETTING_IP_TUNNEL_FLAGS, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_IP_TUNNEL); -} diff --git a/libnm-core/nm-setting-ip-tunnel.h b/libnm-core/nm-setting-ip-tunnel.h deleted file mode 100644 index 802f81e113..0000000000 --- a/libnm-core/nm-setting-ip-tunnel.h +++ /dev/null @@ -1,122 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_IP_TUNNEL_H__ -#define __NM_SETTING_IP_TUNNEL_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_IP_TUNNEL (nm_setting_ip_tunnel_get_type()) -#define NM_SETTING_IP_TUNNEL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnel)) -#define NM_SETTING_IP_TUNNEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelClass)) -#define NM_IS_SETTING_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_IP_TUNNEL)) -#define NM_IS_SETTING_IP_TUNNEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_IP_TUNNEL)) -#define NM_SETTING_IP_TUNNEL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelClass)) - -#define NM_SETTING_IP_TUNNEL_SETTING_NAME "ip-tunnel" - -#define NM_SETTING_IP_TUNNEL_PARENT "parent" -#define NM_SETTING_IP_TUNNEL_MODE "mode" -#define NM_SETTING_IP_TUNNEL_LOCAL "local" -#define NM_SETTING_IP_TUNNEL_REMOTE "remote" -#define NM_SETTING_IP_TUNNEL_TTL "ttl" -#define NM_SETTING_IP_TUNNEL_TOS "tos" -#define NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY "path-mtu-discovery" -#define NM_SETTING_IP_TUNNEL_INPUT_KEY "input-key" -#define NM_SETTING_IP_TUNNEL_OUTPUT_KEY "output-key" -#define NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit" -#define NM_SETTING_IP_TUNNEL_FLOW_LABEL "flow-label" -#define NM_SETTING_IP_TUNNEL_MTU "mtu" -#define NM_SETTING_IP_TUNNEL_FLAGS "flags" - -/** - * NMSettingIPTunnel: - * - * IP Tunneling Settings - */ -struct _NMSettingIPTunnel { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingIPTunnelClass; - -/* - * NMIPTunnelFlags: - * @NM_IP_TUNNEL_FLAG_NONE: no flag - * @NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT: don't add encapsulation limit - * if one isn't present in inner packet - * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS: copy the traffic class field - * from the inner packet - * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL: copy the flowlabel from the - * inner packet - * @NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV: used for Mobile IPv6 - * @NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY: copy DSCP from the outer packet - * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK: copy fwmark from inner packet - * - * IP tunnel flags. - * - * Since: 1.12 - */ -typedef enum { /*< flags, prefix=NM_IP_TUNNEL_FLAG >*/ - NM_IP_TUNNEL_FLAG_NONE = 0x0, - NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT = 0x1, - NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS = 0x2, - NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL = 0x4, - NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV = 0x8, - NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY = 0x10, - NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK = 0x20, -} NMIPTunnelFlags; - -NM_AVAILABLE_IN_1_2 -GType nm_setting_ip_tunnel_get_type(void); - -NM_AVAILABLE_IN_1_2 -NMSetting *nm_setting_ip_tunnel_new(void); - -NM_AVAILABLE_IN_1_2 -const char *nm_setting_ip_tunnel_get_parent(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -NMIPTunnelMode nm_setting_ip_tunnel_get_mode(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_ip_tunnel_get_local(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_ip_tunnel_get_remote(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_ip_tunnel_get_ttl(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_ip_tunnel_get_tos(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_ip_tunnel_get_path_mtu_discovery(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_ip_tunnel_get_input_key(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_ip_tunnel_get_output_key(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_ip_tunnel_get_flow_label(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_ip_tunnel_get_mtu(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_12 -NMIPTunnelFlags nm_setting_ip_tunnel_get_flags(NMSettingIPTunnel *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_IP_TUNNEL_H__ */ diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c deleted file mode 100644 index 4e5ff0f471..0000000000 --- a/libnm-core/nm-setting-ip4-config.c +++ /dev/null @@ -1,1033 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ip4-config.h" - -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-ip4-config - * @short_description: Describes IPv4 addressing, routing, and name service properties - * - * The #NMSettingIP4Config object is a #NMSetting subclass that describes - * properties related to IPv4 addressing, routing, and Domain Name Service. - * - * #NMSettingIP4Config has few properties or methods of its own; it inherits - * almost everything from #NMSettingIPConfig. - * - * NetworkManager supports 5 values for the #NMSettingIPConfig:method property - * for IPv4. If "auto" is specified then the appropriate automatic method - * (DHCP, PPP, etc) is used for the interface and most other properties can be - * left unset. If "link-local" is specified, then a link-local address in the - * 169.254/16 range will be assigned to the interface. If "manual" is - * specified, static IP addressing is used and at least one IP address must be - * given in the "addresses" property. If "shared" is specified (indicating that - * this connection will provide network access to other computers) then the - * interface is assigned an address in the 10.42.x.1/24 range and a DHCP and - * forwarding DNS server are started, and the interface is NAT-ed to the current - * default network connection. "disabled" means IPv4 will not be used on this - * connection. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_DHCP_CLIENT_ID, - PROP_DHCP_FQDN, - PROP_DHCP_VENDOR_CLASS_IDENTIFIER, ); - -typedef struct { - char *dhcp_client_id; - char *dhcp_fqdn; - char *dhcp_vendor_class_identifier; -} NMSettingIP4ConfigPrivate; - -G_DEFINE_TYPE(NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG) - -#define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_ip4_config_get_dhcp_client_id: - * @setting: the #NMSettingIP4Config - * - * Returns the value contained in the #NMSettingIP4Config:dhcp-client-id - * property. - * - * Returns: the configured Client ID to send to the DHCP server when requesting - * addresses via DHCP. - **/ -const char * -nm_setting_ip4_config_get_dhcp_client_id(NMSettingIP4Config *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL); - - return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_client_id; -} - -/** - * nm_setting_ip4_config_get_dhcp_fqdn: - * @setting: the #NMSettingIP4Config - * - * Returns the value contained in the #NMSettingIP4Config:dhcp-fqdn - * property. - * - * Returns: the configured FQDN to send to the DHCP server - * - * Since: 1.2 - **/ -const char * -nm_setting_ip4_config_get_dhcp_fqdn(NMSettingIP4Config *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL); - - return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_fqdn; -} - -/** - * nm_setting_ip4_config_get_dhcp_vendor_class_identifier: - * @setting: the #NMSettingIP4Config - * - * Returns the value contained in the #NMSettingIP4Config:dhcp_vendor_class_identifier - * property. - * - * Returns: the vendor class identifier option to send to the DHCP server - * - * Since: 1.28 - **/ -const char * -nm_setting_ip4_config_get_dhcp_vendor_class_identifier(NMSettingIP4Config *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL); - - return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_vendor_class_identifier; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting); - NMSettingIPConfig * s_ip = NM_SETTING_IP_CONFIG(setting); - NMSettingVerifyResult ret; - const char * method; - - ret = NM_SETTING_CLASS(nm_setting_ip4_config_parent_class)->verify(setting, connection, error); - if (ret != NM_SETTING_VERIFY_SUCCESS) - return ret; - - method = nm_setting_ip_config_get_method(s_ip); - /* Base class already checked that it exists */ - g_assert(method); - - if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { - if (nm_setting_ip_config_get_num_addresses(s_ip) == 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("this property cannot be empty for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - } else if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) - || !strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) - || !strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { - if (nm_setting_ip_config_get_num_dns(s_ip) > 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("this property is not allowed for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DNS); - return FALSE; - } - - if (nm_setting_ip_config_get_num_dns_searches(s_ip) > 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("this property is not allowed for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DNS_SEARCH); - return FALSE; - } - - /* Shared allows IP addresses; link-local and disabled do not */ - if (strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) { - if (nm_setting_ip_config_get_num_addresses(s_ip) > 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("this property is not allowed for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - } - } else if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { - /* nothing to do */ - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_METHOD); - return FALSE; - } - - if (priv->dhcp_client_id && !priv->dhcp_client_id[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID); - return FALSE; - } - - if (priv->dhcp_fqdn && !*priv->dhcp_fqdn) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP4_CONFIG_DHCP_FQDN); - return FALSE; - } - - if (priv->dhcp_fqdn && !strchr(priv->dhcp_fqdn, '.')) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid FQDN"), - priv->dhcp_fqdn); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP4_CONFIG_DHCP_FQDN); - return FALSE; - } - - if (priv->dhcp_fqdn && nm_setting_ip_config_get_dhcp_hostname(s_ip)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property cannot be set when dhcp-hostname is also set")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP4_CONFIG_DHCP_FQDN); - return FALSE; - } - - if (NM_FLAGS_ANY(nm_setting_ip_config_get_dhcp_hostname_flags(s_ip), - NM_DHCP_HOSTNAME_FLAGS_FQDN_MASK) - && !priv->dhcp_fqdn) { - /* Currently, we send a FQDN option only when ipv4.dhcp-fqdn is set */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("FQDN flags requires a FQDN set")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS); - return FALSE; - } - - if (priv->dhcp_vendor_class_identifier - && !nm_utils_validate_dhcp4_vendor_class_id(priv->dhcp_vendor_class_identifier, error)) - return FALSE; - - /* Failures from here on are NORMALIZABLE_ERROR... */ - - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) - && nm_setting_ip_config_get_num_addresses(s_ip) > 1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("multiple addresses are not allowed for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_SHARED); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - /* Failures from here on are NORMALIZABLE... */ - - if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) - && !nm_setting_ip_config_get_may_fail(s_ip)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property should be TRUE when method is set to disabled")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_MAY_FAIL); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - - return TRUE; -} - -static GVariant * -ip4_dns_to_dbus(const GValue *prop_value) -{ - return nm_utils_ip4_dns_to_variant(g_value_get_boxed(prop_value)); -} - -static void -ip4_dns_from_dbus(GVariant *dbus_value, GValue *prop_value) -{ - g_value_take_boxed(prop_value, nm_utils_ip4_dns_from_variant(dbus_value)); -} - -static GVariant * -ip4_addresses_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *addrs = NULL; - const char * gateway; - - g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); - gateway = nm_setting_ip_config_get_gateway(NM_SETTING_IP_CONFIG(setting)); - return nm_utils_ip4_addresses_to_variant(addrs, gateway); -} - -static gboolean -ip4_addresses_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *addrs; - GVariant * s_ip4; - char ** labels, *gateway = NULL; - int i; - - /* FIXME: properly handle errors */ - - if (!_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) - return TRUE; - - addrs = nm_utils_ip4_addresses_from_variant(value, &gateway); - - s_ip4 = g_variant_lookup_value(connection_dict, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - if (g_variant_lookup(s_ip4, "address-labels", "^as", &labels)) { - for (i = 0; i < addrs->len && labels[i]; i++) - if (*labels[i]) - nm_ip_address_set_attribute(addrs->pdata[i], - NM_IP_ADDRESS_ATTRIBUTE_LABEL, - g_variant_new_string(labels[i])); - g_strfreev(labels); - } - g_variant_unref(s_ip4); - - g_object_set(setting, - NM_SETTING_IP_CONFIG_ADDRESSES, - addrs, - NM_SETTING_IP_CONFIG_GATEWAY, - gateway, - NULL); - g_ptr_array_unref(addrs); - g_free(gateway); - return TRUE; -} - -static GVariant * -ip4_address_labels_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG(setting); - gboolean have_labels = FALSE; - GPtrArray * labels; - GVariant * ret; - int num_addrs, i; - - if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - return NULL; - - num_addrs = nm_setting_ip_config_get_num_addresses(s_ip); - for (i = 0; i < num_addrs; i++) { - NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i); - GVariant * label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - - if (label) { - have_labels = TRUE; - break; - } - } - if (!have_labels) - return NULL; - - labels = g_ptr_array_sized_new(num_addrs); - for (i = 0; i < num_addrs; i++) { - NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i); - GVariant * label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - - g_ptr_array_add(labels, (char *) (label ? g_variant_get_string(label, NULL) : "")); - } - - ret = g_variant_new_strv((const char *const *) labels->pdata, labels->len); - g_ptr_array_unref(labels); - - return ret; -} - -static GVariant * -ip4_address_data_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *addrs = NULL; - - if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - return NULL; - - g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); - return nm_utils_ip_addresses_to_variant(addrs); -} - -static gboolean -ip4_address_data_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *addrs; - - /* FIXME: properly handle errors */ - - /* Ignore 'address-data' if we're going to process 'addresses' */ - if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) - return TRUE; - - addrs = nm_utils_ip_addresses_from_variant(value, AF_INET); - g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); - g_ptr_array_unref(addrs); - return TRUE; -} - -static GVariant * -ip4_routes_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *routes = NULL; - - g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL); - return nm_utils_ip4_routes_to_variant(routes); -} - -static gboolean -ip4_routes_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *routes; - - /* FIXME: properly handle errors */ - - if (!_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) - return TRUE; - - routes = nm_utils_ip4_routes_from_variant(value); - g_object_set(setting, property, routes, NULL); - g_ptr_array_unref(routes); - return TRUE; -} - -static GVariant * -ip4_route_data_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *routes = NULL; - - if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - return NULL; - - g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL); - return nm_utils_ip_routes_to_variant(routes); -} - -static gboolean -ip4_route_data_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *routes; - - /* FIXME: properly handle errors */ - - /* Ignore 'route-data' if we're going to process 'routes' */ - if (_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) - return TRUE; - - routes = nm_utils_ip_routes_from_variant(value, AF_INET); - g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); - g_ptr_array_unref(routes); - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingIP4Config *s_ip4 = NM_SETTING_IP4_CONFIG(object); - - switch (prop_id) { - case PROP_DHCP_CLIENT_ID: - g_value_set_string(value, nm_setting_ip4_config_get_dhcp_client_id(s_ip4)); - break; - case PROP_DHCP_FQDN: - g_value_set_string(value, nm_setting_ip4_config_get_dhcp_fqdn(s_ip4)); - break; - case PROP_DHCP_VENDOR_CLASS_IDENTIFIER: - g_value_set_string(value, nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_DHCP_CLIENT_ID: - g_free(priv->dhcp_client_id); - priv->dhcp_client_id = g_value_dup_string(value); - break; - case PROP_DHCP_FQDN: - g_free(priv->dhcp_fqdn); - priv->dhcp_fqdn = g_value_dup_string(value); - break; - case PROP_DHCP_VENDOR_CLASS_IDENTIFIER: - g_free(priv->dhcp_vendor_class_identifier); - priv->dhcp_vendor_class_identifier = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ip4_config_init(NMSettingIP4Config *setting) -{} - -/** - * nm_setting_ip4_config_new: - * - * Creates a new #NMSettingIP4Config object with default values. - * - * Returns: (transfer full): the new empty #NMSettingIP4Config object - **/ -NMSetting * -nm_setting_ip4_config_new(void) -{ - return g_object_new(NM_TYPE_SETTING_IP4_CONFIG, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(object); - - g_free(priv->dhcp_client_id); - g_free(priv->dhcp_fqdn); - g_free(priv->dhcp_vendor_class_identifier); - - G_OBJECT_CLASS(nm_setting_ip4_config_parent_class)->finalize(object); -} - -static void -nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array_ip_config(); - - g_type_class_add_private(setting_class, sizeof(NMSettingIP4ConfigPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /* ---ifcfg-rh--- - * property: method - * variable: BOOTPROTO - * format: string - * values: none, dhcp (bootp), static, ibft, autoip, shared - * default: none - * description: Method used for IPv4 protocol configuration. - * ---end--- - */ - - /* ---keyfile--- - * property: dns - * format: list of DNS IP addresses - * description: List of DNS servers. - * example: dns=1.2.3.4;8.8.8.8;8.8.4.4; - * ---end--- - * ---ifcfg-rh--- - * property: dns - * variable: DNS1, DNS2, ... - * format: string - * description: List of DNS servers. Even if NetworkManager supports many DNS - * servers, initscripts and resolver only care about the first three, usually. - * example: DNS1=1.2.3.4 DNS2=10.0.0.254 DNS3=8.8.8.8 - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dns-search - * variable: DOMAIN - * format: string (space-separated domains) - * description: List of DNS search domains. - * ---end--- - */ - - /* ---keyfile--- - * property: addresses - * variable: address1, address2, ... - * format: address/plen - * description: List of static IP addresses. - * example: address1=192.168.100.100/24 address2=10.1.1.5/24 - * ---end--- - * ---ifcfg-rh--- - * property: addresses - * variable: IPADDR, PREFIX (NETMASK), IPADDR1, PREFIX1 (NETMASK1), ... - * description: List of static IP addresses. - * example: IPADDR=10.5.5.23 PREFIX=24 IPADDR1=1.1.1.2 PREFIX1=16 - * ---end--- - */ - - /* ---keyfile--- - * property: gateway - * variable: gateway - * format: string - * description: Gateway IP addresses as a string. - * example: gateway=192.168.100.1 - * ---end--- - * ---ifcfg-rh--- - * property: gateway - * variable: GATEWAY - * description: Gateway IP address. - * example: GATEWAY=10.5.5.1 - * ---end--- - */ - - /* ---keyfile--- - * property: routes - * variable: route1, route2, ... - * format: route/plen[,gateway,metric] - * description: List of IP routes. - * example: route1=8.8.8.0/24,10.1.1.1,77 - * route2=7.7.0.0/16 - * ---end--- - * ---ifcfg-rh--- - * property: routes - * variable: ADDRESS1, NETMASK1, GATEWAY1, METRIC1, OPTIONS1, ... - * description: List of static routes. They are not stored in ifcfg-* file, - * but in route-* file instead. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: ignore-auto-routes - * variable: PEERROUTES(+) - * default: yes - * description: PEERROUTES has the opposite meaning as 'ignore-auto-routes' property. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: ignore-auto-dns - * variable: PEERDNS - * default: yes - * description: PEERDNS has the opposite meaning as 'ignore-auto-dns' property. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dhcp-send-hostname - * variable: DHCP_SEND_HOSTNAME(+) - * default: yes - * description: Whether DHCP_HOSTNAME should be sent to the DHCP server. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dhcp-hostname - * variable: DHCP_HOSTNAME - * description: Hostname to send to the DHCP server. When both DHCP_HOSTNAME and - * DHCP_FQDN are specified only the latter is used. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: never-default - * variable: DEFROUTE (GATEWAYDEV in /etc/sysconfig/network) - * default: yes - * description: DEFROUTE=no tells NetworkManager that this connection - * should not be assigned the default route. DEFROUTE has the opposite - * meaning as 'never-default' property. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: may-fail - * variable: IPV4_FAILURE_FATAL(+) - * default: no - * description: IPV4_FAILURE_FATAL has the opposite meaning as 'may-fail' property. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: route-metric - * variable: IPV4_ROUTE_METRIC(+) - * default: -1 - * description: IPV4_ROUTE_METRIC is the default IPv4 metric for routes on this connection. - * If set to -1, a default metric based on the device type is used. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: route-table - * variable: IPV4_ROUTE_TABLE(+) - * default: 0 - * description: IPV4_ROUTE_TABLE enables policy-routing and sets the default routing table. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dns-options - * variable: RES_OPTIONS(+) - * description: List of DNS options to be added to /etc/resolv.conf - * example: RES_OPTIONS=ndots:2 timeout:3 - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dns-priority - * variable: IPV4_DNS_PRIORITY(+) - * description: The priority for DNS servers of this connection. Lower values have higher priority. - * If zero, the default value will be used (50 for VPNs, 100 for other connections). - * A negative value prevents DNS from other connections with greater values to be used. - * default: 0 - * example: IPV4_DNS_PRIORITY=20 - * ---end--- - */ - - /** - * NMSettingIP4Config:dhcp-client-id: - * - * A string sent to the DHCP server to identify the local machine which the - * DHCP server may use to customize the DHCP lease and options. - * When the property is a hex string ('aa:bb:cc') it is interpreted as a - * binary client ID, in which case the first byte is assumed to be the - * 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be - * an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet - * ARP type and the rest is a MAC address). - * If the property is not a hex string it is considered as a - * non-hardware-address client ID and the 'type' field is set to 0. - * - * The special values "mac" and "perm-mac" are supported, which use the - * current or permanent MAC address of the device to generate a client identifier - * with type ethernet (01). Currently, these options only work for ethernet - * type of links. - * - * The special value "ipv6-duid" uses the DUID from "ipv6.dhcp-duid" property as - * an RFC4361-compliant client identifier. As IAID it uses "ipv4.dhcp-iaid" - * and falls back to "ipv6.dhcp-iaid" if unset. - * - * The special value "duid" generates a RFC4361-compliant client identifier based - * on "ipv4.dhcp-iaid" and uses a DUID generated by hashing /etc/machine-id. - * - * The special value "stable" is supported to generate a type 0 client identifier based - * on the stable-id (see connection.stable-id) and a per-host key. If you set the - * stable-id, you may want to include the "${DEVICE}" or "${MAC}" specifier to get a - * per-device key. - * - * If unset, a globally configured default is used. If still unset, the default - * depends on the DHCP plugin. - **/ - /* ---ifcfg-rh--- - * property: dhcp-client-id - * variable: DHCP_CLIENT_ID(+) - * description: A string sent to the DHCP server to identify the local machine. - * A binary value can be specified using hex notation ('aa:bb:cc'). - * example: DHCP_CLIENT_ID=ax-srv-1; DHCP_CLIENT_ID=01:44:44:44:44:44:44 - * ---end--- - */ - obj_properties[PROP_DHCP_CLIENT_ID] = - g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /* ---ifcfg-rh--- - * property: dad-timeout - * variable: ACD_TIMEOUT(+), ARPING_WAIT - * default: missing variable means global default (config override or zero) - * description: Timeout (in milliseconds for ACD_TIMEOUT or in seconds - * for ARPING_WAIT) for address conflict detection before configuring - * IPv4 addresses. 0 turns off the ACD completely, -1 means default value. - * example: ACD_TIMEOUT=2000 or ARPING_WAIT=2 - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dhcp-timeout - * variable: IPV4_DHCP_TIMEOUT(+) - * description: A timeout after which the DHCP transaction fails in case of no response. - * example: IPV4_DHCP_TIMEOUT=10 - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dhcp-hostname-flags - * variable: DHCP_HOSTNAME_FLAGS - * description: flags for the DHCP hostname and FQDN properties - * example: DHCP_HOSTNAME_FLAGS=5 - */ - - /** - * NMSettingIP4Config:dhcp-fqdn: - * - * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the - * specified FQDN will be sent to the DHCP server when acquiring a lease. This - * property and #NMSettingIPConfig:dhcp-hostname are mutually exclusive and - * cannot be set at the same time. - * - * Since: 1.2 - */ - /* ---ifcfg-rh--- - * property: dhcp-fqdn - * variable: DHCP_FQDN - * description: FQDN to send to the DHCP server. When both DHCP_HOSTNAME and - * DHCP_FQDN are specified only the latter is used. - * example: DHCP_FQDN=foo.bar.com - * ---end--- - */ - obj_properties[PROP_DHCP_FQDN] = - g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_FQDN, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIP4Config:dhcp-vendor-class-identifier: - * - * The Vendor Class Identifier DHCP option (60). - * Special characters in the data string may be escaped using C-style escapes, - * nevertheless this property cannot contain nul bytes. - * If the per-profile value is unspecified (the default), - * a global connection default gets consulted. - * If still unspecified, the DHCP option is not sent to the server. - * - * Since 1.28 - */ - /* ---ifcfg-rh--- - * property: dhcp-vendor-class-identifier - * variable: DHCP_VENDOR_CLASS_IDENTIFIER(+) - * description: The Vendor Class Identifier DHCP option (60). - * example: DHCP_VENDOR_CLASS_IDENTIFIER=foo - * ---end--- - */ - obj_properties[PROP_DHCP_VENDOR_CLASS_IDENTIFIER] = - g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /* IP4-specific property overrides */ - - /* ---dbus--- - * property: dns - * format: array of uint32 - * description: Array of IP addresses of DNS servers (as network-byte-order - * integers) - * ---end--- - */ - _nm_properties_override_gobj( - properties_override, - g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS), - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("au"), - .gprop_to_dbus_fcn = ip4_dns_to_dbus, - .gprop_from_dbus_fcn = ip4_dns_from_dbus, )); - - /* ---dbus--- - * property: addresses - * format: array of array of uint32 - * description: Deprecated in favor of the 'address-data' and 'gateway' - * properties, but this can be used for backward-compatibility with older - * daemons. Note that if you send this property the daemon will ignore - * 'address-data' and 'gateway'. - * - * Array of IPv4 address structures. Each IPv4 address structure is - * composed of 3 32-bit values; the first being the IPv4 address (network - * byte order), the second the prefix (1 - 32), and last the IPv4 gateway - * (network byte order). The gateway may be left as 0 if no gateway exists - * for that subnet. - * ---end--- - */ - /* ---nmcli--- - * property: addresses - * format: a comma separated list of addresses - * description: A list of IPv4 addresses and their prefix length. Multiple addresses - * can be separated by comma. For example "192.168.1.5/24, 10.1.0.5/24". - * ---end--- - */ - _nm_properties_override_gobj( - properties_override, - g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES), - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aau"), - .to_dbus_fcn = ip4_addresses_get, - .from_dbus_fcn = ip4_addresses_set, )); - _nm_properties_override_dbus( - properties_override, - "address-labels", - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING_ARRAY, - .to_dbus_fcn = ip4_address_labels_get, )); - - /* ---dbus--- - * property: address-data - * format: array of vardict - * description: Array of IPv4 addresses. Each address dictionary contains at - * least 'address' and 'prefix' entries, containing the IP address as a - * string, and the prefix length as a uint32. Additional attributes may - * also exist on some addresses. - * ---end--- - */ - _nm_properties_override_dbus( - properties_override, - "address-data", - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip4_address_data_get, - .from_dbus_fcn = ip4_address_data_set, )); - - /* ---dbus--- - * property: routes - * format: array of array of uint32 - * description: Deprecated in favor of the 'route-data' property, but this - * can be used for backward-compatibility with older daemons. Note that if - * you send this property the daemon will ignore 'route-data'. - * - * Array of IPv4 route structures. Each IPv4 route structure is composed - * of 4 32-bit values; the first being the destination IPv4 network or - * address (network byte order), the second the destination network or - * address prefix (1 - 32), the third being the next-hop (network byte - * order) if any, and the fourth being the route metric. If the metric is - * 0, NM will choose an appropriate default metric for the device. (There - * is no way to explicitly specify an actual metric of 0 with this - * property.) - * ---end--- - */ - _nm_properties_override_gobj( - properties_override, - g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES), - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aau"), - .to_dbus_fcn = ip4_routes_get, - .from_dbus_fcn = ip4_routes_set, )); - - /* ---dbus--- - * property: route-data - * format: array of vardict - * description: Array of IPv4 routes. Each route dictionary contains at - * least 'dest' and 'prefix' entries, containing the destination IP - * address as a string, and the prefix length as a uint32. Most routes - * will also have a 'next-hop' entry, containing the next hop IP address as - * a string. If the route has a 'metric' entry (containing a uint32), that - * will be used as the metric for the route (otherwise NM will pick a - * default value appropriate to the device). Additional attributes may - * also exist on some routes. - * ---end--- - */ - _nm_properties_override_dbus(properties_override, - "route-data", - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip4_route_data_get, - .from_dbus_fcn = ip4_route_data_set, )); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_IP4_CONFIG, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-ip4-config.h b/libnm-core/nm-setting-ip4-config.h deleted file mode 100644 index b1c63a4f6e..0000000000 --- a/libnm-core/nm-setting-ip4-config.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_IP4_CONFIG_H__ -#define __NM_SETTING_IP4_CONFIG_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting-ip-config.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_IP4_CONFIG (nm_setting_ip4_config_get_type()) -#define NM_SETTING_IP4_CONFIG(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4Config)) -#define NM_SETTING_IP4_CONFIG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_IP4CONFIG, NMSettingIP4ConfigClass)) -#define NM_IS_SETTING_IP4_CONFIG(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_IP4_CONFIG)) -#define NM_IS_SETTING_IP4_CONFIG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_IP4_CONFIG)) -#define NM_SETTING_IP4_CONFIG_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigClass)) - -#define NM_SETTING_IP4_CONFIG_SETTING_NAME "ipv4" - -#define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID "dhcp-client-id" -#define NM_SETTING_IP4_CONFIG_DHCP_FQDN "dhcp-fqdn" -#define NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER "dhcp-vendor-class-identifier" - -/** - * NM_SETTING_IP4_CONFIG_METHOD_AUTO: - * - * IPv4 configuration should be automatically determined via a method appropriate - * for the hardware interface, ie DHCP or PPP or some other device-specific - * manner. - */ -#define NM_SETTING_IP4_CONFIG_METHOD_AUTO "auto" - -/** - * NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL: - * - * IPv4 configuration should be automatically configured for link-local-only - * operation. - */ -#define NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL "link-local" - -/** - * NM_SETTING_IP4_CONFIG_METHOD_MANUAL: - * - * All necessary IPv4 configuration (addresses, prefix, DNS, etc) is specified - * in the setting's properties. - */ -#define NM_SETTING_IP4_CONFIG_METHOD_MANUAL "manual" - -/** - * NM_SETTING_IP4_CONFIG_METHOD_SHARED: - * - * This connection specifies configuration that allows other computers to - * connect through it to the default network (usually the Internet). The - * connection's interface will be assigned a private address, and a DHCP server, - * caching DNS server, and Network Address Translation (NAT) functionality will - * be started on this connection's interface to allow other devices to connect - * through that interface to the default network. - */ -#define NM_SETTING_IP4_CONFIG_METHOD_SHARED "shared" - -/** - * NM_SETTING_IP4_CONFIG_METHOD_DISABLED: - * - * This connection does not use or require IPv4 address and it should be disabled. - */ -#define NM_SETTING_IP4_CONFIG_METHOD_DISABLED "disabled" - -/** - * NMSettingIP4Config: - * - * IPv4 Settings - */ -struct _NMSettingIP4Config { - NMSettingIPConfig parent; -}; - -typedef struct { - NMSettingIPConfigClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingIP4ConfigClass; - -GType nm_setting_ip4_config_get_type(void); - -NMSetting *nm_setting_ip4_config_new(void); - -const char *nm_setting_ip4_config_get_dhcp_client_id(NMSettingIP4Config *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_ip4_config_get_dhcp_fqdn(NMSettingIP4Config *setting); - -NM_AVAILABLE_IN_1_28 -const char *nm_setting_ip4_config_get_dhcp_vendor_class_identifier(NMSettingIP4Config *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_IP4_CONFIG_H__ */ diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c deleted file mode 100644 index 06463f82f7..0000000000 --- a/libnm-core/nm-setting-ip6-config.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ip6-config.h" - -#include - -#include "nm-setting-private.h" -#include "nm-core-enum-types.h" -#include "nm-core-internal.h" - -/** - * SECTION:nm-setting-ip6-config - * @short_description: Describes IPv6 addressing, routing, and name service properties - * - * The #NMSettingIP6Config object is a #NMSetting subclass that describes - * properties related to IPv6 addressing, routing, and Domain Name Service - * - * #NMSettingIP6Config has few properties or methods of its own; it inherits - * almost everything from #NMSettingIPConfig. - * - * NetworkManager supports 7 values for the #NMSettingIPConfig:method property - * for IPv6. If "auto" is specified then the appropriate automatic method (PPP, - * router advertisement, etc) is used for the device and most other properties - * can be left unset. To force the use of DHCP only, specify "dhcp"; this - * method is only valid for Ethernet- based hardware. If "link-local" is - * specified, then an IPv6 link-local address will be assigned to the interface. - * If "manual" is specified, static IP addressing is used and at least one IP - * address must be given in the "addresses" property. If "ignore" is specified, - * IPv6 configuration is not done. Note: the "shared" method is not yet - * supported. If "disabled" is specified, IPv6 is disabled completely for the - * interface. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_IP6_PRIVACY, - PROP_ADDR_GEN_MODE, - PROP_TOKEN, - PROP_DHCP_DUID, - PROP_RA_TIMEOUT, ); - -typedef struct { - char * token; - char * dhcp_duid; - NMSettingIP6ConfigPrivacy ip6_privacy; - NMSettingIP6ConfigAddrGenMode addr_gen_mode; - gint32 ra_timeout; -} NMSettingIP6ConfigPrivate; - -G_DEFINE_TYPE(NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG) - -#define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_ip6_config_get_ip6_privacy: - * @setting: the #NMSettingIP6Config - * - * Returns the value contained in the #NMSettingIP6Config:ip6-privacy - * property. - * - * Returns: IPv6 Privacy Extensions configuration value (#NMSettingIP6ConfigPrivacy). - **/ -NMSettingIP6ConfigPrivacy -nm_setting_ip6_config_get_ip6_privacy(NMSettingIP6Config *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - - return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->ip6_privacy; -} - -/** - * nm_setting_ip6_config_get_addr_gen_mode: - * @setting: the #NMSettingIP6Config - * - * Returns the value contained in the #NMSettingIP6Config:addr-gen-mode - * property. - * - * Returns: IPv6 Address Generation Mode. - * - * Since: 1.2 - **/ -NMSettingIP6ConfigAddrGenMode -nm_setting_ip6_config_get_addr_gen_mode(NMSettingIP6Config *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY); - - return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->addr_gen_mode; -} - -/** - * nm_setting_ip6_config_get_token: - * @setting: the #NMSettingIP6Config - * - * Returns the value contained in the #NMSettingIP6Config:token - * property. - * - * Returns: A string. - * - * Since: 1.4 - **/ -const char * -nm_setting_ip6_config_get_token(NMSettingIP6Config *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), NULL); - - return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->token; -} - -/** - * nm_setting_ip6_config_get_dhcp_duid: - * @setting: the #NMSettingIP6Config - * - * Returns the value contained in the #NMSettingIP6Config:dhcp-duid - * property. - * - * Returns: The configured DUID value to be included in the DHCPv6 requests - * sent to the DHCPv6 servers. - * - * Since: 1.12 - **/ -const char * -nm_setting_ip6_config_get_dhcp_duid(NMSettingIP6Config *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), NULL); - - return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->dhcp_duid; -} - -/** - * nm_setting_ip6_config_get_ra_timeout: - * @setting: the #NMSettingIP6Config - * - * Returns: The configured %NM_SETTING_IP6_CONFIG_RA_TIMEOUT value with the - * timeout for router advertisements in seconds. - * - * Since: 1.24 - **/ -gint32 -nm_setting_ip6_config_get_ra_timeout(NMSettingIP6Config *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), 0); - - return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->ra_timeout; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting); - NMSettingIPConfig * s_ip = NM_SETTING_IP_CONFIG(setting); - NMSettingVerifyResult ret; - const char * method; - gboolean token_needs_normalization = FALSE; - - ret = NM_SETTING_CLASS(nm_setting_ip6_config_parent_class)->verify(setting, connection, error); - if (ret != NM_SETTING_VERIFY_SUCCESS) - return ret; - - method = nm_setting_ip_config_get_method(s_ip); - /* Base class already checked that it exists */ - g_assert(method); - - if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { - if (nm_setting_ip_config_get_num_addresses(s_ip) == 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("this property cannot be empty for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - } else if (NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_IGNORE, - NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, - NM_SETTING_IP6_CONFIG_METHOD_SHARED, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { - /* Shared allows IP addresses and DNS; other methods do not */ - if (!nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { - if (nm_setting_ip_config_get_num_dns(s_ip) > 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("this property is not allowed for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DNS); - return FALSE; - } - - if (nm_setting_ip_config_get_num_dns_searches(s_ip) > 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("this property is not allowed for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_DNS_SEARCH); - return FALSE; - } - - if (nm_setting_ip_config_get_num_addresses(s_ip) > 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("this property is not allowed for '%s=%s'"), - NM_SETTING_IP_CONFIG_METHOD, - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - } - } else if (NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { - /* nothing to do */ - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_METHOD); - return FALSE; - } - - if (!NM_IN_SET(priv->addr_gen_mode, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE); - return FALSE; - } - - if (priv->token) { - if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { - struct in6_addr i6_token; - char s_token[NM_UTILS_INET_ADDRSTRLEN]; - - if (inet_pton(AF_INET6, priv->token, &i6_token) != 1 - || !_nm_utils_inet6_is_token(&i6_token)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value is not a valid token")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_TOKEN); - return FALSE; - } - - if (g_strcmp0(priv->token, _nm_utils_inet6_ntop(&i6_token, s_token))) - token_needs_normalization = TRUE; - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("only makes sense with EUI64 address generation mode")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_TOKEN); - return FALSE; - } - } - - if (priv->dhcp_duid) { - if (!_nm_utils_dhcp_duid_valid(priv->dhcp_duid, NULL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid DUID")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_DHCP_DUID); - return FALSE; - } - } - - /* Failures from here on, are NORMALIZABLE_ERROR... */ - - if (token_needs_normalization) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("token is not in canonical form")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_TOKEN); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - /* Failures from here on are NORMALIZABLE... */ - - if (NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_IGNORE, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED) - && !nm_setting_ip_config_get_may_fail(s_ip)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property should be TRUE when method is set to ignore or disabled")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_MAY_FAIL); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - - return TRUE; -} - -static GVariant * -ip6_dns_to_dbus(const GValue *prop_value) -{ - return nm_utils_ip6_dns_to_variant(g_value_get_boxed(prop_value)); -} - -static void -ip6_dns_from_dbus(GVariant *dbus_value, GValue *prop_value) -{ - g_value_take_boxed(prop_value, nm_utils_ip6_dns_from_variant(dbus_value)); -} - -static GVariant * -ip6_addresses_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *addrs = NULL; - const char * gateway; - - g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); - gateway = nm_setting_ip_config_get_gateway(NM_SETTING_IP_CONFIG(setting)); - return nm_utils_ip6_addresses_to_variant(addrs, gateway); -} - -static gboolean -ip6_addresses_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *addrs; - char * gateway = NULL; - - /* FIXME: properly handle errors */ - - if (!_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) - return TRUE; - - addrs = nm_utils_ip6_addresses_from_variant(value, &gateway); - - g_object_set(setting, - NM_SETTING_IP_CONFIG_ADDRESSES, - addrs, - NM_SETTING_IP_CONFIG_GATEWAY, - gateway, - NULL); - g_ptr_array_unref(addrs); - g_free(gateway); - return TRUE; -} - -static GVariant * -ip6_address_data_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *addrs = NULL; - - if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - return NULL; - - g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); - return nm_utils_ip_addresses_to_variant(addrs); -} - -static gboolean -ip6_address_data_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *addrs; - - /* FIXME: properly handle errors */ - - /* Ignore 'address-data' if we're going to process 'addresses' */ - if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) - return TRUE; - - addrs = nm_utils_ip_addresses_from_variant(value, AF_INET6); - g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); - g_ptr_array_unref(addrs); - return TRUE; -} - -static GVariant * -ip6_routes_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *routes = NULL; - - g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL); - return nm_utils_ip6_routes_to_variant(routes); -} - -static gboolean -ip6_routes_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *routes; - - /* FIXME: properly handle errors */ - - if (!_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) - return TRUE; - - routes = nm_utils_ip6_routes_from_variant(value); - g_object_set(setting, property, routes, NULL); - g_ptr_array_unref(routes); - return TRUE; -} - -static GVariant * -ip6_route_data_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *routes = NULL; - - if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - return NULL; - - g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL); - return nm_utils_ip_routes_to_variant(routes); -} - -static gboolean -ip6_route_data_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *routes; - - /* FIXME: properly handle errors */ - - /* Ignore 'route-data' if we're going to process 'routes' */ - if (_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) - return TRUE; - - routes = nm_utils_ip_routes_from_variant(value, AF_INET6); - g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); - g_ptr_array_unref(routes); - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_IP6_PRIVACY: - g_value_set_enum(value, priv->ip6_privacy); - break; - case PROP_ADDR_GEN_MODE: - g_value_set_int(value, priv->addr_gen_mode); - break; - case PROP_TOKEN: - g_value_set_string(value, priv->token); - break; - case PROP_DHCP_DUID: - g_value_set_string(value, priv->dhcp_duid); - break; - case PROP_RA_TIMEOUT: - g_value_set_int(value, priv->ra_timeout); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_IP6_PRIVACY: - priv->ip6_privacy = g_value_get_enum(value); - break; - case PROP_ADDR_GEN_MODE: - priv->addr_gen_mode = g_value_get_int(value); - break; - case PROP_TOKEN: - g_free(priv->token); - priv->token = g_value_dup_string(value); - break; - case PROP_DHCP_DUID: - g_free(priv->dhcp_duid); - priv->dhcp_duid = g_value_dup_string(value); - break; - case PROP_RA_TIMEOUT: - priv->ra_timeout = g_value_get_int(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ip6_config_init(NMSettingIP6Config *setting) -{ - NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting); - - priv->ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; - priv->addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY; -} - -/** - * nm_setting_ip6_config_new: - * - * Creates a new #NMSettingIP6Config object with default values. - * - * Returns: (transfer full): the new empty #NMSettingIP6Config object - **/ -NMSetting * -nm_setting_ip6_config_new(void) -{ - return g_object_new(NM_TYPE_SETTING_IP6_CONFIG, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingIP6Config * self = NM_SETTING_IP6_CONFIG(object); - NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(self); - - g_free(priv->token); - g_free(priv->dhcp_duid); - - G_OBJECT_CLASS(nm_setting_ip6_config_parent_class)->finalize(object); -} - -static void -nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array_ip_config(); - - g_type_class_add_private(klass, sizeof(NMSettingIP6ConfigPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /* ---ifcfg-rh--- - * property: method - * variable: IPV6INIT, IPV6FORWARDING, IPV6_AUTOCONF, DHCPV6C, IPV6_DISABLED - * default: IPV6INIT=yes; IPV6FORWARDING=no; IPV6_AUTOCONF=!IPV6FORWARDING, DHCPV6=no - * description: Method used for IPv6 protocol configuration. - * ignore ~ IPV6INIT=no; auto ~ IPV6_AUTOCONF=yes; dhcp ~ IPV6_AUTOCONF=no and DHCPV6C=yes; - * disabled ~ IPV6_DISABLED=yes - * ---end--- - */ - - /* ---keyfile--- - * property: dns - * format: list of DNS IP addresses - * description: List of DNS servers. - * example: dns=2001:4860:4860::8888;2001:4860:4860::8844; - * ---end--- - * ---ifcfg-rh--- - * property: dns - * variable: DNS1, DNS2, ... - * format: string - * description: List of DNS servers. NetworkManager uses the variables both - * for IPv4 and IPv6. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dns-search - * variable: IPV6_DOMAIN(+) - * format: string (space-separated domains) - * description: List of DNS search domains. - * ---end--- - */ - - /* ---keyfile--- - * property: addresses - * variable: address1, address2, ... - * format: address/plen - * description: List of static IP addresses. - * example: address1=abbe::cafe/96 address2=2001::1234 - * ---end--- - * ---ifcfg-rh--- - * property: addresses - * variable: IPV6ADDR, IPV6ADDR_SECONDARIES - * description: List of static IP addresses. - * example: IPV6ADDR=ab12:9876::1 - * IPV6ADDR_SECONDARIES="ab12:9876::2 ab12:9876::3" - * ---end--- - */ - - /* ---keyfile--- - * property: gateway - * variable: gateway - * format: string - * description: Gateway IP addresses as a string. - * example: gateway=abbe::1 - * ---end--- - * ---ifcfg-rh--- - * property: gateway - * variable: IPV6_DEFAULTGW - * description: Gateway IP address. - * example: IPV6_DEFAULTGW=abbe::1 - * ---end--- - */ - - /* ---keyfile--- - * property: routes - * variable: route1, route2, ... - * format: route/plen[,gateway,metric] - * description: List of IP routes. - * example: route1=2001:4860:4860::/64,2620:52:0:2219:222:68ff:fe11:5403 - * ---end--- - * ---ifcfg-rh--- - * property: routes - * variable: (none) - * description: List of static routes. They are not stored in ifcfg-* file, - * but in route6-* file instead in the form of command line for 'ip route add'. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: ignore-auto-routes - * variable: IPV6_PEERROUTES(+) - * default: yes - * description: IPV6_PEERROUTES has the opposite meaning as 'ignore-auto-routes' property. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: ignore-auto-dns - * variable: IPV6_PEERDNS(+) - * default: yes - * description: IPV6_PEERDNS has the opposite meaning as 'ignore-auto-dns' property. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dhcp-hostname - * variable: DHCPV6_HOSTNAME - * description: Hostname to send the DHCP server. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dhcp-timeout - * variable: IPV6_DHCP_TIMEOUT(+) - * description: A timeout after which the DHCP transaction fails in case of no response. - * example: IPV6_DHCP_TIMEOUT=10 - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dhcp-hostname-flags - * variable: DHCPV6_HOSTNAME_FLAGS - * description: flags for the DHCP hostname property - * example: DHCPV6_HOSTNAME_FLAGS=5 - */ - - /* ---ifcfg-rh--- - * property: never-default - * variable: IPV6_DEFROUTE(+), (and IPV6_DEFAULTGW, IPV6_DEFAULTDEV in /etc/sysconfig/network) - * default: IPV6_DEFROUTE=yes (when no variable specified) - * description: IPV6_DEFROUTE=no tells NetworkManager that this connection - * should not be assigned the default IPv6 route. IPV6_DEFROUTE has the opposite - * meaning as 'never-default' property. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: may-fail - * variable: IPV6_FAILURE_FATAL(+) - * default: no - * description: IPV6_FAILURE_FATAL has the opposite meaning as 'may-fail' property. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: route-metric - * variable: IPV6_ROUTE_METRIC(+) - * default: -1 - * description: IPV6_ROUTE_METRIC is the default IPv6 metric for routes on this connection. - * If set to -1, a default metric based on the device type is used. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: route-table - * variable: IPV6_ROUTE_TABLE(+) - * default: 0 - * description: IPV6_ROUTE_TABLE enables policy-routing and sets the default routing table. - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dns-priority - * variable: IPV6_DNS_PRIORITY(+) - * description: The priority for DNS servers of this connection. Lower values have higher priority. - * If zero, the default value will be used (50 for VPNs, 100 for other connections). - * A negative value prevents DNS from other connections with greater values to be used. - * default: 0 - * example: IPV6_DNS_PRIORITY=20 - * ---end--- - */ - - /* ---ifcfg-rh--- - * property: dns-options - * variable: IPV6_RES_OPTIONS(+) - * description: List of DNS options to be added to /etc/resolv.conf - * example: IPV6_RES_OPTIONS=ndots:2 timeout:3 - * ---end--- - */ - - /** - * NMSettingIP6Config:ip6-privacy: - * - * Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If - * enabled, it makes the kernel generate a temporary IPv6 address in - * addition to the public one generated from MAC address via modified - * EUI-64. This enhances privacy, but could cause problems in some - * applications, on the other hand. The permitted values are: -1: unknown, - * 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary - * addresses). - * - * Having a per-connection setting set to "-1" (unknown) means fallback to - * global configuration "ipv6.ip6-privacy". - * - * If also global configuration is unspecified or set to "-1", fallback to read - * "/proc/sys/net/ipv6/conf/default/use_tempaddr". - * - * Note that this setting is distinct from the Stable Privacy addresses - * that can be enabled with the "addr-gen-mode" property's "stable-privacy" - * setting as another way of avoiding host tracking with IPv6 addresses. - **/ - /* ---ifcfg-rh--- - * property: ip6-privacy - * variable: IPV6_PRIVACY, IPV6_PRIVACY_PREFER_PUBLIC_IP(+) - * values: IPV6_PRIVACY: no, yes (rfc3041 or rfc4941); - * IPV6_PRIVACY_PREFER_PUBLIC_IP: yes, no - * default: no - * description: Configure IPv6 Privacy Extensions for SLAAC (RFC4941). - * example: IPV6_PRIVACY=rfc3041 IPV6_PRIVACY_PREFER_PUBLIC_IP=yes - * ---end--- - */ - obj_properties[PROP_IP6_PRIVACY] = - g_param_spec_enum(NM_SETTING_IP6_CONFIG_IP6_PRIVACY, - "", - "", - NM_TYPE_SETTING_IP6_CONFIG_PRIVACY, - NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIP6Config:addr-gen-mode: - * - * Configure method for creating the address for use with RFC4862 IPv6 - * Stateless Address Autoconfiguration. The permitted values are: - * %NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 or - * %NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY. - * - * If the property is set to EUI64, the addresses will be generated - * using the interface tokens derived from hardware address. This makes - * the host part of the address to stay constant, making it possible - * to track host's presence when it changes networks. The address changes - * when the interface hardware is replaced. - * - * The value of stable-privacy enables use of cryptographically - * secure hash of a secret host-specific key along with the connection's - * stable-id and the network address as specified by RFC7217. - * This makes it impossible to use the address track host's presence, - * and makes the address stable when the network interface hardware is - * replaced. - * - * On D-Bus, the absence of an addr-gen-mode setting equals enabling - * stable-privacy. For keyfile plugin, the absence of the setting - * on disk means EUI64 so that the property doesn't change on upgrade - * from older versions. - * - * Note that this setting is distinct from the Privacy Extensions as - * configured by "ip6-privacy" property and it does not affect the - * temporary addresses configured with this option. - * - * Since: 1.2 - **/ - /* ---ifcfg-rh--- - * property: addr-gen-mode - * variable: IPV6_ADDR_GEN_MODE - * values: IPV6_ADDR_GEN_MODE: eui64, stable-privacy - * default: eui64 - * description: Configure IPv6 Stable Privacy addressing for SLAAC (RFC7217). - * example: IPV6_ADDR_GEN_MODE=stable-privacy - * ---end--- - */ - obj_properties[PROP_ADDR_GEN_MODE] = - g_param_spec_int(NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, - "", - "", - G_MININT, - G_MAXINT, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIP6Config:token: - * - * Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 - * IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode. - * - * Since: 1.4 - **/ - /* ---ifcfg-rh--- - * property: token - * variable: IPV6_TOKEN - * description: The IPv6 tokenized interface identifier token - * example: IPV6_TOKEN=::53 - * ---end--- - */ - obj_properties[PROP_TOKEN] = g_param_spec_string(NM_SETTING_IP6_CONFIG_TOKEN, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIP6Config:ra-timeout: - * - * A timeout for waiting Router Advertisements in seconds. If zero (the default), a - * globally configured default is used. If still unspecified, the timeout depends on the - * sysctl settings of the device. - * - * Set to 2147483647 (MAXINT32) for infinity. - * - * Since: 1.24 - **/ - /* ---ifcfg-rh--- - * property: dhcp-timeout - * variable: IPV6_RA_TIMEOUT(+) - * description: A timeout for waiting Router Advertisements in seconds. - * example: IPV6_RA_TIMEOUT=10 - * ---end--- - */ - - obj_properties[PROP_RA_TIMEOUT] = g_param_spec_int( - NM_SETTING_IP6_CONFIG_RA_TIMEOUT, - "", - "", - 0, - G_MAXINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIP6Config:dhcp-duid: - * - * A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp - * client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried - * in the Client Identifier option. - * If the property is a hex string ('aa:bb:cc') it is interpreted as a binary - * DUID and filled as an opaque value in the Client Identifier option. - * - * The special value "lease" will retrieve the DUID previously used from the - * lease file belonging to the connection. If no DUID is found and "dhclient" - * is the configured dhcp client, the DUID is searched in the system-wide - * dhclient lease file. If still no DUID is found, or another dhcp client is - * used, a global and permanent DUID-UUID (RFC 6355) will be generated based - * on the machine-id. - * - * The special values "llt" and "ll" will generate a DUID of type LLT or LL - * (see RFC 3315) based on the current MAC address of the device. In order to - * try providing a stable DUID-LLT, the time field will contain a constant - * timestamp that is used globally (for all profiles) and persisted to disk. - * - * The special values "stable-llt", "stable-ll" and "stable-uuid" will generate - * a DUID of the corresponding type, derived from the connection's stable-id and - * a per-host unique key. You may want to include the "${DEVICE}" or "${MAC}" specifier - * in the stable-id, in case this profile gets activated on multiple devices. - * So, the link-layer address of "stable-ll" and "stable-llt" will be a generated - * address derived from the stable id. The DUID-LLT time value in the "stable-llt" - * option will be picked among a static timespan of three years (the upper bound - * of the interval is the same constant timestamp used in "llt"). - * - * When the property is unset, the global value provided for "ipv6.dhcp-duid" is - * used. If no global value is provided, the default "lease" value is assumed. - * - * Since: 1.12 - **/ - /* ---ifcfg-rh--- - * property: dhcp-duid - * variable: DHCPV6_DUID(+) - * description: A string sent to the DHCPv6 server to identify the local machine. - * Apart from the special values "lease", "stable-llt", "stable-ll", "stable-uuid", - * "llt" and "ll" a binary value in hex format is expected. An hex string where - * each octet is separated by a colon is also accepted. - * example: DHCPV6_DUID=LL; DHCPV6_DUID=0301deadbeef0001; DHCPV6_DUID=03:01:de:ad:be:ef:00:01 - * ---end--- - */ - obj_properties[PROP_DHCP_DUID] = - g_param_spec_string(NM_SETTING_IP6_CONFIG_DHCP_DUID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /* IP6-specific property overrides */ - - /* ---dbus--- - * property: dns - * format: array of byte array - * description: Array of IP addresses of DNS servers (in network byte order) - * ---end--- - */ - _nm_properties_override_gobj( - properties_override, - g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS), - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aay"), - .gprop_to_dbus_fcn = ip6_dns_to_dbus, - .gprop_from_dbus_fcn = ip6_dns_from_dbus, )); - - /* ---dbus--- - * property: addresses - * format: array of legacy IPv6 address struct (a(ayuay)) - * description: Deprecated in favor of the 'address-data' and 'gateway' - * properties, but this can be used for backward-compatibility with older - * daemons. Note that if you send this property the daemon will ignore - * 'address-data' and 'gateway'. - * - * Array of IPv6 address structures. Each IPv6 address structure is - * composed of an IPv6 address, a prefix length (1 - 128), and an IPv6 - * gateway address. The gateway may be zeroed out if no gateway exists for - * that subnet. - * ---end--- - */ - _nm_properties_override_gobj( - properties_override, - g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES), - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("a(ayuay)"), - .to_dbus_fcn = ip6_addresses_get, - .from_dbus_fcn = ip6_addresses_set, )); - - /* ---dbus--- - * property: address-data - * format: array of vardict - * description: Array of IPv6 addresses. Each address dictionary contains at - * least 'address' and 'prefix' entries, containing the IP address as a - * string, and the prefix length as a uint32. Additional attributes may - * also exist on some addresses. - * ---end--- - */ - _nm_properties_override_dbus( - properties_override, - "address-data", - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip6_address_data_get, - .from_dbus_fcn = ip6_address_data_set, )); - - /* ---dbus--- - * property: routes - * format: array of legacy IPv6 route struct (a(ayuayu)) - * description: Deprecated in favor of the 'route-data' property, but this - * can be used for backward-compatibility with older daemons. Note that if - * you send this property the daemon will ignore 'route-data'. - * - * Array of IPv6 route structures. Each IPv6 route structure is - * composed of an IPv6 address, a prefix length (1 - 128), an IPv6 - * next hop address (which may be zeroed out if there is no next hop), - * and a metric. If the metric is 0, NM will choose an appropriate - * default metric for the device. - * ---end--- - */ - _nm_properties_override_gobj( - properties_override, - g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES), - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("a(ayuayu)"), - .to_dbus_fcn = ip6_routes_get, - .from_dbus_fcn = ip6_routes_set, )); - - /* ---dbus--- - * property: route-data - * format: array of vardict - * description: Array of IPv6 routes. Each route dictionary contains at - * least 'dest' and 'prefix' entries, containing the destination IP - * address as a string, and the prefix length as a uint32. Most routes - * will also have a 'next-hop' entry, containing the next hop IP address as - * a string. If the route has a 'metric' entry (containing a uint32), that - * will be used as the metric for the route (otherwise NM will pick a - * default value appropriate to the device). Additional attributes may - * also exist on some routes. - * ---end--- - */ - _nm_properties_override_dbus(properties_override, - "route-data", - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip6_route_data_get, - .from_dbus_fcn = ip6_route_data_set, )); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_IP6_CONFIG, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-ip6-config.h b/libnm-core/nm-setting-ip6-config.h deleted file mode 100644 index fca6961b86..0000000000 --- a/libnm-core/nm-setting-ip6-config.h +++ /dev/null @@ -1,174 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_IP6_CONFIG_H__ -#define __NM_SETTING_IP6_CONFIG_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting-ip-config.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_IP6_CONFIG (nm_setting_ip6_config_get_type()) -#define NM_SETTING_IP6_CONFIG(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6Config)) -#define NM_SETTING_IP6_CONFIG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_IP6CONFIG, NMSettingIP6ConfigClass)) -#define NM_IS_SETTING_IP6_CONFIG(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_IP6_CONFIG)) -#define NM_IS_SETTING_IP6_CONFIG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_IP6_CONFIG)) -#define NM_SETTING_IP6_CONFIG_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigClass)) - -#define NM_SETTING_IP6_CONFIG_SETTING_NAME "ipv6" - -#define NM_SETTING_IP6_CONFIG_IP6_PRIVACY "ip6-privacy" - -#define NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE "addr-gen-mode" - -#define NM_SETTING_IP6_CONFIG_TOKEN "token" - -#define NM_SETTING_IP6_CONFIG_DHCP_DUID "dhcp-duid" - -#define NM_SETTING_IP6_CONFIG_RA_TIMEOUT "ra-timeout" - -/** - * NM_SETTING_IP6_CONFIG_METHOD_IGNORE: - * - * IPv6 is not required or is handled by some other mechanism, and NetworkManager - * should not configure IPv6 for this connection. - */ -#define NM_SETTING_IP6_CONFIG_METHOD_IGNORE "ignore" - -/** - * NM_SETTING_IP6_CONFIG_METHOD_AUTO: - * - * IPv6 configuration should be automatically determined via a method appropriate - * for the hardware interface, ie router advertisements, DHCP, or PPP or some - * other device-specific manner. - */ -#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto" - -/** - * NM_SETTING_IP6_CONFIG_METHOD_DHCP: - * - * IPv6 configuration should be automatically determined via DHCPv6 only and - * router advertisements should be ignored. - */ -#define NM_SETTING_IP6_CONFIG_METHOD_DHCP "dhcp" - -/** - * NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL: - * - * IPv6 configuration should be automatically configured for link-local-only - * operation. - */ -#define NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL "link-local" - -/** - * NM_SETTING_IP6_CONFIG_METHOD_MANUAL: - * - * All necessary IPv6 configuration (addresses, prefix, DNS, etc) is specified - * in the setting's properties. - */ -#define NM_SETTING_IP6_CONFIG_METHOD_MANUAL "manual" - -/** - * NM_SETTING_IP6_CONFIG_METHOD_SHARED: - * - * This connection specifies configuration that allows other computers to - * connect through it to the default network (usually the Internet). The - * connection's interface will be assigned a private address, and router - * advertisements, a caching DNS server, and Network Address Translation (NAT) - * functionality will be started on this connection's interface to allow other - * devices to connect through that interface to the default network. (not yet - * supported for IPv6) - */ -#define NM_SETTING_IP6_CONFIG_METHOD_SHARED "shared" - -/** - * NM_SETTING_IP6_CONFIG_METHOD_DISABLED: - * - * IPv6 is disabled for the connection. - * - * Since: 1.20 - */ -#define NM_SETTING_IP6_CONFIG_METHOD_DISABLED "disabled" - -/** - * NMSettingIP6ConfigPrivacy: - * @NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: unknown or no value specified - * @NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: IPv6 Privacy Extensions are disabled - * @NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: IPv6 Privacy Extensions - * are enabled, but public addresses are preferred over temporary addresses - * @NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: IPv6 Privacy Extensions - * are enabled and temporary addresses are preferred over public addresses - * - * #NMSettingIP6ConfigPrivacy values indicate if and how IPv6 Privacy - * Extensions are used (RFC4941). - */ -typedef enum { - NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN = -1, - NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED = 0, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR = 1, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR = 2 -} NMSettingIP6ConfigPrivacy; - -/** - * NMSettingIP6ConfigAddrGenMode: - * @NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64: The Interface Identifier is derived - * from the interface hardware address. - * @NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY: The Interface Identifier - * is created by using a cryptographically secure hash of a secret host-specific - * key along with the connection identification and the network address as - * specified by RFC7217. - * - * #NMSettingIP6ConfigAddrGenMode controls how the Interface Identifier for - * RFC4862 Stateless Address Autoconfiguration is created. - * - * Since: 1.2 - */ -typedef enum { - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 = 0, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY = 1, -} NMSettingIP6ConfigAddrGenMode; - -/** - * NMSettingIP6Config: - * - * IPv6 Settings - */ -struct _NMSettingIP6Config { - NMSettingIPConfig parent; -}; - -typedef struct { - NMSettingIPConfigClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingIP6ConfigClass; - -GType nm_setting_ip6_config_get_type(void); - -NMSetting *nm_setting_ip6_config_new(void); - -NMSettingIP6ConfigPrivacy nm_setting_ip6_config_get_ip6_privacy(NMSettingIP6Config *setting); -NM_AVAILABLE_IN_1_2 -NMSettingIP6ConfigAddrGenMode nm_setting_ip6_config_get_addr_gen_mode(NMSettingIP6Config *setting); -NM_AVAILABLE_IN_1_4 -const char *nm_setting_ip6_config_get_token(NMSettingIP6Config *setting); -NM_AVAILABLE_IN_1_12 -const char *nm_setting_ip6_config_get_dhcp_duid(NMSettingIP6Config *setting); -NM_AVAILABLE_IN_1_24 -gint32 nm_setting_ip6_config_get_ra_timeout(NMSettingIP6Config *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_IP6_CONFIG_H__ */ diff --git a/libnm-core/nm-setting-macsec.c b/libnm-core/nm-setting-macsec.c deleted file mode 100644 index d70696d95d..0000000000 --- a/libnm-core/nm-setting-macsec.c +++ /dev/null @@ -1,671 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-macsec.h" - -#include - -#include "nm-glib-aux/nm-secret-utils.h" - -#include "nm-utils.h" -#include "nm-core-types-internal.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" -#include "nm-setting-wired.h" -#include "nm-connection-private.h" - -/** - * SECTION:nm-setting-macsec - * @short_description: Describes connection properties for MACSEC interfaces - * - * The #NMSettingMacsec object is a #NMSetting subclass that describes properties - * necessary for connection to MACsec (IEEE 802.1AE) interfaces. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, - PROP_MODE, - PROP_ENCRYPT, - PROP_MKA_CAK, - PROP_MKA_CAK_FLAGS, - PROP_MKA_CKN, - PROP_PORT, - PROP_VALIDATION, - PROP_SEND_SCI, ); - -typedef struct { - char * parent; - char * mka_cak; - char * mka_ckn; - int port; - NMSettingMacsecMode mode; - NMSettingSecretFlags mka_cak_flags; - NMSettingMacsecValidation validation; - bool encrypt : 1; - bool send_sci : 1; -} NMSettingMacsecPrivate; - -G_DEFINE_TYPE(NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING) - -#define NM_SETTING_MACSEC_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_MACSEC, NMSettingMacsecPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_macsec_get_parent: - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingMacsec:parent property of the setting - * - * Since: 1.6 - **/ -const char * -nm_setting_macsec_get_parent(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NULL); - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->parent; -} - -/** - * nm_setting_macsec_get_mode: - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingMacsec:mode property of the setting - * - * Since: 1.6 - **/ -NMSettingMacsecMode -nm_setting_macsec_get_mode(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NM_SETTING_MACSEC_MODE_PSK); - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->mode; -} - -/** - * nm_setting_macsec_get_encrypt: - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingMacsec:encrypt property of the setting - * - * Since: 1.6 - **/ -gboolean -nm_setting_macsec_get_encrypt(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), TRUE); - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->encrypt; -} - -/** - * nm_setting_macsec_get_mka_cak - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingMacsec:mka-cak property of the setting - * - * Since: 1.6 - **/ -const char * -nm_setting_macsec_get_mka_cak(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NULL); - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->mka_cak; -} - -/** - * nm_setting_macsec_get_mka_cak_flags: - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingMacsec:mka-cak - * - * Since: 1.6 - **/ -NMSettingSecretFlags -nm_setting_macsec_get_mka_cak_flags(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->mka_cak_flags; -} - -/** - * nm_setting_macsec_get_mka_ckn: - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingMacsec:mka-ckn property of the setting - * - * Since: 1.6 - **/ -const char * -nm_setting_macsec_get_mka_ckn(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NULL); - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->mka_ckn; -} - -/** - * nm_setting_macsec_get_port: - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingMacsec:port property of the setting - * - * Since: 1.6 - **/ -int -nm_setting_macsec_get_port(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), 1); - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->port; -} - -/** - * nm_setting_macsec_get_validation: - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingMacsec:validation property of the setting - * - * Since: 1.6 - **/ -NMSettingMacsecValidation -nm_setting_macsec_get_validation(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NM_SETTING_MACSEC_VALIDATION_DISABLE); - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->validation; -} - -/** - * nm_setting_macsec_get_send_sci: - * @setting: the #NMSettingMacsec - * - * Returns: the #NMSettingMacsec:send-sci property of the setting - * - * Since: 1.12 - **/ -gboolean -nm_setting_macsec_get_send_sci(NMSettingMacsec *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), TRUE); - return NM_SETTING_MACSEC_GET_PRIVATE(setting)->send_sci; -} - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); - GPtrArray * secrets = NULL; - - if (priv->mode == NM_SETTING_MACSEC_MODE_PSK) { - if (!priv->mka_cak - && !NM_FLAGS_HAS(priv->mka_cak_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { - secrets = g_ptr_array_sized_new(1); - g_ptr_array_add(secrets, NM_SETTING_MACSEC_MKA_CAK); - } - } - - return secrets; -} - -/*********************************************************************/ - -static gboolean -verify_macsec_key(const char *key, gboolean cak, GError **error) -{ - int req_len; - - /* CAK is a connection secret and can be NULL for various - * reasons (agent-owned, no permissions to get secrets, etc.) - */ - if (cak && !key) - return TRUE; - - if (!key || !key[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the key is empty")); - return FALSE; - } - - req_len = cak ? NM_SETTING_MACSEC_MKA_CAK_LENGTH : NM_SETTING_MACSEC_MKA_CKN_LENGTH; - if (strlen(key) != (gsize) req_len) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the key must be %d characters"), - req_len); - return FALSE; - } - - if (!NM_STRCHAR_ALL(key, ch, g_ascii_isxdigit(ch))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the key contains non-hexadecimal characters")); - return FALSE; - } - - return TRUE; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); - NMSettingConnection * s_con = NULL; - NMSettingWired * s_wired = NULL; - NMSetting8021x * s_8021x = NULL; - - if (connection) { - s_con = nm_connection_get_setting_connection(connection); - s_wired = nm_connection_get_setting_wired(connection); - s_8021x = nm_connection_get_setting_802_1x(connection); - } - - if (priv->parent) { - if (nm_utils_is_uuid(priv->parent)) { - /* If we have an NMSettingConnection:master with slave-type="macsec", - * then it must be the same UUID. - */ - if (s_con) { - const char *master = NULL, *slave_type = NULL; - - slave_type = nm_setting_connection_get_slave_type(s_con); - if (!g_strcmp0(slave_type, NM_SETTING_MACSEC_SETTING_NAME)) - master = nm_setting_connection_get_master(s_con); - - if (master && g_strcmp0(priv->parent, master) != 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' value doesn't match '%s=%s'"), - priv->parent, - NM_SETTING_CONNECTION_MASTER, - master); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACSEC_SETTING_NAME, - NM_SETTING_MACSEC_PARENT); - return FALSE; - } - } - } else if (!nm_utils_iface_valid_name(priv->parent)) { - /* parent must be either a UUID or an interface name */ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is neither an UUID nor an interface name"), - priv->parent); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACSEC_SETTING_NAME, - NM_SETTING_MACSEC_PARENT); - return FALSE; - } - } else { - /* If parent is NULL, the parent must be specified via - * NMSettingWired:mac-address. - */ - if (connection && (!s_wired || !nm_setting_wired_get_mac_address(s_wired))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is not specified and neither is '%s:%s'"), - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_MAC_ADDRESS); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACSEC_SETTING_NAME, - NM_SETTING_MACSEC_PARENT); - return FALSE; - } - } - - if (priv->mode == NM_SETTING_MACSEC_MODE_PSK) { - if (!verify_macsec_key(priv->mka_ckn, FALSE, error)) { - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACSEC_SETTING_NAME, - NM_SETTING_MACSEC_MKA_CKN); - return FALSE; - } - if (!verify_macsec_key(priv->mka_cak, TRUE, error)) { - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACSEC_SETTING_NAME, - NM_SETTING_MACSEC_MKA_CAK); - return FALSE; - } - } else if (priv->mode == NM_SETTING_MACSEC_MODE_EAP) { - if (!s_8021x) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("EAP key management requires '%s' setting presence"), - NM_SETTING_802_1X_SETTING_NAME); - g_prefix_error(error, "%s: ", NM_SETTING_MACSEC_SETTING_NAME); - return FALSE; - } - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("must be either psk (0) or eap (1)")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_MACSEC_SETTING_NAME, NM_SETTING_MACSEC_MODE); - return FALSE; - } - - if (priv->port <= 0 || priv->port > 65534) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("invalid port %d"), - priv->port); - g_prefix_error(error, "%s.%s: ", NM_SETTING_MACSEC_SETTING_NAME, NM_SETTING_MACSEC_PORT); - return FALSE; - } - - if (priv->mode != NM_SETTING_MACSEC_MODE_PSK && (priv->mka_cak || priv->mka_ckn)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("only valid for psk mode")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACSEC_SETTING_NAME, - priv->mka_cak ? NM_SETTING_MACSEC_MKA_CAK : NM_SETTING_MACSEC_MKA_CKN); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingMacsec * setting = NM_SETTING_MACSEC(object); - NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_value_set_string(value, priv->parent); - break; - case PROP_MODE: - g_value_set_int(value, priv->mode); - break; - case PROP_ENCRYPT: - g_value_set_boolean(value, priv->encrypt); - break; - case PROP_MKA_CAK: - g_value_set_string(value, priv->mka_cak); - break; - case PROP_MKA_CAK_FLAGS: - g_value_set_flags(value, priv->mka_cak_flags); - break; - case PROP_MKA_CKN: - g_value_set_string(value, priv->mka_ckn); - break; - case PROP_PORT: - g_value_set_int(value, priv->port); - break; - case PROP_VALIDATION: - g_value_set_int(value, priv->validation); - break; - case PROP_SEND_SCI: - g_value_set_boolean(value, priv->send_sci); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingMacsec * setting = NM_SETTING_MACSEC(object); - NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_free(priv->parent); - priv->parent = g_value_dup_string(value); - break; - case PROP_MODE: - priv->mode = g_value_get_int(value); - break; - case PROP_ENCRYPT: - priv->encrypt = g_value_get_boolean(value); - break; - case PROP_MKA_CAK: - nm_free_secret(priv->mka_cak); - priv->mka_cak = g_value_dup_string(value); - break; - case PROP_MKA_CAK_FLAGS: - priv->mka_cak_flags = g_value_get_flags(value); - break; - case PROP_MKA_CKN: - g_free(priv->mka_ckn); - priv->mka_ckn = g_value_dup_string(value); - break; - case PROP_PORT: - priv->port = g_value_get_int(value); - break; - case PROP_VALIDATION: - priv->validation = g_value_get_int(value); - break; - case PROP_SEND_SCI: - priv->send_sci = g_value_get_boolean(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_macsec_init(NMSettingMacsec *self) -{ - NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(self); - - nm_assert(priv->mode == NM_SETTING_MACSEC_MODE_PSK); - priv->encrypt = TRUE; - priv->port = 1; - priv->send_sci = TRUE; - priv->validation = NM_SETTING_MACSEC_VALIDATION_STRICT; -} - -/** - * nm_setting_macsec_new: - * - * Creates a new #NMSettingMacsec object with default values. - * - * Returns: (transfer full): the new empty #NMSettingMacsec object - * - * Since: 1.6 - **/ -NMSetting * -nm_setting_macsec_new(void) -{ - return g_object_new(NM_TYPE_SETTING_MACSEC, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingMacsec * setting = NM_SETTING_MACSEC(object); - NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); - - g_free(priv->parent); - nm_free_secret(priv->mka_cak); - g_free(priv->mka_ckn); - - G_OBJECT_CLASS(nm_setting_macsec_parent_class)->finalize(object); -} - -static void -nm_setting_macsec_class_init(NMSettingMacsecClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingMacsecPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->need_secrets = need_secrets; - - /** - * NMSettingMacsec:parent: - * - * If given, specifies the parent interface name or parent connection UUID - * from which this MACSEC interface should be created. If this property is - * not specified, the connection must contain an #NMSettingWired setting - * with a #NMSettingWired:mac-address property. - * - * Since: 1.6 - **/ - obj_properties[PROP_PARENT] = g_param_spec_string( - NM_SETTING_MACSEC_PARENT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacsec:mode: - * - * Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key - * Agreement) is obtained. - * - * Since: 1.6 - **/ - obj_properties[PROP_MODE] = - g_param_spec_int(NM_SETTING_MACSEC_MODE, - "", - "", - G_MININT, - G_MAXINT, - NM_SETTING_MACSEC_MODE_PSK, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacsec:encrypt: - * - * Whether the transmitted traffic must be encrypted. - * - * Since: 1.6 - **/ - obj_properties[PROP_ENCRYPT] = g_param_spec_boolean(NM_SETTING_MACSEC_ENCRYPT, - "", - "", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacsec:mka-cak: - * - * The pre-shared CAK (Connectivity Association Key) for MACsec - * Key Agreement. - * - * Since: 1.6 - **/ - obj_properties[PROP_MKA_CAK] = - g_param_spec_string(NM_SETTING_MACSEC_MKA_CAK, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacsec:mka-cak-flags: - * - * Flags indicating how to handle the #NMSettingMacsec:mka-cak - * property. - * - * Since: 1.6 - **/ - obj_properties[PROP_MKA_CAK_FLAGS] = - g_param_spec_flags(NM_SETTING_MACSEC_MKA_CAK_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacsec:mka-ckn: - * - * The pre-shared CKN (Connectivity-association Key Name) for - * MACsec Key Agreement. - * - * Since: 1.6 - **/ - obj_properties[PROP_MKA_CKN] = g_param_spec_string(NM_SETTING_MACSEC_MKA_CKN, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacsec:port: - * - * The port component of the SCI (Secure Channel Identifier), between 1 and 65534. - * - * Since: 1.6 - **/ - obj_properties[PROP_PORT] = - g_param_spec_int(NM_SETTING_MACSEC_PORT, - "", - "", - 1, - 65534, - 1, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacsec:validation: - * - * Specifies the validation mode for incoming frames. - * - * Since: 1.6 - **/ - obj_properties[PROP_VALIDATION] = - g_param_spec_int(NM_SETTING_MACSEC_VALIDATION, - "", - "", - G_MININT, - G_MAXINT, - NM_SETTING_MACSEC_VALIDATION_STRICT, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacsec:send-sci: - * - * Specifies whether the SCI (Secure Channel Identifier) is included - * in every packet. - * - * Since: 1.12 - **/ - obj_properties[PROP_SEND_SCI] = - g_param_spec_boolean(NM_SETTING_MACSEC_SEND_SCI, - "", - "", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_MACSEC); -} diff --git a/libnm-core/nm-setting-macsec.h b/libnm-core/nm-setting-macsec.h deleted file mode 100644 index bc33dd9dfb..0000000000 --- a/libnm-core/nm-setting-macsec.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_MACSEC_H__ -#define __NM_SETTING_MACSEC_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_MACSEC (nm_setting_macsec_get_type()) -#define NM_SETTING_MACSEC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_MACSEC, NMSettingMacsec)) -#define NM_SETTING_MACSEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_MACSECCONFIG, NMSettingMacsecClass)) -#define NM_IS_SETTING_MACSEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_MACSEC)) -#define NM_IS_SETTING_MACSEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_MACSEC)) -#define NM_SETTING_MACSEC_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_MACSEC, NMSettingMacsecClass)) - -#define NM_SETTING_MACSEC_SETTING_NAME "macsec" - -#define NM_SETTING_MACSEC_PARENT "parent" -#define NM_SETTING_MACSEC_MODE "mode" -#define NM_SETTING_MACSEC_ENCRYPT "encrypt" -#define NM_SETTING_MACSEC_MKA_CAK "mka-cak" -#define NM_SETTING_MACSEC_MKA_CAK_FLAGS "mka-cak-flags" -#define NM_SETTING_MACSEC_MKA_CKN "mka-ckn" -#define NM_SETTING_MACSEC_PORT "port" -#define NM_SETTING_MACSEC_VALIDATION "validation" -#define NM_SETTING_MACSEC_SEND_SCI "send-sci" - -/** - * NMSettingMacsec: - * - * MACSec Settings - */ -struct _NMSettingMacsec { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingMacsecClass; - -/** - * NMSettingMacsecMode: - * @NM_SETTING_MACSEC_MODE_PSK: The CAK is pre-shared - * @NM_SETTING_MACSEC_MODE_EAP: The CAK is the result of participation in EAP - * - * #NMSettingMacsecMode controls how the CAK (Connectivity Association Key) used - * in MKA (MACsec Key Agreement) is obtained. - * - * Since: 1.6 - */ -typedef enum { - NM_SETTING_MACSEC_MODE_PSK = 0, - NM_SETTING_MACSEC_MODE_EAP = 1, -} NMSettingMacsecMode; - -/** - * NMSettingMacsecValidation: - * @NM_SETTING_MACSEC_VALIDATION_DISABLE: All incoming frames are accepted if - * possible - * @NM_SETTING_MACSEC_VALIDATION_CHECK: Non protected, invalid, or impossible to - * verify frames are accepted and counted as "invalid" - * @NM_SETTING_MACSEC_VALIDATION_STRICT: Non protected, invalid, or impossible to - * verify frames are dropped - * - * #NMSettingMacsecValidation specifies a validation mode for incoming frames. - * - * Since: 1.6 - */ -typedef enum { - NM_SETTING_MACSEC_VALIDATION_DISABLE = 0, - NM_SETTING_MACSEC_VALIDATION_CHECK = 1, - NM_SETTING_MACSEC_VALIDATION_STRICT = 2, -} NMSettingMacsecValidation; - -#define NM_SETTING_MACSEC_MKA_CAK_LENGTH 32 -#define NM_SETTING_MACSEC_MKA_CKN_LENGTH 64 - -NM_AVAILABLE_IN_1_6 -GType nm_setting_macsec_get_type(void); -NM_AVAILABLE_IN_1_6 -NMSetting *nm_setting_macsec_new(void); - -NM_AVAILABLE_IN_1_6 -const char *nm_setting_macsec_get_parent(NMSettingMacsec *setting); -NM_AVAILABLE_IN_1_6 -NMSettingMacsecMode nm_setting_macsec_get_mode(NMSettingMacsec *setting); -NM_AVAILABLE_IN_1_6 -gboolean nm_setting_macsec_get_encrypt(NMSettingMacsec *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_macsec_get_mka_cak(NMSettingMacsec *setting); -NM_AVAILABLE_IN_1_6 -NMSettingSecretFlags nm_setting_macsec_get_mka_cak_flags(NMSettingMacsec *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_macsec_get_mka_ckn(NMSettingMacsec *setting); -NM_AVAILABLE_IN_1_6 -int nm_setting_macsec_get_port(NMSettingMacsec *setting); -NM_AVAILABLE_IN_1_6 -NMSettingMacsecValidation nm_setting_macsec_get_validation(NMSettingMacsec *setting); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_macsec_get_send_sci(NMSettingMacsec *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_MACSEC_H__ */ diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c deleted file mode 100644 index 8c8c6279be..0000000000 --- a/libnm-core/nm-setting-macvlan.c +++ /dev/null @@ -1,332 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-macvlan.h" - -#include - -#include "nm-utils.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" -#include "nm-setting-wired.h" -#include "nm-connection-private.h" - -/** - * SECTION:nm-setting-macvlan - * @short_description: Describes connection properties for macvlan interfaces - * - * The #NMSettingMacvlan object is a #NMSetting subclass that describes properties - * necessary for connection to macvlan interfaces. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, PROP_MODE, PROP_PROMISCUOUS, PROP_TAP, ); - -typedef struct { - char * parent; - NMSettingMacvlanMode mode; - bool promiscuous : 1; - bool tap : 1; -} NMSettingMacvlanPrivate; - -G_DEFINE_TYPE(NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING) - -#define NM_SETTING_MACVLAN_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_macvlan_get_parent: - * @setting: the #NMSettingMacvlan - * - * Returns: the #NMSettingMacvlan:parent property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_macvlan_get_parent(NMSettingMacvlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACVLAN(setting), NULL); - return NM_SETTING_MACVLAN_GET_PRIVATE(setting)->parent; -} - -/** - * nm_setting_macvlan_get_mode: - * @setting: the #NMSettingMacvlan - * - * Returns: the #NMSettingMacvlan:mode property of the setting - * - * Since: 1.2 - **/ -NMSettingMacvlanMode -nm_setting_macvlan_get_mode(NMSettingMacvlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACVLAN(setting), NM_SETTING_MACVLAN_MODE_UNKNOWN); - return NM_SETTING_MACVLAN_GET_PRIVATE(setting)->mode; -} - -/** - * nm_setting_macvlan_get_promiscuous: - * @setting: the #NMSettingMacvlan - * - * Returns: the #NMSettingMacvlan:promiscuous property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_macvlan_get_promiscuous(NMSettingMacvlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACVLAN(setting), FALSE); - return NM_SETTING_MACVLAN_GET_PRIVATE(setting)->promiscuous; -} - -/** - * nm_setting_macvlan_get_tap: - * @setting: the #NMSettingMacvlan - * - * Returns: the #NMSettingMacvlan:tap property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_macvlan_get_tap(NMSettingMacvlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MACVLAN(setting), FALSE); - return NM_SETTING_MACVLAN_GET_PRIVATE(setting)->tap; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(setting); - NMSettingWired * s_wired; - - if (connection) - s_wired = nm_connection_get_setting_wired(connection); - else - s_wired = NULL; - - if (priv->parent) { - if (!nm_utils_is_uuid(priv->parent) && !nm_utils_ifname_valid_kernel(priv->parent, NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is neither an UUID nor an interface name"), - priv->parent); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACVLAN_SETTING_NAME, - NM_SETTING_MACVLAN_PARENT); - return FALSE; - } - } else { - /* If parent is NULL, the parent must be specified via - * NMSettingWired:mac-address. - */ - if (connection && (!s_wired || !nm_setting_wired_get_mac_address(s_wired))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is not specified and neither is '%s:%s'"), - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_MAC_ADDRESS); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACVLAN_SETTING_NAME, - NM_SETTING_MACVLAN_PARENT); - return FALSE; - } - } - - if (!priv->promiscuous && priv->mode != NM_SETTING_MACVLAN_MODE_PASSTHRU) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("non promiscuous operation is allowed only in passthru mode")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MACVLAN_SETTING_NAME, - NM_SETTING_MACVLAN_PROMISCUOUS); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingMacvlan * setting = NM_SETTING_MACVLAN(object); - NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_value_set_string(value, priv->parent); - break; - case PROP_MODE: - g_value_set_uint(value, priv->mode); - break; - case PROP_PROMISCUOUS: - g_value_set_boolean(value, priv->promiscuous); - break; - case PROP_TAP: - g_value_set_boolean(value, priv->tap); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingMacvlan * setting = NM_SETTING_MACVLAN(object); - NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_free(priv->parent); - priv->parent = g_value_dup_string(value); - break; - case PROP_MODE: - priv->mode = g_value_get_uint(value); - break; - case PROP_PROMISCUOUS: - priv->promiscuous = g_value_get_boolean(value); - break; - case PROP_TAP: - priv->tap = g_value_get_boolean(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_macvlan_init(NMSettingMacvlan *self) -{ - NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(self); - - priv->promiscuous = TRUE; -} - -/** - * nm_setting_macvlan_new: - * - * Creates a new #NMSettingMacvlan object with default values. - * - * Returns: (transfer full): the new empty #NMSettingMacvlan object - * - * Since: 1.2 - **/ -NMSetting * -nm_setting_macvlan_new(void) -{ - return g_object_new(NM_TYPE_SETTING_MACVLAN, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingMacvlan * setting = NM_SETTING_MACVLAN(object); - NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(setting); - - g_free(priv->parent); - - G_OBJECT_CLASS(nm_setting_macvlan_parent_class)->finalize(object); -} - -static void -nm_setting_macvlan_class_init(NMSettingMacvlanClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingMacvlanPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingMacvlan:parent: - * - * If given, specifies the parent interface name or parent connection UUID - * from which this MAC-VLAN interface should be created. If this property is - * not specified, the connection must contain an #NMSettingWired setting - * with a #NMSettingWired:mac-address property. - * - * Since: 1.2 - **/ - obj_properties[PROP_PARENT] = g_param_spec_string( - NM_SETTING_MACVLAN_PARENT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacvlan:mode: - * - * The macvlan mode, which specifies the communication mechanism between multiple - * macvlans on the same lower device. - * - * Since: 1.2 - **/ - obj_properties[PROP_MODE] = - g_param_spec_uint(NM_SETTING_MACVLAN_MODE, - "", - "", - 0, - G_MAXUINT, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacvlan:promiscuous: - * - * Whether the interface should be put in promiscuous mode. - * - * Since: 1.2 - **/ - obj_properties[PROP_PROMISCUOUS] = g_param_spec_boolean( - NM_SETTING_MACVLAN_PROMISCUOUS, - "", - "", - TRUE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMacvlan:tap: - * - * Whether the interface should be a MACVTAP. - * - * Since: 1.2 - **/ - obj_properties[PROP_TAP] = g_param_spec_boolean(NM_SETTING_MACVLAN_TAP, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_MACVLAN); -} diff --git a/libnm-core/nm-setting-macvlan.h b/libnm-core/nm-setting-macvlan.h deleted file mode 100644 index 05c0b36508..0000000000 --- a/libnm-core/nm-setting-macvlan.h +++ /dev/null @@ -1,87 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_MACVLAN_H__ -#define __NM_SETTING_MACVLAN_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_MACVLAN (nm_setting_macvlan_get_type()) -#define NM_SETTING_MACVLAN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlan)) -#define NM_SETTING_MACVLAN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_MACVLANCONFIG, NMSettingMacvlanClass)) -#define NM_IS_SETTING_MACVLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_MACVLAN)) -#define NM_IS_SETTING_MACVLAN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_MACVLAN)) -#define NM_SETTING_MACVLAN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanClass)) - -#define NM_SETTING_MACVLAN_SETTING_NAME "macvlan" - -#define NM_SETTING_MACVLAN_PARENT "parent" -#define NM_SETTING_MACVLAN_MODE "mode" -#define NM_SETTING_MACVLAN_PROMISCUOUS "promiscuous" -#define NM_SETTING_MACVLAN_TAP "tap" - -/** - * NMSettingMacvlan: - * - * MAC VLAN Settings - */ -struct _NMSettingMacvlan { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingMacvlanClass; - -/** - * NMSettingMacvlanMode: - * @NM_SETTING_MACVLAN_MODE_UNKNOWN: unknown/unset mode - * @NM_SETTING_MACVLAN_MODE_VEPA: Virtual Ethernet Port Aggregator mode - * @NM_SETTING_MACVLAN_MODE_BRIDGE: bridge mode - * @NM_SETTING_MACVLAN_MODE_PRIVATE: private mode - * @NM_SETTING_MACVLAN_MODE_PASSTHRU: passthru mode - * @NM_SETTING_MACVLAN_MODE_SOURCE: source mode - **/ -typedef enum { - NM_SETTING_MACVLAN_MODE_UNKNOWN = 0, - NM_SETTING_MACVLAN_MODE_VEPA = 1, - NM_SETTING_MACVLAN_MODE_BRIDGE = 2, - NM_SETTING_MACVLAN_MODE_PRIVATE = 3, - NM_SETTING_MACVLAN_MODE_PASSTHRU = 4, - NM_SETTING_MACVLAN_MODE_SOURCE = 5, - _NM_SETTING_MACVLAN_MODE_NUM, /*< skip >*/ - NM_SETTING_MACVLAN_MODE_LAST = _NM_SETTING_MACVLAN_MODE_NUM - 1, /*< skip >*/ -} NMSettingMacvlanMode; - -NM_AVAILABLE_IN_1_2 -GType nm_setting_macvlan_get_type(void); -NM_AVAILABLE_IN_1_2 -NMSetting *nm_setting_macvlan_new(void); - -NM_AVAILABLE_IN_1_2 -const char *nm_setting_macvlan_get_parent(NMSettingMacvlan *setting); -NM_AVAILABLE_IN_1_2 -NMSettingMacvlanMode nm_setting_macvlan_get_mode(NMSettingMacvlan *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_macvlan_get_promiscuous(NMSettingMacvlan *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_macvlan_get_tap(NMSettingMacvlan *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_MACVLAN_H__ */ diff --git a/libnm-core/nm-setting-match.c b/libnm-core/nm-setting-match.c deleted file mode 100644 index 108aba95f2..0000000000 --- a/libnm-core/nm-setting-match.c +++ /dev/null @@ -1,899 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-match.h" - -#include "nm-setting-private.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-match - * @short_description: Properties to match a connection with a device. - * @include: nm-setting-match.h - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingMatch, - PROP_INTERFACE_NAME, - PROP_KERNEL_COMMAND_LINE, - PROP_DRIVER, - PROP_PATH, ); - -/** - * NMSettingMatch: - * - * Match settings - * - * Since: 1.14 - */ -struct _NMSettingMatch { - NMSetting parent; - GArray * interface_name; - GArray * kernel_command_line; - GArray * driver; - GArray * path; -}; - -struct _NMSettingMatchClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingMatch, nm_setting_match, NM_TYPE_SETTING) - -/*****************************************************************************/ - -/** - * nm_setting_match_get_num_interface_names: - * @setting: the #NMSettingMatch - * - * Returns: the number of configured interface names - * - * Since: 1.14 - **/ -guint -nm_setting_match_get_num_interface_names(NMSettingMatch *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), 0); - - return nm_g_array_len(setting->interface_name); -} - -/** - * nm_setting_match_get_interface_name: - * @setting: the #NMSettingMatch - * @idx: index number of the DNS search domain to return - * - * Returns: the interface name at index @idx - * - * Since: 1.14 - **/ -const char * -nm_setting_match_get_interface_name(NMSettingMatch *setting, int idx) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); - - g_return_val_if_fail(setting->interface_name && idx >= 0 && idx < setting->interface_name->len, - NULL); - - return g_array_index(setting->interface_name, const char *, idx); -} - -/** - * nm_setting_match_add_interface_name: - * @setting: the #NMSettingMatch - * @interface_name: the interface name to add - * - * Adds a new interface name to the setting. - * - * Since: 1.14 - **/ -void -nm_setting_match_add_interface_name(NMSettingMatch *setting, const char *interface_name) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - g_return_if_fail(interface_name != NULL); - g_return_if_fail(interface_name[0] != '\0'); - - nm_strvarray_add(nm_strvarray_ensure(&setting->interface_name), interface_name); - _notify(setting, PROP_INTERFACE_NAME); -} - -/** - * nm_setting_match_remove_interface_name: - * @setting: the #NMSettingMatch - * @idx: index number of the interface name - * - * Removes the interface name at index @idx. - * - * Since: 1.14 - **/ -void -nm_setting_match_remove_interface_name(NMSettingMatch *setting, int idx) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - - g_return_if_fail(setting->interface_name && idx >= 0 && idx < setting->interface_name->len); - - g_array_remove_index(setting->interface_name, idx); - _notify(setting, PROP_INTERFACE_NAME); -} - -/** - * nm_setting_match_remove_interface_name_by_value: - * @setting: the #NMSettingMatch - * @interface_name: the interface name to remove - * - * Removes @interface_name. - * - * Returns: %TRUE if the interface name was found and removed; %FALSE if it was not. - * - * Since: 1.14 - **/ -gboolean -nm_setting_match_remove_interface_name_by_value(NMSettingMatch *setting, const char *interface_name) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), FALSE); - g_return_val_if_fail(interface_name != NULL, FALSE); - g_return_val_if_fail(interface_name[0] != '\0', FALSE); - - if (nm_strvarray_remove_first(setting->interface_name, interface_name)) { - _notify(setting, PROP_INTERFACE_NAME); - return TRUE; - } - - return FALSE; -} - -/** - * nm_setting_match_clear_interface_names: - * @setting: the #NMSettingMatch - * - * Removes all configured interface names. - * - * Since: 1.14 - **/ -void -nm_setting_match_clear_interface_names(NMSettingMatch *setting) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - - if (nm_g_array_len(setting->interface_name) != 0) { - nm_clear_pointer(&setting->interface_name, g_array_unref); - _notify(setting, PROP_INTERFACE_NAME); - } -} - -/** - * nm_setting_match_get_interface_names: - * @setting: the #NMSettingMatch - * @length: (out) (allow-none): the length of the returned interface names array. - * - * Returns all the interface names. - * - * Returns: (transfer none) (array length=length): the NULL terminated list of - * configured interface names. - * - * Before 1.26, the returned array was not %NULL terminated and you MUST provide a length. - * - * Since: 1.14 - **/ -const char *const * -nm_setting_match_get_interface_names(NMSettingMatch *setting, guint *length) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); - - return nm_strvarray_get_strv(&setting->interface_name, length); -} - -/*****************************************************************************/ - -/** - * nm_setting_match_get_num_kernel_command_lines: - * @setting: the #NMSettingMatch - * - * Returns: the number of configured kernel command line arguments - * - * Since: 1.26 - **/ -guint -nm_setting_match_get_num_kernel_command_lines(NMSettingMatch *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), 0); - - return nm_g_array_len(setting->kernel_command_line); -} - -/** - * nm_setting_match_get_kernel_command_line: - * @setting: the #NMSettingMatch - * @idx: index number of the kernel command line argument to return - * - * Returns: the kernel command line argument at index @idx - * - * Since: 1.26 - **/ -const char * -nm_setting_match_get_kernel_command_line(NMSettingMatch *setting, guint idx) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); - - g_return_val_if_fail(setting->kernel_command_line && idx < setting->kernel_command_line->len, - NULL); - - return g_array_index(setting->kernel_command_line, const char *, idx); -} - -/** - * nm_setting_match_add_kernel_command_line: - * @setting: the #NMSettingMatch - * @kernel_command_line: the kernel command line argument to add - * - * Adds a new kernel command line argument to the setting. - * - * Since: 1.26 - **/ -void -nm_setting_match_add_kernel_command_line(NMSettingMatch *setting, const char *kernel_command_line) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - g_return_if_fail(kernel_command_line != NULL); - g_return_if_fail(kernel_command_line[0] != '\0'); - - nm_strvarray_add(nm_strvarray_ensure(&setting->kernel_command_line), kernel_command_line); - _notify(setting, PROP_KERNEL_COMMAND_LINE); -} - -/** - * nm_setting_match_remove_kernel_command_line: - * @setting: the #NMSettingMatch - * @idx: index number of the kernel command line argument - * - * Removes the kernel command line argument at index @idx. - * - * Since: 1.26 - **/ -void -nm_setting_match_remove_kernel_command_line(NMSettingMatch *setting, guint idx) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - - g_return_if_fail(setting->kernel_command_line && idx < setting->kernel_command_line->len); - - g_array_remove_index(setting->kernel_command_line, idx); - _notify(setting, PROP_KERNEL_COMMAND_LINE); -} - -/** - * nm_setting_match_remove_kernel_command_line_by_value: - * @setting: the #NMSettingMatch - * @kernel_command_line: the kernel command line argument name to remove - * - * Removes @kernel_command_line. - * - * Returns: %TRUE if the kernel command line argument was found and removed; %FALSE if it was not. - * - * Since: 1.26 - **/ -gboolean -nm_setting_match_remove_kernel_command_line_by_value(NMSettingMatch *setting, - const char * kernel_command_line) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), FALSE); - g_return_val_if_fail(kernel_command_line != NULL, FALSE); - g_return_val_if_fail(kernel_command_line[0] != '\0', FALSE); - - if (nm_strvarray_remove_first(setting->kernel_command_line, kernel_command_line)) { - _notify(setting, PROP_KERNEL_COMMAND_LINE); - return TRUE; - } - - return FALSE; -} - -/** - * nm_setting_match_clear_kernel_command_lines: - * @setting: the #NMSettingMatch - * - * Removes all configured kernel command line arguments. - * - * Since: 1.26 - **/ -void -nm_setting_match_clear_kernel_command_lines(NMSettingMatch *setting) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - - if (nm_g_array_len(setting->kernel_command_line) != 0) { - nm_clear_pointer(&setting->kernel_command_line, g_array_unref); - _notify(setting, PROP_KERNEL_COMMAND_LINE); - } -} - -/** - * nm_setting_match_get_kernel_command_lines: - * @setting: the #NMSettingMatch - * @length: (out) (allow-none): the length of the returned interface names array. - * - * Returns all the interface names. - * - * Returns: (transfer none) (array length=length): the configured interface names. - * - * Since: 1.26 - **/ -const char *const * -nm_setting_match_get_kernel_command_lines(NMSettingMatch *setting, guint *length) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); - - return nm_strvarray_get_strv(&setting->kernel_command_line, length); -} - -/*****************************************************************************/ - -/** - * nm_setting_match_get_num_drivers: - * @setting: the #NMSettingMatch - * - * Returns: the number of configured drivers - * - * Since: 1.26 - **/ -guint -nm_setting_match_get_num_drivers(NMSettingMatch *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), 0); - - return nm_g_array_len(setting->driver); -} - -/** - * nm_setting_match_get_driver: - * @setting: the #NMSettingMatch - * @idx: index number of the DNS search domain to return - * - * Returns: the driver at index @idx - * - * Since: 1.26 - **/ -const char * -nm_setting_match_get_driver(NMSettingMatch *setting, guint idx) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); - - g_return_val_if_fail(setting->driver && idx < setting->driver->len, NULL); - - return g_array_index(setting->driver, const char *, idx); -} - -/** - * nm_setting_match_add_driver: - * @setting: the #NMSettingMatch - * @driver: the driver to add - * - * Adds a new driver to the setting. - * - * Since: 1.26 - **/ -void -nm_setting_match_add_driver(NMSettingMatch *setting, const char *driver) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - g_return_if_fail(driver != NULL); - g_return_if_fail(driver[0] != '\0'); - - nm_strvarray_add(nm_strvarray_ensure(&setting->driver), driver); - _notify(setting, PROP_DRIVER); -} - -/** - * nm_setting_match_remove_driver: - * @setting: the #NMSettingMatch - * @idx: index number of the driver - * - * Removes the driver at index @idx. - * - * Since: 1.26 - **/ -void -nm_setting_match_remove_driver(NMSettingMatch *setting, guint idx) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - - g_return_if_fail(setting->driver && idx < setting->driver->len); - - g_array_remove_index(setting->driver, idx); - _notify(setting, PROP_DRIVER); -} - -/** - * nm_setting_match_remove_driver_by_value: - * @setting: the #NMSettingMatch - * @driver: the driver to remove - * - * Removes @driver. - * - * Returns: %TRUE if the driver was found and removed; %FALSE if it was not. - * - * Since: 1.26 - **/ -gboolean -nm_setting_match_remove_driver_by_value(NMSettingMatch *setting, const char *driver) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), FALSE); - g_return_val_if_fail(driver != NULL, FALSE); - g_return_val_if_fail(driver[0] != '\0', FALSE); - - if (nm_strvarray_remove_first(setting->driver, driver)) { - _notify(setting, PROP_DRIVER); - return TRUE; - } - - return FALSE; -} - -/** - * nm_setting_match_clear_drivers: - * @setting: the #NMSettingMatch - * - * Removes all configured drivers. - * - * Since: 1.26 - **/ -void -nm_setting_match_clear_drivers(NMSettingMatch *setting) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - - if (nm_g_array_len(setting->driver) != 0) { - nm_clear_pointer(&setting->driver, g_array_unref); - _notify(setting, PROP_DRIVER); - } -} - -/** - * nm_setting_match_get_drivers: - * @setting: the #NMSettingMatch - * @length: (out) (allow-none): the length of the returned interface names array. - * - * Returns all the drivers. - * - * Returns: (transfer none) (array length=length): the configured drivers. - * - * Since: 1.26 - **/ -const char *const * -nm_setting_match_get_drivers(NMSettingMatch *setting, guint *length) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); - - return nm_strvarray_get_strv(&setting->driver, length); -} - -/*****************************************************************************/ - -/** - * nm_setting_match_get_num_paths: - * @setting: the #NMSettingMatch - * - * Returns: the number of configured paths - * - * Since: 1.26 - **/ -guint -nm_setting_match_get_num_paths(NMSettingMatch *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), 0); - - return nm_g_array_len(setting->path); -} - -/** - * nm_setting_match_get_path: - * @setting: the #NMSettingMatch - * @idx: index number of the path to return - * - * Returns: the path at index @idx - * - * Since: 1.26 - **/ -const char * -nm_setting_match_get_path(NMSettingMatch *setting, guint idx) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); - - g_return_val_if_fail(setting->path && idx < setting->path->len, NULL); - - return g_array_index(setting->path, const char *, idx); -} - -/** - * nm_setting_match_add_path: - * @setting: the #NMSettingMatch - * @path: the path to add - * - * Adds a new path to the setting. - * - * Since: 1.26 - **/ -void -nm_setting_match_add_path(NMSettingMatch *setting, const char *path) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - g_return_if_fail(path != NULL); - g_return_if_fail(path[0] != '\0'); - - nm_strvarray_add(nm_strvarray_ensure(&setting->path), path); - _notify(setting, PROP_PATH); -} - -/** - * nm_setting_match_remove_path: - * @setting: the #NMSettingMatch - * @idx: index number of the path - * - * Removes the path at index @idx. - * - * Since: 1.26 - **/ -void -nm_setting_match_remove_path(NMSettingMatch *setting, guint idx) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - - g_return_if_fail(setting->path && idx < setting->path->len); - - g_array_remove_index(setting->path, idx); - _notify(setting, PROP_PATH); -} - -/** - * nm_setting_match_remove_path_by_value: - * @setting: the #NMSettingMatch - * @path: the path to remove - * - * Removes @path. - * - * Returns: %TRUE if the path was found and removed; %FALSE if it was not. - * - * Since: 1.26 - **/ -gboolean -nm_setting_match_remove_path_by_value(NMSettingMatch *setting, const char *path) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), FALSE); - g_return_val_if_fail(path != NULL, FALSE); - g_return_val_if_fail(path[0] != '\0', FALSE); - - if (nm_strvarray_remove_first(setting->path, path)) { - _notify(setting, PROP_PATH); - return TRUE; - } - - return FALSE; -} - -/** - * nm_setting_match_clear_paths: - * @setting: the #NMSettingMatch - * - * Removes all configured paths. - * - * Since: 1.26 - **/ -void -nm_setting_match_clear_paths(NMSettingMatch *setting) -{ - g_return_if_fail(NM_IS_SETTING_MATCH(setting)); - - if (nm_g_array_len(setting->path) != 0) { - nm_clear_pointer(&setting->path, g_array_unref); - _notify(setting, PROP_PATH); - } -} - -/** - * nm_setting_match_get_paths: - * @setting: the #NMSettingMatch - * @length: (out) (allow-none): the length of the returned paths array. - * - * Returns all the paths. - * - * Returns: (transfer none) (array length=length): the configured paths. - * - * Since: 1.26 - **/ -const char *const * -nm_setting_match_get_paths(NMSettingMatch *setting, guint *length) -{ - g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); - - return nm_strvarray_get_strv(&setting->path, length); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingMatch *self = NM_SETTING_MATCH(object); - - switch (prop_id) { - case PROP_INTERFACE_NAME: - g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(self->interface_name, NULL)); - break; - case PROP_KERNEL_COMMAND_LINE: - g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(self->kernel_command_line, NULL)); - break; - case PROP_DRIVER: - g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(self->driver, NULL)); - break; - case PROP_PATH: - g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(self->path, NULL)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingMatch *self = NM_SETTING_MATCH(object); - - switch (prop_id) { - case PROP_INTERFACE_NAME: - nm_strvarray_set_strv(&self->interface_name, g_value_get_boxed(value)); - break; - case PROP_KERNEL_COMMAND_LINE: - nm_strvarray_set_strv(&self->kernel_command_line, g_value_get_boxed(value)); - break; - case PROP_DRIVER: - nm_strvarray_set_strv(&self->driver, g_value_get_boxed(value)); - break; - case PROP_PATH: - nm_strvarray_set_strv(&self->path, g_value_get_boxed(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_match_init(NMSettingMatch *setting) -{} - -/** - * nm_setting_match_new: - * - * Creates a new #NMSettingMatch object with default values. - * - * Returns: (transfer full): the new empty #NMSettingMatch object - * - * Since: 1.14 - **/ -NMSetting * -nm_setting_match_new(void) -{ - return g_object_new(NM_TYPE_SETTING_MATCH, NULL); -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingMatch *self = NM_SETTING_MATCH(setting); - guint i; - - if (self->interface_name) { - for (i = 0; i < self->interface_name->len; i++) { - if (nm_str_is_empty(g_array_index(self->interface_name, const char *, i))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MATCH_SETTING_NAME, - NM_SETTING_MATCH_INTERFACE_NAME); - return FALSE; - } - } - } - - if (self->kernel_command_line) { - for (i = 0; i < self->kernel_command_line->len; i++) { - if (nm_str_is_empty(g_array_index(self->kernel_command_line, const char *, i))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MATCH_SETTING_NAME, - NM_SETTING_MATCH_KERNEL_COMMAND_LINE); - return FALSE; - } - } - } - - if (self->driver) { - for (i = 0; i < self->driver->len; i++) { - if (nm_str_is_empty(g_array_index(self->driver, const char *, i))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MATCH_SETTING_NAME, - NM_SETTING_MATCH_DRIVER); - return FALSE; - } - } - } - - if (self->path) { - for (i = 0; i < self->path->len; i++) { - if (nm_str_is_empty(g_array_index(self->path, const char *, i))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_MATCH_SETTING_NAME, - NM_SETTING_MATCH_PATH); - return FALSE; - } - } - } - - return TRUE; -} - -static void -finalize(GObject *object) -{ - NMSettingMatch *self = NM_SETTING_MATCH(object); - - nm_clear_pointer(&self->interface_name, g_array_unref); - nm_clear_pointer(&self->kernel_command_line, g_array_unref); - nm_clear_pointer(&self->driver, g_array_unref); - nm_clear_pointer(&self->path, g_array_unref); - - G_OBJECT_CLASS(nm_setting_match_parent_class)->finalize(object); -} - -static void -nm_setting_match_class_init(NMSettingMatchClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingMatch:interface-name - * - * A list of interface names to match. Each element is a shell wildcard - * pattern. - * - * An element can be prefixed with a pipe symbol (|) or an ampersand (&). - * The former means that the element is optional and the latter means that - * it is mandatory. If there are any optional elements, than the match - * evaluates to true if at least one of the optional element matches - * (logical OR). If there are any mandatory elements, then they all - * must match (logical AND). By default, an element is optional. This means - * that an element "foo" behaves the same as "|foo". An element can also be inverted - * with exclamation mark (!) between the pipe symbol (or the ampersand) and before - * the pattern. Note that "!foo" is a shortcut for the mandatory match "&!foo". Finally, - * a backslash can be used at the beginning of the element (after the optional special characters) - * to escape the start of the pattern. For example, "&\\!a" is an mandatory match for literally "!a". - * - * Since: 1.14 - **/ - obj_properties[PROP_INTERFACE_NAME] = g_param_spec_boxed( - NM_SETTING_MATCH_INTERFACE_NAME, - "", - "", - G_TYPE_STRV, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMatch:kernel-command-line - * - * A list of kernel command line arguments to match. This may be used to check - * whether a specific kernel command line option is set (or if prefixed with - * the exclamation mark unset). The argument must either be a single word, or - * an assignment (i.e. two words, separated "="). In the former case the kernel - * command line is searched for the word appearing as is, or as left hand side - * of an assignment. In the latter case, the exact assignment is looked for - * with right and left hand side matching. - * - * See NMSettingMatch:interface-name for how special characters '|', '&', - * '!' and '\\' are used for optional and mandatory matches and inverting the - * pattern. - * - * Since: 1.26 - **/ - obj_properties[PROP_KERNEL_COMMAND_LINE] = g_param_spec_boxed( - NM_SETTING_MATCH_KERNEL_COMMAND_LINE, - "", - "", - G_TYPE_STRV, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMatch:driver - * - * A list of driver names to match. Each element is a shell wildcard pattern. - * - * See NMSettingMatch:interface-name for how special characters '|', '&', - * '!' and '\\' are used for optional and mandatory matches and inverting the - * pattern. - * - * Since: 1.26 - **/ - obj_properties[PROP_DRIVER] = g_param_spec_boxed( - NM_SETTING_MATCH_DRIVER, - "", - "", - G_TYPE_STRV, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingMatch:path - * - * A list of paths to match against the ID_PATH udev property of - * devices. ID_PATH represents the topological persistent path of a - * device. It typically contains a subsystem string (pci, usb, platform, - * etc.) and a subsystem-specific identifier. - * - * For PCI devices the path has the form - * "pci-$domain:$bus:$device.$function", where each variable is an - * hexadecimal value; for example "pci-0000:0a:00.0". - * - * The path of a device can be obtained with "udevadm info - * /sys/class/net/$dev | grep ID_PATH=" or by looking at the "path" - * property exported by NetworkManager ("nmcli -f general.path device - * show $dev"). - * - * Each element of the list is a shell wildcard pattern. - * - * See NMSettingMatch:interface-name for how special characters '|', '&', - * '!' and '\\' are used for optional and mandatory matches and inverting the - * pattern. - * - * Since: 1.26 - **/ - /* ---ifcfg-rh--- - * property: path - * variable: MATCH_PATH - * description: space-separated list of paths to match against the udev - * property ID_PATHS of devices - * example: MATCH_PATH="pci-0000:01:00.0 pci-0000:0c:00.0" - * ---end--- - */ - obj_properties[PROP_PATH] = g_param_spec_boxed(NM_SETTING_MATCH_PATH, - "", - "", - G_TYPE_STRV, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_MATCH); -} diff --git a/libnm-core/nm-setting-match.h b/libnm-core/nm-setting-match.h deleted file mode 100644 index 9b3e29e7c0..0000000000 --- a/libnm-core/nm-setting-match.h +++ /dev/null @@ -1,107 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#ifndef NM_SETTING_MATCH_H -#define NM_SETTING_MATCH_H - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_MATCH (nm_setting_match_get_type()) -#define NM_SETTING_MATCH(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_MATCH, NMSettingMatch)) -#define NM_SETTING_MATCH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_MATCH, NMSettingMatchClass)) -#define NM_IS_SETTING_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_MATCH)) -#define NM_IS_SETTING_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_MATCH)) -#define NM_SETTING_MATCH_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_MATCH, NMSettingMatchClass)) - -#define NM_SETTING_MATCH_SETTING_NAME "match" - -#define NM_SETTING_MATCH_INTERFACE_NAME "interface-name" -#define NM_SETTING_MATCH_KERNEL_COMMAND_LINE "kernel-command-line" -#define NM_SETTING_MATCH_DRIVER "driver" -#define NM_SETTING_MATCH_PATH "path" - -typedef struct _NMSettingMatchClass NMSettingMatchClass; - -NM_AVAILABLE_IN_1_14 -GType nm_setting_match_get_type(void); -NM_AVAILABLE_IN_1_14 -NMSetting *nm_setting_match_new(void); - -NM_AVAILABLE_IN_1_14 -guint nm_setting_match_get_num_interface_names(NMSettingMatch *setting); -NM_AVAILABLE_IN_1_14 -const char *nm_setting_match_get_interface_name(NMSettingMatch *setting, int idx); -NM_AVAILABLE_IN_1_14 -void nm_setting_match_remove_interface_name(NMSettingMatch *setting, int idx); -NM_AVAILABLE_IN_1_14 -gboolean nm_setting_match_remove_interface_name_by_value(NMSettingMatch *setting, - const char * interface_name); -NM_AVAILABLE_IN_1_14 -void nm_setting_match_add_interface_name(NMSettingMatch *setting, const char *interface_name); -NM_AVAILABLE_IN_1_14 -void nm_setting_match_clear_interface_names(NMSettingMatch *setting); -NM_AVAILABLE_IN_1_14 -const char *const *nm_setting_match_get_interface_names(NMSettingMatch *setting, guint *length); - -NM_AVAILABLE_IN_1_26 -guint nm_setting_match_get_num_kernel_command_lines(NMSettingMatch *setting); -NM_AVAILABLE_IN_1_26 -const char *nm_setting_match_get_kernel_command_line(NMSettingMatch *setting, guint idx); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_remove_kernel_command_line(NMSettingMatch *setting, guint idx); -NM_AVAILABLE_IN_1_26 -gboolean nm_setting_match_remove_kernel_command_line_by_value(NMSettingMatch *setting, - const char * kernel_command_line); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_add_kernel_command_line(NMSettingMatch *setting, - const char * kernel_command_line); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_clear_kernel_command_lines(NMSettingMatch *setting); -NM_AVAILABLE_IN_1_26 -const char *const *nm_setting_match_get_kernel_command_lines(NMSettingMatch *setting, - guint * length); - -NM_AVAILABLE_IN_1_26 -guint nm_setting_match_get_num_drivers(NMSettingMatch *setting); -NM_AVAILABLE_IN_1_26 -const char *nm_setting_match_get_driver(NMSettingMatch *setting, guint idx); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_remove_driver(NMSettingMatch *setting, guint idx); -NM_AVAILABLE_IN_1_26 -gboolean nm_setting_match_remove_driver_by_value(NMSettingMatch *setting, const char *driver); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_add_driver(NMSettingMatch *setting, const char *driver); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_clear_drivers(NMSettingMatch *setting); -NM_AVAILABLE_IN_1_26 -const char *const *nm_setting_match_get_drivers(NMSettingMatch *setting, guint *length); - -NM_AVAILABLE_IN_1_26 -guint nm_setting_match_get_num_paths(NMSettingMatch *setting); -NM_AVAILABLE_IN_1_26 -const char *nm_setting_match_get_path(NMSettingMatch *setting, guint idx); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_remove_path(NMSettingMatch *setting, guint idx); -NM_AVAILABLE_IN_1_26 -gboolean nm_setting_match_remove_path_by_value(NMSettingMatch *setting, const char *path); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_add_path(NMSettingMatch *setting, const char *path); -NM_AVAILABLE_IN_1_26 -void nm_setting_match_clear_paths(NMSettingMatch *setting); -NM_AVAILABLE_IN_1_26 -const char *const *nm_setting_match_get_paths(NMSettingMatch *setting, guint *length); - -G_END_DECLS - -#endif /* NM_SETTING_MATCH_H */ diff --git a/libnm-core/nm-setting-olpc-mesh.c b/libnm-core/nm-setting-olpc-mesh.c deleted file mode 100644 index ef0b5d603d..0000000000 --- a/libnm-core/nm-setting-olpc-mesh.c +++ /dev/null @@ -1,274 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2009 One Laptop per Child - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-olpc-mesh.h" - -#include - -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-olpc-mesh - * @short_description: Describes connection properties for OLPC-Mesh devices - * - * The #NMSettingOlpcMesh object is a #NMSetting subclass that describes properties - * necessary for connection to OLPC-Mesh devices. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_SSID, PROP_CHANNEL, PROP_DHCP_ANYCAST_ADDRESS, ); - -typedef struct { - GBytes *ssid; - char * dhcp_anycast_addr; - guint32 channel; -} NMSettingOlpcMeshPrivate; - -G_DEFINE_TYPE(NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING) - -#define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_olpc_mesh_get_ssid: - * @setting: the #NMSettingOlpcMesh - * - * Returns: (transfer none): - */ -GBytes * -nm_setting_olpc_mesh_get_ssid(NMSettingOlpcMesh *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_OLPC_MESH(setting), NULL); - - return NM_SETTING_OLPC_MESH_GET_PRIVATE(setting)->ssid; -} - -guint32 -nm_setting_olpc_mesh_get_channel(NMSettingOlpcMesh *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_OLPC_MESH(setting), 0); - - return NM_SETTING_OLPC_MESH_GET_PRIVATE(setting)->channel; -} - -const char * -nm_setting_olpc_mesh_get_dhcp_anycast_address(NMSettingOlpcMesh *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_OLPC_MESH(setting), NULL); - - return NM_SETTING_OLPC_MESH_GET_PRIVATE(setting)->dhcp_anycast_addr; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE(setting); - gsize length; - - if (!priv->ssid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OLPC_MESH_SETTING_NAME, - NM_SETTING_OLPC_MESH_SSID); - return FALSE; - } - - length = g_bytes_get_size(priv->ssid); - if (length == 0 || length > 32) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("SSID length is out of range <1-32> bytes")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OLPC_MESH_SETTING_NAME, - NM_SETTING_OLPC_MESH_SSID); - return FALSE; - } - - if (priv->channel == 0 || priv->channel > 13) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%d' is not a valid channel"), - priv->channel); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OLPC_MESH_SETTING_NAME, - NM_SETTING_OLPC_MESH_CHANNEL); - return FALSE; - } - - if (priv->dhcp_anycast_addr && !nm_utils_hwaddr_valid(priv->dhcp_anycast_addr, ETH_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OLPC_MESH_SETTING_NAME, - NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingOlpcMesh *setting = NM_SETTING_OLPC_MESH(object); - - switch (prop_id) { - case PROP_SSID: - g_value_set_boxed(value, nm_setting_olpc_mesh_get_ssid(setting)); - break; - case PROP_CHANNEL: - g_value_set_uint(value, nm_setting_olpc_mesh_get_channel(setting)); - break; - case PROP_DHCP_ANYCAST_ADDRESS: - g_value_set_string(value, nm_setting_olpc_mesh_get_dhcp_anycast_address(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_SSID: - if (priv->ssid) - g_bytes_unref(priv->ssid); - priv->ssid = g_value_dup_boxed(value); - break; - case PROP_CHANNEL: - priv->channel = g_value_get_uint(value); - break; - case PROP_DHCP_ANYCAST_ADDRESS: - g_free(priv->dhcp_anycast_addr); - priv->dhcp_anycast_addr = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_olpc_mesh_init(NMSettingOlpcMesh *setting) -{} - -/** - * nm_setting_olpc_mesh_new: - * - * Creates a new #NMSettingOlpcMesh object with default values. - * - * Returns: the new empty #NMSettingOlpcMesh object - **/ -NMSetting * -nm_setting_olpc_mesh_new(void) -{ - return g_object_new(NM_TYPE_SETTING_OLPC_MESH, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE(object); - - if (priv->ssid) - g_bytes_unref(priv->ssid); - g_free(priv->dhcp_anycast_addr); - - G_OBJECT_CLASS(nm_setting_olpc_mesh_parent_class)->finalize(object); -} - -static void -nm_setting_olpc_mesh_class_init(NMSettingOlpcMeshClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingOlpcMeshPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingOlpcMesh:ssid: - * - * SSID of the mesh network to join. - **/ - obj_properties[PROP_SSID] = g_param_spec_boxed(NM_SETTING_OLPC_MESH_SSID, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOlpcMesh:channel: - * - * Channel on which the mesh network to join is located. - **/ - obj_properties[PROP_CHANNEL] = - g_param_spec_uint(NM_SETTING_OLPC_MESH_CHANNEL, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOlpcMesh:dhcp-anycast-address: - * - * Anycast DHCP MAC address used when requesting an IP address via DHCP. - * The specific anycast address used determines which DHCP server class - * answers the request. - **/ - obj_properties[PROP_DHCP_ANYCAST_ADDRESS] = - g_param_spec_string(NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_DHCP_ANYCAST_ADDRESS], - &nm_sett_info_propert_type_mac_address); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_OLPC_MESH, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-olpc-mesh.h b/libnm-core/nm-setting-olpc-mesh.h deleted file mode 100644 index fdba4a4b9a..0000000000 --- a/libnm-core/nm-setting-olpc-mesh.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2008 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2009 One Laptop per Child - */ - -#ifndef __NM_SETTING_OLPC_MESH_H__ -#define __NM_SETTING_OLPC_MESH_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_OLPC_MESH (nm_setting_olpc_mesh_get_type()) -#define NM_SETTING_OLPC_MESH(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMesh)) -#define NM_SETTING_OLPC_MESH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass)) -#define NM_IS_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OLPC_MESH)) -#define NM_IS_SETTING_OLPC_MESH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OLPC_MESH)) -#define NM_SETTING_OLPC_MESH_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass)) - -#define NM_SETTING_OLPC_MESH_SETTING_NAME "802-11-olpc-mesh" - -#define NM_SETTING_OLPC_MESH_SSID "ssid" -#define NM_SETTING_OLPC_MESH_CHANNEL "channel" -#define NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS "dhcp-anycast-address" - -/** - * NMSettingOlpcMesh: - * - * OLPC Wireless Mesh Settings - */ -struct _NMSettingOlpcMesh { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingOlpcMeshClass; - -GType nm_setting_olpc_mesh_get_type(void); - -NMSetting * nm_setting_olpc_mesh_new(void); -GBytes * nm_setting_olpc_mesh_get_ssid(NMSettingOlpcMesh *setting); -guint32 nm_setting_olpc_mesh_get_channel(NMSettingOlpcMesh *setting); -const char *nm_setting_olpc_mesh_get_dhcp_anycast_address(NMSettingOlpcMesh *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_OLPC_MESH_H__ */ diff --git a/libnm-core/nm-setting-ovs-bridge.c b/libnm-core/nm-setting-ovs-bridge.c deleted file mode 100644 index 07d24d7bf0..0000000000 --- a/libnm-core/nm-setting-ovs-bridge.c +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ovs-bridge.h" - -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-ovs-bridge - * @short_description: Describes connection properties for Open vSwitch bridges. - * - * The #NMSettingOvsBridge object is a #NMSetting subclass that describes properties - * necessary for Open vSwitch bridges. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_FAIL_MODE, - PROP_MCAST_SNOOPING_ENABLE, - PROP_RSTP_ENABLE, - PROP_STP_ENABLE, - PROP_DATAPATH_TYPE, ); - -/** - * NMSettingOvsBridge: - * - * OvsBridge Link Settings - */ -struct _NMSettingOvsBridge { - NMSetting parent; - - char *fail_mode; - char *datapath_type; - bool mcast_snooping_enable : 1; - bool rstp_enable : 1; - bool stp_enable : 1; -}; - -struct _NMSettingOvsBridgeClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING) - -/*****************************************************************************/ - -/** - * nm_setting_ovs_bridge_get_fail_mode: - * @self: the #NMSettingOvsBridge - * - * Returns: the #NMSettingOvsBridge:fail_mode property of the setting - * - * Since: 1.10 - **/ -const char * -nm_setting_ovs_bridge_get_fail_mode(NMSettingOvsBridge *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), NULL); - - return self->fail_mode; -} - -/** - * nm_setting_ovs_bridge_get_mcast_snooping_enable: - * @self: the #NMSettingOvsBridge - * - * Returns: the #NMSettingOvsBridge:mcast_snooping_enable property of the setting - * - * Since: 1.10 - **/ -gboolean -nm_setting_ovs_bridge_get_mcast_snooping_enable(NMSettingOvsBridge *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), FALSE); - - return self->mcast_snooping_enable; -} - -/** - * nm_setting_ovs_bridge_get_rstp_enable: - * @self: the #NMSettingOvsBridge - * - * Returns: the #NMSettingOvsBridge:rstp_enable property of the setting - * - * Since: 1.10 - **/ -gboolean -nm_setting_ovs_bridge_get_rstp_enable(NMSettingOvsBridge *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), FALSE); - - return self->rstp_enable; -} - -/** - * nm_setting_ovs_bridge_get_stp_enable: - * @self: the #NMSettingOvsBridge - * - * Returns: the #NMSettingOvsBridge:stp_enable property of the setting - * - * Since: 1.10 - **/ -gboolean -nm_setting_ovs_bridge_get_stp_enable(NMSettingOvsBridge *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), FALSE); - - return self->stp_enable; -} - -/** - * nm_setting_ovs_bridge_get_datapath_type: - * @self: the #NMSettingOvsBridge - * - * Returns: the #NMSettingOvsBridge:datapath_type property of the setting - * - * Since: 1.20 - **/ -const char * -nm_setting_ovs_bridge_get_datapath_type(NMSettingOvsBridge *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), NULL); - - return self->datapath_type; -} - -/*****************************************************************************/ - -static int -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE(setting); - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - if (connection) { - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("missing setting")); - g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); - return FALSE; - } - - if (nm_setting_connection_get_master(s_con)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting must not have a master."), - NM_SETTING_OVS_BRIDGE_SETTING_NAME); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_MASTER); - return FALSE; - } - } - - if (!NM_IN_STRSET(self->fail_mode, "secure", "standalone", NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not allowed in fail_mode"), - self->fail_mode); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_BRIDGE_FAIL_MODE); - return FALSE; - } - - if (!NM_IN_STRSET(self->datapath_type, "system", "netdev", NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not valid"), - self->datapath_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_BRIDGE_DATAPATH_TYPE); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE(object); - - switch (prop_id) { - case PROP_FAIL_MODE: - g_value_set_string(value, self->fail_mode); - break; - case PROP_MCAST_SNOOPING_ENABLE: - g_value_set_boolean(value, self->mcast_snooping_enable); - break; - case PROP_RSTP_ENABLE: - g_value_set_boolean(value, self->rstp_enable); - break; - case PROP_STP_ENABLE: - g_value_set_boolean(value, self->stp_enable); - break; - case PROP_DATAPATH_TYPE: - g_value_set_string(value, self->datapath_type); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE(object); - - switch (prop_id) { - case PROP_FAIL_MODE: - g_free(self->fail_mode); - self->fail_mode = g_value_dup_string(value); - break; - case PROP_MCAST_SNOOPING_ENABLE: - self->mcast_snooping_enable = g_value_get_boolean(value); - break; - case PROP_RSTP_ENABLE: - self->rstp_enable = g_value_get_boolean(value); - break; - case PROP_STP_ENABLE: - self->stp_enable = g_value_get_boolean(value); - break; - case PROP_DATAPATH_TYPE: - g_free(self->datapath_type); - self->datapath_type = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ovs_bridge_init(NMSettingOvsBridge *self) -{} - -/** - * nm_setting_ovs_bridge_new: - * - * Creates a new #NMSettingOvsBridge object with default values. - * - * Returns: (transfer full): the new empty #NMSettingOvsBridge object - * - * Since: 1.10 - **/ -NMSetting * -nm_setting_ovs_bridge_new(void) -{ - return g_object_new(NM_TYPE_SETTING_OVS_BRIDGE, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE(object); - - g_free(self->fail_mode); - g_free(self->datapath_type); - - G_OBJECT_CLASS(nm_setting_ovs_bridge_parent_class)->finalize(object); -} - -static void -nm_setting_ovs_bridge_class_init(NMSettingOvsBridgeClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingOvsBridge:fail-mode: - * - * The bridge failure mode. One of "secure", "standalone" or empty. - * - * Since: 1.10 - **/ - obj_properties[PROP_FAIL_MODE] = g_param_spec_string( - NM_SETTING_OVS_BRIDGE_FAIL_MODE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsBridge:mcast-snooping-enable: - * - * Enable or disable multicast snooping. - * - * Since: 1.10 - **/ - obj_properties[PROP_MCAST_SNOOPING_ENABLE] = - g_param_spec_boolean(NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsBridge:rstp-enable: - * - * Enable or disable RSTP. - * - * Since: 1.10 - **/ - obj_properties[PROP_RSTP_ENABLE] = - g_param_spec_boolean(NM_SETTING_OVS_BRIDGE_RSTP_ENABLE, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsBridge:stp-enable: - * - * Enable or disable STP. - * - * Since: 1.10 - **/ - obj_properties[PROP_STP_ENABLE] = - g_param_spec_boolean(NM_SETTING_OVS_BRIDGE_STP_ENABLE, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsBridge:datapath-type: - * - * The data path type. One of "system", "netdev" or empty. - * - * Since: 1.20 - **/ - obj_properties[PROP_DATAPATH_TYPE] = g_param_spec_string( - NM_SETTING_OVS_BRIDGE_DATAPATH_TYPE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_BRIDGE); -} diff --git a/libnm-core/nm-setting-ovs-bridge.h b/libnm-core/nm-setting-ovs-bridge.h deleted file mode 100644 index b307871503..0000000000 --- a/libnm-core/nm-setting-ovs-bridge.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_OVS_BRIDGE_H__ -#define __NM_SETTING_OVS_BRIDGE_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_OVS_BRIDGE (nm_setting_ovs_bridge_get_type()) -#define NM_SETTING_OVS_BRIDGE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_BRIDGE, NMSettingOvsBridge)) -#define NM_SETTING_OVS_BRIDGE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OVS_BRIDGECONFIG, NMSettingOvsBridgeClass)) -#define NM_IS_SETTING_OVS_BRIDGE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_BRIDGE)) -#define NM_IS_SETTING_OVS_BRIDGE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_BRIDGE)) -#define NM_SETTING_OVS_BRIDGE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_BRIDGE, NMSettingOvsBridgeClass)) - -#define NM_SETTING_OVS_BRIDGE_SETTING_NAME "ovs-bridge" - -#define NM_SETTING_OVS_BRIDGE_FAIL_MODE "fail-mode" -#define NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE "mcast-snooping-enable" -#define NM_SETTING_OVS_BRIDGE_RSTP_ENABLE "rstp-enable" -#define NM_SETTING_OVS_BRIDGE_STP_ENABLE "stp-enable" -#define NM_SETTING_OVS_BRIDGE_DATAPATH_TYPE "datapath-type" - -typedef struct _NMSettingOvsBridgeClass NMSettingOvsBridgeClass; - -NM_AVAILABLE_IN_1_10 -GType nm_setting_ovs_bridge_get_type(void); -NM_AVAILABLE_IN_1_10 -NMSetting *nm_setting_ovs_bridge_new(void); - -NM_AVAILABLE_IN_1_10 -const char *nm_setting_ovs_bridge_get_fail_mode(NMSettingOvsBridge *self); -NM_AVAILABLE_IN_1_10 -gboolean nm_setting_ovs_bridge_get_mcast_snooping_enable(NMSettingOvsBridge *self); -NM_AVAILABLE_IN_1_10 -gboolean nm_setting_ovs_bridge_get_rstp_enable(NMSettingOvsBridge *self); -NM_AVAILABLE_IN_1_10 -gboolean nm_setting_ovs_bridge_get_stp_enable(NMSettingOvsBridge *self); -NM_AVAILABLE_IN_1_20 -const char *nm_setting_ovs_bridge_get_datapath_type(NMSettingOvsBridge *self); - -G_END_DECLS - -#endif /* __NM_SETTING_OVS_BRIDGE_H__ */ diff --git a/libnm-core/nm-setting-ovs-dpdk.c b/libnm-core/nm-setting-ovs-dpdk.c deleted file mode 100644 index 6d27d78c4d..0000000000 --- a/libnm-core/nm-setting-ovs-dpdk.c +++ /dev/null @@ -1,152 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ovs-dpdk.h" - -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-ovs-dpdk - * @short_description: Describes connection properties for Open vSwitch DPDK interfaces. - * - * The #NMSettingOvsDpdk object is a #NMSetting subclass that describes properties - * necessary for Open vSwitch interfaces of type "dpdk". - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_DEVARGS, ); - -/** - * NMSettingOvsDpdk: - * - * OvsDpdk Link Settings - */ -struct _NMSettingOvsDpdk { - NMSetting parent; - - char *devargs; -}; - -struct _NMSettingOvsDpdkClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingOvsDpdk, nm_setting_ovs_dpdk, NM_TYPE_SETTING) - -/*****************************************************************************/ - -/** - * nm_setting_ovs_dpdk_get_devargs: - * @self: the #NMSettingOvsDpdk - * - * Returns: the #NMSettingOvsDpdk:devargs property of the setting - * - * Since: 1.20 - **/ -const char * -nm_setting_ovs_dpdk_get_devargs(NMSettingOvsDpdk *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_DPDK(self), NULL); - - return self->devargs; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingOvsDpdk *self = NM_SETTING_OVS_DPDK(object); - - switch (prop_id) { - case PROP_DEVARGS: - g_value_set_string(value, self->devargs); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingOvsDpdk *self = NM_SETTING_OVS_DPDK(object); - - switch (prop_id) { - case PROP_DEVARGS: - g_free(self->devargs); - self->devargs = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ovs_dpdk_init(NMSettingOvsDpdk *self) -{} - -/** - * nm_setting_ovs_dpdk_new: - * - * Creates a new #NMSettingOvsDpdk object with default values. - * - * Returns: (transfer full): the new empty #NMSettingOvsDpdk object - * - * Since: 1.20 - **/ -NMSetting * -nm_setting_ovs_dpdk_new(void) -{ - return g_object_new(NM_TYPE_SETTING_OVS_DPDK, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingOvsDpdk *self = NM_SETTING_OVS_DPDK(object); - - g_free(self->devargs); - - G_OBJECT_CLASS(nm_setting_ovs_dpdk_parent_class)->finalize(object); -} - -static void -nm_setting_ovs_dpdk_class_init(NMSettingOvsDpdkClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - - /** - * NMSettingOvsDpdk:devargs: - * - * Open vSwitch DPDK device arguments. - * - * Since: 1.20 - **/ - obj_properties[PROP_DEVARGS] = g_param_spec_string( - NM_SETTING_OVS_DPDK_DEVARGS, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_DPDK); -} diff --git a/libnm-core/nm-setting-ovs-dpdk.h b/libnm-core/nm-setting-ovs-dpdk.h deleted file mode 100644 index 72de2243c0..0000000000 --- a/libnm-core/nm-setting-ovs-dpdk.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_OVS_DPDK_H__ -#define __NM_SETTING_OVS_DPDK_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_OVS_DPDK (nm_setting_ovs_dpdk_get_type()) -#define NM_SETTING_OVS_DPDK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_DPDK, NMSettingOvsDpdk)) -#define NM_SETTING_OVS_DPDK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OVS_DPDKCONFIG, NMSettingOvsDpdkClass)) -#define NM_IS_SETTING_OVS_DPDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_DPDK)) -#define NM_IS_SETTING_OVS_DPDK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_DPDK)) -#define NM_SETTING_OVS_DPDK_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_DPDK, NMSettingOvsDpdkClass)) - -#define NM_SETTING_OVS_DPDK_SETTING_NAME "ovs-dpdk" - -#define NM_SETTING_OVS_DPDK_DEVARGS "devargs" - -typedef struct _NMSettingOvsDpdkClass NMSettingOvsDpdkClass; - -NM_AVAILABLE_IN_1_20 -GType nm_setting_ovs_dpdk_get_type(void); -NM_AVAILABLE_IN_1_20 -NMSetting *nm_setting_ovs_dpdk_new(void); - -NM_AVAILABLE_IN_1_20 -const char *nm_setting_ovs_dpdk_get_devargs(NMSettingOvsDpdk *self); - -G_END_DECLS - -#endif /* __NM_SETTING_OVS_DPDK_H__ */ diff --git a/libnm-core/nm-setting-ovs-external-ids.c b/libnm-core/nm-setting-ovs-external-ids.c deleted file mode 100644 index 16becb7272..0000000000 --- a/libnm-core/nm-setting-ovs-external-ids.c +++ /dev/null @@ -1,551 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 - 2020 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ovs-external-ids.h" - -#include "nm-setting-private.h" -#include "nm-utils-private.h" -#include "nm-connection-private.h" - -#define MAX_NUM_KEYS 256 - -/*****************************************************************************/ - -/** - * SECTION:nm-setting-ovs-external-ids - * @short_description: External-IDs for OVS database - * - * The #NMSettingOvsExternalIDs object is a #NMSetting subclass that allow to - * configure external ids for OVS. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingOvsExternalIDs, PROP_DATA, ); - -typedef struct { - GHashTable * data; - const char **data_keys; -} NMSettingOvsExternalIDsPrivate; - -/** - * NMSettingOvsExternalIDs: - * - * OVS External IDs Settings - */ -struct _NMSettingOvsExternalIDs { - NMSetting parent; - NMSettingOvsExternalIDsPrivate _priv; -}; - -struct _NMSettingOvsExternalIDsClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingOvsExternalIDs, nm_setting_ovs_external_ids, NM_TYPE_SETTING) - -#define NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMSettingOvsExternalIDs, NM_IS_SETTING_OVS_EXTERNAL_IDS) - -/*****************************************************************************/ - -static gboolean -_exid_key_char_is_regular(char ch) -{ - /* allow words of printable characters, plus some - * special characters, for example to support base64 encoding. */ - return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') - || NM_IN_SET(ch, '-', '_', '+', '/', '=', '.'); -} - -/** - * nm_setting_ovs_external_ids_check_key: - * @key: (allow-none): the key to check - * @error: a #GError, %NULL to ignore. - * - * Checks whether @key is a valid key for OVS' external-ids. - * This means, the key cannot be %NULL, not too large and valid ASCII. - * Also, only digits and numbers are allowed with a few special - * characters. They key must also not start with "NM.". - * - * Since: 1.30 - * - * Returns: %TRUE if @key is a valid user data key. - */ -gboolean -nm_setting_ovs_external_ids_check_key(const char *key, GError **error) -{ - gsize len; - - g_return_val_if_fail(!error || !*error, FALSE); - - if (!key || !key[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing key")); - return FALSE; - } - len = strlen(key); - if (len > 255u) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key is too long")); - return FALSE; - } - if (!g_utf8_validate(key, len, NULL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key must be UTF8")); - return FALSE; - } - if (!NM_STRCHAR_ALL(key, ch, _exid_key_char_is_regular(ch))) { - /* Probably OVS is more forgiving about what makes a valid key for - * an external-id. However, we are strict (at least, for now). */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key contains invalid characters")); - return FALSE; - } - - if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX)) { - /* these keys are reserved. */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key cannot start with \"NM.\"")); - return FALSE; - } - - return TRUE; -} - -/** - * nm_setting_ovs_external_ids_check_val: - * @val: (allow-none): the value to check - * @error: a #GError, %NULL to ignore. - * - * Checks whether @val is a valid user data value. This means, - * value is not %NULL, not too large and valid UTF-8. - * - * Since: 1.30 - * - * Returns: %TRUE if @val is a valid user data value. - */ -gboolean -nm_setting_ovs_external_ids_check_val(const char *val, GError **error) -{ - gsize len; - - g_return_val_if_fail(!error || !*error, FALSE); - - if (!val) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value is missing")); - return FALSE; - } - - len = strlen(val); - if (len > (8u * 1024u)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value is too large")); - return FALSE; - } - - if (!g_utf8_validate(val, len, NULL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value is not valid UTF8")); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static GHashTable * -_create_data_hash(void) -{ - return g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); -} - -GHashTable * -_nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *self) -{ - return NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self)->data; -} - -/** - * nm_setting_ovs_external_ids_get_data_keys: - * @setting: the #NMSettingOvsExternalIDs - * @out_len: (out): the length of the returned array - * - * Returns: (array length=out_len) (transfer none): a - * %NULL-terminated array containing each key from the table. - **/ -const char *const * -nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting, guint *out_len) -{ - NMSettingOvsExternalIDs * self = setting; - NMSettingOvsExternalIDsPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self), NULL); - - priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); - - if (priv->data_keys) { - NM_SET_OUT(out_len, g_hash_table_size(priv->data)); - return priv->data_keys; - } - - priv->data_keys = nm_utils_strdict_get_keys(priv->data, TRUE, out_len); - - /* don't return %NULL, but hijack the @data_keys fields as a pseudo - * empty strv array. */ - return priv->data_keys ?: ((const char **) &priv->data_keys); -} - -/*****************************************************************************/ - -/** - * nm_setting_ovs_external_ids_get_data: - * @setting: the #NMSettingOvsExternalIDs instance - * @key: the external-id to lookup - * - * Since: 1.30 - * - * Returns: (transfer none): the value associated with @key or %NULL if no such - * value exists. - */ -const char * -nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *setting, const char *key) -{ - NMSettingOvsExternalIDs * self = setting; - NMSettingOvsExternalIDsPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self), NULL); - g_return_val_if_fail(key, NULL); - - priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); - - if (!priv->data) - return NULL; - - return g_hash_table_lookup(priv->data, key); -} - -/** - * nm_setting_ovs_external_ids_set_data: - * @setting: the #NMSettingOvsExternalIDs instance - * @key: the key to set - * @val: (allow-none): the value to set or %NULL to clear a key. - * - * Since: 1.30 - */ -void -nm_setting_ovs_external_ids_set_data(NMSettingOvsExternalIDs *setting, - const char * key, - const char * val) -{ - NMSettingOvsExternalIDs * self = setting; - NMSettingOvsExternalIDsPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self)); - - priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); - - if (!val) { - if (priv->data && g_hash_table_remove(priv->data, key)) - goto out_changed; - return; - } - - if (priv->data) { - const char *val2; - - if (g_hash_table_lookup_extended(priv->data, key, NULL, (gpointer *) &val2)) { - if (nm_streq(val, val2)) - return; - } - } else - priv->data = _create_data_hash(); - - g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); - -out_changed: - nm_clear_g_free(&priv->data_keys); - _notify(self, PROP_DATA); -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(setting); - NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); - - if (priv->data) { - gs_free_error GError *local = NULL; - GHashTableIter iter; - const char * key; - const char * val; - - g_hash_table_iter_init(&iter, priv->data); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - if (!nm_setting_ovs_external_ids_check_key(key, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid key \"%s\": %s"), - key, - local->message); - } else if (!nm_setting_ovs_external_ids_check_val(val, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid value for \"%s\": %s"), - key, - local->message); - } else - continue; - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, - NM_SETTING_OVS_EXTERNAL_IDS_DATA); - return FALSE; - } - } - - if (priv->data && g_hash_table_size(priv->data) > MAX_NUM_KEYS) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("maximum number of user data entries reached (%u instead of %u)"), - g_hash_table_size(priv->data), - (unsigned) MAX_NUM_KEYS); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, - NM_SETTING_OVS_EXTERNAL_IDS_DATA); - return FALSE; - } - - if (connection) { - NMSettingConnection *s_con; - const char * type; - const char * slave_type; - - type = nm_connection_get_connection_type(connection); - if (!type) { - NMSetting *s_base; - - s_base = _nm_connection_find_base_type_setting(connection); - if (s_base) - type = nm_setting_get_name(s_base); - } - if (NM_IN_STRSET(type, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME)) - goto connection_type_is_good; - - if ((s_con = nm_connection_get_setting_connection(connection)) - && _nm_connection_detect_slave_type_full(s_con, - connection, - &slave_type, - NULL, - NULL, - NULL, - NULL) - && nm_streq0(slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) - goto connection_type_is_good; - - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("OVS external IDs can only be added to a profile of type OVS " - "bridge/port/interface or to OVS system interface")); - return FALSE; - } -connection_type_is_good: - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingOvsExternalIDsPrivate *priv; - NMSettingOvsExternalIDsPrivate *pri2; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) - return NM_TERNARY_DEFAULT; - - if (!set_b) - return TRUE; - - priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(NM_SETTING_OVS_EXTERNAL_IDS(set_a)); - pri2 = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(NM_SETTING_OVS_EXTERNAL_IDS(set_b)); - return nm_utils_hashtable_equal(priv->data, pri2->data, TRUE, g_str_equal); - } - - return NM_SETTING_CLASS(nm_setting_ovs_external_ids_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object); - NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); - GHashTableIter iter; - GHashTable * data; - const char * key; - const char * val; - - switch (prop_id) { - case PROP_DATA: - data = _create_data_hash(); - if (priv->data) { - g_hash_table_iter_init(&iter, priv->data); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) - g_hash_table_insert(data, g_strdup(key), g_strdup(val)); - } - g_value_take_boxed(value, data); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object); - NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); - - switch (prop_id) { - case PROP_DATA: - { - gs_unref_hashtable GHashTable *old = NULL; - GHashTableIter iter; - GHashTable * data; - const char * key; - const char * val; - - nm_clear_g_free(&priv->data_keys); - - old = g_steal_pointer(&priv->data); - - data = g_value_get_boxed(value); - if (nm_g_hash_table_size(data) <= 0) - return; - - priv->data = _create_data_hash(); - g_hash_table_iter_init(&iter, data); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) - g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ovs_external_ids_init(NMSettingOvsExternalIDs *self) -{} - -/** - * nm_setting_ovs_external_ids_new: - * - * Creates a new #NMSettingOvsExternalIDs object with default values. - * - * Returns: (transfer full) (type NMSettingOvsExternalIDs): the new empty - * #NMSettingOvsExternalIDs object - * - * Since: 1.30 - */ -NMSetting * -nm_setting_ovs_external_ids_new(void) -{ - return g_object_new(NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object); - NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); - - g_free(priv->data_keys); - if (priv->data) - g_hash_table_unref(priv->data); - - G_OBJECT_CLASS(nm_setting_ovs_external_ids_parent_class)->finalize(object); -} - -static void -nm_setting_ovs_external_ids_class_init(NMSettingOvsExternalIDsClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - - /** - * NMSettingOvsExternalIDs:data: (type GHashTable(utf8,utf8)) - * - * A dictionary of key/value pairs with exernal-ids for OVS. - * - * Since: 1.30 - **/ - obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_OVS_EXTERNAL_IDS_DATA, - "", - "", - G_TYPE_HASH_TABLE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_DATA], - &nm_sett_info_propert_type_strdict); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-ovs-external-ids.h b/libnm-core/nm-setting-ovs-external-ids.h deleted file mode 100644 index 906db392f1..0000000000 --- a/libnm-core/nm-setting-ovs-external-ids.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 - 2020 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_OVS_EXTERNAL_IDS_H__ -#define __NM_SETTING_OVS_EXTERNAL_IDS_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_OVS_EXTERNAL_IDS (nm_setting_ovs_external_ids_get_type()) -#define NM_SETTING_OVS_EXTERNAL_IDS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NMSettingOvsExternalIDs)) -#define NM_SETTING_OVS_EXTERNAL_IDS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), \ - NM_TYPE_SETTING_OVS_EXTERNAL_IDS, \ - NMSettingOvsExternalIDsClass)) -#define NM_IS_SETTING_OVS_EXTERNAL_IDS(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_EXTERNAL_IDS)) -#define NM_IS_SETTING_OVS_EXTERNAL_IDS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_EXTERNAL_IDS)) -#define NM_SETTING_OVS_EXTERNAL_IDS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), \ - NM_TYPE_SETTING_OVS_EXTERNAL_IDS, \ - NMSettingOvsExternalIDsClass)) - -#define NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME "ovs-external-ids" - -#define NM_SETTING_OVS_EXTERNAL_IDS_DATA "data" - -typedef struct _NMSettingOvsExternalIDsClass NMSettingOvsExternalIDsClass; - -NM_AVAILABLE_IN_1_30 -GType nm_setting_ovs_external_ids_get_type(void); - -NM_AVAILABLE_IN_1_30 -NMSetting *nm_setting_ovs_external_ids_new(void); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_30 -const char *const *nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting, - guint * out_len); - -NM_AVAILABLE_IN_1_30 -const char *nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *setting, const char *key); - -NM_AVAILABLE_IN_1_30 -void nm_setting_ovs_external_ids_set_data(NMSettingOvsExternalIDs *setting, - const char * key, - const char * val); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_30 -gboolean nm_setting_ovs_external_ids_check_key(const char *key, GError **error); -NM_AVAILABLE_IN_1_30 -gboolean nm_setting_ovs_external_ids_check_val(const char *val, GError **error); - -G_END_DECLS - -#endif /* __NM_SETTING_OVS_EXTERNAL_IDS_H__ */ diff --git a/libnm-core/nm-setting-ovs-interface.c b/libnm-core/nm-setting-ovs-interface.c deleted file mode 100644 index 0c04a66cbb..0000000000 --- a/libnm-core/nm-setting-ovs-interface.c +++ /dev/null @@ -1,427 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ovs-interface.h" - -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-ovs-interface - * @short_description: Describes connection properties for Open vSwitch interfaces. - * - * The #NMSettingOvsInterface object is a #NMSetting subclass that describes properties - * necessary for Open vSwitch interfaces. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_TYPE, ); - -/** - * NMSettingOvsInterface: - * - * Open vSwitch Interface Settings - */ -struct _NMSettingOvsInterface { - NMSetting parent; - - char *type; -}; - -struct _NMSettingOvsInterfaceClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING) - -/*****************************************************************************/ - -/** - * nm_setting_ovs_interface_get_interface_type: - * @self: the #NMSettingOvsInterface - * - * Returns: the #NMSettingOvsInterface:type property of the setting - * - * Since: 1.10 - **/ -const char * -nm_setting_ovs_interface_get_interface_type(NMSettingOvsInterface *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_INTERFACE(self), NULL); - - return self->type; -} - -/*****************************************************************************/ - -int -_nm_setting_ovs_interface_verify_interface_type(NMSettingOvsInterface *self, - const char * type, - NMConnection * connection, - gboolean normalize, - gboolean * out_modified, - const char ** out_normalized_type, - GError ** error) -{ - const char *type_from_setting = NULL; - const char *type_setting = NULL; - const char *connection_type; - gboolean is_ovs_connection_type; - - if (normalize) { - g_return_val_if_fail(NM_IS_SETTING_OVS_INTERFACE(self), FALSE); - g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); - nm_assert(self == nm_connection_get_setting_ovs_interface(connection)); - } else { - g_return_val_if_fail(!self || NM_IS_SETTING_OVS_INTERFACE(self), FALSE); - g_return_val_if_fail(!connection || NM_IS_CONNECTION(connection), FALSE); - } - - NM_SET_OUT(out_modified, FALSE); - NM_SET_OUT(out_normalized_type, NULL); - - if (type && !NM_IN_STRSET(type, "internal", "system", "patch", "dpdk")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid interface type"), - type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_TYPE); - return FALSE; - } - - if (!connection) { - NM_SET_OUT(out_normalized_type, type); - return TRUE; - } - - connection_type = nm_connection_get_connection_type(connection); - if (!connection_type) { - /* if we have an ovs-interface, then the connection type must be either - * "ovs-interface" (for non "system" type) or anything else (for "system" type). - * - * The connection type usually can be normalized based on the presence of a - * base setting. However, in this case, if the connection type is missing, - * that is too complicate to guess what the user wanted. - * - * Require the use to be explicit and fail. */ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting needs connection.type explicitly set"), - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_TYPE); - return FALSE; - } - - if (nm_streq(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) { - if (type && nm_streq(type, "system")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection of type '%s' cannot have ovs-interface.type \"system\""), - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_TYPE); - return FALSE; - } - is_ovs_connection_type = TRUE; - } else { - if (type && !nm_streq(type, "system")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection of type '%s' cannot have an ovs-interface.type \"%s\""), - connection_type, - type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_TYPE); - return FALSE; - } - is_ovs_connection_type = FALSE; - } - - if (nm_connection_get_setting_by_name(connection, NM_SETTING_OVS_PATCH_SETTING_NAME)) { - type_from_setting = "patch"; - type_setting = NM_SETTING_OVS_PATCH_SETTING_NAME; - } - - if (nm_connection_get_setting_by_name(connection, NM_SETTING_OVS_DPDK_SETTING_NAME)) { - if (type_from_setting) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection can not have both '%s' and '%s' settings at the same time"), - NM_SETTING_OVS_DPDK_SETTING_NAME, - type_setting); - return FALSE; - } - type_from_setting = "dpdk"; - type_setting = NM_SETTING_OVS_DPDK_SETTING_NAME; - } - - if (type_from_setting) { - if (!is_ovs_connection_type) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with '%s' setting must be of connection.type " - "\"ovs-interface\" but is \"%s\""), - NM_SETTING_OVS_PATCH_SETTING_NAME, - connection_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_TYPE); - return FALSE; - } - - if (type) { - if (!nm_streq(type, type_from_setting)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with '%s' setting needs to be of '%s' interface type, " - "not '%s'"), - type_setting, - type_from_setting, - type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_TYPE); - return FALSE; - } - NM_SET_OUT(out_normalized_type, type); - return TRUE; - } - type = type_from_setting; - goto normalize; - } else { - if (nm_streq0(type, "patch")) { - g_set_error( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("A connection with ovs-interface.type '%s' setting a 'ovs-patch' setting"), - type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_TYPE); - return FALSE; - } - } - - if (type) { - NM_SET_OUT(out_normalized_type, type); - return TRUE; - } - - if (is_ovs_connection_type) - type = "internal"; - else - type = "system"; - - NM_SET_OUT(out_normalized_type, type); - -normalize: - if (!normalize) { - if (!self) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("Missing ovs interface setting")); - g_prefix_error(error, "%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME); - } else { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("Missing ovs interface type")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_TYPE); - } - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - if (!self) { - self = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); - nm_connection_add_setting(connection, NM_SETTING(self)); - } - g_object_set(self, NM_SETTING_OVS_INTERFACE_TYPE, type, NULL); - NM_SET_OUT(out_modified, TRUE); - - return TRUE; -} - -static int -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE(setting); - NMSettingConnection * s_con = NULL; - - if (connection) { - const char *slave_type; - - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("missing setting")); - g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); - return FALSE; - } - - if (!nm_setting_connection_get_master(s_con)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting must have a master."), - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_MASTER); - return FALSE; - } - - slave_type = nm_setting_connection_get_slave_type(s_con); - if (slave_type && !nm_streq(slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting must have the slave-type set to '%s'. " - "Instead it is '%s'"), - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME, - slave_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return FALSE; - } - } - - return _nm_setting_ovs_interface_verify_interface_type(self, - self->type, - connection, - FALSE, - NULL, - NULL, - error); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE(object); - - switch (prop_id) { - case PROP_TYPE: - g_value_set_string(value, self->type); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE(object); - - switch (prop_id) { - case PROP_TYPE: - g_free(self->type); - self->type = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ovs_interface_init(NMSettingOvsInterface *self) -{} - -/** - * nm_setting_ovs_interface_new: - * - * Creates a new #NMSettingOvsInterface object with default values. - * - * Returns: (transfer full): the new empty #NMSettingOvsInterface object - * - * Since: 1.10 - **/ -NMSetting * -nm_setting_ovs_interface_new(void) -{ - return g_object_new(NM_TYPE_SETTING_OVS_INTERFACE, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE(object); - - g_free(self->type); - - G_OBJECT_CLASS(nm_setting_ovs_interface_parent_class)->finalize(object); -} - -static void -nm_setting_ovs_interface_class_init(NMSettingOvsInterfaceClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingOvsInterface:type: - * - * The interface type. Either "internal", "system", "patch", "dpdk", or empty. - * - * Since: 1.10 - **/ - obj_properties[PROP_TYPE] = g_param_spec_string(NM_SETTING_OVS_INTERFACE_TYPE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_INTERFACE); -} diff --git a/libnm-core/nm-setting-ovs-interface.h b/libnm-core/nm-setting-ovs-interface.h deleted file mode 100644 index 47ad5817cd..0000000000 --- a/libnm-core/nm-setting-ovs-interface.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_OVS_INTERFACE_H__ -#define __NM_SETTING_OVS_INTERFACE_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_get_type()) -#define NM_SETTING_OVS_INTERFACE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_INTERFACE, NMSettingOvsInterface)) -#define NM_SETTING_OVS_INTERFACE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), \ - NM_TYPE_SETTING_OVS_INTERFACECONFIG, \ - NMSettingOvsInterfaceClass)) -#define NM_IS_SETTING_OVS_INTERFACE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_INTERFACE)) -#define NM_IS_SETTING_OVS_INTERFACE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_INTERFACE)) -#define NM_SETTING_OVS_INTERFACE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_INTERFACE, NMSettingOvsInterfaceClass)) - -#define NM_SETTING_OVS_INTERFACE_SETTING_NAME "ovs-interface" - -#define NM_SETTING_OVS_INTERFACE_TYPE "type" - -typedef struct _NMSettingOvsInterfaceClass NMSettingOvsInterfaceClass; - -NM_AVAILABLE_IN_1_10 -GType nm_setting_ovs_interface_get_type(void); -NM_AVAILABLE_IN_1_10 -NMSetting *nm_setting_ovs_interface_new(void); - -NM_AVAILABLE_IN_1_10 -const char *nm_setting_ovs_interface_get_interface_type(NMSettingOvsInterface *self); - -G_END_DECLS - -#endif /* __NM_SETTING_OVS_INTERFACE_H__ */ diff --git a/libnm-core/nm-setting-ovs-patch.c b/libnm-core/nm-setting-ovs-patch.c deleted file mode 100644 index 18a62d2eb4..0000000000 --- a/libnm-core/nm-setting-ovs-patch.c +++ /dev/null @@ -1,188 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ovs-patch.h" - -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-ovs-patch - * @short_description: Describes connection properties for Open vSwitch patch interfaces. - * - * The #NMSettingOvsPatch object is a #NMSetting subclass that describes properties - * necessary for Open vSwitch interfaces of type "patch". - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PEER, ); - -/** - * NMSettingOvsPatch: - * - * OvsPatch Link Settings - */ -struct _NMSettingOvsPatch { - NMSetting parent; - - char *peer; -}; - -struct _NMSettingOvsPatchClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING) - -/*****************************************************************************/ - -/** - * nm_setting_ovs_patch_get_peer: - * @self: the #NMSettingOvsPatch - * - * Returns: the #NMSettingOvsPatch:peer property of the setting - * - * Since: 1.10 - **/ -const char * -nm_setting_ovs_patch_get_peer(NMSettingOvsPatch *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_PATCH(self), NULL); - - return self->peer; -} - -/*****************************************************************************/ - -static int -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH(setting); - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - if (!self->peer) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_PATCH_SETTING_NAME, - NM_SETTING_OVS_PATCH_PEER); - return FALSE; - } - - if (!nm_utils_ifname_valid(self->peer, NMU_IFACE_OVS, error)) { - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_PATCH_SETTING_NAME, - NM_SETTING_OVS_PATCH_PEER); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH(object); - - switch (prop_id) { - case PROP_PEER: - g_value_set_string(value, self->peer); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH(object); - - switch (prop_id) { - case PROP_PEER: - g_free(self->peer); - self->peer = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ovs_patch_init(NMSettingOvsPatch *self) -{} - -/** - * nm_setting_ovs_patch_new: - * - * Creates a new #NMSettingOvsPatch object with default values. - * - * Returns: (transfer full): the new empty #NMSettingOvsPatch object - * - * Since: 1.10 - **/ -NMSetting * -nm_setting_ovs_patch_new(void) -{ - return g_object_new(NM_TYPE_SETTING_OVS_PATCH, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH(object); - - g_free(self->peer); - - G_OBJECT_CLASS(nm_setting_ovs_patch_parent_class)->finalize(object); -} - -static void -nm_setting_ovs_patch_class_init(NMSettingOvsPatchClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingOvsPatch:peer: - * - * Specifies the name of the interface for the other side of the patch. - * The patch on the other side must also set this interface as peer. - * - * Since: 1.10 - **/ - obj_properties[PROP_PEER] = g_param_spec_string(NM_SETTING_OVS_PATCH_PEER, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_PATCH); -} diff --git a/libnm-core/nm-setting-ovs-patch.h b/libnm-core/nm-setting-ovs-patch.h deleted file mode 100644 index fd80d45a48..0000000000 --- a/libnm-core/nm-setting-ovs-patch.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_OVS_PATCH_H__ -#define __NM_SETTING_OVS_PATCH_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_OVS_PATCH (nm_setting_ovs_patch_get_type()) -#define NM_SETTING_OVS_PATCH(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_PATCH, NMSettingOvsPatch)) -#define NM_SETTING_OVS_PATCH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OVS_PATCHCONFIG, NMSettingOvsPatchClass)) -#define NM_IS_SETTING_OVS_PATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_PATCH)) -#define NM_IS_SETTING_OVS_PATCH_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_PATCH)) -#define NM_SETTING_OVS_PATCH_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_PATCH, NMSettingOvsPatchClass)) - -#define NM_SETTING_OVS_PATCH_SETTING_NAME "ovs-patch" - -#define NM_SETTING_OVS_PATCH_PEER "peer" - -typedef struct _NMSettingOvsPatchClass NMSettingOvsPatchClass; - -NM_AVAILABLE_IN_1_10 -GType nm_setting_ovs_patch_get_type(void); -NM_AVAILABLE_IN_1_10 -NMSetting *nm_setting_ovs_patch_new(void); - -NM_AVAILABLE_IN_1_10 -const char *nm_setting_ovs_patch_get_peer(NMSettingOvsPatch *self); - -G_END_DECLS - -#endif /* __NM_SETTING_OVS_PATCH_H__ */ diff --git a/libnm-core/nm-setting-ovs-port.c b/libnm-core/nm-setting-ovs-port.c deleted file mode 100644 index 63da66fca1..0000000000 --- a/libnm-core/nm-setting-ovs-port.c +++ /dev/null @@ -1,467 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ovs-port.h" - -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-ovs-port - * @short_description: Describes connection properties for Open vSwitch ports. - * - * The #NMSettingOvsPort object is a #NMSetting subclass that describes properties - * necessary for Open vSwitch ports. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_VLAN_MODE, - PROP_TAG, - PROP_LACP, - PROP_BOND_MODE, - PROP_BOND_UPDELAY, - PROP_BOND_DOWNDELAY, ); - -/** - * NMSettingOvsPort: - * - * OvsPort Link Settings - */ -struct _NMSettingOvsPort { - NMSetting parent; - - char *vlan_mode; - char *lacp; - char *bond_mode; - guint tag; - guint bond_updelay; - guint bond_downdelay; -}; - -struct _NMSettingOvsPortClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING) - -/*****************************************************************************/ - -/** - * nm_setting_ovs_port_get_vlan_mode: - * @self: the #NMSettingOvsPort - * - * Returns: the #NMSettingOvsPort:vlan-mode property of the setting - * - * Since: 1.10 - **/ -const char * -nm_setting_ovs_port_get_vlan_mode(NMSettingOvsPort *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), NULL); - - return self->vlan_mode; -} - -/** - * nm_setting_ovs_port_get_tag: - * @self: the #NMSettingOvsPort - * - * Returns: the #NMSettingOvsPort:tag property of the setting - * - * Since: 1.10 - **/ -guint -nm_setting_ovs_port_get_tag(NMSettingOvsPort *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), 0); - - return self->tag; -} - -/** - * nm_setting_ovs_port_get_lacp: - * @self: the #NMSettingOvsPort - * - * Returns: the #NMSettingOvsPort:lacp property of the setting - * - * Since: 1.10 - **/ -const char * -nm_setting_ovs_port_get_lacp(NMSettingOvsPort *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), NULL); - - return self->lacp; -} - -/** - * nm_setting_ovs_port_get_bond_mode: - * @self: the #NMSettingOvsPort - * - * Returns: the #NMSettingOvsPort:bond-mode property of the setting - * - * Since: 1.10 - **/ -const char * -nm_setting_ovs_port_get_bond_mode(NMSettingOvsPort *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), NULL); - - return self->bond_mode; -} - -/** - * nm_setting_ovs_port_get_bond_updelay: - * @self: the #NMSettingOvsPort - * - * Returns: the #NMSettingOvsPort:bond-updelay property of the setting - * - * Since: 1.10 - **/ -guint -nm_setting_ovs_port_get_bond_updelay(NMSettingOvsPort *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), 0); - - return self->bond_updelay; -} - -/** - * nm_setting_ovs_port_get_bond_downdelay: - * @self: the #NMSettingOvsPort - * - * Returns: the #NMSettingOvsPort:bond-downdelay property of the setting - * - * Since: 1.10 - **/ -guint -nm_setting_ovs_port_get_bond_downdelay(NMSettingOvsPort *self) -{ - g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), 0); - - return self->bond_downdelay; -} - -/*****************************************************************************/ - -static int -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingOvsPort *self = NM_SETTING_OVS_PORT(setting); - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - if (connection) { - NMSettingConnection *s_con; - const char * slave_type; - - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("missing setting")); - g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); - return FALSE; - } - - if (!nm_setting_connection_get_master(s_con)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting must have a master."), - NM_SETTING_OVS_PORT_SETTING_NAME); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_MASTER); - return FALSE; - } - - slave_type = nm_setting_connection_get_slave_type(s_con); - if (slave_type && strcmp(slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting must have the slave-type set to '%s'. " - "Instead it is '%s'"), - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - slave_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return FALSE; - } - } - - if (!NM_IN_STRSET(self->vlan_mode, - "access", - "native-tagged", - "native-untagged", - "trunk", - NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not allowed in vlan_mode"), - self->vlan_mode); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_OVS_PORT_VLAN_MODE); - return FALSE; - } - - if (self->tag >= 4095) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the tag id must be in range 0-4094 but is %u"), - self->tag); - g_prefix_error(error, "%s.%s: ", NM_SETTING_OVS_PORT_SETTING_NAME, NM_SETTING_OVS_PORT_TAG); - return FALSE; - } - - if (!NM_IN_STRSET(self->lacp, "active", "off", "passive", NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not allowed in lacp"), - self->lacp); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_OVS_PORT_LACP); - return FALSE; - } - - if (!NM_IN_STRSET(self->bond_mode, "active-backup", "balance-slb", "balance-tcp", NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not allowed in bond_mode"), - self->bond_mode); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_OVS_PORT_BOND_MODE); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); - - switch (prop_id) { - case PROP_VLAN_MODE: - g_value_set_string(value, self->vlan_mode); - break; - case PROP_TAG: - g_value_set_uint(value, self->tag); - break; - case PROP_LACP: - g_value_set_string(value, self->lacp); - break; - case PROP_BOND_MODE: - g_value_set_string(value, self->bond_mode); - break; - case PROP_BOND_UPDELAY: - g_value_set_uint(value, self->bond_updelay); - break; - case PROP_BOND_DOWNDELAY: - g_value_set_uint(value, self->bond_downdelay); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); - - switch (prop_id) { - case PROP_VLAN_MODE: - g_free(self->vlan_mode); - self->vlan_mode = g_value_dup_string(value); - break; - case PROP_TAG: - self->tag = g_value_get_uint(value); - break; - case PROP_LACP: - g_free(self->lacp); - self->lacp = g_value_dup_string(value); - break; - case PROP_BOND_MODE: - g_free(self->bond_mode); - self->bond_mode = g_value_dup_string(value); - break; - case PROP_BOND_UPDELAY: - self->bond_updelay = g_value_get_uint(value); - break; - case PROP_BOND_DOWNDELAY: - self->bond_downdelay = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ovs_port_init(NMSettingOvsPort *self) -{} - -/** - * nm_setting_ovs_port_new: - * - * Creates a new #NMSettingOvsPort object with default values. - * - * Returns: (transfer full): the new empty #NMSettingOvsPort object - * - * Since: 1.10 - **/ -NMSetting * -nm_setting_ovs_port_new(void) -{ - return g_object_new(NM_TYPE_SETTING_OVS_PORT, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); - - g_free(self->vlan_mode); - g_free(self->lacp); - g_free(self->bond_mode); - - G_OBJECT_CLASS(nm_setting_ovs_port_parent_class)->finalize(object); -} - -static void -nm_setting_ovs_port_class_init(NMSettingOvsPortClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingOvsPort:vlan-mode: - * - * The VLAN mode. One of "access", "native-tagged", "native-untagged", - * "trunk" or unset. - * - * Since: 1.10 - **/ - obj_properties[PROP_VLAN_MODE] = g_param_spec_string( - NM_SETTING_OVS_PORT_VLAN_MODE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsPort:tag: - * - * The VLAN tag in the range 0-4095. - * - * Since: 1.10 - **/ - obj_properties[PROP_TAG] = - g_param_spec_uint(NM_SETTING_OVS_PORT_TAG, - "", - "", - 0, - 4095, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsPort:lacp: - * - * LACP mode. One of "active", "off", or "passive". - * - * Since: 1.10 - **/ - obj_properties[PROP_LACP] = g_param_spec_string(NM_SETTING_OVS_PORT_LACP, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsPort:bond-mode: - * - * Bonding mode. One of "active-backup", "balance-slb", or "balance-tcp". - * - * Since: 1.10 - **/ - obj_properties[PROP_BOND_MODE] = g_param_spec_string( - NM_SETTING_OVS_PORT_BOND_MODE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsPort:bond-updelay: - * - * The time port must be active before it starts forwarding traffic. - * - * Since: 1.10 - **/ - obj_properties[PROP_BOND_UPDELAY] = - g_param_spec_uint(NM_SETTING_OVS_PORT_BOND_UPDELAY, - "", - "", - 0, - G_MAXUINT, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingOvsPort:bond-downdelay: - * - * The time port must be inactive in order to be considered down. - * - * Since: 1.10 - **/ - obj_properties[PROP_BOND_DOWNDELAY] = - g_param_spec_uint(NM_SETTING_OVS_PORT_BOND_DOWNDELAY, - "", - "", - 0, - G_MAXUINT, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_PORT); -} diff --git a/libnm-core/nm-setting-ovs-port.h b/libnm-core/nm-setting-ovs-port.h deleted file mode 100644 index 06d3a2aa0f..0000000000 --- a/libnm-core/nm-setting-ovs-port.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_OVS_PORT_H__ -#define __NM_SETTING_OVS_PORT_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_OVS_PORT (nm_setting_ovs_port_get_type()) -#define NM_SETTING_OVS_PORT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_PORT, NMSettingOvsPort)) -#define NM_SETTING_OVS_PORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OVS_PORTCONFIG, NMSettingOvsPortClass)) -#define NM_IS_SETTING_OVS_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_PORT)) -#define NM_IS_SETTING_OVS_PORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_PORT)) -#define NM_SETTING_OVS_PORT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_PORT, NMSettingOvsPortClass)) - -#define NM_SETTING_OVS_PORT_SETTING_NAME "ovs-port" - -#define NM_SETTING_OVS_PORT_VLAN_MODE "vlan-mode" -#define NM_SETTING_OVS_PORT_TAG "tag" -#define NM_SETTING_OVS_PORT_LACP "lacp" -#define NM_SETTING_OVS_PORT_BOND_MODE "bond-mode" -#define NM_SETTING_OVS_PORT_BOND_UPDELAY "bond-updelay" -#define NM_SETTING_OVS_PORT_BOND_DOWNDELAY "bond-downdelay" - -typedef struct _NMSettingOvsPortClass NMSettingOvsPortClass; - -NM_AVAILABLE_IN_1_10 -GType nm_setting_ovs_port_get_type(void); -NM_AVAILABLE_IN_1_10 -NMSetting *nm_setting_ovs_port_new(void); - -NM_AVAILABLE_IN_1_10 -const char *nm_setting_ovs_port_get_vlan_mode(NMSettingOvsPort *self); -NM_AVAILABLE_IN_1_10 -guint nm_setting_ovs_port_get_tag(NMSettingOvsPort *self); -NM_AVAILABLE_IN_1_10 -const char *nm_setting_ovs_port_get_lacp(NMSettingOvsPort *self); -NM_AVAILABLE_IN_1_10 -const char *nm_setting_ovs_port_get_bond_mode(NMSettingOvsPort *self); -NM_AVAILABLE_IN_1_10 -guint nm_setting_ovs_port_get_bond_updelay(NMSettingOvsPort *self); -NM_AVAILABLE_IN_1_10 -guint nm_setting_ovs_port_get_bond_downdelay(NMSettingOvsPort *self); - -G_END_DECLS - -#endif /* __NM_SETTING_OVS_PORT_H__ */ diff --git a/libnm-core/nm-setting-ppp.c b/libnm-core/nm-setting-ppp.c deleted file mode 100644 index 36fe84c34b..0000000000 --- a/libnm-core/nm-setting-ppp.c +++ /dev/null @@ -1,778 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ppp.h" - -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-ppp - * @short_description: Describes connection properties for devices/networks - * that require PPP to deliver IP capability - * - * The #NMSettingPpp object is a #NMSetting subclass that describes properties - * necessary for connection to networks that require PPP transport, like PPPoE - * cable and DSL modems and some mobile broadband devices. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_NOAUTH, - PROP_REFUSE_EAP, - PROP_REFUSE_PAP, - PROP_REFUSE_CHAP, - PROP_REFUSE_MSCHAP, - PROP_REFUSE_MSCHAPV2, - PROP_NOBSDCOMP, - PROP_NODEFLATE, - PROP_NO_VJ_COMP, - PROP_REQUIRE_MPPE, - PROP_REQUIRE_MPPE_128, - PROP_MPPE_STATEFUL, - PROP_CRTSCTS, - PROP_BAUD, - PROP_MRU, - PROP_MTU, - PROP_LCP_ECHO_FAILURE, - PROP_LCP_ECHO_INTERVAL, ); - -typedef struct { - guint32 baud; - guint32 mru; - guint32 mtu; - guint32 lcp_echo_failure; - guint32 lcp_echo_interval; - bool noauth : 1; - bool refuse_eap : 1; - bool refuse_pap : 1; - bool refuse_chap : 1; - bool refuse_mschap : 1; - bool refuse_mschapv2 : 1; - bool nobsdcomp : 1; - bool nodeflate : 1; - bool no_vj_comp : 1; - bool require_mppe : 1; - bool require_mppe_128 : 1; - bool mppe_stateful : 1; - bool crtscts : 1; -} NMSettingPppPrivate; - -G_DEFINE_TYPE(NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING) - -#define NM_SETTING_PPP_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_PPP, NMSettingPppPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_ppp_get_noauth: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:noauth property of the setting - **/ -gboolean -nm_setting_ppp_get_noauth(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->noauth; -} - -/** - * nm_setting_ppp_get_refuse_eap: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:refuse-eap property of the setting - **/ -gboolean -nm_setting_ppp_get_refuse_eap(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_eap; -} - -/** - * nm_setting_ppp_get_refuse_pap: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:refuse-pap property of the setting - **/ -gboolean -nm_setting_ppp_get_refuse_pap(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_pap; -} - -/** - * nm_setting_ppp_get_refuse_chap: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:refuse-chap property of the setting - **/ -gboolean -nm_setting_ppp_get_refuse_chap(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_chap; -} - -/** - * nm_setting_ppp_get_refuse_mschap: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:refuse-mschap property of the setting - **/ -gboolean -nm_setting_ppp_get_refuse_mschap(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_mschap; -} - -/** - * nm_setting_ppp_get_refuse_mschapv2: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:refuse-mschapv2 property of the setting - **/ -gboolean -nm_setting_ppp_get_refuse_mschapv2(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_mschapv2; -} - -/** - * nm_setting_ppp_get_nobsdcomp: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:nobsdcomp property of the setting - **/ -gboolean -nm_setting_ppp_get_nobsdcomp(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->nobsdcomp; -} - -/** - * nm_setting_ppp_get_nodeflate: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:nodeflate property of the setting - **/ -gboolean -nm_setting_ppp_get_nodeflate(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->nodeflate; -} - -/** - * nm_setting_ppp_get_no_vj_comp: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:no-vj-comp property of the setting - **/ -gboolean -nm_setting_ppp_get_no_vj_comp(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->no_vj_comp; -} - -/** - * nm_setting_ppp_get_require_mppe: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:require-mppe property of the setting - **/ -gboolean -nm_setting_ppp_get_require_mppe(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->require_mppe; -} - -/** - * nm_setting_ppp_get_require_mppe_128: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:require-mppe-128 property of the setting - **/ -gboolean -nm_setting_ppp_get_require_mppe_128(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->require_mppe_128; -} - -/** - * nm_setting_ppp_get_mppe_stateful: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:mppe-stateful property of the setting - **/ -gboolean -nm_setting_ppp_get_mppe_stateful(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->mppe_stateful; -} - -/** - * nm_setting_ppp_get_crtscts: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:crtscts property of the setting - **/ -gboolean -nm_setting_ppp_get_crtscts(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->crtscts; -} - -/** - * nm_setting_ppp_get_baud: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:baud property of the setting - **/ -guint32 -nm_setting_ppp_get_baud(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->baud; -} - -/** - * nm_setting_ppp_get_mru: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:mru property of the setting - **/ -guint32 -nm_setting_ppp_get_mru(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->mru; -} - -/** - * nm_setting_ppp_get_mtu: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:mtu property of the setting - **/ -guint32 -nm_setting_ppp_get_mtu(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->mtu; -} - -/** - * nm_setting_ppp_get_lcp_echo_failure: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:lcp-echo-failure property of the setting - **/ -guint32 -nm_setting_ppp_get_lcp_echo_failure(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->lcp_echo_failure; -} - -/** - * nm_setting_ppp_get_lcp_echo_interval: - * @setting: the #NMSettingPpp - * - * Returns: the #NMSettingPpp:lcp-echo-interval property of the setting - **/ -guint32 -nm_setting_ppp_get_lcp_echo_interval(NMSettingPpp *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); - - return NM_SETTING_PPP_GET_PRIVATE(setting)->lcp_echo_interval; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE(setting); - - /* FIXME: Do we even want this or can we just let pppd evaluate the options? */ - if (priv->mru > 0) { - if (priv->mru < 128 || priv->mru > 16384) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%d' is out of valid range <128-16384>"), - priv->mru); - g_prefix_error(error, "%s.%s: ", NM_SETTING_PPP_SETTING_NAME, NM_SETTING_PPP_MRU); - return FALSE; - } - } - - if (priv->lcp_echo_failure > 0) { - /* lcp_echo_interval must also be non-zero */ - if (priv->lcp_echo_interval == 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("setting this property requires non-zero '%s' property"), - NM_SETTING_PPP_LCP_ECHO_INTERVAL); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_PPP_SETTING_NAME, - NM_SETTING_PPP_LCP_ECHO_FAILURE); - return FALSE; - } - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingPpp *setting = NM_SETTING_PPP(object); - - switch (prop_id) { - case PROP_NOAUTH: - g_value_set_boolean(value, nm_setting_ppp_get_noauth(setting)); - break; - case PROP_REFUSE_EAP: - g_value_set_boolean(value, nm_setting_ppp_get_refuse_eap(setting)); - break; - case PROP_REFUSE_PAP: - g_value_set_boolean(value, nm_setting_ppp_get_refuse_pap(setting)); - break; - case PROP_REFUSE_CHAP: - g_value_set_boolean(value, nm_setting_ppp_get_refuse_chap(setting)); - break; - case PROP_REFUSE_MSCHAP: - g_value_set_boolean(value, nm_setting_ppp_get_refuse_mschap(setting)); - break; - case PROP_REFUSE_MSCHAPV2: - g_value_set_boolean(value, nm_setting_ppp_get_refuse_mschapv2(setting)); - break; - case PROP_NOBSDCOMP: - g_value_set_boolean(value, nm_setting_ppp_get_nobsdcomp(setting)); - break; - case PROP_NODEFLATE: - g_value_set_boolean(value, nm_setting_ppp_get_nodeflate(setting)); - break; - case PROP_NO_VJ_COMP: - g_value_set_boolean(value, nm_setting_ppp_get_no_vj_comp(setting)); - break; - case PROP_REQUIRE_MPPE: - g_value_set_boolean(value, nm_setting_ppp_get_require_mppe(setting)); - break; - case PROP_REQUIRE_MPPE_128: - g_value_set_boolean(value, nm_setting_ppp_get_require_mppe_128(setting)); - break; - case PROP_MPPE_STATEFUL: - g_value_set_boolean(value, nm_setting_ppp_get_mppe_stateful(setting)); - break; - case PROP_CRTSCTS: - g_value_set_boolean(value, nm_setting_ppp_get_crtscts(setting)); - break; - case PROP_BAUD: - g_value_set_uint(value, nm_setting_ppp_get_baud(setting)); - break; - case PROP_MRU: - g_value_set_uint(value, nm_setting_ppp_get_mru(setting)); - break; - case PROP_MTU: - g_value_set_uint(value, nm_setting_ppp_get_mtu(setting)); - break; - case PROP_LCP_ECHO_FAILURE: - g_value_set_uint(value, nm_setting_ppp_get_lcp_echo_failure(setting)); - break; - case PROP_LCP_ECHO_INTERVAL: - g_value_set_uint(value, nm_setting_ppp_get_lcp_echo_interval(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_NOAUTH: - priv->noauth = g_value_get_boolean(value); - break; - case PROP_REFUSE_EAP: - priv->refuse_eap = g_value_get_boolean(value); - break; - case PROP_REFUSE_PAP: - priv->refuse_pap = g_value_get_boolean(value); - break; - case PROP_REFUSE_CHAP: - priv->refuse_chap = g_value_get_boolean(value); - break; - case PROP_REFUSE_MSCHAP: - priv->refuse_mschap = g_value_get_boolean(value); - break; - case PROP_REFUSE_MSCHAPV2: - priv->refuse_mschapv2 = g_value_get_boolean(value); - break; - case PROP_NOBSDCOMP: - priv->nobsdcomp = g_value_get_boolean(value); - break; - case PROP_NODEFLATE: - priv->nodeflate = g_value_get_boolean(value); - break; - case PROP_NO_VJ_COMP: - priv->no_vj_comp = g_value_get_boolean(value); - break; - case PROP_REQUIRE_MPPE: - priv->require_mppe = g_value_get_boolean(value); - break; - case PROP_REQUIRE_MPPE_128: - priv->require_mppe_128 = g_value_get_boolean(value); - break; - case PROP_MPPE_STATEFUL: - priv->mppe_stateful = g_value_get_boolean(value); - break; - case PROP_CRTSCTS: - priv->crtscts = g_value_get_boolean(value); - break; - case PROP_BAUD: - priv->baud = g_value_get_uint(value); - break; - case PROP_MRU: - priv->mru = g_value_get_uint(value); - break; - case PROP_MTU: - priv->mtu = g_value_get_uint(value); - break; - case PROP_LCP_ECHO_FAILURE: - priv->lcp_echo_failure = g_value_get_uint(value); - break; - case PROP_LCP_ECHO_INTERVAL: - priv->lcp_echo_interval = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ppp_init(NMSettingPpp *self) -{ - NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE(self); - - priv->noauth = TRUE; -} - -/** - * nm_setting_ppp_new: - * - * Creates a new #NMSettingPpp object with default values. - * - * Returns: (transfer full): the new empty #NMSettingPpp object - **/ -NMSetting * -nm_setting_ppp_new(void) -{ - return g_object_new(NM_TYPE_SETTING_PPP, NULL); -} - -static void -nm_setting_ppp_class_init(NMSettingPppClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingPppPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - - setting_class->verify = verify; - - /** - * NMSettingPpp:noauth: - * - * If %TRUE, do not require the other side (usually the PPP server) to - * authenticate itself to the client. If %FALSE, require authentication - * from the remote side. In almost all cases, this should be %TRUE. - **/ - obj_properties[PROP_NOAUTH] = g_param_spec_boolean(NM_SETTING_PPP_NOAUTH, - "", - "", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:refuse-eap: - * - * If %TRUE, the EAP authentication method will not be used. - **/ - obj_properties[PROP_REFUSE_EAP] = - g_param_spec_boolean(NM_SETTING_PPP_REFUSE_EAP, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:refuse-pap: - * - * If %TRUE, the PAP authentication method will not be used. - **/ - obj_properties[PROP_REFUSE_PAP] = - g_param_spec_boolean(NM_SETTING_PPP_REFUSE_PAP, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:refuse-chap: - * - * If %TRUE, the CHAP authentication method will not be used. - **/ - obj_properties[PROP_REFUSE_CHAP] = - g_param_spec_boolean(NM_SETTING_PPP_REFUSE_CHAP, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:refuse-mschap: - * - * If %TRUE, the MSCHAP authentication method will not be used. - **/ - obj_properties[PROP_REFUSE_MSCHAP] = - g_param_spec_boolean(NM_SETTING_PPP_REFUSE_MSCHAP, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:refuse-mschapv2: - * - * If %TRUE, the MSCHAPv2 authentication method will not be used. - **/ - obj_properties[PROP_REFUSE_MSCHAPV2] = - g_param_spec_boolean(NM_SETTING_PPP_REFUSE_MSCHAPV2, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:nobsdcomp: - * - * If %TRUE, BSD compression will not be requested. - **/ - obj_properties[PROP_NOBSDCOMP] = g_param_spec_boolean( - NM_SETTING_PPP_NOBSDCOMP, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:nodeflate: - * - * If %TRUE, "deflate" compression will not be requested. - **/ - obj_properties[PROP_NODEFLATE] = g_param_spec_boolean( - NM_SETTING_PPP_NODEFLATE, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:no-vj-comp: - * - * If %TRUE, Van Jacobsen TCP header compression will not be requested. - **/ - obj_properties[PROP_NO_VJ_COMP] = g_param_spec_boolean( - NM_SETTING_PPP_NO_VJ_COMP, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:require-mppe: - * - * If %TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for - * the PPP session. If either 64-bit or 128-bit MPPE is not available the - * session will fail. Note that MPPE is not used on mobile broadband - * connections. - **/ - obj_properties[PROP_REQUIRE_MPPE] = - g_param_spec_boolean(NM_SETTING_PPP_REQUIRE_MPPE, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:require-mppe-128: - * - * If %TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be - * required for the PPP session, and the "require-mppe" property must also - * be set to %TRUE. If 128-bit MPPE is not available the session will fail. - **/ - obj_properties[PROP_REQUIRE_MPPE_128] = - g_param_spec_boolean(NM_SETTING_PPP_REQUIRE_MPPE_128, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:mppe-stateful: - * - * If %TRUE, stateful MPPE is used. See pppd documentation for more - * information on stateful MPPE. - **/ - obj_properties[PROP_MPPE_STATEFUL] = - g_param_spec_boolean(NM_SETTING_PPP_MPPE_STATEFUL, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:crtscts: - * - * If %TRUE, specify that pppd should set the serial port to use hardware - * flow control with RTS and CTS signals. This value should normally be set - * to %FALSE. - **/ - obj_properties[PROP_CRTSCTS] = g_param_spec_boolean(NM_SETTING_PPP_CRTSCTS, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:baud: - * - * If non-zero, instruct pppd to set the serial port to the specified - * baudrate. This value should normally be left as 0 to automatically - * choose the speed. - **/ - obj_properties[PROP_BAUD] = g_param_spec_uint(NM_SETTING_PPP_BAUD, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:mru: - * - * If non-zero, instruct pppd to request that the peer send packets no - * larger than the specified size. If non-zero, the MRU should be between - * 128 and 16384. - */ - obj_properties[PROP_MRU] = g_param_spec_uint(NM_SETTING_PPP_MRU, - "", - "", - 0, - 16384, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:mtu: - * - * If non-zero, instruct pppd to send packets no larger than the specified - * size. - **/ - obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_PPP_MTU, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:lcp-echo-failure: - * - * If non-zero, instruct pppd to presume the connection to the peer has - * failed if the specified number of LCP echo-requests go unanswered by the - * peer. The "lcp-echo-interval" property must also be set to a non-zero - * value if this property is used. - **/ - obj_properties[PROP_LCP_ECHO_FAILURE] = g_param_spec_uint( - NM_SETTING_PPP_LCP_ECHO_FAILURE, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPpp:lcp-echo-interval: - * - * If non-zero, instruct pppd to send an LCP echo-request frame to the peer - * every n seconds (where n is the specified value). Note that some PPP - * peers will respond to echo requests and some will not, and it is not - * possible to autodetect this. - **/ - obj_properties[PROP_LCP_ECHO_INTERVAL] = g_param_spec_uint( - NM_SETTING_PPP_LCP_ECHO_INTERVAL, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_PPP); -} diff --git a/libnm-core/nm-setting-ppp.h b/libnm-core/nm-setting-ppp.h deleted file mode 100644 index 91c5347f07..0000000000 --- a/libnm-core/nm-setting-ppp.h +++ /dev/null @@ -1,88 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2008 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_PPP_H__ -#define __NM_SETTING_PPP_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_PPP (nm_setting_ppp_get_type()) -#define NM_SETTING_PPP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_PPP, NMSettingPpp)) -#define NM_SETTING_PPP_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_PPP, NMSettingPppClass)) -#define NM_IS_SETTING_PPP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_PPP)) -#define NM_IS_SETTING_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_PPP)) -#define NM_SETTING_PPP_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_PPP, NMSettingPppClass)) - -#define NM_SETTING_PPP_SETTING_NAME "ppp" - -#define NM_SETTING_PPP_NOAUTH "noauth" -#define NM_SETTING_PPP_REFUSE_EAP "refuse-eap" -#define NM_SETTING_PPP_REFUSE_PAP "refuse-pap" -#define NM_SETTING_PPP_REFUSE_CHAP "refuse-chap" -#define NM_SETTING_PPP_REFUSE_MSCHAP "refuse-mschap" -#define NM_SETTING_PPP_REFUSE_MSCHAPV2 "refuse-mschapv2" -#define NM_SETTING_PPP_NOBSDCOMP "nobsdcomp" -#define NM_SETTING_PPP_NODEFLATE "nodeflate" -#define NM_SETTING_PPP_NO_VJ_COMP "no-vj-comp" -#define NM_SETTING_PPP_REQUIRE_MPPE "require-mppe" -#define NM_SETTING_PPP_REQUIRE_MPPE_128 "require-mppe-128" -#define NM_SETTING_PPP_MPPE_STATEFUL "mppe-stateful" -#define NM_SETTING_PPP_CRTSCTS "crtscts" -#define NM_SETTING_PPP_BAUD "baud" -#define NM_SETTING_PPP_MRU "mru" -#define NM_SETTING_PPP_MTU "mtu" -#define NM_SETTING_PPP_LCP_ECHO_FAILURE "lcp-echo-failure" -#define NM_SETTING_PPP_LCP_ECHO_INTERVAL "lcp-echo-interval" - -/** - * NMSettingPpp: - * - * Point-to-Point Protocol Settings - */ -struct _NMSettingPpp { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingPppClass; - -GType nm_setting_ppp_get_type(void); - -NMSetting *nm_setting_ppp_new(void); -gboolean nm_setting_ppp_get_noauth(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_refuse_eap(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_refuse_pap(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_refuse_chap(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_refuse_mschap(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_refuse_mschapv2(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_nobsdcomp(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_nodeflate(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_no_vj_comp(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_require_mppe(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_require_mppe_128(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_mppe_stateful(NMSettingPpp *setting); -gboolean nm_setting_ppp_get_crtscts(NMSettingPpp *setting); -guint32 nm_setting_ppp_get_baud(NMSettingPpp *setting); -guint32 nm_setting_ppp_get_mru(NMSettingPpp *setting); -guint32 nm_setting_ppp_get_mtu(NMSettingPpp *setting); -guint32 nm_setting_ppp_get_lcp_echo_failure(NMSettingPpp *setting); -guint32 nm_setting_ppp_get_lcp_echo_interval(NMSettingPpp *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_PPP_H__ */ diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c deleted file mode 100644 index ef1d9ba1a9..0000000000 --- a/libnm-core/nm-setting-pppoe.c +++ /dev/null @@ -1,358 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-pppoe.h" - -#include "nm-setting-ppp.h" -#include "nm-setting-private.h" -#include "nm-core-enum-types.h" - -/** - * SECTION:nm-setting-pppoe - * @short_description: Describes PPPoE connection properties - * - * The #NMSettingPppoe object is a #NMSetting subclass that describes - * properties necessary for connection to networks that require PPPoE connections - * to provide IP transport, for example cable or DSL modems. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, - PROP_SERVICE, - PROP_USERNAME, - PROP_PASSWORD, - PROP_PASSWORD_FLAGS, ); - -typedef struct { - char * parent; - char * service; - char * username; - char * password; - NMSettingSecretFlags password_flags; -} NMSettingPppoePrivate; - -G_DEFINE_TYPE(NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING) - -#define NM_SETTING_PPPOE_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_PPPOE, NMSettingPppoePrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_pppoe_get_parent: - * @setting: the #NMSettingPppoe - * - * Returns: the #NMSettingPppoe:parent property of the setting - * - * Since: 1.10 - **/ -const char * -nm_setting_pppoe_get_parent(NMSettingPppoe *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NULL); - - return NM_SETTING_PPPOE_GET_PRIVATE(setting)->parent; -} - -/** - * nm_setting_pppoe_get_service: - * @setting: the #NMSettingPppoe - * - * Returns: the #NMSettingPppoe:service property of the setting - **/ -const char * -nm_setting_pppoe_get_service(NMSettingPppoe *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NULL); - - return NM_SETTING_PPPOE_GET_PRIVATE(setting)->service; -} - -/** - * nm_setting_pppoe_get_username: - * @setting: the #NMSettingPppoe - * - * Returns: the #NMSettingPppoe:username property of the setting - **/ -const char * -nm_setting_pppoe_get_username(NMSettingPppoe *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NULL); - - return NM_SETTING_PPPOE_GET_PRIVATE(setting)->username; -} - -/** - * nm_setting_pppoe_get_password: - * @setting: the #NMSettingPppoe - * - * Returns: the #NMSettingPppoe:password property of the setting - **/ -const char * -nm_setting_pppoe_get_password(NMSettingPppoe *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NULL); - - return NM_SETTING_PPPOE_GET_PRIVATE(setting)->password; -} - -/** - * nm_setting_pppoe_get_password_flags: - * @setting: the #NMSettingPppoe - * - * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingPppoe:password - **/ -NMSettingSecretFlags -nm_setting_pppoe_get_password_flags(NMSettingPppoe *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_PPPOE_GET_PRIVATE(setting)->password_flags; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(setting); - gs_free_error GError *local_error = NULL; - - if (!priv->username) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_USERNAME); - return FALSE; - } else if (!strlen(priv->username)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_USERNAME); - return FALSE; - } - - if (priv->service && !strlen(priv->service)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_SERVICE); - return FALSE; - } - - if (priv->parent && !nm_utils_ifname_valid_kernel(priv->parent, &local_error)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - "'%s': %s", - priv->parent, - local_error->message); - g_prefix_error(error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_PARENT); - return FALSE; - } - - return TRUE; -} - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(setting); - GPtrArray * secrets = NULL; - - if (priv->password) - return NULL; - - if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { - secrets = g_ptr_array_sized_new(1); - g_ptr_array_add(secrets, NM_SETTING_PPPOE_PASSWORD); - } - - return secrets; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingPppoe *setting = NM_SETTING_PPPOE(object); - - switch (prop_id) { - case PROP_PARENT: - g_value_set_string(value, nm_setting_pppoe_get_parent(setting)); - break; - case PROP_SERVICE: - g_value_set_string(value, nm_setting_pppoe_get_service(setting)); - break; - case PROP_USERNAME: - g_value_set_string(value, nm_setting_pppoe_get_username(setting)); - break; - case PROP_PASSWORD: - g_value_set_string(value, nm_setting_pppoe_get_password(setting)); - break; - case PROP_PASSWORD_FLAGS: - g_value_set_flags(value, nm_setting_pppoe_get_password_flags(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_PARENT: - g_free(priv->parent); - priv->parent = g_value_dup_string(value); - break; - case PROP_SERVICE: - g_free(priv->service); - priv->service = g_value_dup_string(value); - break; - case PROP_USERNAME: - g_free(priv->username); - priv->username = g_value_dup_string(value); - break; - case PROP_PASSWORD: - g_free(priv->password); - priv->password = g_value_dup_string(value); - break; - case PROP_PASSWORD_FLAGS: - priv->password_flags = g_value_get_flags(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_pppoe_init(NMSettingPppoe *setting) -{} - -/** - * nm_setting_pppoe_new: - * - * Creates a new #NMSettingPppoe object with default values. - * - * Returns: (transfer full): the new empty #NMSettingPppoe object - **/ -NMSetting * -nm_setting_pppoe_new(void) -{ - return g_object_new(NM_TYPE_SETTING_PPPOE, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(object); - - g_free(priv->parent); - g_free(priv->username); - g_free(priv->password); - g_free(priv->service); - - G_OBJECT_CLASS(nm_setting_pppoe_parent_class)->finalize(object); -} - -static void -nm_setting_pppoe_class_init(NMSettingPppoeClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingPppoePrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->need_secrets = need_secrets; - - /** - * NMSettingPppoe:parent: - * - * If given, specifies the parent interface name on which this PPPoE - * connection should be created. If this property is not specified, - * the connection is activated on the interface specified in - * #NMSettingConnection:interface-name of #NMSettingConnection. - * - * Since: 1.10 - **/ - obj_properties[PROP_PARENT] = g_param_spec_string( - NM_SETTING_PPPOE_PARENT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPppoe:service: - * - * If specified, instruct PPPoE to only initiate sessions with access - * concentrators that provide the specified service. For most providers, - * this should be left blank. It is only required if there are multiple - * access concentrators or a specific service is known to be required. - **/ - obj_properties[PROP_SERVICE] = g_param_spec_string(NM_SETTING_PPPOE_SERVICE, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPppoe:username: - * - * Username used to authenticate with the PPPoE service. - **/ - obj_properties[PROP_USERNAME] = g_param_spec_string(NM_SETTING_PPPOE_USERNAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPppoe:password: - * - * Password used to authenticate with the PPPoE service. - **/ - obj_properties[PROP_PASSWORD] = - g_param_spec_string(NM_SETTING_PPPOE_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingPppoe:password-flags: - * - * Flags indicating how to handle the #NMSettingPppoe:password property. - **/ - obj_properties[PROP_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_PPPOE_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_PPPOE); -} diff --git a/libnm-core/nm-setting-pppoe.h b/libnm-core/nm-setting-pppoe.h deleted file mode 100644 index 0a30f5a189..0000000000 --- a/libnm-core/nm-setting-pppoe.h +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2011 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_PPPOE_H__ -#define __NM_SETTING_PPPOE_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_PPPOE (nm_setting_pppoe_get_type()) -#define NM_SETTING_PPPOE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_PPPOE, NMSettingPppoe)) -#define NM_SETTING_PPPOE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_PPPOE, NMSettingPppoeClass)) -#define NM_IS_SETTING_PPPOE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_PPPOE)) -#define NM_IS_SETTING_PPPOE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_PPPOE)) -#define NM_SETTING_PPPOE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_PPPOE, NMSettingPppoeClass)) - -#define NM_SETTING_PPPOE_SETTING_NAME "pppoe" - -#define NM_SETTING_PPPOE_PARENT "parent" -#define NM_SETTING_PPPOE_SERVICE "service" -#define NM_SETTING_PPPOE_USERNAME "username" -#define NM_SETTING_PPPOE_PASSWORD "password" -#define NM_SETTING_PPPOE_PASSWORD_FLAGS "password-flags" - -/** - * NMSettingPppoe: - * - * PPP-over-Ethernet Settings - */ -struct _NMSettingPppoe { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingPppoeClass; - -GType nm_setting_pppoe_get_type(void); - -NMSetting *nm_setting_pppoe_new(void); -NM_AVAILABLE_IN_1_10 -const char * nm_setting_pppoe_get_parent(NMSettingPppoe *setting); -const char * nm_setting_pppoe_get_service(NMSettingPppoe *setting); -const char * nm_setting_pppoe_get_username(NMSettingPppoe *setting); -const char * nm_setting_pppoe_get_password(NMSettingPppoe *setting); -NMSettingSecretFlags nm_setting_pppoe_get_password_flags(NMSettingPppoe *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_PPPOE_H__ */ diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h deleted file mode 100644 index 7edb5cb2ab..0000000000 --- a/libnm-core/nm-setting-private.h +++ /dev/null @@ -1,184 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_PRIVATE_H__ -#define __NM_SETTING_PRIVATE_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) - #error Cannot use this header. -#endif - -#include "nm-setting.h" -#include "nm-setting-bridge.h" -#include "nm-connection.h" -#include "nm-core-enum-types.h" - -#include "nm-core-internal.h" - -/*****************************************************************************/ - -NMSettingPriority _nm_setting_get_base_type_priority(NMSetting *setting); -int _nm_setting_compare_priority(gconstpointer a, gconstpointer b); - -/*****************************************************************************/ - -void _nm_setting_emit_property_changed(NMSetting *setting); - -typedef enum NMSettingUpdateSecretResult { - NM_SETTING_UPDATE_SECRET_ERROR = FALSE, - NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE, - NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED = 2, -} NMSettingUpdateSecretResult; - -NMSettingUpdateSecretResult - _nm_setting_update_secrets(NMSetting *setting, GVariant *secrets, GError **error); -gboolean _nm_setting_clear_secrets(NMSetting * setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data); - -/* The property of the #NMSetting should be considered during comparisons that - * use the %NM_SETTING_COMPARE_FLAG_INFERRABLE flag. Properties that don't have - * this flag, are ignored when doing an infrerrable comparison. This flag should - * be set on all properties that are read from the kernel or the system when a - * connection is generated. eg, IP addresses/routes can be read from the - * kernel, but the 'autoconnect' property cannot, so - * %NM_SETTING_IP4_CONFIG_ADDRESSES gets the INFERRABLE flag, but - * %NM_SETTING_CONNECTION_AUTOCONNECT would not. - * - * This flag should not be used with properties where the default cannot be - * read separately from the current value, like MTU or wired duplex mode. - */ -#define NM_SETTING_PARAM_INFERRABLE (1 << (4 + G_PARAM_USER_SHIFT)) - -/* This is a legacy property, which clients should not send to the daemon. */ -#define NM_SETTING_PARAM_LEGACY (1 << (5 + G_PARAM_USER_SHIFT)) - -/* When a connection is active and gets modified, usually the change - * to the settings-connection does not propagate automatically to the - * applied-connection of the device. For certain properties like the - * firewall zone and the metered property, this is different. - * - * Such fields can be ignored during nm_connection_compare() with the - * NMSettingCompareFlag NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY. - */ -#define NM_SETTING_PARAM_REAPPLY_IMMEDIATELY (1 << (6 + G_PARAM_USER_SHIFT)) - -/* property_to_dbus() should ignore the property flags, and instead always calls to_dbus_fcn() - */ -#define NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS (1 << (7 + G_PARAM_USER_SHIFT)) - -extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_interface_name; -extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_i; -extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_u; - -extern const NMSettInfoPropertType nm_sett_info_propert_type_plain_i; -extern const NMSettInfoPropertType nm_sett_info_propert_type_plain_u; - -NMSettingVerifyResult -_nm_setting_verify(NMSetting *setting, NMConnection *connection, GError **error); - -gboolean _nm_setting_verify_secret_string(const char *str, - const char *setting_name, - const char *property, - GError ** error); - -gboolean _nm_setting_aggregate(NMSetting *setting, NMConnectionAggregateType type, gpointer arg); - -gboolean _nm_setting_slave_type_is_valid(const char *slave_type, const char **out_port_type); - -GVariant *_nm_setting_to_dbus(NMSetting * setting, - NMConnection * connection, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options); - -NMSetting *_nm_setting_new_from_dbus(GType setting_type, - GVariant * setting_dict, - GVariant * connection_dict, - NMSettingParseFlags parse_flags, - GError ** error); - -gboolean _nm_setting_property_is_regular_secret(NMSetting *setting, const char *secret_name); -gboolean _nm_setting_property_is_regular_secret_flags(NMSetting * setting, - const char *secret_flags_name); - -/*****************************************************************************/ - -static inline GArray * -_nm_sett_info_property_override_create_array(void) -{ - return g_array_new(FALSE, FALSE, sizeof(NMSettInfoProperty)); -} - -GArray *_nm_sett_info_property_override_create_array_ip_config(void); - -void _nm_setting_class_commit_full(NMSettingClass * setting_class, - NMMetaSettingType meta_type, - const NMSettInfoSettDetail *detail, - GArray * properties_override); - -static inline void -_nm_setting_class_commit(NMSettingClass *setting_class, NMMetaSettingType meta_type) -{ - _nm_setting_class_commit_full(setting_class, meta_type, NULL, NULL); -} - -#define NM_SETT_INFO_SETT_GENDATA(...) \ - ({ \ - static const NMSettInfoSettGendata _g = {__VA_ARGS__}; \ - \ - &_g; \ - }) - -#define NM_SETT_INFO_SETT_DETAIL(...) (&((const NMSettInfoSettDetail){__VA_ARGS__})) - -#define NM_SETT_INFO_PROPERT_TYPE(...) \ - ({ \ - static const NMSettInfoPropertType _g = {__VA_ARGS__}; \ - \ - &_g; \ - }) - -#define NM_SETT_INFO_PROPERTY(...) (&((const NMSettInfoProperty){__VA_ARGS__})) - -gboolean _nm_properties_override_assert(const NMSettInfoProperty *prop_info); - -static inline void -_nm_properties_override(GArray *properties_override, const NMSettInfoProperty *prop_info) -{ - nm_assert(properties_override); - nm_assert(_nm_properties_override_assert(prop_info)); - g_array_append_vals(properties_override, prop_info, 1); -} - -#define _nm_properties_override_gobj(properties_override, p_param_spec, p_property_type) \ - _nm_properties_override( \ - (properties_override), \ - NM_SETT_INFO_PROPERTY(.param_spec = (p_param_spec), .property_type = (p_property_type), )) - -#define _nm_properties_override_dbus(properties_override, p_name, p_property_type) \ - _nm_properties_override( \ - (properties_override), \ - NM_SETT_INFO_PROPERTY(.name = ("" p_name ""), .property_type = (p_property_type), )) - -/*****************************************************************************/ - -gboolean _nm_setting_use_legacy_property(NMSetting * setting, - GVariant * connection_dict, - const char *legacy_property, - const char *new_property); - -GPtrArray *_nm_setting_need_secrets(NMSetting *setting); - -gboolean _nm_setting_should_compare_secret_property(NMSetting * setting, - NMSetting * other, - const char * secret_name, - NMSettingCompareFlags flags); - -NMBridgeVlan *_nm_bridge_vlan_dup(const NMBridgeVlan *vlan); -NMBridgeVlan *_nm_bridge_vlan_dup_and_seal(const NMBridgeVlan *vlan); - -/*****************************************************************************/ - -#endif /* NM_SETTING_PRIVATE_H */ diff --git a/libnm-core/nm-setting-proxy.c b/libnm-core/nm-setting-proxy.c deleted file mode 100644 index 10cebc7370..0000000000 --- a/libnm-core/nm-setting-proxy.c +++ /dev/null @@ -1,383 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2016 Atul Anand . - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-proxy.h" - -#include "nm-utils.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-proxy - * @short_description: Describes proxy URL, script and other related properties - * - * The #NMSettingProxy object is a #NMSetting subclass that describes properties - * related to Proxy settings like PAC URL, PAC script etc. - * - * NetworkManager support 2 values for the #NMSettingProxy:method property for - * proxy. If "auto" is specified then WPAD takes place and the appropriate details - * are pushed into PacRunner or user can override this URL with a new PAC URL or a - * PAC script. If "none" is selected then no proxy configuration is given to PacRunner - * to fulfill client queries. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_METHOD, PROP_BROWSER_ONLY, PROP_PAC_URL, PROP_PAC_SCRIPT, ); - -typedef struct { - char *pac_url; - char *pac_script; - int method; - bool browser_only : 1; -} NMSettingProxyPrivate; - -G_DEFINE_TYPE(NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING) - -#define NM_SETTING_PROXY_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_PROXY, NMSettingProxyPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_proxy_get_method: - * @setting: the #NMSettingProxy - * - * Returns the proxy configuration method. By default the value is %NM_SETTING_PROXY_METHOD_NONE. - * %NM_SETTING_PROXY_METHOD_NONE should be selected for a connection intended for direct network - * access. - * - * Returns: the proxy configuration method - * - * Since: 1.6 - **/ -NMSettingProxyMethod -nm_setting_proxy_get_method(NMSettingProxy *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PROXY(setting), NM_SETTING_PROXY_METHOD_NONE); - - return NM_SETTING_PROXY_GET_PRIVATE(setting)->method; -} - -/** - * nm_setting_proxy_get_browser_only: - * @setting: the #NMSettingProxy - * - * Returns: %TRUE if this proxy configuration is only for browser - * clients/schemes, %FALSE otherwise. - * - * Since: 1.6 - **/ -gboolean -nm_setting_proxy_get_browser_only(NMSettingProxy *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PROXY(setting), FALSE); - - return NM_SETTING_PROXY_GET_PRIVATE(setting)->browser_only; -} - -/** - * nm_setting_proxy_get_pac_url: - * @setting: the #NMSettingProxy - * - * Returns: the PAC URL for obtaining PAC file - * - * Since: 1.6 - **/ -const char * -nm_setting_proxy_get_pac_url(NMSettingProxy *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PROXY(setting), NULL); - - return NM_SETTING_PROXY_GET_PRIVATE(setting)->pac_url; -} - -/** - * nm_setting_proxy_get_pac_script: - * @setting: the #NMSettingProxy - * - * Returns: the PAC script - * - * Since: 1.6 - **/ -const char * -nm_setting_proxy_get_pac_script(NMSettingProxy *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_PROXY(setting), NULL); - - return NM_SETTING_PROXY_GET_PRIVATE(setting)->pac_script; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE(setting); - - if (!NM_IN_SET(priv->method, NM_SETTING_PROXY_METHOD_NONE, NM_SETTING_PROXY_METHOD_AUTO)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid proxy method")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_PAC_URL); - return FALSE; - } - - if (priv->method != NM_SETTING_PROXY_METHOD_AUTO) { - if (priv->pac_url) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("this property is not allowed for method none")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_PROXY_PAC_URL); - return FALSE; - } - - if (priv->pac_script) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("this property is not allowed for method none")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_PROXY_PAC_SCRIPT); - return FALSE; - } - } - - if (priv->pac_script) { - if (strlen(priv->pac_script) > 1 * 1024 * 1024) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the script is too large")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_PROXY_PAC_SCRIPT); - return FALSE; - } - if (!g_utf8_validate(priv->pac_script, -1, NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the script is not valid utf8")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_PROXY_PAC_SCRIPT); - return FALSE; - } - if (!strstr(priv->pac_script, "FindProxyForURL")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the script lacks FindProxyForURL function")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_PROXY_PAC_SCRIPT); - return FALSE; - } - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingProxy *setting = NM_SETTING_PROXY(object); - - switch (prop_id) { - case PROP_METHOD: - g_value_set_int(value, nm_setting_proxy_get_method(setting)); - break; - case PROP_BROWSER_ONLY: - g_value_set_boolean(value, nm_setting_proxy_get_browser_only(setting)); - break; - case PROP_PAC_URL: - g_value_set_string(value, nm_setting_proxy_get_pac_url(setting)); - break; - case PROP_PAC_SCRIPT: - g_value_set_string(value, nm_setting_proxy_get_pac_script(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_METHOD: - priv->method = g_value_get_int(value); - break; - case PROP_BROWSER_ONLY: - priv->browser_only = g_value_get_boolean(value); - break; - case PROP_PAC_URL: - g_free(priv->pac_url); - priv->pac_url = g_value_dup_string(value); - break; - case PROP_PAC_SCRIPT: - g_free(priv->pac_script); - priv->pac_script = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_proxy_init(NMSettingProxy *self) -{ - nm_assert(NM_SETTING_PROXY_GET_PRIVATE(self)->method == NM_SETTING_PROXY_METHOD_NONE); -} - -/** - * nm_setting_proxy_new: - * - * Creates a new #NMSettingProxy object. - * - * Returns: the new empty #NMSettingProxy object - * - * Since: 1.6 - **/ -NMSetting * -nm_setting_proxy_new(void) -{ - return g_object_new(NM_TYPE_SETTING_PROXY, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingProxy * self = NM_SETTING_PROXY(object); - NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE(self); - - g_free(priv->pac_url); - g_free(priv->pac_script); - - G_OBJECT_CLASS(nm_setting_proxy_parent_class)->finalize(object); -} - -static void -nm_setting_proxy_class_init(NMSettingProxyClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingProxyPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingProxy:method: - * - * Method for proxy configuration, Default is %NM_SETTING_PROXY_METHOD_NONE - * - * Since: 1.6 - **/ - /* ---ifcfg-rh--- - * property: method - * variable: PROXY_METHOD(+) - * default: none - * description: Method for proxy configuration. For "auto", WPAD is used for - * proxy configuration, or set the PAC file via PAC_URL or PAC_SCRIPT. - * values: none, auto - * ---end--- - */ - obj_properties[PROP_METHOD] = g_param_spec_int(NM_SETTING_PROXY_METHOD, - "", - "", - G_MININT32, - G_MAXINT32, - NM_SETTING_PROXY_METHOD_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingProxy:browser-only: - * - * Whether the proxy configuration is for browser only. - * - * Since: 1.6 - **/ - /* ---ifcfg-rh--- - * property: browser-only - * variable: BROWSER_ONLY(+) - * default: no - * description: Whether the proxy configuration is for browser only. - * ---end--- - */ - obj_properties[PROP_BROWSER_ONLY] = - g_param_spec_boolean(NM_SETTING_PROXY_BROWSER_ONLY, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingProxy:pac-url: - * - * PAC URL for obtaining PAC file. - * - * Since: 1.6 - **/ - /* ---ifcfg-rh--- - * property: pac-url - * variable: PAC_URL(+) - * description: URL for PAC file. - * example: PAC_URL=http://wpad.mycompany.com/wpad.dat - * ---end--- - */ - obj_properties[PROP_PAC_URL] = g_param_spec_string(NM_SETTING_PROXY_PAC_URL, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingProxy:pac-script: - * - * PAC script for the connection. - * - * Since: 1.6 - **/ - /* ---ifcfg-rh--- - * property: pac-script - * variable: PAC_SCRIPT(+) - * description: Path of the PAC script. - * example: PAC_SCRIPT=/home/joe/proxy.pac - * ---end--- - */ - obj_properties[PROP_PAC_SCRIPT] = - g_param_spec_string(NM_SETTING_PROXY_PAC_SCRIPT, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_PROXY); -} diff --git a/libnm-core/nm-setting-proxy.h b/libnm-core/nm-setting-proxy.h deleted file mode 100644 index 70227df169..0000000000 --- a/libnm-core/nm-setting-proxy.h +++ /dev/null @@ -1,80 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2016 Atul Anand . - */ - -#ifndef __NM_SETTING_PROXY_H__ -#define __NM_SETTING_PROXY_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -/** - * NMSettingProxyMethod: - * @NM_SETTING_PROXY_METHOD_NONE: No Proxy for the Connection - * @NM_SETTING_PROXY_METHOD_AUTO: DHCP obtained Proxy/ Manual override - * - * The Proxy method. - * - * Since: 1.6 - */ -typedef enum { - NM_SETTING_PROXY_METHOD_NONE = 0, - NM_SETTING_PROXY_METHOD_AUTO = 1, -} NMSettingProxyMethod; - -#define NM_TYPE_SETTING_PROXY (nm_setting_proxy_get_type()) -#define NM_SETTING_PROXY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_PROXY, NMSettingProxy)) -#define NM_SETTING_PROXY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_PROXY, NMSettingProxyClass)) -#define NM_IS_SETTING_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_PROXY)) -#define NM_IS_SETTING_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_PROXY)) -#define NM_SETTING_PROXY_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_PROXY, NMSettingProxyClass)) - -#define NM_SETTING_PROXY_SETTING_NAME "proxy" - -#define NM_SETTING_PROXY_METHOD "method" -#define NM_SETTING_PROXY_BROWSER_ONLY "browser-only" -#define NM_SETTING_PROXY_PAC_URL "pac-url" -#define NM_SETTING_PROXY_PAC_SCRIPT "pac-script" - -/** - * NMSettingProxy: - * - * WWW Proxy Settings - */ -struct _NMSettingProxy { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - gpointer padding[4]; -} NMSettingProxyClass; - -NM_AVAILABLE_IN_1_6 -GType nm_setting_proxy_get_type(void); - -NM_AVAILABLE_IN_1_6 -NMSetting *nm_setting_proxy_new(void); - -NM_AVAILABLE_IN_1_6 -NMSettingProxyMethod nm_setting_proxy_get_method(NMSettingProxy *setting); -NM_AVAILABLE_IN_1_6 -gboolean nm_setting_proxy_get_browser_only(NMSettingProxy *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_proxy_get_pac_url(NMSettingProxy *setting); -NM_AVAILABLE_IN_1_6 -const char *nm_setting_proxy_get_pac_script(NMSettingProxy *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_PROXY_H__ */ diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c deleted file mode 100644 index 1e5418a149..0000000000 --- a/libnm-core/nm-setting-serial.c +++ /dev/null @@ -1,336 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2018 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-serial.h" - -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-serial - * @short_description: Describes connection properties for devices that use - * serial communications - * - * The #NMSettingSerial object is a #NMSetting subclass that describes - * properties necessary for connections that may use serial communications, - * such as mobile broadband or analog telephone connections. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_BAUD, - PROP_BITS, - PROP_PARITY, - PROP_STOPBITS, - PROP_SEND_DELAY, ); - -typedef struct { - guint64 send_delay; - guint baud; - guint bits; - guint stopbits; - char parity; -} NMSettingSerialPrivate; - -G_DEFINE_TYPE(NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING) - -#define NM_SETTING_SERIAL_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_SERIAL, NMSettingSerialPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_serial_get_baud: - * @setting: the #NMSettingSerial - * - * Returns: the #NMSettingSerial:baud property of the setting - **/ -guint -nm_setting_serial_get_baud(NMSettingSerial *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); - - return NM_SETTING_SERIAL_GET_PRIVATE(setting)->baud; -} - -/** - * nm_setting_serial_get_bits: - * @setting: the #NMSettingSerial - * - * Returns: the #NMSettingSerial:bits property of the setting - **/ -guint -nm_setting_serial_get_bits(NMSettingSerial *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); - - return NM_SETTING_SERIAL_GET_PRIVATE(setting)->bits; -} - -/** - * nm_setting_serial_get_parity: - * @setting: the #NMSettingSerial - * - * Returns: the #NMSettingSerial:parity property of the setting - **/ -NMSettingSerialParity -nm_setting_serial_get_parity(NMSettingSerial *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); - - return NM_SETTING_SERIAL_GET_PRIVATE(setting)->parity; -} - -/** - * nm_setting_serial_get_stopbits: - * @setting: the #NMSettingSerial - * - * Returns: the #NMSettingSerial:stopbits property of the setting - **/ -guint -nm_setting_serial_get_stopbits(NMSettingSerial *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); - - return NM_SETTING_SERIAL_GET_PRIVATE(setting)->stopbits; -} - -/** - * nm_setting_serial_get_send_delay: - * @setting: the #NMSettingSerial - * - * Returns: the #NMSettingSerial:send-delay property of the setting - **/ -guint64 -nm_setting_serial_get_send_delay(NMSettingSerial *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); - - return NM_SETTING_SERIAL_GET_PRIVATE(setting)->send_delay; -} - -static GVariant * -parity_to_dbus(const GValue *from) -{ - switch (g_value_get_enum(from)) { - case NM_SETTING_SERIAL_PARITY_EVEN: - return g_variant_new_byte('E'); - case NM_SETTING_SERIAL_PARITY_ODD: - return g_variant_new_byte('o'); - case NM_SETTING_SERIAL_PARITY_NONE: - default: - return g_variant_new_byte('n'); - } -} - -static void -parity_from_dbus(GVariant *from, GValue *to) -{ - switch (g_variant_get_byte(from)) { - case 'E': - g_value_set_enum(to, NM_SETTING_SERIAL_PARITY_EVEN); - break; - case 'o': - g_value_set_enum(to, NM_SETTING_SERIAL_PARITY_ODD); - break; - case 'n': - default: - g_value_set_enum(to, NM_SETTING_SERIAL_PARITY_NONE); - break; - } -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingSerial *setting = NM_SETTING_SERIAL(object); - - switch (prop_id) { - case PROP_BAUD: - g_value_set_uint(value, nm_setting_serial_get_baud(setting)); - break; - case PROP_BITS: - g_value_set_uint(value, nm_setting_serial_get_bits(setting)); - break; - case PROP_PARITY: - g_value_set_enum(value, nm_setting_serial_get_parity(setting)); - break; - case PROP_STOPBITS: - g_value_set_uint(value, nm_setting_serial_get_stopbits(setting)); - break; - case PROP_SEND_DELAY: - g_value_set_uint64(value, nm_setting_serial_get_send_delay(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingSerialPrivate *priv = NM_SETTING_SERIAL_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_BAUD: - priv->baud = g_value_get_uint(value); - break; - case PROP_BITS: - priv->bits = g_value_get_uint(value); - break; - case PROP_PARITY: - priv->parity = g_value_get_enum(value); - break; - case PROP_STOPBITS: - priv->stopbits = g_value_get_uint(value); - break; - case PROP_SEND_DELAY: - priv->send_delay = g_value_get_uint64(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_serial_init(NMSettingSerial *self) -{ - NMSettingSerialPrivate *priv = NM_SETTING_SERIAL_GET_PRIVATE(self); - - nm_assert(priv->parity == NM_SETTING_SERIAL_PARITY_NONE); - priv->stopbits = 1; - priv->baud = 57600; - priv->bits = 8; -} - -/** - * nm_setting_serial_new: - * - * Creates a new #NMSettingSerial object with default values. - * - * Returns: (transfer full): the new empty #NMSettingSerial object - **/ -NMSetting * -nm_setting_serial_new(void) -{ - return g_object_new(NM_TYPE_SETTING_SERIAL, NULL); -} - -static void -nm_setting_serial_class_init(NMSettingSerialClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingSerialPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - - /** - * NMSettingSerial:baud: - * - * Speed to use for communication over the serial port. Note that this - * value usually has no effect for mobile broadband modems as they generally - * ignore speed settings and use the highest available speed. - **/ - obj_properties[PROP_BAUD] = g_param_spec_uint(NM_SETTING_SERIAL_BAUD, - "", - "", - 0, - G_MAXUINT, - 57600, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingSerial:bits: - * - * Byte-width of the serial communication. The 8 in "8n1" for example. - **/ - obj_properties[PROP_BITS] = g_param_spec_uint(NM_SETTING_SERIAL_BITS, - "", - "", - 5, - 8, - 8, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingSerial:parity: - * - * Parity setting of the serial port. - **/ - /* ---keyfile--- - * property: parity - * format: 'e', 'o', or 'n' - * description: The connection parity; even, odd, or none. Note that older - * versions of NetworkManager stored this as an integer: 69 ('E') for even, - * 111 ('o') for odd, or 110 ('n') for none. - * example: parity=n - * ---end--- - * ---dbus--- - * property: parity - * format: byte - * description: The connection parity: 69 (ASCII 'E') for even parity, - * 111 (ASCII 'o') for odd, 110 (ASCII 'n') for none. - * ---end--- - */ - obj_properties[PROP_PARITY] = g_param_spec_enum(NM_SETTING_SERIAL_PARITY, - "", - "", - NM_TYPE_SETTING_SERIAL_PARITY, - NM_SETTING_SERIAL_PARITY_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj( - properties_override, - obj_properties[PROP_PARITY], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BYTE, - .gprop_to_dbus_fcn = parity_to_dbus, - .gprop_from_dbus_fcn = parity_from_dbus, )); - - /** - * NMSettingSerial:stopbits: - * - * Number of stop bits for communication on the serial port. Either 1 or 2. - * The 1 in "8n1" for example. - **/ - obj_properties[PROP_STOPBITS] = g_param_spec_uint(NM_SETTING_SERIAL_STOPBITS, - "", - "", - 1, - 2, - 1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingSerial:send-delay: - * - * Time to delay between each byte sent to the modem, in microseconds. - **/ - obj_properties[PROP_SEND_DELAY] = - g_param_spec_uint64(NM_SETTING_SERIAL_SEND_DELAY, - "", - "", - 0, - G_MAXUINT64, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_SERIAL, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-serial.h b/libnm-core/nm-setting-serial.h deleted file mode 100644 index abd232e8f1..0000000000 --- a/libnm-core/nm-setting-serial.h +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2008 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_SERIAL_H__ -#define __NM_SETTING_SERIAL_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_SERIAL (nm_setting_serial_get_type()) -#define NM_SETTING_SERIAL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_SERIAL, NMSettingSerial)) -#define NM_SETTING_SERIAL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_SERIAL, NMSettingSerialClass)) -#define NM_IS_SETTING_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_SERIAL)) -#define NM_IS_SETTING_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_SERIAL)) -#define NM_SETTING_SERIAL_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_SERIAL, NMSettingSerialClass)) - -#define NM_SETTING_SERIAL_SETTING_NAME "serial" - -/** - * NMSettingSerialParity: - * @NM_SETTING_SERIAL_PARITY_NONE: No parity bits (default) - * @NM_SETTING_SERIAL_PARITY_EVEN: Even parity - * @NM_SETTING_SERIAL_PARITY_ODD: Odd parity - * - * The parity setting of a serial port. - */ -typedef enum { - NM_SETTING_SERIAL_PARITY_NONE = 0, - NM_SETTING_SERIAL_PARITY_EVEN, - NM_SETTING_SERIAL_PARITY_ODD -} NMSettingSerialParity; - -#define NM_SETTING_SERIAL_BAUD "baud" -#define NM_SETTING_SERIAL_BITS "bits" -#define NM_SETTING_SERIAL_PARITY "parity" -#define NM_SETTING_SERIAL_STOPBITS "stopbits" -#define NM_SETTING_SERIAL_SEND_DELAY "send-delay" - -/** - * NMSettingSerial: - * - * Serial Link Settings - */ -struct _NMSettingSerial { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingSerialClass; - -GType nm_setting_serial_get_type(void); - -NMSetting * nm_setting_serial_new(void); -guint nm_setting_serial_get_baud(NMSettingSerial *setting); -guint nm_setting_serial_get_bits(NMSettingSerial *setting); -NMSettingSerialParity nm_setting_serial_get_parity(NMSettingSerial *setting); -guint nm_setting_serial_get_stopbits(NMSettingSerial *setting); -guint64 nm_setting_serial_get_send_delay(NMSettingSerial *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_SERIAL_H__ */ diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c deleted file mode 100644 index 47625a4109..0000000000 --- a/libnm-core/nm-setting-sriov.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-sriov.h" - -#include "nm-setting-private.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-sriov - * @short_description: Describes SR-IOV connection properties - * @include: nm-setting-sriov.h - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingSriov, PROP_TOTAL_VFS, PROP_VFS, PROP_AUTOPROBE_DRIVERS, ); - -/** - * NMSettingSriov: - * - * SR-IOV settings - * - * Since: 1.14 - */ -struct _NMSettingSriov { - NMSetting parent; - GPtrArray *vfs; - guint total_vfs; - NMTernary autoprobe_drivers; -}; - -struct _NMSettingSriovClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingSriov, nm_setting_sriov, NM_TYPE_SETTING) - -/*****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMSriovVF, nm_sriov_vf, nm_sriov_vf_dup, nm_sriov_vf_unref) - -struct _NMSriovVF { - guint refcount; - guint index; - GHashTable *attributes; - GHashTable *vlans; - guint * vlan_ids; -}; - -typedef struct { - guint id; - guint qos; - NMSriovVFVlanProtocol protocol; -} VFVlan; - -static guint -_vf_vlan_hash(gconstpointer ptr) -{ - return nm_hash_val(1348254767u, *((guint *) ptr)); -} - -static gboolean -_vf_vlan_equal(gconstpointer a, gconstpointer b) -{ - return *((guint *) a) == *((guint *) b); -} - -static GHashTable * -_vf_vlan_create_hash(void) -{ - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(VFVlan, id) == 0); - return g_hash_table_new_full(_vf_vlan_hash, _vf_vlan_equal, NULL, nm_g_slice_free_fcn(VFVlan)); -} - -/** - * nm_sriov_vf_new: - * @index: the VF index - * - * Creates a new #NMSriovVF object. - * - * Returns: (transfer full): the new #NMSriovVF object. - * - * Since: 1.14 - **/ -NMSriovVF * -nm_sriov_vf_new(guint index) -{ - NMSriovVF *vf; - - vf = g_slice_new(NMSriovVF); - *vf = (NMSriovVF){ - .refcount = 1, - .index = index, - .attributes = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref), - }; - return vf; -} - -/** - * nm_sriov_vf_ref: - * @vf: the #NMSriovVF - * - * Increases the reference count of the object. - * - * Since: 1.14 - **/ -void -nm_sriov_vf_ref(NMSriovVF *vf) -{ - g_return_if_fail(vf); - g_return_if_fail(vf->refcount > 0); - - vf->refcount++; -} - -/** - * nm_sriov_vf_unref: - * @vf: the #NMSriovVF - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - * - * Since: 1.14 - **/ -void -nm_sriov_vf_unref(NMSriovVF *vf) -{ - g_return_if_fail(vf); - g_return_if_fail(vf->refcount > 0); - - vf->refcount--; - if (vf->refcount == 0) { - g_hash_table_unref(vf->attributes); - if (vf->vlans) - g_hash_table_unref(vf->vlans); - g_free(vf->vlan_ids); - nm_g_slice_free(vf); - } -} - -/** - * nm_sriov_vf_equal: - * @vf: the #NMSriovVF - * @other: the #NMSriovVF to compare @vf to. - * - * Determines if two #NMSriovVF objects have the same index, - * attributes and VLANs. - * - * Returns: %TRUE if the objects contain the same values, %FALSE - * if they do not. - * - * Since: 1.14 - **/ -gboolean -nm_sriov_vf_equal(const NMSriovVF *vf, const NMSriovVF *other) -{ - GHashTableIter iter; - const char * key; - GVariant * value, *value2; - VFVlan * vlan, *vlan2; - guint n_vlans; - - g_return_val_if_fail(vf, FALSE); - g_return_val_if_fail(vf->refcount > 0, FALSE); - g_return_val_if_fail(other, FALSE); - g_return_val_if_fail(other->refcount > 0, FALSE); - - if (vf == other) - return TRUE; - - if (vf->index != other->index) - return FALSE; - - if (g_hash_table_size(vf->attributes) != g_hash_table_size(other->attributes)) - return FALSE; - g_hash_table_iter_init(&iter, vf->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { - value2 = g_hash_table_lookup(other->attributes, key); - if (!value2) - return FALSE; - if (!g_variant_equal(value, value2)) - return FALSE; - } - - n_vlans = vf->vlans ? g_hash_table_size(vf->vlans) : 0u; - if (n_vlans != (other->vlans ? g_hash_table_size(other->vlans) : 0u)) - return FALSE; - if (n_vlans > 0) { - g_hash_table_iter_init(&iter, vf->vlans); - while (g_hash_table_iter_next(&iter, (gpointer *) &vlan, NULL)) { - vlan2 = g_hash_table_lookup(other->vlans, vlan); - if (!vlan2) - return FALSE; - if (vlan->qos != vlan2->qos || vlan->protocol != vlan2->protocol) - return FALSE; - } - } - - return TRUE; -} - -static void -vf_add_vlan(NMSriovVF *vf, guint vlan_id, guint qos, NMSriovVFVlanProtocol protocol) -{ - VFVlan *vlan; - - vlan = g_slice_new(VFVlan); - *vlan = (VFVlan){ - .id = vlan_id, - .qos = qos, - .protocol = protocol, - }; - - if (!vf->vlans) - vf->vlans = _vf_vlan_create_hash(); - - g_hash_table_add(vf->vlans, vlan); - nm_clear_g_free(&vf->vlan_ids); -} - -/** - * nm_sriov_vf_dup: - * @vf: the #NMSriovVF - * - * Creates a copy of @vf. - * - * Returns: (transfer full): a copy of @vf - * - * Since: 1.14 - **/ -NMSriovVF * -nm_sriov_vf_dup(const NMSriovVF *vf) -{ - NMSriovVF * copy; - GHashTableIter iter; - const char * name; - GVariant * variant; - VFVlan * vlan; - - g_return_val_if_fail(vf, NULL); - g_return_val_if_fail(vf->refcount > 0, NULL); - - copy = nm_sriov_vf_new(vf->index); - - g_hash_table_iter_init(&iter, vf->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) - nm_sriov_vf_set_attribute(copy, name, variant); - - if (vf->vlans) { - g_hash_table_iter_init(&iter, vf->vlans); - while (g_hash_table_iter_next(&iter, (gpointer *) &vlan, NULL)) - vf_add_vlan(copy, vlan->id, vlan->qos, vlan->protocol); - } - - return copy; -} - -/** - * nm_sriov_vf_get_index: - * @vf: the #NMSriovVF - * - * Gets the index property of this VF object. - * - * Returns: the VF index - * - * Since: 1.14 - **/ -guint -nm_sriov_vf_get_index(const NMSriovVF *vf) -{ - g_return_val_if_fail(vf, 0); - g_return_val_if_fail(vf->refcount > 0, 0); - - return vf->index; -} - -/** - * nm_sriov_vf_set_attribute: - * @vf: the #NMSriovVF - * @name: the name of a route attribute - * @value: (transfer none) (allow-none): the value - * - * Sets the named attribute on @vf to the given value. - * - * Since: 1.14 - **/ -void -nm_sriov_vf_set_attribute(NMSriovVF *vf, const char *name, GVariant *value) -{ - g_return_if_fail(vf); - g_return_if_fail(vf->refcount > 0); - g_return_if_fail(name && *name != '\0'); - g_return_if_fail(!nm_streq(name, "index")); - - if (value) { - g_hash_table_insert(vf->attributes, g_strdup(name), g_variant_ref_sink(value)); - } else - g_hash_table_remove(vf->attributes, name); -} - -/** - * nm_sriov_vf_get_attribute_names: - * @vf: the #NMSriovVF - * - * Gets an array of attribute names defined on @vf. - * - * Returns: (transfer container): a %NULL-terminated array of attribute names - * - * Since: 1.14 - **/ -const char ** -nm_sriov_vf_get_attribute_names(const NMSriovVF *vf) -{ - g_return_val_if_fail(vf, NULL); - g_return_val_if_fail(vf->refcount > 0, NULL); - - return nm_utils_strdict_get_keys(vf->attributes, TRUE, NULL); -} - -/** - * nm_sriov_vf_get_attribute: - * @vf: the #NMSriovVF - * @name: the name of a VF attribute - * - * Gets the value of the attribute with name @name on @vf - * - * Returns: (transfer none): the value of the attribute with name @name on - * @vf, or %NULL if @vf has no such attribute. - * - * Since: 1.14 - **/ -GVariant * -nm_sriov_vf_get_attribute(const NMSriovVF *vf, const char *name) -{ - g_return_val_if_fail(vf, NULL); - g_return_val_if_fail(vf->refcount > 0, NULL); - g_return_val_if_fail(name && *name != '\0', NULL); - - return g_hash_table_lookup(vf->attributes, name); -} - -const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MAC, - G_VARIANT_TYPE_STRING, - .str_type = 'm', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, ), - /* D-Bus only, synthetic attributes */ - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("vlans", G_VARIANT_TYPE_STRING, .str_type = 'd', ), - NULL, -}; - -/** - * nm_sriov_vf_attribute_validate: - * @name: the attribute name - * @value: the attribute value - * @known: (out): on return, whether the attribute name is a known one - * @error: (allow-none): return location for a #GError, or %NULL - * - * Validates a VF attribute, i.e. checks that the attribute is a known one, - * the value is of the correct type and well-formed. - * - * Returns: %TRUE if the attribute is valid, %FALSE otherwise - * - * Since: 1.14 - */ -gboolean -nm_sriov_vf_attribute_validate(const char *name, GVariant *value, gboolean *known, GError **error) -{ - const NMVariantAttributeSpec *const *iter; - const NMVariantAttributeSpec * spec = NULL; - - g_return_val_if_fail(name, FALSE); - g_return_val_if_fail(value, FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - for (iter = _nm_sriov_vf_attribute_spec; *iter; iter++) { - if (nm_streq(name, (*iter)->name)) { - spec = *iter; - break; - } - } - - if (!spec || spec->str_type == 'd') { - NM_SET_OUT(known, FALSE); - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unknown attribute")); - return FALSE; - } - - NM_SET_OUT(known, TRUE); - - if (!g_variant_is_of_type(value, spec->type)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid attribute type '%s'"), - g_variant_get_type_string(value)); - return FALSE; - } - - if (g_variant_type_equal(spec->type, G_VARIANT_TYPE_STRING)) { - const char *string; - - switch (spec->str_type) { - case 'm': /* MAC address */ - string = g_variant_get_string(value, NULL); - if (!nm_utils_hwaddr_valid(string, -1)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("'%s' is not a valid MAC address"), - string); - return FALSE; - } - break; - default: - break; - } - } - - return TRUE; -} - -gboolean -_nm_sriov_vf_attribute_validate_all(const NMSriovVF *vf, GError **error) -{ - GHashTableIter iter; - const char * name; - GVariant * variant; - GVariant * min, *max; - - g_return_val_if_fail(vf, FALSE); - g_return_val_if_fail(vf->refcount > 0, FALSE); - - g_hash_table_iter_init(&iter, vf->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) { - if (!nm_sriov_vf_attribute_validate(name, variant, NULL, error)) { - g_prefix_error(error, "attribute '%s':", name); - return FALSE; - } - } - - min = g_hash_table_lookup(vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE); - max = g_hash_table_lookup(vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE); - if (min && max && g_variant_get_uint32(min) > g_variant_get_uint32(max)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "min_tx_rate is greater than max_tx_rate"); - return FALSE; - } - - return TRUE; -} - -/** - * nm_sriov_vf_add_vlan: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * - * Adds a VLAN to the VF. - * - * Returns: %TRUE if the VLAN was added; %FALSE if it already existed - * - * Since: 1.14 - **/ -gboolean -nm_sriov_vf_add_vlan(NMSriovVF *vf, guint vlan_id) -{ - g_return_val_if_fail(vf, FALSE); - g_return_val_if_fail(vf->refcount > 0, FALSE); - - if (vf->vlans && g_hash_table_contains(vf->vlans, &vlan_id)) - return FALSE; - - vf_add_vlan(vf, vlan_id, 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - - return TRUE; -} - -/** - * nm_sriov_vf_remove_vlan: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * - * Removes a VLAN from a VF. - * - * Returns: %TRUE if the VLAN was removed, %FALSE if the VLAN @vlan_id - * did not belong to the VF. - * - * Since: 1.14 - */ -gboolean -nm_sriov_vf_remove_vlan(NMSriovVF *vf, guint vlan_id) -{ - g_return_val_if_fail(vf, FALSE); - g_return_val_if_fail(vf->refcount > 0, FALSE); - - if (!vf->vlans || !g_hash_table_remove(vf->vlans, &vlan_id)) - return FALSE; - - nm_clear_g_free(&vf->vlan_ids); - return TRUE; -} - -static int -vlan_id_compare(gconstpointer a, gconstpointer b, gpointer user_data) -{ - guint id_a = *(guint *) a; - guint id_b = *(guint *) b; - - if (id_a < id_b) - return -1; - else if (id_a > id_b) - return 1; - else - return 0; -} - -/** - * nm_sriov_vf_get_vlan_ids: - * @vf: the #NMSriovVF - * @length: (out) (allow-none): on return, the number of VLANs configured - * - * Returns the VLANs currently configured on the VF. - * - * Returns: (transfer none) (array length=length): a list of VLAN ids configured on the VF. - * - * Since: 1.14 - */ -const guint * -nm_sriov_vf_get_vlan_ids(const NMSriovVF *vf, guint *length) -{ - GHashTableIter iter; - VFVlan * vlan; - guint num, i; - - g_return_val_if_fail(vf, NULL); - g_return_val_if_fail(vf->refcount > 0, NULL); - - num = vf->vlans ? g_hash_table_size(vf->vlans) : 0u; - NM_SET_OUT(length, num); - - if (vf->vlan_ids) - return vf->vlan_ids; - if (num == 0) - return NULL; - - /* vf is const, however, vlan_ids is a mutable field caching the - * result ("mutable" in C++ terminology) */ - ((NMSriovVF *) vf)->vlan_ids = g_new0(guint, num); - - i = 0; - g_hash_table_iter_init(&iter, vf->vlans); - while (g_hash_table_iter_next(&iter, (gpointer *) &vlan, NULL)) - vf->vlan_ids[i++] = vlan->id; - - nm_assert(num == i); - - g_qsort_with_data(vf->vlan_ids, num, sizeof(guint), vlan_id_compare, NULL); - - return vf->vlan_ids; -} - -/** - * nm_sriov_vf_set_vlan_qos: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * @qos: a QoS (priority) value - * - * Sets a QoS value for the given VLAN. - * - * Since: 1.14 - */ -void -nm_sriov_vf_set_vlan_qos(NMSriovVF *vf, guint vlan_id, guint32 qos) -{ - VFVlan *vlan; - - g_return_if_fail(vf); - g_return_if_fail(vf->refcount > 0); - - if (!vf->vlans || !(vlan = g_hash_table_lookup(vf->vlans, &vlan_id))) - g_return_if_reached(); - - vlan->qos = qos; -} - -/** - * nm_sriov_vf_set_vlan_protocol: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * @protocol: the VLAN protocol - * - * Sets the protocol for the given VLAN. - * - * Since: 1.14 - */ -void -nm_sriov_vf_set_vlan_protocol(NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol) -{ - VFVlan *vlan; - - g_return_if_fail(vf); - g_return_if_fail(vf->refcount > 0); - - if (!vf->vlans || !(vlan = g_hash_table_lookup(vf->vlans, &vlan_id))) - g_return_if_reached(); - - vlan->protocol = protocol; -} - -/** - * nm_sriov_vf_get_vlan_qos: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * - * Returns the QoS value for the given VLAN. - * - * Returns: the QoS value - * - * Since: 1.14 - */ -guint32 -nm_sriov_vf_get_vlan_qos(const NMSriovVF *vf, guint vlan_id) -{ - VFVlan *vlan; - - g_return_val_if_fail(vf, 0); - g_return_val_if_fail(vf->refcount > 0, 0); - - if (!vf->vlans || !(vlan = g_hash_table_lookup(vf->vlans, &vlan_id))) - g_return_val_if_reached(0); - - return vlan->qos; -} - -/* - * nm_sriov_vf_get_vlan_protocol: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * - * Returns the configured protocol for the given VLAN. - * - * Returns: the configured protocol - * - * Since: 1.14 - */ -NMSriovVFVlanProtocol -nm_sriov_vf_get_vlan_protocol(const NMSriovVF *vf, guint vlan_id) -{ - VFVlan *vlan; - - g_return_val_if_fail(vf, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - g_return_val_if_fail(vf->refcount > 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - - if (!vf->vlans || !(vlan = g_hash_table_lookup(vf->vlans, &vlan_id))) - g_return_val_if_reached(NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - - return vlan->protocol; -} - -/*****************************************************************************/ - -/** - * nm_setting_sriov_get_total_vfs: - * @setting: the #NMSettingSriov - * - * Returns the value contained in the #NMSettingSriov:total-vfs - * property. - * - * Returns: the total number of SR-IOV virtual functions to create - * - * Since: 1.14 - **/ -guint -nm_setting_sriov_get_total_vfs(NMSettingSriov *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), 0); - - return setting->total_vfs; -} - -/** - * nm_setting_sriov_get_num_vfs: - * @setting: the #NMSettingSriov - * - * Returns: the number of configured VFs - * - * Since: 1.14 - **/ -guint -nm_setting_sriov_get_num_vfs(NMSettingSriov *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), 0); - - return setting->vfs->len; -} - -/** - * nm_setting_sriov_get_vf: - * @setting: the #NMSettingSriov - * @idx: index number of the VF to return - * - * Returns: (transfer none): the VF at index @idx - * - * Since: 1.14 - **/ -NMSriovVF * -nm_setting_sriov_get_vf(NMSettingSriov *setting, guint idx) -{ - g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NULL); - g_return_val_if_fail(idx < setting->vfs->len, NULL); - - return setting->vfs->pdata[idx]; -} - -/** - * nm_setting_sriov_add_vf: - * @setting: the #NMSettingSriov - * @vf: the VF to add - * - * Appends a new VF and associated information to the setting. The - * given VF is duplicated internally and is not changed by this function. - * - * Since: 1.14 - **/ -void -nm_setting_sriov_add_vf(NMSettingSriov *setting, NMSriovVF *vf) -{ - g_return_if_fail(NM_IS_SETTING_SRIOV(setting)); - g_return_if_fail(vf); - g_return_if_fail(vf->refcount > 0); - - g_ptr_array_add(setting->vfs, nm_sriov_vf_dup(vf)); - _notify(setting, PROP_VFS); -} - -/** - * nm_setting_sriov_remove_vf: - * @setting: the #NMSettingSriov - * @idx: index number of the VF - * - * Removes the VF at index @idx. - * - * Since: 1.14 - **/ -void -nm_setting_sriov_remove_vf(NMSettingSriov *setting, guint idx) -{ - g_return_if_fail(NM_IS_SETTING_SRIOV(setting)); - g_return_if_fail(idx < setting->vfs->len); - - g_ptr_array_remove_index(setting->vfs, idx); - _notify(setting, PROP_VFS); -} - -/** - * nm_setting_sriov_remove_vf_by_index: - * @setting: the #NMSettingSriov - * @index: the VF index of the VF to remove - * - * Removes the VF with VF index @index. - * - * Returns: %TRUE if the VF was found and removed; %FALSE if it was not - * - * Since: 1.14 - **/ -gboolean -nm_setting_sriov_remove_vf_by_index(NMSettingSriov *setting, guint index) -{ - guint i; - - g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), FALSE); - - for (i = 0; i < setting->vfs->len; i++) { - if (nm_sriov_vf_get_index(setting->vfs->pdata[i]) == index) { - g_ptr_array_remove_index(setting->vfs, i); - _notify(setting, PROP_VFS); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_sriov_clear_vfs: - * @setting: the #NMSettingSriov - * - * Removes all configured VFs. - * - * Since: 1.14 - **/ -void -nm_setting_sriov_clear_vfs(NMSettingSriov *setting) -{ - g_return_if_fail(NM_IS_SETTING_SRIOV(setting)); - - if (setting->vfs->len != 0) { - g_ptr_array_set_size(setting->vfs, 0); - _notify(setting, PROP_VFS); - } -} - -/** - * nm_setting_sriov_get_autoprobe_drivers: - * @setting: the #NMSettingSriov - * - * Returns the value contained in the #NMSettingSriov:autoprobe-drivers - * property. - * - * Returns: the autoprobe-drivers property value - * - * Since: 1.14 - **/ -NMTernary -nm_setting_sriov_get_autoprobe_drivers(NMSettingSriov *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NM_TERNARY_DEFAULT); - - return setting->autoprobe_drivers; -} - -static int -vf_index_compare(gconstpointer a, gconstpointer b) -{ - NMSriovVF *vf_a = *(NMSriovVF **) a; - NMSriovVF *vf_b = *(NMSriovVF **) b; - - if (vf_a->index < vf_b->index) - return -1; - else if (vf_a->index > vf_b->index) - return 1; - else - return 0; -} - -gboolean -_nm_setting_sriov_sort_vfs(NMSettingSriov *setting) -{ - gboolean need_sort = FALSE; - guint i; - - for (i = 1; i < setting->vfs->len; i++) { - NMSriovVF *vf_prev = setting->vfs->pdata[i - 1]; - NMSriovVF *vf = setting->vfs->pdata[i]; - - if (vf->index <= vf_prev->index) { - need_sort = TRUE; - break; - } - } - - if (need_sort) { - g_ptr_array_sort(setting->vfs, vf_index_compare); - _notify(setting, PROP_VFS); - } - - return need_sort; -} - -/*****************************************************************************/ - -static GVariant * -vfs_to_dbus(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *vfs = NULL; - GVariantBuilder builder; - guint i; - - g_object_get(setting, NM_SETTING_SRIOV_VFS, &vfs, NULL); - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - - if (vfs) { - for (i = 0; i < vfs->len; i++) { - gs_free const char **attr_names = NULL; - NMSriovVF * vf = vfs->pdata[i]; - GVariantBuilder vf_builder; - const guint * vlan_ids; - const char ** name; - guint num_vlans = 0; - - g_variant_builder_init(&vf_builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add(&vf_builder, - "{sv}", - "index", - g_variant_new_uint32(nm_sriov_vf_get_index(vf))); - - attr_names = nm_utils_strdict_get_keys(vf->attributes, TRUE, NULL); - if (attr_names) { - for (name = attr_names; *name; name++) { - g_variant_builder_add(&vf_builder, - "{sv}", - *name, - nm_sriov_vf_get_attribute(vf, *name)); - } - } - - /* VLANs are translated into an array of maps, where each map has - * keys 'id', 'qos' and 'proto'. This guarantees enough flexibility - * to accommodate any future new option. */ - vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num_vlans); - if (num_vlans) { - GVariantBuilder vlans_builder; - guint j; - - g_variant_builder_init(&vlans_builder, G_VARIANT_TYPE("aa{sv}")); - for (j = 0; j < num_vlans; j++) { - GVariantBuilder vlan_builder; - - g_variant_builder_init(&vlan_builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&vlan_builder, - "{sv}", - "id", - g_variant_new_uint32(vlan_ids[j])); - g_variant_builder_add( - &vlan_builder, - "{sv}", - "qos", - g_variant_new_uint32(nm_sriov_vf_get_vlan_qos(vf, vlan_ids[j]))); - g_variant_builder_add( - &vlan_builder, - "{sv}", - "protocol", - g_variant_new_uint32(nm_sriov_vf_get_vlan_protocol(vf, vlan_ids[j]))); - g_variant_builder_add(&vlans_builder, "a{sv}", &vlan_builder); - } - g_variant_builder_add(&vf_builder, - "{sv}", - "vlans", - g_variant_builder_end(&vlans_builder)); - } - g_variant_builder_add(&builder, "a{sv}", &vf_builder); - } - } - - return g_variant_builder_end(&builder); -} - -static gboolean -vfs_from_dbus(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray * vfs; - GVariantIter vf_iter; - GVariant * vf_var; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), FALSE); - - vfs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_sriov_vf_unref); - g_variant_iter_init(&vf_iter, value); - while (g_variant_iter_next(&vf_iter, "@a{sv}", &vf_var)) { - NMSriovVF * vf; - guint32 index; - GVariantIter attr_iter; - const char * attr_name; - GVariant * attr_var, *vlans_var; - - if (!g_variant_lookup(vf_var, "index", "u", &index)) - goto next; - - vf = nm_sriov_vf_new(index); - - g_variant_iter_init(&attr_iter, vf_var); - while (g_variant_iter_next(&attr_iter, "{&sv}", &attr_name, &attr_var)) { - if (!NM_IN_STRSET(attr_name, "index", "vlans")) - nm_sriov_vf_set_attribute(vf, attr_name, attr_var); - g_variant_unref(attr_var); - } - - if (g_variant_lookup(vf_var, "vlans", "@aa{sv}", &vlans_var)) { - GVariantIter vlan_iter; - GVariant * vlan_var; - - g_variant_iter_init(&vlan_iter, vlans_var); - while (g_variant_iter_next(&vlan_iter, "@a{sv}", &vlan_var)) { - NMSriovVFVlanProtocol proto = NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q; - gint64 vlan_id = -1; - guint qos = 0; - - g_variant_iter_init(&attr_iter, vlan_var); - while (g_variant_iter_next(&attr_iter, "{&sv}", &attr_name, &attr_var)) { - if (nm_streq(attr_name, "id") - && g_variant_is_of_type(attr_var, G_VARIANT_TYPE_UINT32)) - vlan_id = g_variant_get_uint32(attr_var); - else if (nm_streq(attr_name, "qos") - && g_variant_is_of_type(attr_var, G_VARIANT_TYPE_UINT32)) - qos = g_variant_get_uint32(attr_var); - else if (nm_streq(attr_name, "protocol") - && g_variant_is_of_type(attr_var, G_VARIANT_TYPE_UINT32)) - proto = g_variant_get_uint32(attr_var); - g_variant_unref(attr_var); - } - if (vlan_id != -1) - vf_add_vlan(vf, vlan_id, qos, proto); - g_variant_unref(vlan_var); - } - g_variant_unref(vlans_var); - } - - g_ptr_array_add(vfs, vf); -next: - g_variant_unref(vf_var); - } - - g_object_set(setting, NM_SETTING_SRIOV_VFS, vfs, NULL); - g_ptr_array_unref(vfs); - - return TRUE; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingSriov *self = NM_SETTING_SRIOV(setting); - guint i; - - if (self->vfs->len) { - gs_unref_hashtable GHashTable *h = NULL; - - h = g_hash_table_new(nm_direct_hash, NULL); - for (i = 0; i < self->vfs->len; i++) { - NMSriovVF * vf = self->vfs->pdata[i]; - gs_free_error GError *local = NULL; - - if (vf->index >= self->total_vfs) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("VF with index %u, but the total number of VFs is %u"), - vf->index, - self->total_vfs); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_SRIOV_SETTING_NAME, - NM_SETTING_SRIOV_VFS); - return FALSE; - } - - if (!_nm_sriov_vf_attribute_validate_all(vf, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid VF %u: %s"), - vf->index, - local->message); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_SRIOV_SETTING_NAME, - NM_SETTING_SRIOV_VFS); - return FALSE; - } - - if (g_hash_table_contains(h, GUINT_TO_POINTER(vf->index))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("duplicate VF index %u"), - vf->index); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_SRIOV_SETTING_NAME, - NM_SETTING_SRIOV_VFS); - return FALSE; - } - - g_hash_table_add(h, GUINT_TO_POINTER(vf->index)); - } - } - - /* Failures from here on are NORMALIZABLE... */ - - if (self->vfs->len) { - for (i = 1; i < self->vfs->len; i++) { - NMSriovVF *vf_prev = self->vfs->pdata[i - 1]; - NMSriovVF *vf = self->vfs->pdata[i]; - - if (vf->index <= vf_prev->index) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("VFs %d and %d are not sorted by ascending index"), - vf_prev->index, - vf->index); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_SRIOV_SETTING_NAME, - NM_SETTING_SRIOV_VFS); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - } - } - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingSriov *a; - NMSettingSriov *b; - guint i; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_SRIOV_VFS)) { - if (set_b) { - a = NM_SETTING_SRIOV(set_a); - b = NM_SETTING_SRIOV(set_b); - - if (a->vfs->len != b->vfs->len) - return FALSE; - for (i = 0; i < a->vfs->len; i++) { - if (!nm_sriov_vf_equal(a->vfs->pdata[i], b->vfs->pdata[i])) - return FALSE; - } - } - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_sriov_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingSriov *self = NM_SETTING_SRIOV(object); - - switch (prop_id) { - case PROP_TOTAL_VFS: - g_value_set_uint(value, self->total_vfs); - break; - case PROP_VFS: - g_value_take_boxed(value, - _nm_utils_copy_array(self->vfs, - (NMUtilsCopyFunc) nm_sriov_vf_dup, - (GDestroyNotify) nm_sriov_vf_unref)); - break; - case PROP_AUTOPROBE_DRIVERS: - g_value_set_enum(value, self->autoprobe_drivers); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingSriov *self = NM_SETTING_SRIOV(object); - - switch (prop_id) { - case PROP_TOTAL_VFS: - self->total_vfs = g_value_get_uint(value); - break; - case PROP_VFS: - g_ptr_array_unref(self->vfs); - self->vfs = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) nm_sriov_vf_dup, - (GDestroyNotify) nm_sriov_vf_unref); - break; - case PROP_AUTOPROBE_DRIVERS: - self->autoprobe_drivers = g_value_get_enum(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_sriov_init(NMSettingSriov *setting) -{ - setting->vfs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_sriov_vf_unref); - - setting->autoprobe_drivers = NM_TERNARY_DEFAULT; -} - -/** - * nm_setting_sriov_new: - * - * Creates a new #NMSettingSriov object with default values. - * - * Returns: (transfer full): the new empty #NMSettingSriov object - * - * Since: 1.14 - **/ -NMSetting * -nm_setting_sriov_new(void) -{ - return g_object_new(NM_TYPE_SETTING_SRIOV, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingSriov *self = NM_SETTING_SRIOV(object); - - g_ptr_array_unref(self->vfs); - - G_OBJECT_CLASS(nm_setting_sriov_parent_class)->finalize(object); -} - -static void -nm_setting_sriov_class_init(NMSettingSriovClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - - /** - * NMSettingSriov:total-vfs - * - * The total number of virtual functions to create. - * - * Note that when the sriov setting is present NetworkManager - * enforces the number of virtual functions on the interface - * (also when it is zero) during activation and resets it - * upon deactivation. To prevent any changes to SR-IOV - * parameters don't add a sriov setting to the connection. - * - * Since: 1.14 - **/ - /* ---ifcfg-rh--- - * property: total-vfs - * variable: SRIOV_TOTAL_VFS(+) - * description: The total number of virtual functions to create - * example: SRIOV_TOTAL_VFS=16 - * ---end--- - */ - obj_properties[PROP_TOTAL_VFS] = g_param_spec_uint( - NM_SETTING_SRIOV_TOTAL_VFS, - "", - "", - 0, - G_MAXUINT32, - 0, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingSriov:vfs: (type GPtrArray(NMSriovVF)) - * - * Array of virtual function descriptors. - * - * Each VF descriptor is a dictionary mapping attribute names - * to GVariant values. The 'index' entry is mandatory for - * each VF. - * - * When represented as string a VF is in the form: - * - * "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". - * - * for example: - * - * "2 mac=00:11:22:33:44:55 spoof-check=true". - * - * Multiple VFs can be specified using a comma as separator. - * Currently, the following attributes are supported: mac, - * spoof-check, trust, min-tx-rate, max-tx-rate, vlans. - * - * The "vlans" attribute is represented as a semicolon-separated - * list of VLAN descriptors, where each descriptor has the form - * - * "ID[.PRIORITY[.PROTO]]". - * - * PROTO can be either 'q' for 802.1Q (the default) or 'ad' for - * 802.1ad. - * - - * Since: 1.14 - **/ - /* ---ifcfg-rh--- - * property: vfs - * variable: SRIOV_VF1(+), SRIOV_VF2(+), ... - * description: SR-IOV virtual function descriptors - * example: SRIOV_VF10="mac=00:11:22:33:44:55", ... - * ---end--- - */ - obj_properties[PROP_VFS] = g_param_spec_boxed(NM_SETTING_SRIOV_VFS, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_VFS], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = vfs_to_dbus, - .from_dbus_fcn = vfs_from_dbus, )); - - /** - * NMSettingSriov:autoprobe-drivers - * - * Whether to autoprobe virtual functions by a compatible driver. - * - * If set to %NM_TERNARY_TRUE, the kernel will try to bind VFs to - * a compatible driver and if this succeeds a new network - * interface will be instantiated for each VF. - * - * If set to %NM_TERNARY_FALSE, VFs will not be claimed and no - * network interfaces will be created for them. - * - * When set to %NM_TERNARY_DEFAULT, the global default is used; in - * case the global default is unspecified it is assumed to be - * %NM_TERNARY_TRUE. - * - * Since: 1.14 - **/ - /* ---ifcfg-rh--- - * property: autoprobe-drivers - * variable: SRIOV_AUTOPROBE_DRIVERS(+) - * default: missing variable means global default - * description: Whether to autoprobe virtual functions by a compatible driver - * example: SRIOV_AUTOPROBE_DRIVERS=0,1 - * ---end--- - */ - obj_properties[PROP_AUTOPROBE_DRIVERS] = g_param_spec_enum( - NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, - "", - "", - NM_TYPE_TERNARY, - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_SRIOV, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-sriov.h b/libnm-core/nm-setting-sriov.h deleted file mode 100644 index fe5fc3766f..0000000000 --- a/libnm-core/nm-setting-sriov.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#ifndef NM_SETTING_SRIOV_H -#define NM_SETTING_SRIOV_H - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_SRIOV (nm_setting_sriov_get_type()) -#define NM_SETTING_SRIOV(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriov)) -#define NM_SETTING_SRIOV_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass)) -#define NM_IS_SETTING_SRIOV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_SRIOV)) -#define NM_IS_SETTING_SRIOV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_SRIOV)) -#define NM_SETTING_SRIOV_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass)) - -#define NM_SETTING_SRIOV_SETTING_NAME "sriov" - -#define NM_SETTING_SRIOV_TOTAL_VFS "total-vfs" -#define NM_SETTING_SRIOV_VFS "vfs" -#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS "autoprobe-drivers" - -#define NM_SRIOV_VF_ATTRIBUTE_MAC "mac" -#define NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK "spoof-check" -#define NM_SRIOV_VF_ATTRIBUTE_TRUST "trust" -#define NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE "min-tx-rate" -#define NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE "max-tx-rate" - -typedef struct _NMSettingSriovClass NMSettingSriovClass; -typedef struct _NMSriovVF NMSriovVF; - -/** - * NMSriovVFVlanProtocol: - * @NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q: use 802.1Q - * @NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD: use 802.1ad - * - * #NMSriovVFVlanProtocol indicates the VLAN protocol to use. - * - * Since: 1.14 - */ -typedef enum { - NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q = 0, - NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD = 1, -} NMSriovVFVlanProtocol; - -NM_AVAILABLE_IN_1_14 -GType nm_setting_sriov_get_type(void); -NM_AVAILABLE_IN_1_14 -NMSetting *nm_setting_sriov_new(void); -NM_AVAILABLE_IN_1_14 -guint nm_setting_sriov_get_total_vfs(NMSettingSriov *setting); -NM_AVAILABLE_IN_1_14 -guint nm_setting_sriov_get_num_vfs(NMSettingSriov *setting); -NM_AVAILABLE_IN_1_14 -NMSriovVF *nm_setting_sriov_get_vf(NMSettingSriov *setting, guint idx); -NM_AVAILABLE_IN_1_14 -void nm_setting_sriov_add_vf(NMSettingSriov *setting, NMSriovVF *vf); -NM_AVAILABLE_IN_1_14 -void nm_setting_sriov_remove_vf(NMSettingSriov *setting, guint idx); -NM_AVAILABLE_IN_1_14 -gboolean nm_setting_sriov_remove_vf_by_index(NMSettingSriov *setting, guint index); -NM_AVAILABLE_IN_1_14 -void nm_setting_sriov_clear_vfs(NMSettingSriov *setting); -NM_AVAILABLE_IN_1_14 -NMTernary nm_setting_sriov_get_autoprobe_drivers(NMSettingSriov *setting); - -NM_AVAILABLE_IN_1_14 -gboolean nm_sriov_vf_add_vlan(NMSriovVF *vf, guint vlan_id); -NM_AVAILABLE_IN_1_14 -gboolean nm_sriov_vf_remove_vlan(NMSriovVF *vf, guint vlan_id); -NM_AVAILABLE_IN_1_14 -const guint *nm_sriov_vf_get_vlan_ids(const NMSriovVF *vf, guint *length); -NM_AVAILABLE_IN_1_14 -void nm_sriov_vf_set_vlan_qos(NMSriovVF *vf, guint vlan_id, guint32 qos); -NM_AVAILABLE_IN_1_14 -void nm_sriov_vf_set_vlan_protocol(NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol); -NM_AVAILABLE_IN_1_14 -guint32 nm_sriov_vf_get_vlan_qos(const NMSriovVF *vf, guint vlan_id); -NM_AVAILABLE_IN_1_14 -NMSriovVFVlanProtocol nm_sriov_vf_get_vlan_protocol(const NMSriovVF *vf, guint vlan_id); - -NM_AVAILABLE_IN_1_14 -GType nm_sriov_vf_get_type(void); -NM_AVAILABLE_IN_1_14 -NMSriovVF *nm_sriov_vf_new(guint index); -NM_AVAILABLE_IN_1_14 -void nm_sriov_vf_ref(NMSriovVF *vf); -NM_AVAILABLE_IN_1_14 -void nm_sriov_vf_unref(NMSriovVF *vf); -NM_AVAILABLE_IN_1_14 -gboolean nm_sriov_vf_equal(const NMSriovVF *vf, const NMSriovVF *other); -NM_AVAILABLE_IN_1_14 -NMSriovVF *nm_sriov_vf_dup(const NMSriovVF *vf); -NM_AVAILABLE_IN_1_14 -guint nm_sriov_vf_get_index(const NMSriovVF *vf); -NM_AVAILABLE_IN_1_14 -void nm_sriov_vf_set_attribute(NMSriovVF *vf, const char *name, GVariant *value); -NM_AVAILABLE_IN_1_14 -const char **nm_sriov_vf_get_attribute_names(const NMSriovVF *vf); -NM_AVAILABLE_IN_1_14 -GVariant *nm_sriov_vf_get_attribute(const NMSriovVF *vf, const char *name); -NM_AVAILABLE_IN_1_14 -gboolean -nm_sriov_vf_attribute_validate(const char *name, GVariant *value, gboolean *known, GError **error); - -G_END_DECLS - -#endif /* NM_SETTING_SRIOV_H */ diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c deleted file mode 100644 index 33df6d34e5..0000000000 --- a/libnm-core/nm-setting-tc-config.c +++ /dev/null @@ -1,1863 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-tc-config.h" - -#include - -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-tc-config - * @short_description: Describes connection properties for the Linux Traffic Control - * @include: nm-setting-tc-config.h - **/ - -/*****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMTCQdisc, nm_tc_qdisc, nm_tc_qdisc_dup, nm_tc_qdisc_unref) - -struct NMTCQdisc { - guint refcount; - - char * kind; - guint32 handle; - guint32 parent; - GHashTable *attributes; -}; - -/** - * nm_tc_qdisc_new: - * @kind: name of the queueing discipline - * @parent: the parent queueing discipline - * @error: location to store error, or %NULL - * - * Creates a new #NMTCQdisc object. - * - * Returns: (transfer full): the new #NMTCQdisc object, or %NULL on error - * - * Since: 1.12 - **/ -NMTCQdisc * -nm_tc_qdisc_new(const char *kind, guint32 parent, GError **error) -{ - NMTCQdisc *qdisc; - - if (!kind || !*kind) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("kind is missing")); - return NULL; - } - - if (strchr(kind, ' ') || strchr(kind, '\t')) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid kind"), - kind); - return NULL; - } - - if (!parent) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("parent handle missing")); - return NULL; - } - - qdisc = g_slice_new0(NMTCQdisc); - qdisc->refcount = 1; - - qdisc->kind = g_strdup(kind); - qdisc->parent = parent; - - return qdisc; -} - -/** - * nm_tc_qdisc_ref: - * @qdisc: the #NMTCQdisc - * - * Increases the reference count of the object. - * - * Since: 1.12 - **/ -void -nm_tc_qdisc_ref(NMTCQdisc *qdisc) -{ - g_return_if_fail(qdisc != NULL); - g_return_if_fail(qdisc->refcount > 0); - - qdisc->refcount++; -} - -/** - * nm_tc_qdisc_unref: - * @qdisc: the #NMTCQdisc - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - * - * Since: 1.12 - **/ -void -nm_tc_qdisc_unref(NMTCQdisc *qdisc) -{ - g_return_if_fail(qdisc != NULL); - g_return_if_fail(qdisc->refcount > 0); - - qdisc->refcount--; - if (qdisc->refcount == 0) { - g_free(qdisc->kind); - if (qdisc->attributes) - g_hash_table_unref(qdisc->attributes); - g_slice_free(NMTCQdisc, qdisc); - } -} - -/** - * nm_tc_qdisc_equal: - * @qdisc: the #NMTCQdisc - * @other: the #NMTCQdisc to compare @qdisc to. - * - * Determines if two #NMTCQdisc objects contain the same kind, * handle - * and parent. - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - * - * Since: 1.12 - **/ -gboolean -nm_tc_qdisc_equal(NMTCQdisc *qdisc, NMTCQdisc *other) -{ - GHashTableIter iter; - const char * key; - GVariant * value, *value2; - guint n; - - g_return_val_if_fail(qdisc != NULL, FALSE); - g_return_val_if_fail(qdisc->refcount > 0, FALSE); - - g_return_val_if_fail(other != NULL, FALSE); - g_return_val_if_fail(other->refcount > 0, FALSE); - - if (qdisc->handle != other->handle || qdisc->parent != other->parent - || g_strcmp0(qdisc->kind, other->kind) != 0) - return FALSE; - - n = qdisc->attributes ? g_hash_table_size(qdisc->attributes) : 0; - if (n != (other->attributes ? g_hash_table_size(other->attributes) : 0)) - return FALSE; - if (n) { - g_hash_table_iter_init(&iter, qdisc->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { - value2 = g_hash_table_lookup(other->attributes, key); - if (!value2) - return FALSE; - if (!g_variant_equal(value, value2)) - return FALSE; - } - } - - return TRUE; -} - -static guint -_nm_tc_qdisc_hash(NMTCQdisc *qdisc) -{ - NMUtilsNamedValue attrs_static[30]; - gs_free NMUtilsNamedValue *attrs_free = NULL; - const NMUtilsNamedValue * attrs; - NMHashState h; - guint length; - guint i; - - attrs = - nm_utils_named_values_from_strdict(qdisc->attributes, &length, attrs_static, &attrs_free); - - nm_hash_init(&h, 43869703); - nm_hash_update_vals(&h, qdisc->handle, qdisc->parent, length); - nm_hash_update_str0(&h, qdisc->kind); - for (i = 0; i < length; i++) { - const char * key = attrs[i].name; - GVariant * variant = attrs[i].value_ptr; - const GVariantType *vtype; - - vtype = g_variant_get_type(variant); - - nm_hash_update_str(&h, key); - nm_hash_update_str(&h, (const char *) vtype); - if (g_variant_type_is_basic(vtype)) - nm_hash_update_val(&h, g_variant_hash(variant)); - } - - return nm_hash_complete(&h); -} - -/** - * nm_tc_qdisc_dup: - * @qdisc: the #NMTCQdisc - * - * Creates a copy of @qdisc - * - * Returns: (transfer full): a copy of @qdisc - * - * Since: 1.12 - **/ -NMTCQdisc * -nm_tc_qdisc_dup(NMTCQdisc *qdisc) -{ - NMTCQdisc *copy; - - g_return_val_if_fail(qdisc != NULL, NULL); - g_return_val_if_fail(qdisc->refcount > 0, NULL); - - copy = nm_tc_qdisc_new(qdisc->kind, qdisc->parent, NULL); - nm_tc_qdisc_set_handle(copy, qdisc->handle); - - if (qdisc->attributes) { - GHashTableIter iter; - const char * key; - GVariant * value; - - g_hash_table_iter_init(&iter, qdisc->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) - nm_tc_qdisc_set_attribute(copy, key, value); - } - - return copy; -} - -/** - * nm_tc_qdisc_get_kind: - * @qdisc: the #NMTCQdisc - * - * Returns: - * - * Since: 1.12 - **/ -const char * -nm_tc_qdisc_get_kind(NMTCQdisc *qdisc) -{ - g_return_val_if_fail(qdisc != NULL, NULL); - g_return_val_if_fail(qdisc->refcount > 0, NULL); - - return qdisc->kind; -} - -/** - * nm_tc_qdisc_get_handle: - * @qdisc: the #NMTCQdisc - * - * Returns: the queueing discipline handle - * - * Since: 1.12 - **/ -guint32 -nm_tc_qdisc_get_handle(NMTCQdisc *qdisc) -{ - g_return_val_if_fail(qdisc != NULL, TC_H_UNSPEC); - g_return_val_if_fail(qdisc->refcount > 0, TC_H_UNSPEC); - - return qdisc->handle; -} - -/** - * nm_tc_qdisc_set_handle: - * @qdisc: the #NMTCQdisc - * @handle: the queueing discipline handle - * - * Sets the queueing discipline handle. - * - * Since: 1.12 - **/ -void -nm_tc_qdisc_set_handle(NMTCQdisc *qdisc, guint32 handle) -{ - g_return_if_fail(qdisc != NULL); - g_return_if_fail(qdisc->refcount > 0); - - qdisc->handle = handle; -} - -/** - * nm_tc_qdisc_get_parent: - * @qdisc: the #NMTCQdisc - * - * Returns: the parent class - * - * Since: 1.12 - **/ -guint32 -nm_tc_qdisc_get_parent(NMTCQdisc *qdisc) -{ - g_return_val_if_fail(qdisc != NULL, TC_H_UNSPEC); - g_return_val_if_fail(qdisc->refcount > 0, TC_H_UNSPEC); - - return qdisc->parent; -} - -/** - * nm_tc_qdisc_get_attribute_names: - * @qdisc: the #NMTCQdisc - * - * Gets an array of attribute names defined on @qdisc. - * - * Returns: (transfer container): a %NULL-terminated array of attribute names - * or %NULL if no attributes are set. - * - * Since: 1.18 - **/ -const char ** -nm_tc_qdisc_get_attribute_names(NMTCQdisc *qdisc) -{ - g_return_val_if_fail(qdisc, NULL); - - return nm_utils_strdict_get_keys(qdisc->attributes, TRUE, NULL); -} - -GHashTable * -_nm_tc_qdisc_get_attributes(NMTCQdisc *qdisc) -{ - nm_assert(qdisc); - - return qdisc->attributes; -} - -/** - * nm_tc_qdisc_get_attribute: - * @qdisc: the #NMTCQdisc - * @name: the name of an qdisc attribute - * - * Gets the value of the attribute with name @name on @qdisc - * - * Returns: (transfer none): the value of the attribute with name @name on - * @qdisc, or %NULL if @qdisc has no such attribute. - * - * Since: 1.18 - **/ -GVariant * -nm_tc_qdisc_get_attribute(NMTCQdisc *qdisc, const char *name) -{ - g_return_val_if_fail(qdisc != NULL, NULL); - g_return_val_if_fail(name != NULL && *name != '\0', NULL); - - if (qdisc->attributes) - return g_hash_table_lookup(qdisc->attributes, name); - else - return NULL; -} - -/** - * nm_tc_qdisc_set_attribute: - * @qdisc: the #NMTCQdisc - * @name: the name of an qdisc attribute - * @value: (transfer none) (allow-none): the value - * - * Sets or clears the named attribute on @qdisc to the given value. - * - * Since: 1.18 - **/ -void -nm_tc_qdisc_set_attribute(NMTCQdisc *qdisc, const char *name, GVariant *value) -{ - g_return_if_fail(qdisc != NULL); - g_return_if_fail(name != NULL && *name != '\0'); - g_return_if_fail(strcmp(name, "kind") != 0); - - if (!qdisc->attributes) { - qdisc->attributes = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref); - } - - if (value) - g_hash_table_insert(qdisc->attributes, g_strdup(name), g_variant_ref_sink(value)); - else - g_hash_table_remove(qdisc->attributes, name); -} - -/*****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMTCAction, nm_tc_action, nm_tc_action_dup, nm_tc_action_unref) - -struct NMTCAction { - guint refcount; - - char *kind; - - GHashTable *attributes; -}; - -/** - * nm_tc_action_new: - * @kind: name of the queueing discipline - * @error: location to store error, or %NULL - * - * Creates a new #NMTCAction object. - * - * Returns: (transfer full): the new #NMTCAction object, or %NULL on error - * - * Since: 1.12 - **/ -NMTCAction * -nm_tc_action_new(const char *kind, GError **error) -{ - NMTCAction *action; - - if (!kind || !*kind) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("kind is missing")); - return NULL; - } - - if (strchr(kind, ' ') || strchr(kind, '\t')) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid kind"), - kind); - return NULL; - } - - action = g_slice_new0(NMTCAction); - action->refcount = 1; - - action->kind = g_strdup(kind); - - return action; -} - -/** - * nm_tc_action_ref: - * @action: the #NMTCAction - * - * Increases the reference count of the object. - * - * Since: 1.12 - **/ -void -nm_tc_action_ref(NMTCAction *action) -{ - g_return_if_fail(action != NULL); - g_return_if_fail(action->refcount > 0); - - action->refcount++; -} - -/** - * nm_tc_action_unref: - * @action: the #NMTCAction - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - * - * Since: 1.12 - **/ -void -nm_tc_action_unref(NMTCAction *action) -{ - g_return_if_fail(action != NULL); - g_return_if_fail(action->refcount > 0); - - action->refcount--; - if (action->refcount == 0) { - g_free(action->kind); - if (action->attributes) - g_hash_table_unref(action->attributes); - g_slice_free(NMTCAction, action); - } -} - -/** - * nm_tc_action_equal: - * @action: the #NMTCAction - * @other: the #NMTCAction to compare @action to. - * - * Determines if two #NMTCAction objects contain the same kind, family, - * handle, parent and info. - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - * - * Since: 1.12 - **/ -gboolean -nm_tc_action_equal(NMTCAction *action, NMTCAction *other) -{ - GHashTableIter iter; - const char * key; - GVariant * value, *value2; - guint n; - - g_return_val_if_fail(!action || action->refcount > 0, FALSE); - g_return_val_if_fail(!other || other->refcount > 0, FALSE); - - if (action == other) - return TRUE; - if (!action || !other) - return FALSE; - - if (g_strcmp0(action->kind, other->kind) != 0) - return FALSE; - - n = action->attributes ? g_hash_table_size(action->attributes) : 0; - if (n != (other->attributes ? g_hash_table_size(other->attributes) : 0)) - return FALSE; - if (n) { - g_hash_table_iter_init(&iter, action->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { - value2 = g_hash_table_lookup(other->attributes, key); - if (!value2) - return FALSE; - if (!g_variant_equal(value, value2)) - return FALSE; - } - } - - return TRUE; -} - -/** - * nm_tc_action_dup: - * @action: the #NMTCAction - * - * Creates a copy of @action - * - * Returns: (transfer full): a copy of @action - * - * Since: 1.12 - **/ -NMTCAction * -nm_tc_action_dup(NMTCAction *action) -{ - NMTCAction *copy; - - g_return_val_if_fail(action != NULL, NULL); - g_return_val_if_fail(action->refcount > 0, NULL); - - copy = nm_tc_action_new(action->kind, NULL); - - if (action->attributes) { - GHashTableIter iter; - const char * key; - GVariant * value; - - g_hash_table_iter_init(&iter, action->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) - nm_tc_action_set_attribute(copy, key, value); - } - - return copy; -} - -/** - * nm_tc_action_get_kind: - * @action: the #NMTCAction - * - * Returns: - * - * Since: 1.12 - **/ -const char * -nm_tc_action_get_kind(NMTCAction *action) -{ - g_return_val_if_fail(action != NULL, NULL); - g_return_val_if_fail(action->refcount > 0, NULL); - - return action->kind; -} - -/** - * nm_tc_action_get_attribute_names: - * @action: the #NMTCAction - * - * Gets an array of attribute names defined on @action. - * - * Returns: (transfer full): a %NULL-terminated array of attribute names, - * - * Since: 1.12 - **/ -char ** -nm_tc_action_get_attribute_names(NMTCAction *action) -{ - const char **names; - - g_return_val_if_fail(action, NULL); - - names = nm_utils_strdict_get_keys(action->attributes, TRUE, NULL); - return nm_utils_strv_make_deep_copied_nonnull(names); -} - -GHashTable * -_nm_tc_action_get_attributes(NMTCAction *action) -{ - nm_assert(action); - - return action->attributes; -} - -/** - * nm_tc_action_get_attribute: - * @action: the #NMTCAction - * @name: the name of an action attribute - * - * Gets the value of the attribute with name @name on @action - * - * Returns: (transfer none): the value of the attribute with name @name on - * @action, or %NULL if @action has no such attribute. - * - * Since: 1.12 - **/ -GVariant * -nm_tc_action_get_attribute(NMTCAction *action, const char *name) -{ - g_return_val_if_fail(action != NULL, NULL); - g_return_val_if_fail(name != NULL && *name != '\0', NULL); - - if (action->attributes) - return g_hash_table_lookup(action->attributes, name); - else - return NULL; -} - -/** - * nm_tc_action_set_attribute: - * @action: the #NMTCAction - * @name: the name of an action attribute - * @value: (transfer none) (allow-none): the value - * - * Sets or clears the named attribute on @action to the given value. - * - * Since: 1.12 - **/ -void -nm_tc_action_set_attribute(NMTCAction *action, const char *name, GVariant *value) -{ - g_return_if_fail(action != NULL); - g_return_if_fail(name != NULL && *name != '\0'); - g_return_if_fail(strcmp(name, "kind") != 0); - - if (!action->attributes) { - action->attributes = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref); - } - - if (value) - g_hash_table_insert(action->attributes, g_strdup(name), g_variant_ref_sink(value)); - else - g_hash_table_remove(action->attributes, name); -} - -/*****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMTCTfilter, nm_tc_tfilter, nm_tc_tfilter_dup, nm_tc_tfilter_unref) - -struct NMTCTfilter { - guint refcount; - - char * kind; - guint32 handle; - guint32 parent; - NMTCAction *action; -}; - -/** - * nm_tc_tfilter_new: - * @kind: name of the queueing discipline - * @parent: the parent queueing discipline - * @error: location to store error, or %NULL - * - * Creates a new #NMTCTfilter object. - * - * Returns: (transfer full): the new #NMTCTfilter object, or %NULL on error - * - * Since: 1.12 - **/ -NMTCTfilter * -nm_tc_tfilter_new(const char *kind, guint32 parent, GError **error) -{ - NMTCTfilter *tfilter; - - if (!kind || !*kind) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("kind is missing")); - return NULL; - } - - if (strchr(kind, ' ') || strchr(kind, '\t')) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid kind"), - kind); - return NULL; - } - - if (!parent) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("parent handle missing")); - return NULL; - } - - tfilter = g_slice_new0(NMTCTfilter); - tfilter->refcount = 1; - - tfilter->kind = g_strdup(kind); - tfilter->parent = parent; - - return tfilter; -} - -/** - * nm_tc_tfilter_ref: - * @tfilter: the #NMTCTfilter - * - * Increases the reference count of the object. - * - * Since: 1.12 - **/ -void -nm_tc_tfilter_ref(NMTCTfilter *tfilter) -{ - g_return_if_fail(tfilter != NULL); - g_return_if_fail(tfilter->refcount > 0); - - tfilter->refcount++; -} - -/** - * nm_tc_tfilter_unref: - * @tfilter: the #NMTCTfilter - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - * - * Since: 1.12 - **/ -void -nm_tc_tfilter_unref(NMTCTfilter *tfilter) -{ - g_return_if_fail(tfilter != NULL); - g_return_if_fail(tfilter->refcount > 0); - - tfilter->refcount--; - if (tfilter->refcount == 0) { - g_free(tfilter->kind); - if (tfilter->action) - nm_tc_action_unref(tfilter->action); - g_slice_free(NMTCTfilter, tfilter); - } -} - -/** - * nm_tc_tfilter_equal: - * @tfilter: the #NMTCTfilter - * @other: the #NMTCTfilter to compare @tfilter to. - * - * Determines if two #NMTCTfilter objects contain the same kind, family, - * handle, parent and info. - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - * - * Since: 1.12 - **/ -gboolean -nm_tc_tfilter_equal(NMTCTfilter *tfilter, NMTCTfilter *other) -{ - g_return_val_if_fail(tfilter != NULL, FALSE); - g_return_val_if_fail(tfilter->refcount > 0, FALSE); - - g_return_val_if_fail(other != NULL, FALSE); - g_return_val_if_fail(other->refcount > 0, FALSE); - - if (tfilter->handle != other->handle || tfilter->parent != other->parent - || g_strcmp0(tfilter->kind, other->kind) != 0 - || !nm_tc_action_equal(tfilter->action, other->action)) - return FALSE; - - return TRUE; -} - -static guint -_nm_tc_tfilter_hash(NMTCTfilter *tfilter) -{ - NMHashState h; - - nm_hash_init(&h, 63624437); - nm_hash_update_vals(&h, tfilter->handle, tfilter->parent); - nm_hash_update_str0(&h, tfilter->kind); - - if (tfilter->action) { - gs_free NMUtilsNamedValue *attrs_free = NULL; - NMUtilsNamedValue attrs_static[30]; - const NMUtilsNamedValue * attrs; - guint length; - guint i; - - nm_hash_update_str0(&h, tfilter->action->kind); - - attrs = nm_utils_named_values_from_strdict(tfilter->action->attributes, - &length, - attrs_static, - &attrs_free); - for (i = 0; i < length; i++) { - GVariant *variant = attrs[i].value_ptr; - - nm_hash_update_str(&h, attrs[i].name); - if (g_variant_type_is_basic(g_variant_get_type(variant))) { - guint attr_hash; - - /* g_variant_hash() works only for basic types, thus - * we ignore any non-basic attribute. Actions differing - * only for non-basic attributes will collide. */ - attr_hash = g_variant_hash(variant); - nm_hash_update_val(&h, attr_hash); - } - } - } - - return nm_hash_complete(&h); -} - -/** - * nm_tc_tfilter_dup: - * @tfilter: the #NMTCTfilter - * - * Creates a copy of @tfilter - * - * Returns: (transfer full): a copy of @tfilter - * - * Since: 1.12 - **/ -NMTCTfilter * -nm_tc_tfilter_dup(NMTCTfilter *tfilter) -{ - NMTCTfilter *copy; - - g_return_val_if_fail(tfilter != NULL, NULL); - g_return_val_if_fail(tfilter->refcount > 0, NULL); - - copy = nm_tc_tfilter_new(tfilter->kind, tfilter->parent, NULL); - nm_tc_tfilter_set_handle(copy, tfilter->handle); - nm_tc_tfilter_set_action(copy, tfilter->action); - - return copy; -} - -/** - * nm_tc_tfilter_get_kind: - * @tfilter: the #NMTCTfilter - * - * Returns: - * - * Since: 1.12 - **/ -const char * -nm_tc_tfilter_get_kind(NMTCTfilter *tfilter) -{ - g_return_val_if_fail(tfilter != NULL, NULL); - g_return_val_if_fail(tfilter->refcount > 0, NULL); - - return tfilter->kind; -} - -/** - * nm_tc_tfilter_get_handle: - * @tfilter: the #NMTCTfilter - * - * Returns: the queueing discipline handle - * - * Since: 1.12 - **/ -guint32 -nm_tc_tfilter_get_handle(NMTCTfilter *tfilter) -{ - g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC); - g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC); - - return tfilter->handle; -} - -/** - * nm_tc_tfilter_set_handle: - * @tfilter: the #NMTCTfilter - * @handle: the queueing discipline handle - * - * Sets the queueing discipline handle. - * - * Since: 1.12 - **/ -void -nm_tc_tfilter_set_handle(NMTCTfilter *tfilter, guint32 handle) -{ - g_return_if_fail(tfilter != NULL); - g_return_if_fail(tfilter->refcount > 0); - - tfilter->handle = handle; -} - -/** - * nm_tc_tfilter_get_parent: - * @tfilter: the #NMTCTfilter - * - * Returns: the parent class - * - * Since: 1.12 - **/ -guint32 -nm_tc_tfilter_get_parent(NMTCTfilter *tfilter) -{ - g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC); - g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC); - - return tfilter->parent; -} - -/** - * nm_tc_tfilter_get_action: - * @tfilter: the #NMTCTfilter - * - * Returns: the action associated with a traffic filter. - * - * Since: 1.12 - **/ -NMTCAction * -nm_tc_tfilter_get_action(NMTCTfilter *tfilter) -{ - g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC); - g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC); - - if (tfilter->action == NULL) - return NULL; - - return tfilter->action; -} - -/** - * nm_tc_tfilter_set_action: - * @tfilter: the #NMTCTfilter - * @action: the action object - * - * Sets the action associated with a traffic filter. - * - * Since: 1.12 - **/ -void -nm_tc_tfilter_set_action(NMTCTfilter *tfilter, NMTCAction *action) -{ - g_return_if_fail(tfilter != NULL); - g_return_if_fail(tfilter->refcount > 0); - - if (action) - nm_tc_action_ref(action); - if (tfilter->action) - nm_tc_action_unref(tfilter->action); - tfilter->action = action; -} - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingTCConfig, PROP_QDISCS, PROP_TFILTERS, ); - -/** - * NMSettingTCConfig: - * - * Linux Traffic Control Settings - * - * Since: 1.12 - */ -struct _NMSettingTCConfig { - NMSetting parent; - GPtrArray *qdiscs; - GPtrArray *tfilters; -}; - -struct _NMSettingTCConfigClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING) - -/*****************************************************************************/ - -/** - * nm_setting_tc_config_get_num_qdiscs: - * @setting: the #NMSettingTCConfig - * - * Returns: the number of configured queueing disciplines - * - * Since: 1.12 - **/ -guint -nm_setting_tc_config_get_num_qdiscs(NMSettingTCConfig *self) -{ - g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), 0); - - return self->qdiscs->len; -} - -/** - * nm_setting_tc_config_get_qdisc: - * @setting: the #NMSettingTCConfig - * @idx: index number of the qdisc to return - * - * Returns: (transfer none): the qdisc at index @idx - * - * Since: 1.12 - **/ -NMTCQdisc * -nm_setting_tc_config_get_qdisc(NMSettingTCConfig *self, guint idx) -{ - g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), NULL); - g_return_val_if_fail(idx < self->qdiscs->len, NULL); - - return self->qdiscs->pdata[idx]; -} - -/** - * nm_setting_tc_config_add_qdisc: - * @setting: the #NMSettingTCConfig - * @qdisc: the qdisc to add - * - * Appends a new qdisc and associated information to the setting. The - * given qdisc is duplicated internally and is not changed by this function. - * If an identical qdisc (considering attributes as well) already exists, the - * qdisc is not added and the function returns %FALSE. - * - * Returns: %TRUE if the qdisc was added; %FALSE if the qdisc was already known. - * - * Since: 1.12 - **/ -gboolean -nm_setting_tc_config_add_qdisc(NMSettingTCConfig *self, NMTCQdisc *qdisc) -{ - guint i; - - g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE); - g_return_val_if_fail(qdisc != NULL, FALSE); - - for (i = 0; i < self->qdiscs->len; i++) { - if (nm_tc_qdisc_equal(self->qdiscs->pdata[i], qdisc)) - return FALSE; - } - - g_ptr_array_add(self->qdiscs, nm_tc_qdisc_dup(qdisc)); - _notify(self, PROP_QDISCS); - return TRUE; -} - -/** - * nm_setting_tc_config_remove_qdisc: - * @setting: the #NMSettingTCConfig - * @idx: index number of the qdisc - * - * Removes the qdisc at index @idx. - * - * Since: 1.12 - **/ -void -nm_setting_tc_config_remove_qdisc(NMSettingTCConfig *self, guint idx) -{ - g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self)); - - g_return_if_fail(idx < self->qdiscs->len); - - g_ptr_array_remove_index(self->qdiscs, idx); - _notify(self, PROP_QDISCS); -} - -/** - * nm_setting_tc_config_remove_qdisc_by_value: - * @setting: the #NMSettingTCConfig - * @qdisc: the qdisc to remove - * - * Removes the first matching qdisc that matches @qdisc. - * - * Returns: %TRUE if the qdisc was found and removed; %FALSE if it was not. - * - * Since: 1.12 - **/ -gboolean -nm_setting_tc_config_remove_qdisc_by_value(NMSettingTCConfig *self, NMTCQdisc *qdisc) -{ - guint i; - - g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE); - g_return_val_if_fail(qdisc != NULL, FALSE); - - for (i = 0; i < self->qdiscs->len; i++) { - if (nm_tc_qdisc_equal(self->qdiscs->pdata[i], qdisc)) { - g_ptr_array_remove_index(self->qdiscs, i); - _notify(self, PROP_QDISCS); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_tc_config_clear_qdiscs: - * @setting: the #NMSettingTCConfig - * - * Removes all configured queueing disciplines. - * - * Since: 1.12 - **/ -void -nm_setting_tc_config_clear_qdiscs(NMSettingTCConfig *self) -{ - g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self)); - - if (self->qdiscs->len != 0) { - g_ptr_array_set_size(self->qdiscs, 0); - _notify(self, PROP_QDISCS); - } -} - -/*****************************************************************************/ -/** - * nm_setting_tc_config_get_num_tfilters: - * @setting: the #NMSettingTCConfig - * - * Returns: the number of configured queueing disciplines - * - * Since: 1.12 - **/ -guint -nm_setting_tc_config_get_num_tfilters(NMSettingTCConfig *self) -{ - g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), 0); - - return self->tfilters->len; -} - -/** - * nm_setting_tc_config_get_tfilter: - * @setting: the #NMSettingTCConfig - * @idx: index number of the tfilter to return - * - * Returns: (transfer none): the tfilter at index @idx - * - * Since: 1.12 - **/ -NMTCTfilter * -nm_setting_tc_config_get_tfilter(NMSettingTCConfig *self, guint idx) -{ - g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), NULL); - g_return_val_if_fail(idx < self->tfilters->len, NULL); - - return self->tfilters->pdata[idx]; -} - -/** - * nm_setting_tc_config_add_tfilter: - * @setting: the #NMSettingTCConfig - * @tfilter: the tfilter to add - * - * Appends a new tfilter and associated information to the setting. The - * given tfilter is duplicated internally and is not changed by this function. - * If an identical tfilter (considering attributes as well) already exists, the - * tfilter is not added and the function returns %FALSE. - * - * Returns: %TRUE if the tfilter was added; %FALSE if the tfilter was already known. - * - * Since: 1.12 - **/ -gboolean -nm_setting_tc_config_add_tfilter(NMSettingTCConfig *self, NMTCTfilter *tfilter) -{ - guint i; - - g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE); - g_return_val_if_fail(tfilter != NULL, FALSE); - - for (i = 0; i < self->tfilters->len; i++) { - if (nm_tc_tfilter_equal(self->tfilters->pdata[i], tfilter)) - return FALSE; - } - - g_ptr_array_add(self->tfilters, nm_tc_tfilter_dup(tfilter)); - _notify(self, PROP_TFILTERS); - return TRUE; -} - -/** - * nm_setting_tc_config_remove_tfilter: - * @setting: the #NMSettingTCConfig - * @idx: index number of the tfilter - * - * Removes the tfilter at index @idx. - * - * Since: 1.12 - **/ -void -nm_setting_tc_config_remove_tfilter(NMSettingTCConfig *self, guint idx) -{ - g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self)); - g_return_if_fail(idx < self->tfilters->len); - - g_ptr_array_remove_index(self->tfilters, idx); - _notify(self, PROP_TFILTERS); -} - -/** - * nm_setting_tc_config_remove_tfilter_by_value: - * @setting: the #NMSettingTCConfig - * @tfilter: the tfilter to remove - * - * Removes the first matching tfilter that matches @tfilter. - * - * Returns: %TRUE if the tfilter was found and removed; %FALSE if it was not. - * - * Since: 1.12 - **/ -gboolean -nm_setting_tc_config_remove_tfilter_by_value(NMSettingTCConfig *self, NMTCTfilter *tfilter) -{ - guint i; - - g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE); - g_return_val_if_fail(tfilter != NULL, FALSE); - - for (i = 0; i < self->tfilters->len; i++) { - if (nm_tc_tfilter_equal(self->tfilters->pdata[i], tfilter)) { - g_ptr_array_remove_index(self->tfilters, i); - _notify(self, PROP_TFILTERS); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_tc_config_clear_tfilters: - * @setting: the #NMSettingTCConfig - * - * Removes all configured queueing disciplines. - * - * Since: 1.12 - **/ -void -nm_setting_tc_config_clear_tfilters(NMSettingTCConfig *self) -{ - g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self)); - - if (self->tfilters->len != 0) { - g_ptr_array_set_size(self->tfilters, 0); - _notify(self, PROP_TFILTERS); - } -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(setting); - guint i; - - if (self->qdiscs->len != 0) { - gs_unref_hashtable GHashTable *ht = NULL; - - ht = g_hash_table_new((GHashFunc) _nm_tc_qdisc_hash, (GEqualFunc) nm_tc_qdisc_equal); - for (i = 0; i < self->qdiscs->len; i++) { - if (!g_hash_table_add(ht, self->qdiscs->pdata[i])) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("there are duplicate TC qdiscs")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_TC_CONFIG_SETTING_NAME, - NM_SETTING_TC_CONFIG_QDISCS); - return FALSE; - } - } - } - - if (self->tfilters->len != 0) { - gs_unref_hashtable GHashTable *ht = NULL; - - ht = g_hash_table_new((GHashFunc) _nm_tc_tfilter_hash, (GEqualFunc) nm_tc_tfilter_equal); - for (i = 0; i < self->tfilters->len; i++) { - if (!g_hash_table_add(ht, self->tfilters->pdata[i])) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("there are duplicate TC filters")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_TC_CONFIG_SETTING_NAME, - NM_SETTING_TC_CONFIG_TFILTERS); - return FALSE; - } - } - } - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingTCConfig *a_tc_config = NM_SETTING_TC_CONFIG(set_a); - NMSettingTCConfig *b_tc_config = NM_SETTING_TC_CONFIG(set_b); - guint i; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TC_CONFIG_QDISCS)) { - if (set_b) { - if (a_tc_config->qdiscs->len != b_tc_config->qdiscs->len) - return FALSE; - for (i = 0; i < a_tc_config->qdiscs->len; i++) { - if (!nm_tc_qdisc_equal(a_tc_config->qdiscs->pdata[i], - b_tc_config->qdiscs->pdata[i])) - return FALSE; - } - } - return TRUE; - } - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TC_CONFIG_TFILTERS)) { - if (set_b) { - if (a_tc_config->tfilters->len != b_tc_config->tfilters->len) - return FALSE; - for (i = 0; i < a_tc_config->tfilters->len; i++) { - if (!nm_tc_tfilter_equal(a_tc_config->tfilters->pdata[i], - b_tc_config->tfilters->pdata[i])) - return FALSE; - } - } - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_tc_config_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/** - * _qdiscs_to_variant: - * @qdiscs: (element-type NMTCQdisc): an array of #NMTCQdisc objects - * - * Utility function to convert a #GPtrArray of #NMTCQdisc objects representing - * TC qdiscs into a #GVariant of type 'aa{sv}' representing an array - * of NetworkManager TC qdiscs. - * - * Returns: (transfer none): a new floating #GVariant representing @qdiscs. - **/ -static GVariant * -_qdiscs_to_variant(GPtrArray *qdiscs) -{ - GVariantBuilder builder; - int i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - - if (qdiscs) { - for (i = 0; i < qdiscs->len; i++) { - NMUtilsNamedValue attrs_static[30]; - gs_free NMUtilsNamedValue *attrs_free = NULL; - const NMUtilsNamedValue * attrs; - NMTCQdisc * qdisc = qdiscs->pdata[i]; - guint length; - GVariantBuilder qdisc_builder; - guint y; - - g_variant_builder_init(&qdisc_builder, G_VARIANT_TYPE_VARDICT); - - g_variant_builder_add(&qdisc_builder, - "{sv}", - "kind", - g_variant_new_string(nm_tc_qdisc_get_kind(qdisc))); - - g_variant_builder_add(&qdisc_builder, - "{sv}", - "handle", - g_variant_new_uint32(nm_tc_qdisc_get_handle(qdisc))); - - g_variant_builder_add(&qdisc_builder, - "{sv}", - "parent", - g_variant_new_uint32(nm_tc_qdisc_get_parent(qdisc))); - - attrs = nm_utils_named_values_from_strdict(qdisc->attributes, - &length, - attrs_static, - &attrs_free); - for (y = 0; y < length; y++) { - g_variant_builder_add(&qdisc_builder, "{sv}", attrs[y].name, attrs[y].value_ptr); - } - - g_variant_builder_add(&builder, "a{sv}", &qdisc_builder); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * _qdiscs_from_variant: - * @value: a #GVariant of type 'aa{sv}' - * - * Utility function to convert a #GVariant representing a list of TC qdiscs - * into a #GPtrArray of * #NMTCQdisc objects. - * - * Returns: (transfer full) (element-type NMTCQdisc): a newly allocated - * #GPtrArray of #NMTCQdisc objects - **/ -static GPtrArray * -_qdiscs_from_variant(GVariant *value) -{ - GPtrArray * qdiscs; - GVariant * qdisc_var; - GVariantIter iter; - GError * error = NULL; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); - - g_variant_iter_init(&iter, value); - qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref); - - while (g_variant_iter_next(&iter, "@a{sv}", &qdisc_var)) { - const char * kind; - guint32 parent; - NMTCQdisc * qdisc; - GVariantIter qdisc_iter; - const char * key; - GVariant * attr_value; - - if (!g_variant_lookup(qdisc_var, "kind", "&s", &kind) - || !g_variant_lookup(qdisc_var, "parent", "u", &parent)) { - //g_warning ("Ignoring invalid qdisc"); - goto next; - } - - qdisc = nm_tc_qdisc_new(kind, parent, &error); - if (!qdisc) { - //g_warning ("Ignoring invalid qdisc: %s", error->message); - g_clear_error(&error); - goto next; - } - - g_variant_iter_init(&qdisc_iter, qdisc_var); - while (g_variant_iter_next(&qdisc_iter, "{&sv}", &key, &attr_value)) { - if (strcmp(key, "kind") == 0 || strcmp(key, "parent") == 0) { - /* Already processed above */ - } else if (strcmp(key, "handle") == 0) { - nm_tc_qdisc_set_handle(qdisc, g_variant_get_uint32(attr_value)); - } else { - nm_tc_qdisc_set_attribute(qdisc, key, attr_value); - } - g_variant_unref(attr_value); - } - - g_ptr_array_add(qdiscs, qdisc); -next: - g_variant_unref(qdisc_var); - } - - return qdiscs; -} - -static GVariant * -tc_qdiscs_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *qdiscs = NULL; - - g_object_get(setting, NM_SETTING_TC_CONFIG_QDISCS, &qdiscs, NULL); - return _qdiscs_to_variant(qdiscs); -} - -static gboolean -tc_qdiscs_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GPtrArray *qdiscs; - - qdiscs = _qdiscs_from_variant(value); - g_object_set(setting, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL); - g_ptr_array_unref(qdiscs); - - return TRUE; -} - -static GVariant * -_action_to_variant(NMTCAction *action) -{ - GVariantBuilder builder; - gs_strfreev char **attrs = nm_tc_action_get_attribute_names(action); - int i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - - g_variant_builder_add(&builder, - "{sv}", - "kind", - g_variant_new_string(nm_tc_action_get_kind(action))); - - for (i = 0; attrs[i]; i++) { - g_variant_builder_add(&builder, - "{sv}", - attrs[i], - nm_tc_action_get_attribute(action, attrs[i])); - } - - return g_variant_builder_end(&builder); -} - -/** - * _tfilters_to_variant: - * @tfilters: (element-type NMTCTfilter): an array of #NMTCTfilter objects - * - * Utility function to convert a #GPtrArray of #NMTCTfilter objects representing - * TC tfilters into a #GVariant of type 'aa{sv}' representing an array - * of NetworkManager TC tfilters. - * - * Returns: (transfer none): a new floating #GVariant representing @tfilters. - **/ -static GVariant * -_tfilters_to_variant(GPtrArray *tfilters) -{ - GVariantBuilder builder; - int i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - - if (tfilters) { - for (i = 0; i < tfilters->len; i++) { - NMTCTfilter * tfilter = tfilters->pdata[i]; - NMTCAction * action = nm_tc_tfilter_get_action(tfilter); - GVariantBuilder tfilter_builder; - - g_variant_builder_init(&tfilter_builder, G_VARIANT_TYPE("a{sv}")); - - g_variant_builder_add(&tfilter_builder, - "{sv}", - "kind", - g_variant_new_string(nm_tc_tfilter_get_kind(tfilter))); - g_variant_builder_add(&tfilter_builder, - "{sv}", - "handle", - g_variant_new_uint32(nm_tc_tfilter_get_handle(tfilter))); - g_variant_builder_add(&tfilter_builder, - "{sv}", - "parent", - g_variant_new_uint32(nm_tc_tfilter_get_parent(tfilter))); - - if (action) { - g_variant_builder_add(&tfilter_builder, - "{sv}", - "action", - _action_to_variant(action)); - } - - g_variant_builder_add(&builder, "a{sv}", &tfilter_builder); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * _tfilters_from_variant: - * @value: a #GVariant of type 'aa{sv}' - * - * Utility function to convert a #GVariant representing a list of TC tfilters - * into a #GPtrArray of * #NMTCTfilter objects. - * - * Returns: (transfer full) (element-type NMTCTfilter): a newly allocated - * #GPtrArray of #NMTCTfilter objects - **/ -static GPtrArray * -_tfilters_from_variant(GVariant *value) -{ - GPtrArray * tfilters; - GVariant * tfilter_var; - GVariantIter iter; - GError * error = NULL; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); - - g_variant_iter_init(&iter, value); - tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref); - - while (g_variant_iter_next(&iter, "@a{sv}", &tfilter_var)) { - NMTCTfilter *tfilter = NULL; - const char * kind; - guint32 handle; - guint32 parent; - NMTCAction * action; - const char * action_kind = NULL; - char * action_key; - GVariantIter action_iter; - GVariant * action_var = NULL; - GVariant * action_val; - - if (!g_variant_lookup(tfilter_var, "kind", "&s", &kind) - || !g_variant_lookup(tfilter_var, "parent", "u", &parent)) { - //g_warning ("Ignoring invalid tfilter"); - goto next; - } - - tfilter = nm_tc_tfilter_new(kind, parent, &error); - if (!tfilter) { - //g_warning ("Ignoring invalid tfilter: %s", error->message); - g_clear_error(&error); - goto next; - } - - if (g_variant_lookup(tfilter_var, "handle", "u", &handle)) - nm_tc_tfilter_set_handle(tfilter, handle); - - action_var = g_variant_lookup_value(tfilter_var, "action", G_VARIANT_TYPE_VARDICT); - - if (action_var) { - if (!g_variant_lookup(action_var, "kind", "&s", &action_kind)) { - //g_warning ("Ignoring tfilter with invalid action"); - goto next; - } - - action = nm_tc_action_new(action_kind, &error); - if (!action) { - //g_warning ("Ignoring tfilter with invalid action: %s", error->message); - g_clear_error(&error); - goto next; - } - - g_variant_iter_init(&action_iter, action_var); - while (g_variant_iter_next(&action_iter, "{&sv}", &action_key, &action_val)) { - if (strcmp(action_key, "kind") != 0) - nm_tc_action_set_attribute(action, action_key, action_val); - g_variant_unref(action_val); - } - - nm_tc_tfilter_set_action(tfilter, action); - nm_tc_action_unref(action); - } - - nm_tc_tfilter_ref(tfilter); - g_ptr_array_add(tfilters, tfilter); -next: - if (tfilter) - nm_tc_tfilter_unref(tfilter); - if (action_var) - g_variant_unref(action_var); - g_variant_unref(tfilter_var); - } - - return tfilters; -} - -static GVariant * -tc_tfilters_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *tfilters = NULL; - - g_object_get(setting, NM_SETTING_TC_CONFIG_TFILTERS, &tfilters, NULL); - return _tfilters_to_variant(tfilters); -} - -static gboolean -tc_tfilters_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - gs_unref_ptrarray GPtrArray *tfilters = NULL; - - tfilters = _tfilters_from_variant(value); - g_object_set(setting, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL); - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object); - - switch (prop_id) { - case PROP_QDISCS: - g_value_take_boxed(value, - _nm_utils_copy_array(self->qdiscs, - (NMUtilsCopyFunc) nm_tc_qdisc_dup, - (GDestroyNotify) nm_tc_qdisc_unref)); - break; - case PROP_TFILTERS: - g_value_take_boxed(value, - _nm_utils_copy_array(self->tfilters, - (NMUtilsCopyFunc) nm_tc_tfilter_dup, - (GDestroyNotify) nm_tc_tfilter_unref)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object); - - switch (prop_id) { - case PROP_QDISCS: - g_ptr_array_unref(self->qdiscs); - self->qdiscs = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) nm_tc_qdisc_dup, - (GDestroyNotify) nm_tc_qdisc_unref); - break; - case PROP_TFILTERS: - g_ptr_array_unref(self->tfilters); - self->tfilters = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) nm_tc_tfilter_dup, - (GDestroyNotify) nm_tc_tfilter_unref); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_tc_config_init(NMSettingTCConfig *self) -{ - self->qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref); - self->tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref); -} - -/** - * nm_setting_tc_config_new: - * - * Creates a new #NMSettingTCConfig object with default values. - * - * Returns: (transfer full): the new empty #NMSettingTCConfig object - * - * Since: 1.12 - **/ -NMSetting * -nm_setting_tc_config_new(void) -{ - return g_object_new(NM_TYPE_SETTING_TC_CONFIG, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object); - - g_ptr_array_unref(self->qdiscs); - g_ptr_array_unref(self->tfilters); - - G_OBJECT_CLASS(nm_setting_tc_config_parent_class)->finalize(object); -} - -static void -nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - - /** - * NMSettingTCConfig:qdiscs: (type GPtrArray(NMTCQdisc)) - * - * Array of TC queueing disciplines. - **/ - /* ---ifcfg-rh--- - * property: qdiscs - * variable: QDISC1(+), QDISC2(+), ... - * description: Queueing disciplines - * example: QDISC1=ingress, QDISC2="root handle 1234: fq_codel" - * ---end--- - */ - obj_properties[PROP_QDISCS] = g_param_spec_boxed(NM_SETTING_TC_CONFIG_QDISCS, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_QDISCS], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = tc_qdiscs_get, - .from_dbus_fcn = tc_qdiscs_set, )); - - /** - * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter)) - * - * Array of TC traffic filters. - **/ - /* ---ifcfg-rh--- - * property: qdiscs - * variable: FILTER1(+), FILTER2(+), ... - * description: Traffic filters - * example: FILTER1="parent ffff: matchall action simple sdata Input", ... - * ---end--- - */ - obj_properties[PROP_TFILTERS] = g_param_spec_boxed( - NM_SETTING_TC_CONFIG_TFILTERS, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_TFILTERS], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = tc_tfilters_get, - .from_dbus_fcn = tc_tfilters_set, )); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_TC_CONFIG, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-tc-config.h b/libnm-core/nm-setting-tc-config.h deleted file mode 100644 index a2bc9a0dae..0000000000 --- a/libnm-core/nm-setting-tc-config.h +++ /dev/null @@ -1,162 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef NM_SETTING_TC_CONFIG_H -#define NM_SETTING_TC_CONFIG_H - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -typedef struct NMTCQdisc NMTCQdisc; - -NM_AVAILABLE_IN_1_12 -GType nm_tc_qdisc_get_type(void); - -NM_AVAILABLE_IN_1_12 -NMTCQdisc *nm_tc_qdisc_new(const char *kind, guint32 parent, GError **error); - -NM_AVAILABLE_IN_1_12 -void nm_tc_qdisc_ref(NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_12 -void nm_tc_qdisc_unref(NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_12 -gboolean nm_tc_qdisc_equal(NMTCQdisc *qdisc, NMTCQdisc *other); - -NM_AVAILABLE_IN_1_12 -NMTCQdisc *nm_tc_qdisc_dup(NMTCQdisc *qdisc); - -NM_AVAILABLE_IN_1_12 -const char *nm_tc_qdisc_get_kind(NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_12 -guint32 nm_tc_qdisc_get_handle(NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_12 -void nm_tc_qdisc_set_handle(NMTCQdisc *qdisc, guint32 handle); -NM_AVAILABLE_IN_1_12 -guint32 nm_tc_qdisc_get_parent(NMTCQdisc *qdisc); - -NM_AVAILABLE_IN_1_18 -const char **nm_tc_qdisc_get_attribute_names(NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_18 -GVariant *nm_tc_qdisc_get_attribute(NMTCQdisc *qdisc, const char *name); -NM_AVAILABLE_IN_1_18 -void nm_tc_qdisc_set_attribute(NMTCQdisc *qdisc, const char *name, GVariant *value); - -typedef struct NMTCAction NMTCAction; - -NM_AVAILABLE_IN_1_12 -GType nm_tc_action_get_type(void); - -NM_AVAILABLE_IN_1_12 -NMTCAction *nm_tc_action_new(const char *kind, GError **error); - -NM_AVAILABLE_IN_1_12 -void nm_tc_action_ref(NMTCAction *action); -NM_AVAILABLE_IN_1_12 -void nm_tc_action_unref(NMTCAction *action); -NM_AVAILABLE_IN_1_12 -gboolean nm_tc_action_equal(NMTCAction *action, NMTCAction *other); - -NM_AVAILABLE_IN_1_12 -NMTCAction *nm_tc_action_dup(NMTCAction *action); - -NM_AVAILABLE_IN_1_12 -const char *nm_tc_action_get_kind(NMTCAction *action); - -NM_AVAILABLE_IN_1_12 -char **nm_tc_action_get_attribute_names(NMTCAction *action); -NM_AVAILABLE_IN_1_12 -GVariant *nm_tc_action_get_attribute(NMTCAction *action, const char *name); -NM_AVAILABLE_IN_1_12 -void nm_tc_action_set_attribute(NMTCAction *action, const char *name, GVariant *value); - -typedef struct NMTCTfilter NMTCTfilter; - -NM_AVAILABLE_IN_1_12 -GType nm_tc_tfilter_get_type(void); - -NM_AVAILABLE_IN_1_12 -NMTCTfilter *nm_tc_tfilter_new(const char *kind, guint32 parent, GError **error); - -NM_AVAILABLE_IN_1_12 -void nm_tc_tfilter_ref(NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 -void nm_tc_tfilter_unref(NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 -gboolean nm_tc_tfilter_equal(NMTCTfilter *tfilter, NMTCTfilter *other); - -NM_AVAILABLE_IN_1_12 -NMTCTfilter *nm_tc_tfilter_dup(NMTCTfilter *tfilter); - -NM_AVAILABLE_IN_1_12 -const char *nm_tc_tfilter_get_kind(NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 -guint32 nm_tc_tfilter_get_handle(NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 -void nm_tc_tfilter_set_handle(NMTCTfilter *tfilter, guint32 handle); -NM_AVAILABLE_IN_1_12 -guint32 nm_tc_tfilter_get_parent(NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 -NMTCAction *nm_tc_tfilter_get_action(NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 -void nm_tc_tfilter_set_action(NMTCTfilter *tfilter, NMTCAction *action); - -#define NM_TYPE_SETTING_TC_CONFIG (nm_setting_tc_config_get_type()) -#define NM_SETTING_TC_CONFIG(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_TC_CONFIG, NMSettingTCConfig)) -#define NM_SETTING_TC_CONFIG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_TC_CONFIG, NMSettingTCConfigClass)) -#define NM_IS_SETTING_TC_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_TC_CONFIG)) -#define NM_IS_SETTING_TC_CONFIG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_TC_CONFIG)) -#define NM_SETTING_TC_CONFIG_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_TC_CONFIG, NMSettingTCConfigClass)) - -#define NM_SETTING_TC_CONFIG_SETTING_NAME "tc" - -#define NM_SETTING_TC_CONFIG_QDISCS "qdiscs" -#define NM_SETTING_TC_CONFIG_TFILTERS "tfilters" - -typedef struct _NMSettingTCConfigClass NMSettingTCConfigClass; - -GType nm_setting_tc_config_get_type(void); - -NM_AVAILABLE_IN_1_12 -NMSetting *nm_setting_tc_config_new(void); - -NM_AVAILABLE_IN_1_12 -guint nm_setting_tc_config_get_num_qdiscs(NMSettingTCConfig *setting); -NM_AVAILABLE_IN_1_12 -NMTCQdisc *nm_setting_tc_config_get_qdisc(NMSettingTCConfig *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_tc_config_add_qdisc(NMSettingTCConfig *setting, NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_12 -void nm_setting_tc_config_remove_qdisc(NMSettingTCConfig *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_tc_config_remove_qdisc_by_value(NMSettingTCConfig *setting, NMTCQdisc *qdisc); -NM_AVAILABLE_IN_1_12 -void nm_setting_tc_config_clear_qdiscs(NMSettingTCConfig *setting); - -NM_AVAILABLE_IN_1_12 -guint nm_setting_tc_config_get_num_tfilters(NMSettingTCConfig *setting); -NM_AVAILABLE_IN_1_12 -NMTCTfilter *nm_setting_tc_config_get_tfilter(NMSettingTCConfig *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_tc_config_add_tfilter(NMSettingTCConfig *setting, NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 -void nm_setting_tc_config_remove_tfilter(NMSettingTCConfig *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_tc_config_remove_tfilter_by_value(NMSettingTCConfig *setting, - NMTCTfilter * tfilter); -NM_AVAILABLE_IN_1_12 -void nm_setting_tc_config_clear_tfilters(NMSettingTCConfig *setting); - -G_END_DECLS - -#endif /* NM_SETTING_TC_CONFIG_H */ diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c deleted file mode 100644 index ea8115a74a..0000000000 --- a/libnm-core/nm-setting-team-port.c +++ /dev/null @@ -1,685 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - * Copyright (C) 2013 Jiri Pirko - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-team-port.h" - -#include -#include - -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-team-utils.h" - -/** - * SECTION:nm-setting-team-port - * @short_description: Describes connection properties for team ports - * - * The #NMSettingTeamPort object is a #NMSetting subclass that describes - * optional properties that apply to team ports. - **/ - -/*****************************************************************************/ - -static GParamSpec *obj_properties[_NM_TEAM_ATTRIBUTE_PORT_NUM] = { - NULL, -}; - -typedef struct { - NMTeamSetting *team_setting; -} NMSettingTeamPortPrivate; - -G_DEFINE_TYPE(NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING) - -#define NM_SETTING_TEAM_PORT_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortPrivate)) - -/*****************************************************************************/ - -NMTeamSetting * -_nm_setting_team_port_get_team_setting(NMSettingTeamPort *setting) -{ - return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting; -} - -/*****************************************************************************/ - -#define _maybe_changed(self, changed) \ - nm_team_setting_maybe_changed(NM_SETTING(_NM_ENSURE_TYPE(NMSettingTeamPort *, self)), \ - (const GParamSpec *const *) obj_properties, \ - (changed)) - -#define _maybe_changed_with_assert(self, changed) \ - G_STMT_START \ - { \ - if (!_maybe_changed((self), (changed))) \ - nm_assert_not_reached(); \ - } \ - G_STMT_END - -/*****************************************************************************/ - -/** - * nm_setting_team_port_get_config: - * @setting: the #NMSettingTeamPort - * - * Returns: the #NMSettingTeamPort:config property of the setting - **/ -const char * -nm_setting_team_port_get_config(NMSettingTeamPort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), NULL); - - return nm_team_setting_config_get(NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting); -} - -/** - * nm_setting_team_port_get_queue_id: - * @setting: the #NMSettingTeamPort - * - * Returns: the #NMSettingTeamPort:queue_id property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_port_get_queue_id(NMSettingTeamPort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), -1); - - return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.queue_id; -} - -/** - * nm_setting_team_port_get_prio: - * @setting: the #NMSettingTeamPort - * - * Returns: the #NMSettingTeamPort:prio property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_port_get_prio(NMSettingTeamPort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), 0); - - return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.prio; -} - -/** - * nm_setting_team_port_get_sticky: - * @setting: the #NMSettingTeamPort - * - * Returns: the #NMSettingTeamPort:sticky property of the setting - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_port_get_sticky(NMSettingTeamPort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), FALSE); - - return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.sticky; -} - -/** - * nm_setting_team_port_get_lacp_prio: - * @setting: the #NMSettingTeamPort - * - * Returns: the #NMSettingTeamPort:lacp-prio property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_port_get_lacp_prio(NMSettingTeamPort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), 0); - - return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.lacp_prio; -} - -/** - * nm_setting_team_port_get_lacp_key: - * @setting: the #NMSettingTeamPort - * - * Returns: the #NMSettingTeamPort:lacp-key property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_port_get_lacp_key(NMSettingTeamPort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), 0); - - return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.lacp_key; -} - -/** - * nm_setting_team_port_get_num_link_watchers: - * @setting: the #NMSettingTeamPort - * - * Returns: the number of configured link watchers - * - * Since: 1.12 - **/ -guint -nm_setting_team_port_get_num_link_watchers(NMSettingTeamPort *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), 0); - - return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.link_watchers->len; -} - -/** - * nm_setting_team_port_get_link_watcher: - * @setting: the #NMSettingTeamPort - * @idx: index number of the link watcher to return - * - * Returns: (transfer none): the link watcher at index @idx. - * - * Since: 1.12 - **/ -NMTeamLinkWatcher * -nm_setting_team_port_get_link_watcher(NMSettingTeamPort *setting, guint idx) -{ - NMSettingTeamPortPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), NULL); - - priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); - - g_return_val_if_fail(idx < priv->team_setting->d.link_watchers->len, NULL); - - return priv->team_setting->d.link_watchers->pdata[idx]; -} - -/** - * nm_setting_team_port_add_link_watcher: - * @setting: the #NMSettingTeamPort - * @link_watcher: the link watcher to add - * - * Appends a new link watcher to the setting. - * - * Returns: %TRUE if the link watcher is added; %FALSE if an identical link - * watcher was already there. - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_port_add_link_watcher(NMSettingTeamPort *setting, NMTeamLinkWatcher *link_watcher) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), FALSE); - g_return_val_if_fail(link_watcher != NULL, FALSE); - - return _maybe_changed(setting, - nm_team_setting_value_link_watchers_add( - NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting, - link_watcher)); -} - -/** - * nm_setting_team_port_remove_link_watcher: - * @setting: the #NMSettingTeamPort - * @idx: index number of the link watcher to remove - * - * Removes the link watcher at index #idx. - * - * Since: 1.12 - **/ -void -nm_setting_team_port_remove_link_watcher(NMSettingTeamPort *setting, guint idx) -{ - NMSettingTeamPortPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_TEAM_PORT(setting)); - - priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); - - g_return_if_fail(idx < priv->team_setting->d.link_watchers->len); - - _maybe_changed_with_assert(setting, - nm_team_setting_value_link_watchers_remove(priv->team_setting, idx)); -} - -/** - * nm_setting_team_port_remove_link_watcher_by_value: - * @setting: the #NMSettingTeamPort - * @link_watcher: the link watcher to remove - * - * Removes the link watcher entry matching link_watcher. - * - * Returns: %TRUE if the link watcher was found and removed, %FALSE otherwise. - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_port_remove_link_watcher_by_value(NMSettingTeamPort *setting, - NMTeamLinkWatcher *link_watcher) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), FALSE); - g_return_val_if_fail(link_watcher, FALSE); - - return _maybe_changed(setting, - nm_team_setting_value_link_watchers_remove_by_value( - NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting, - link_watcher)); -} - -/** - * nm_setting_team_port_clear_link_watchers: - * @setting: the #NMSettingTeamPort - * - * Removes all configured link watchers. - * - * Since: 1.12 - **/ -void -nm_setting_team_port_clear_link_watchers(NMSettingTeamPort *setting) -{ - g_return_if_fail(NM_IS_SETTING_TEAM_PORT(setting)); - - _maybe_changed(setting, - nm_team_setting_value_link_watchers_set_list( - NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting, - NULL, - 0)); -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); - - if (connection) { - NMSettingConnection *s_con; - const char * slave_type; - - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("missing setting")); - g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); - return FALSE; - } - - slave_type = nm_setting_connection_get_slave_type(s_con); - if (slave_type && strcmp(slave_type, NM_SETTING_TEAM_SETTING_NAME)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting must have the slave-type set to '%s'. " - "Instead it is '%s'"), - NM_SETTING_TEAM_PORT_SETTING_NAME, - NM_SETTING_TEAM_SETTING_NAME, - slave_type); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_SLAVE_TYPE); - return FALSE; - } - } - - if (!nm_team_setting_verify(priv->team_setting, error)) - return FALSE; - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingTeamPortPrivate *a_priv; - NMSettingTeamPortPrivate *b_priv; - - if (nm_streq(sett_info->property_infos[property_idx].name, - NM_SETTING_TEAM_PORT_LINK_WATCHERS)) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) - return NM_TERNARY_DEFAULT; - if (!set_b) - return TRUE; - a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(set_a); - b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(set_b); - return nm_team_link_watchers_equal(a_priv->team_setting->d.link_watchers, - b_priv->team_setting->d.link_watchers, - TRUE); - } - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_PORT_CONFIG)) { - if (set_b) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) { - /* If we are trying to match a connection in order to assume it (and thus - * @flags contains INFERRABLE), use the "relaxed" matching for team - * configuration. Otherwise, for all other purposes (including connection - * comparison before an update), resort to the default string comparison. */ - return TRUE; - } - - a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(set_a); - b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(set_b); - - return nm_streq0(nm_team_setting_config_get(a_priv->team_setting), - nm_team_setting_config_get(b_priv->team_setting)); - } - - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_team_port_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -static void -duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) -{ - _maybe_changed(NM_SETTING_TEAM_PORT(dst), - nm_team_setting_reset(NM_SETTING_TEAM_PORT_GET_PRIVATE(dst)->team_setting, - NM_SETTING_TEAM_PORT_GET_PRIVATE(src)->team_setting)); -} - -static gboolean -init_from_dbus(NMSetting * setting, - GHashTable * keys, - GVariant * setting_dict, - GVariant * connection_dict, - guint /* NMSettingParseFlags */ parse_flags, - GError ** error) -{ - guint32 changed = 0; - gboolean success; - - success = - nm_team_setting_reset_from_dbus(NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting, - setting_dict, - keys, - &changed, - parse_flags, - error); - _maybe_changed(NM_SETTING_TEAM_PORT(setting), changed); - return success; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingTeamPort * setting = NM_SETTING_TEAM_PORT(object); - NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); - - switch (prop_id) { - case NM_TEAM_ATTRIBUTE_CONFIG: - g_value_set_string(value, nm_team_setting_config_get(priv->team_setting)); - break; - case NM_TEAM_ATTRIBUTE_PORT_STICKY: - g_value_set_boolean(value, nm_team_setting_value_get_bool(priv->team_setting, prop_id)); - break; - case NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID: - case NM_TEAM_ATTRIBUTE_PORT_PRIO: - case NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO: - case NM_TEAM_ATTRIBUTE_PORT_LACP_KEY: - g_value_set_int(value, nm_team_setting_value_get_int32(priv->team_setting, prop_id)); - break; - case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: - g_value_take_boxed(value, - _nm_utils_copy_array(priv->team_setting->d.link_watchers, - (NMUtilsCopyFunc) _nm_team_link_watcher_ref, - (GDestroyNotify) nm_team_link_watcher_unref)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingTeamPort * setting = NM_SETTING_TEAM_PORT(object); - NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); - guint32 changed; - const GPtrArray * v_ptrarr; - - switch (prop_id) { - case NM_TEAM_ATTRIBUTE_CONFIG: - changed = nm_team_setting_config_set(priv->team_setting, g_value_get_string(value)); - break; - case NM_TEAM_ATTRIBUTE_PORT_STICKY: - changed = - nm_team_setting_value_set_bool(priv->team_setting, prop_id, g_value_get_boolean(value)); - break; - case NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID: - case NM_TEAM_ATTRIBUTE_PORT_PRIO: - case NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO: - case NM_TEAM_ATTRIBUTE_PORT_LACP_KEY: - changed = - nm_team_setting_value_set_int32(priv->team_setting, prop_id, g_value_get_int(value)); - break; - case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: - v_ptrarr = g_value_get_boxed(value); - changed = nm_team_setting_value_link_watchers_set_list( - priv->team_setting, - v_ptrarr ? (const NMTeamLinkWatcher *const *) v_ptrarr->pdata : NULL, - v_ptrarr ? v_ptrarr->len : 0u); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - return; - } - - _maybe_changed(setting, changed & ~(((guint32) 1) << prop_id)); -} - -/*****************************************************************************/ - -static void -nm_setting_team_port_init(NMSettingTeamPort *setting) -{ - NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); - - priv->team_setting = nm_team_setting_new(TRUE, NULL); -} - -/** - * nm_setting_team_port_new: - * - * Creates a new #NMSettingTeamPort object with default values. - * - * Returns: (transfer full): the new empty #NMSettingTeamPort object - **/ -NMSetting * -nm_setting_team_port_new(void) -{ - return g_object_new(NM_TYPE_SETTING_TEAM_PORT, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(object); - - nm_team_setting_free(priv->team_setting); - - G_OBJECT_CLASS(nm_setting_team_port_parent_class)->finalize(object); -} - -static void -nm_setting_team_port_class_init(NMSettingTeamPortClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingTeamPortPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - setting_class->duplicate_copy_properties = duplicate_copy_properties; - setting_class->init_from_dbus = init_from_dbus; - - /** - * NMSettingTeamPort:config: - * - * The JSON configuration for the team port. The property should contain raw - * JSON configuration data suitable for teamd, because the value is passed - * directly to teamd. If not specified, the default configuration is - * used. See man teamd.conf for the format details. - **/ - /* ---ifcfg-rh--- - * property: config - * variable: TEAM_PORT_CONFIG - * description: Team port configuration in JSON. See man teamd.conf for details. - * ---end--- - */ - obj_properties[NM_TEAM_ATTRIBUTE_CONFIG] = g_param_spec_string( - NM_SETTING_TEAM_PORT_CONFIG, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_CONFIG], - &nm_sett_info_propert_type_team_s); - - /** - * NMSettingTeamPort:queue-id: - * - * Corresponds to the teamd ports.PORTIFNAME.queue_id. - * When set to -1 means the parameter is skipped from the json config. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID] = - g_param_spec_int(NM_SETTING_TEAM_PORT_QUEUE_ID, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeamPort:prio: - * - * Corresponds to the teamd ports.PORTIFNAME.prio. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_PORT_PRIO] = - g_param_spec_int(NM_SETTING_TEAM_PORT_PRIO, - "", - "", - G_MININT32, - G_MAXINT32, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_PORT_PRIO], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeamPort:sticky: - * - * Corresponds to the teamd ports.PORTIFNAME.sticky. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_PORT_STICKY] = - g_param_spec_boolean(NM_SETTING_TEAM_PORT_STICKY, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_PORT_STICKY], - &nm_sett_info_propert_type_team_b); - - /** - * NMSettingTeamPort:lacp-prio: - * - * Corresponds to the teamd ports.PORTIFNAME.lacp_prio. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO] = - g_param_spec_int(NM_SETTING_TEAM_PORT_LACP_PRIO, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeamPort:lacp-key: - * - * Corresponds to the teamd ports.PORTIFNAME.lacp_key. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_KEY] = - g_param_spec_int(NM_SETTING_TEAM_PORT_LACP_KEY, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_KEY], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeamPort:link-watchers: (type GPtrArray(NMTeamLinkWatcher)) - * - * Link watchers configuration for the connection: each link watcher is - * defined by a dictionary, whose keys depend upon the selected link - * watcher. Available link watchers are 'ethtool', 'nsna_ping' and - * 'arp_ping' and it is specified in the dictionary with the key 'name'. - * Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; - * nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; - * arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', - * 'validate-inactive', 'send-always'. See teamd.conf man for more details. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS] = - g_param_spec_boxed(NM_SETTING_TEAM_PORT_LINK_WATCHERS, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], - &nm_sett_info_propert_type_team_link_watchers); - - g_object_class_install_properties(object_class, G_N_ELEMENTS(obj_properties), obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_TEAM_PORT, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-team-port.h b/libnm-core/nm-setting-team-port.h deleted file mode 100644 index 4d4d9bdca0..0000000000 --- a/libnm-core/nm-setting-team-port.h +++ /dev/null @@ -1,89 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2013 Jiri Pirko - */ - -#ifndef __NM_SETTING_TEAM_PORT_H__ -#define __NM_SETTING_TEAM_PORT_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" -#include "nm-setting-team.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_TEAM_PORT (nm_setting_team_port_get_type()) -#define NM_SETTING_TEAM_PORT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPort)) -#define NM_SETTING_TEAM_PORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortClass)) -#define NM_IS_SETTING_TEAM_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_TEAM_PORT)) -#define NM_IS_SETTING_TEAM_PORT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_TEAM_PORT)) -#define NM_SETTING_TEAM_PORT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortClass)) - -#define NM_SETTING_TEAM_PORT_SETTING_NAME "team-port" - -#define NM_SETTING_TEAM_PORT_CONFIG "config" -#define NM_SETTING_TEAM_PORT_QUEUE_ID "queue-id" -#define NM_SETTING_TEAM_PORT_PRIO "prio" -#define NM_SETTING_TEAM_PORT_STICKY "sticky" -#define NM_SETTING_TEAM_PORT_LACP_PRIO "lacp-prio" -#define NM_SETTING_TEAM_PORT_LACP_KEY "lacp-key" -#define NM_SETTING_TEAM_PORT_LINK_WATCHERS "link-watchers" - -#define NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT -1 -#define NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT 255 - -/** - * NMSettingTeamPort: - * - * Team Port Settings - */ -struct _NMSettingTeamPort { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingTeamPortClass; - -GType nm_setting_team_port_get_type(void); - -NMSetting *nm_setting_team_port_new(void); - -const char *nm_setting_team_port_get_config(NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_port_get_queue_id(NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_port_get_prio(NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_port_get_sticky(NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_port_get_lacp_prio(NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_port_get_lacp_key(NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_12 -guint nm_setting_team_port_get_num_link_watchers(NMSettingTeamPort *setting); -NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_setting_team_port_get_link_watcher(NMSettingTeamPort *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_port_add_link_watcher(NMSettingTeamPort *setting, - NMTeamLinkWatcher *link_watcher); -NM_AVAILABLE_IN_1_12 -void nm_setting_team_port_remove_link_watcher(NMSettingTeamPort *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_port_remove_link_watcher_by_value(NMSettingTeamPort *setting, - NMTeamLinkWatcher *link_watcher); -NM_AVAILABLE_IN_1_12 -void nm_setting_team_port_clear_link_watchers(NMSettingTeamPort *setting); -G_END_DECLS - -#endif /* __NM_SETTING_TEAM_PORT_H__ */ diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c deleted file mode 100644 index f89a3031f3..0000000000 --- a/libnm-core/nm-setting-team.c +++ /dev/null @@ -1,1818 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - * Copyright (C) 2013 Jiri Pirko - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-team.h" - -#include - -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-team-utils.h" -#include "nm-connection-private.h" - -/** - * SECTION:nm-setting-team - * @short_description: Describes connection properties for teams - * - * The #NMSettingTeam object is a #NMSetting subclass that describes properties - * necessary for team connections. - **/ - -/***************************************************************************** - * NMTeamLinkWatcher - *****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMTeamLinkWatcher, - nm_team_link_watcher, - _nm_team_link_watcher_ref, - nm_team_link_watcher_unref) - -typedef enum { - LINK_WATCHER_ETHTOOL = 0, - LINK_WATCHER_NSNA_PING = 1, - LINK_WATCHER_ARP_PING = 2, -} LinkWatcherTypes; - -static const char *_link_watcher_name[] = {[LINK_WATCHER_ETHTOOL] = NM_TEAM_LINK_WATCHER_ETHTOOL, - [LINK_WATCHER_NSNA_PING] = - NM_TEAM_LINK_WATCHER_NSNA_PING, - [LINK_WATCHER_ARP_PING] = NM_TEAM_LINK_WATCHER_ARP_PING}; - -struct NMTeamLinkWatcher { - int ref_count; - - guint8 type; /* LinkWatcherTypes */ - - union { - struct { - int delay_up; - int delay_down; - } ethtool; - struct { - const char *target_host; - int init_wait; - int interval; - int missed_max; - } nsna_ping; - struct { - const char * target_host; - const char * source_host; - int init_wait; - int interval; - int missed_max; - int vlanid; - NMTeamLinkWatcherArpPingFlags flags; - } arp_ping; - }; -}; - -#define _CHECK_WATCHER_VOID(watcher) \ - G_STMT_START \ - { \ - g_return_if_fail(watcher != NULL); \ - g_return_if_fail(watcher->ref_count > 0); \ - nm_assert(watcher->type <= LINK_WATCHER_ARP_PING); \ - } \ - G_STMT_END - -#define _CHECK_WATCHER(watcher, err_val) \ - G_STMT_START \ - { \ - g_return_val_if_fail(watcher != NULL, err_val); \ - g_return_val_if_fail(watcher->ref_count > 0, err_val); \ - nm_assert(watcher->type <= LINK_WATCHER_ARP_PING); \ - } \ - G_STMT_END - -/** - * nm_team_link_watcher_new_ethtool: - * @delay_up: delay_up value - * @delay_down: delay_down value - * @error: this call never fails, so this var is not used but kept for format - * consistency with the link_watcher constructors of other type - * - * Creates a new ethtool #NMTeamLinkWatcher object - * - * Returns: (transfer full): the new #NMTeamLinkWatcher object - * - * Since: 1.12 - **/ -NMTeamLinkWatcher * -nm_team_link_watcher_new_ethtool(int delay_up, int delay_down, GError **error) -{ - NMTeamLinkWatcher *watcher; - const char * val_fail = NULL; - - if (delay_up < 0 || !_NM_INT_LE_MAXINT32(delay_up)) - val_fail = "delay-up"; - if (delay_down < 0 || !_NM_INT_LE_MAXINT32(delay_down)) - val_fail = "delay-down"; - if (val_fail) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("%s is out of range [0, %d]"), - val_fail, - G_MAXINT32); - return NULL; - } - - NM_PRAGMA_WARNING_DISABLE("-Warray-bounds") - - watcher = g_malloc(nm_offsetofend(NMTeamLinkWatcher, ethtool)); - - watcher->ref_count = 1; - watcher->type = LINK_WATCHER_ETHTOOL; - watcher->ethtool.delay_up = delay_up; - watcher->ethtool.delay_down = delay_down; - - NM_PRAGMA_WARNING_REENABLE - - return watcher; -} - -/** - * nm_team_link_watcher_new_nsna_ping: - * @init_wait: init_wait value - * @interval: interval value - * @missed_max: missed_max value - * @target_host: the host name or the ipv6 address that will be used as - * target address in the NS packet - * @error: (out) (allow-none): location to store the error on failure - * - * Creates a new nsna_ping #NMTeamLinkWatcher object - * - * Returns: (transfer full): the new #NMTeamLinkWatcher object, or %NULL on error - * - * Since: 1.12 - **/ -NMTeamLinkWatcher * -nm_team_link_watcher_new_nsna_ping(int init_wait, - int interval, - int missed_max, - const char *target_host, - GError ** error) -{ - NMTeamLinkWatcher *watcher; - const char * val_fail = NULL; - char * str; - gsize l_target_host; - - if (!target_host) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Missing target-host in nsna_ping link watcher")); - return NULL; - } - - if (strpbrk(target_host, " \\/\t=\"\'")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("target-host '%s' contains invalid characters"), - target_host); - return NULL; - } - - if (init_wait < 0 || !_NM_INT_LE_MAXINT32(init_wait)) - val_fail = "init-wait"; - if (interval < 0 || !_NM_INT_LE_MAXINT32(interval)) - val_fail = "interval"; - if (missed_max < 0 || !_NM_INT_LE_MAXINT32(missed_max)) - val_fail = "missed-max"; - if (val_fail) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("%s is out of range [0, %d]"), - val_fail, - G_MAXINT32); - return NULL; - } - - l_target_host = strlen(target_host) + 1; - - watcher = g_malloc(nm_offsetofend(NMTeamLinkWatcher, nsna_ping) + l_target_host); - - watcher->ref_count = 1; - watcher->type = LINK_WATCHER_NSNA_PING; - watcher->nsna_ping.init_wait = init_wait; - watcher->nsna_ping.interval = interval; - watcher->nsna_ping.missed_max = missed_max; - - str = &((char *) watcher)[nm_offsetofend(NMTeamLinkWatcher, nsna_ping)]; - watcher->nsna_ping.target_host = str; - memcpy(str, target_host, l_target_host); - - return watcher; -} - -/** - * nm_team_link_watcher_new_arp_ping: - * @init_wait: init_wait value - * @interval: interval value - * @missed_max: missed_max value - * @target_host: the host name or the ip address that will be used as destination - * address in the arp request - * @source_host: the host name or the ip address that will be used as source - * address in the arp request - * @flags: the watcher #NMTeamLinkWatcherArpPingFlags - * @error: (out) (allow-none): location to store the error on failure - * - * Creates a new arp_ping #NMTeamLinkWatcher object - * - * Returns: (transfer full): the new #NMTeamLinkWatcher object, or %NULL on error - * - * Since: 1.12 - **/ -NMTeamLinkWatcher * -nm_team_link_watcher_new_arp_ping(int init_wait, - int interval, - int missed_max, - const char * target_host, - const char * source_host, - NMTeamLinkWatcherArpPingFlags flags, - GError ** error) -{ - return nm_team_link_watcher_new_arp_ping2(init_wait, - interval, - missed_max, - -1, - target_host, - source_host, - flags, - error); -} - -/** - * nm_team_link_watcher_new_arp_ping2: - * @init_wait: init_wait value - * @interval: interval value - * @missed_max: missed_max value - * @vlanid: vlanid value - * @target_host: the host name or the ip address that will be used as destination - * address in the arp request - * @source_host: the host name or the ip address that will be used as source - * address in the arp request - * @flags: the watcher #NMTeamLinkWatcherArpPingFlags - * @error: (out) (allow-none): location to store the error on failure - * - * Creates a new arp_ping #NMTeamLinkWatcher object - * - * Returns: (transfer full): the new #NMTeamLinkWatcher object, or %NULL on error - * - * Since: 1.16 - **/ -NMTeamLinkWatcher * -nm_team_link_watcher_new_arp_ping2(int init_wait, - int interval, - int missed_max, - int vlanid, - const char * target_host, - const char * source_host, - NMTeamLinkWatcherArpPingFlags flags, - GError ** error) -{ - NMTeamLinkWatcher *watcher; - const char * val_fail = NULL; - char * str; - gsize l_target_host; - gsize l_source_host; - - if (!target_host || !source_host) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Missing %s in arp_ping link watcher"), - target_host ? "source-host" : "target-host"); - return NULL; - } - - if (strpbrk(target_host, " \\/\t=\"\'")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("target-host '%s' contains invalid characters"), - target_host); - return NULL; - } - - if (strpbrk(source_host, " \\/\t=\"\'")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("source-host '%s' contains invalid characters"), - source_host); - return NULL; - } - - else if (init_wait < 0 || !_NM_INT_LE_MAXINT32(init_wait)) - val_fail = "init-wait"; - else if (interval < 0 || !_NM_INT_LE_MAXINT32(interval)) - val_fail = "interval"; - else if (missed_max < 0 || !_NM_INT_LE_MAXINT32(missed_max)) - val_fail = "missed-max"; - if (val_fail) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("%s is out of range [0, %d]"), - val_fail, - G_MAXINT32); - return NULL; - } - - if (vlanid < -1 || vlanid > 4094) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("vlanid is out of range [-1, 4094]")); - return NULL; - } - - l_target_host = strlen(target_host) + 1; - l_source_host = strlen(source_host) + 1; - - watcher = g_malloc(nm_offsetofend(NMTeamLinkWatcher, arp_ping) + l_target_host + l_source_host); - - watcher->ref_count = 1; - watcher->type = LINK_WATCHER_ARP_PING; - watcher->arp_ping.init_wait = init_wait; - watcher->arp_ping.interval = interval; - watcher->arp_ping.missed_max = missed_max; - watcher->arp_ping.flags = flags; - watcher->arp_ping.vlanid = vlanid; - - str = &((char *) watcher)[nm_offsetofend(NMTeamLinkWatcher, arp_ping)]; - watcher->arp_ping.target_host = str; - memcpy(str, target_host, l_target_host); - - str += l_target_host; - watcher->arp_ping.source_host = str; - memcpy(str, source_host, l_source_host); - - return watcher; -} - -NMTeamLinkWatcher * -_nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, NULL); - - g_atomic_int_inc(&watcher->ref_count); - return watcher; -} - -/** - * nm_team_link_watcher_ref: - * @watcher: the #NMTeamLinkWatcher - * - * Increases the reference count of the object. - * - * Since: 1.12 - **/ -void -nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher) -{ - _nm_team_link_watcher_ref(watcher); -} - -/** - * nm_team_link_watcher_unref: - * @watcher: the #NMTeamLinkWatcher - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - * - * Since: 1.12 - **/ -void -nm_team_link_watcher_unref(NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER_VOID(watcher); - - if (g_atomic_int_dec_and_test(&watcher->ref_count)) - g_free(watcher); -} - -int -nm_team_link_watcher_cmp(const NMTeamLinkWatcher *watcher, const NMTeamLinkWatcher *other) -{ - NM_CMP_SELF(watcher, other); - - NM_CMP_FIELD(watcher, other, type); - - switch (watcher->type) { - case LINK_WATCHER_ETHTOOL: - NM_CMP_FIELD(watcher, other, ethtool.delay_up); - NM_CMP_FIELD(watcher, other, ethtool.delay_down); - break; - case LINK_WATCHER_NSNA_PING: - NM_CMP_FIELD_STR(watcher, other, nsna_ping.target_host); - NM_CMP_FIELD(watcher, other, nsna_ping.init_wait); - NM_CMP_FIELD(watcher, other, nsna_ping.interval); - NM_CMP_FIELD(watcher, other, nsna_ping.missed_max); - break; - case LINK_WATCHER_ARP_PING: - NM_CMP_FIELD_STR(watcher, other, arp_ping.target_host); - NM_CMP_FIELD_STR(watcher, other, arp_ping.source_host); - NM_CMP_FIELD(watcher, other, arp_ping.init_wait); - NM_CMP_FIELD(watcher, other, arp_ping.interval); - NM_CMP_FIELD(watcher, other, arp_ping.missed_max); - NM_CMP_FIELD(watcher, other, arp_ping.vlanid); - NM_CMP_FIELD(watcher, other, arp_ping.flags); - break; - } - return 0; -} - -/** - * nm_team_link_watcher_equal: - * @watcher: the #NMTeamLinkWatcher - * @other: the #NMTeamLinkWatcher to compare @watcher to. - * - * Determines if two #NMTeamLinkWatcher objects contain the same values - * in all the properties. - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - * - * Since: 1.12 - **/ -gboolean -nm_team_link_watcher_equal(const NMTeamLinkWatcher *watcher, const NMTeamLinkWatcher *other) -{ - return nm_team_link_watcher_cmp(watcher, other) == 0; -} - -static int -_team_link_watchers_cmp_p_with_data(gconstpointer data_a, gconstpointer data_b, gpointer user_data) -{ - return nm_team_link_watcher_cmp(*((const NMTeamLinkWatcher *const *) data_a), - *((const NMTeamLinkWatcher *const *) data_b)); -} - -int -nm_team_link_watchers_cmp(const NMTeamLinkWatcher *const *a, - const NMTeamLinkWatcher *const *b, - gsize len, - gboolean ignore_order) -{ - gs_free const NMTeamLinkWatcher **a_free = NULL; - gs_free const NMTeamLinkWatcher **b_free = NULL; - guint i; - - if (ignore_order && len > 1) { - a = nm_memdup_maybe_a(200, a, len * sizeof(*a), &a_free); - b = nm_memdup_maybe_a(200, b, len * sizeof(*b), &b_free); - g_qsort_with_data((gpointer) a, len, sizeof(*a), _team_link_watchers_cmp_p_with_data, NULL); - g_qsort_with_data((gpointer) b, len, sizeof(*b), _team_link_watchers_cmp_p_with_data, NULL); - } - for (i = 0; i < len; i++) { - NM_CMP_RETURN(nm_team_link_watcher_cmp(a[i], b[i])); - } - return 0; -} - -gboolean -nm_team_link_watchers_equal(const GPtrArray *a, const GPtrArray *b, gboolean ignore_order) -{ - return a == b - || (a && b && a->len == b->len - && (nm_team_link_watchers_cmp((const NMTeamLinkWatcher *const *) a->pdata, - (const NMTeamLinkWatcher *const *) b->pdata, - a->len, - ignore_order) - == 0)); -} - -/** - * nm_team_link_watcher_dup: - * @watcher: the #NMTeamLinkWatcher - * - * Creates a copy of @watcher - * - * Returns: (transfer full): a copy of @watcher - * - * Since: 1.12 - **/ -NMTeamLinkWatcher * -nm_team_link_watcher_dup(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, NULL); - - switch (watcher->type) { - case LINK_WATCHER_ETHTOOL: - return nm_team_link_watcher_new_ethtool(watcher->ethtool.delay_up, - watcher->ethtool.delay_down, - NULL); - break; - case LINK_WATCHER_NSNA_PING: - return nm_team_link_watcher_new_nsna_ping(watcher->nsna_ping.init_wait, - watcher->nsna_ping.interval, - watcher->nsna_ping.missed_max, - watcher->nsna_ping.target_host, - NULL); - break; - case LINK_WATCHER_ARP_PING: - return nm_team_link_watcher_new_arp_ping2(watcher->arp_ping.init_wait, - watcher->arp_ping.interval, - watcher->arp_ping.missed_max, - watcher->arp_ping.vlanid, - watcher->arp_ping.target_host, - watcher->arp_ping.source_host, - watcher->arp_ping.flags, - NULL); - default: - nm_assert_not_reached(); - return NULL; - } -} - -/** - * nm_team_link_watcher_get_name: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the name of the link watcher to be used. - * - * Since: 1.12 - **/ -const char * -nm_team_link_watcher_get_name(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, NULL); - - return _link_watcher_name[watcher->type]; -} - -/** - * nm_team_link_watcher_get_delay_up: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the delay_up interval (in milliseconds) that elapses between the link - * coming up and the runner being notified about it. - * - * Since: 1.12 - **/ -int -nm_team_link_watcher_get_delay_up(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, 0); - - if (watcher->type == LINK_WATCHER_ETHTOOL) - return watcher->ethtool.delay_up; - return -1; -} - -/** - * nm_team_link_watcher_get_delay_down: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the delay_down interval (in milliseconds) that elapses between the link - * going down and the runner being notified about it. - * - * Since: 1.12 - **/ -int -nm_team_link_watcher_get_delay_down(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, 0); - - if (watcher->type == LINK_WATCHER_ETHTOOL) - return watcher->ethtool.delay_down; - return -1; -} - -/** - * nm_team_link_watcher_get_init_wait: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the init_wait interval (in milliseconds) that the team slave should - * wait before sending the first packet to the target host. - * - * Since: 1.12 - **/ -int -nm_team_link_watcher_get_init_wait(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, 0); - - if (watcher->type == LINK_WATCHER_NSNA_PING) - return watcher->nsna_ping.init_wait; - if (watcher->type == LINK_WATCHER_ARP_PING) - return watcher->arp_ping.init_wait; - return -1; -} - -/** - * nm_team_link_watcher_get_interval: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the interval (in milliseconds) that the team slave should wait between - * sending two check packets to the target host. - * - * Since: 1.12 - **/ -int -nm_team_link_watcher_get_interval(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, 0); - - if (watcher->type == LINK_WATCHER_NSNA_PING) - return watcher->nsna_ping.interval; - if (watcher->type == LINK_WATCHER_ARP_PING) - return watcher->arp_ping.interval; - return -1; -} - -/** - * nm_team_link_watcher_get_missed_max: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the number of missed replies after which the link is considered down. - * - * Since: 1.12 - **/ -int -nm_team_link_watcher_get_missed_max(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, 0); - - if (watcher->type == LINK_WATCHER_NSNA_PING) - return watcher->nsna_ping.missed_max; - if (watcher->type == LINK_WATCHER_ARP_PING) - return watcher->arp_ping.missed_max; - return -1; -} - -/** - * nm_team_link_watcher_get_vlanid: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the VLAN tag ID to be used to outgoing link probes - * - * Since: 1.16 - **/ -int -nm_team_link_watcher_get_vlanid(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, -1); - - if (watcher->type == LINK_WATCHER_ARP_PING) - return watcher->arp_ping.vlanid; - return -1; -} - -/** - * nm_team_link_watcher_get_target_host: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the host name/ip address to be used as destination for the link probing - * packets. - * - * Since: 1.12 - **/ -const char * -nm_team_link_watcher_get_target_host(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, NULL); - - if (watcher->type == LINK_WATCHER_NSNA_PING) - return watcher->nsna_ping.target_host; - if (watcher->type == LINK_WATCHER_ARP_PING) - return watcher->arp_ping.target_host; - return NULL; -} - -/** - * nm_team_link_watcher_get_source_host: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the ip address to be used as source for the link probing packets. - * - * Since: 1.12 - **/ -const char * -nm_team_link_watcher_get_source_host(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, NULL); - - if (watcher->type == LINK_WATCHER_ARP_PING) - return watcher->arp_ping.source_host; - return NULL; -} - -/** - * nm_team_link_watcher_get_flags: - * @watcher: the #NMTeamLinkWatcher - * - * Gets the arp ping watcher flags. - * - * Since: 1.12 - **/ -NMTeamLinkWatcherArpPingFlags -nm_team_link_watcher_get_flags(const NMTeamLinkWatcher *watcher) -{ - _CHECK_WATCHER(watcher, 0); - - if (watcher->type == LINK_WATCHER_ARP_PING) - return watcher->arp_ping.flags; - return 0; -} - -/*****************************************************************************/ - -static GParamSpec *obj_properties[_NM_TEAM_ATTRIBUTE_MASTER_NUM] = { - NULL, -}; - -typedef struct { - NMTeamSetting *team_setting; -} NMSettingTeamPrivate; - -G_DEFINE_TYPE(NMSettingTeam, nm_setting_team, NM_TYPE_SETTING) - -#define NM_SETTING_TEAM_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_TEAM, NMSettingTeamPrivate)) - -/*****************************************************************************/ - -NMTeamSetting * -_nm_setting_team_get_team_setting(NMSettingTeam *setting) -{ - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting; -} - -/*****************************************************************************/ - -#define _maybe_changed(self, changed) \ - nm_team_setting_maybe_changed(NM_SETTING(_NM_ENSURE_TYPE(NMSettingTeam *, self)), \ - (const GParamSpec *const *) obj_properties, \ - (changed)) - -#define _maybe_changed_with_assert(self, changed) \ - G_STMT_START \ - { \ - if (!_maybe_changed((self), (changed))) \ - nm_assert_not_reached(); \ - } \ - G_STMT_END - -/** - * nm_setting_team_get_config: - * @setting: the #NMSettingTeam - * - * Returns: the #NMSettingTeam:config property of the setting - **/ -const char * -nm_setting_team_get_config(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); - - return nm_team_setting_config_get(NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting); -} - -/** - * nm_setting_team_get_notify_peers_count: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:notify-peers-count property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_get_notify_peers_count(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.notify_peers_count; -} - -/** - * nm_setting_team_get_notify_peers_interval: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:notify-peers-interval property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_get_notify_peers_interval(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.notify_peers_interval; -} - -/** - * nm_setting_team_get_mcast_rejoin_count: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:mcast-rejoin-count property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_get_mcast_rejoin_count(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.mcast_rejoin_count; -} - -/** - * nm_setting_team_get_mcast_rejoin_interval: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:mcast-rejoin-interval property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_get_mcast_rejoin_interval(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.mcast_rejoin_interval; -} - -/** - * nm_setting_team_get_runner: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner property of the setting - * - * Since: 1.12 - **/ -const char * -nm_setting_team_get_runner(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner; -} - -/** - * nm_setting_team_get_runner_hwaddr_policy: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner-hwaddr-policy property of the setting - * - * Since: 1.12 - **/ -const char * -nm_setting_team_get_runner_hwaddr_policy(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_hwaddr_policy; -} - -/** - * nm_setting_team_get_runner_tx_balancer: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner-tx-balancer property of the setting - * - * Since: 1.12 - **/ -const char * -nm_setting_team_get_runner_tx_balancer(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_tx_balancer; -} - -/** - * nm_setting_team_get_runner_tx_balancer_interval: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner-tx-balancer_interval property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_get_runner_tx_balancer_interval(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_tx_balancer_interval; -} - -/** - * nm_setting_team_get_runner_active: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner_active property of the setting - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_get_runner_active(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_active; -} - -/** - * nm_setting_team_get_runner_fast_rate: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner-fast-rate property of the setting - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_get_runner_fast_rate(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_fast_rate; -} - -/** - * nm_setting_team_get_runner_sys_prio: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner-sys-prio property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_get_runner_sys_prio(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_sys_prio; -} - -/** - * nm_setting_team_get_runner_min_ports: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner-min-ports property of the setting - * - * Since: 1.12 - **/ -int -nm_setting_team_get_runner_min_ports(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_min_ports; -} - -/** - * nm_setting_team_get_runner_agg_select_policy: - * @setting: the #NMSettingTeam - * - * Returns: the ##NMSettingTeam:runner-agg-select-policy property of the setting - * - * Since: 1.12 - **/ -const char * -nm_setting_team_get_runner_agg_select_policy(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_agg_select_policy; -} - -/** - * nm_setting_team_remove_runner_tx_hash_by_value: - * @setting: the #NMSetetingTeam - * @txhash: the txhash element to remove - * - * Removes the txhash element #txhash - * - * Returns: %TRUE if the txhash element was found and removed; %FALSE if it was not. - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_remove_runner_tx_hash_by_value(NMSettingTeam *setting, const char *txhash) -{ - NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(setting); - const GPtrArray * arr; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); - g_return_val_if_fail(txhash != NULL, FALSE); - - arr = priv->team_setting->d.master.runner_tx_hash; - if (arr) { - for (i = 0; i < arr->len; i++) { - if (nm_streq(txhash, arr->pdata[i])) { - _maybe_changed_with_assert( - setting, - nm_team_setting_value_master_runner_tx_hash_remove(priv->team_setting, i)); - return TRUE; - } - } - } - return FALSE; -} - -/** - * nm_setting_team_get_num_runner_tx_hash: - * @setting: the #NMSettingTeam - * - * Returns: the number of elements in txhash - * - * Since: 1.12 - **/ -guint -nm_setting_team_get_num_runner_tx_hash(NMSettingTeam *setting) -{ - const GPtrArray *arr; - - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - arr = NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_tx_hash; - return arr ? arr->len : 0u; -} - -/** - * nm_setting_team_get_runner_tx_hash - * @setting: the #NMSettingTeam - * @idx: index number of the txhash element to return - * - * Returns: the txhash element at index @idx - * - * Since: 1.12 - **/ -const char * -nm_setting_team_get_runner_tx_hash(NMSettingTeam *setting, guint idx) -{ - const GPtrArray *arr; - - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); - - arr = NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_tx_hash; - - g_return_val_if_fail(arr, NULL); - g_return_val_if_fail(idx < arr->len, NULL); - - return arr->pdata[idx]; -} - -/** - * nm_setting_team_remove_runner_tx_hash: - * @setting: the #NMSettingTeam - * @idx: index number of the element to remove from txhash - * - * Removes the txhash element at index @idx. - * - * Since: 1.12 - **/ -void -nm_setting_team_remove_runner_tx_hash(NMSettingTeam *setting, guint idx) -{ - NMSettingTeamPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_TEAM(setting)); - - priv = NM_SETTING_TEAM_GET_PRIVATE(setting); - - g_return_if_fail(priv->team_setting->d.master.runner_tx_hash); - g_return_if_fail(idx < priv->team_setting->d.master.runner_tx_hash->len); - - _maybe_changed_with_assert( - setting, - nm_team_setting_value_master_runner_tx_hash_remove(priv->team_setting, idx)); -} - -/** - * nm_setting_team_add_runner_tx_hash: - * @setting: the #NMSettingTeam - * @txhash: the element to add to txhash - * - * Adds a new txhash element to the setting. - * - * Returns: %TRUE if the txhash element was added; %FALSE if the element - * was already knnown. - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_add_runner_tx_hash(NMSettingTeam *setting, const char *txhash) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); - g_return_val_if_fail(txhash, FALSE); - - return _maybe_changed(setting, - nm_team_setting_value_master_runner_tx_hash_add( - NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, - txhash)); -} - -/** - * nm_setting_team_get_num_link_watchers: - * @setting: the #NMSettingTeam - * - * Returns: the number of configured link watchers - * - * Since: 1.12 - **/ -guint -nm_setting_team_get_num_link_watchers(NMSettingTeam *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); - - return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.link_watchers->len; -} - -/** - * nm_setting_team_get_link_watcher: - * @setting: the #NMSettingTeam - * @idx: index number of the link watcher to return - * - * Returns: (transfer none): the link watcher at index @idx. - * - * Since: 1.12 - **/ -NMTeamLinkWatcher * -nm_setting_team_get_link_watcher(NMSettingTeam *setting, guint idx) -{ - const GPtrArray *arr; - - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); - - arr = NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.link_watchers; - - g_return_val_if_fail(idx < arr->len, NULL); - - return arr->pdata[idx]; -} - -/** - * nm_setting_team_add_link_watcher: - * @setting: the #NMSettingTeam - * @link_watcher: the link watcher to add - * - * Appends a new link watcher to the setting. - * - * Returns: %TRUE if the link watcher is added; %FALSE if an identical link - * watcher was already there. - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_add_link_watcher(NMSettingTeam *setting, NMTeamLinkWatcher *link_watcher) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); - g_return_val_if_fail(link_watcher != NULL, FALSE); - - return _maybe_changed( - setting, - nm_team_setting_value_link_watchers_add(NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, - link_watcher)); -} - -/** - * nm_setting_team_remove_link_watcher: - * @setting: the #NMSettingTeam - * @idx: index number of the link watcher to remove - * - * Removes the link watcher at index #idx. - * - * Since: 1.12 - **/ -void -nm_setting_team_remove_link_watcher(NMSettingTeam *setting, guint idx) -{ - NMSettingTeamPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_TEAM(setting)); - - priv = NM_SETTING_TEAM_GET_PRIVATE(setting); - - g_return_if_fail(idx < priv->team_setting->d.link_watchers->len); - - _maybe_changed_with_assert(setting, - nm_team_setting_value_link_watchers_remove(priv->team_setting, idx)); -} - -/** - * nm_setting_team_remove_link_watcher_by_value: - * @setting: the #NMSettingTeam - * @link_watcher: the link watcher to remove - * - * Removes the link watcher entry matching link_watcher. - * - * Returns: %TRUE if the link watcher was found and removed, %FALSE otherwise. - * - * Since: 1.12 - **/ -gboolean -nm_setting_team_remove_link_watcher_by_value(NMSettingTeam * setting, - NMTeamLinkWatcher *link_watcher) -{ - g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); - g_return_val_if_fail(link_watcher, FALSE); - - return _maybe_changed(setting, - nm_team_setting_value_link_watchers_remove_by_value( - NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, - link_watcher)); -} - -/** - * nm_setting_team_clear_link_watchers: - * @setting: the #NMSettingTeam - * - * Removes all configured link watchers. - * - * Since: 1.12 - **/ -void -nm_setting_team_clear_link_watchers(NMSettingTeam *setting) -{ - g_return_if_fail(NM_IS_SETTING_TEAM(setting)); - - _maybe_changed(setting, - nm_team_setting_value_link_watchers_set_list( - NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, - NULL, - 0)); -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(setting); - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - if (!nm_team_setting_verify(priv->team_setting, error)) - return FALSE; - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingTeamPrivate *a_priv, *b_priv; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_LINK_WATCHERS)) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) - return NM_TERNARY_DEFAULT; - if (!set_b) - return TRUE; - a_priv = NM_SETTING_TEAM_GET_PRIVATE(set_a); - b_priv = NM_SETTING_TEAM_GET_PRIVATE(set_b); - return nm_team_link_watchers_equal(a_priv->team_setting->d.link_watchers, - b_priv->team_setting->d.link_watchers, - TRUE); - } - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_CONFIG)) { - if (set_b) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) { - /* If we are trying to match a connection in order to assume it (and thus - * @flags contains INFERRABLE), use the "relaxed" matching for team - * configuration. Otherwise, for all other purposes (including connection - * comparison before an update), resort to the default string comparison. */ - return TRUE; - } - - a_priv = NM_SETTING_TEAM_GET_PRIVATE(set_a); - b_priv = NM_SETTING_TEAM_GET_PRIVATE(set_b); - - return nm_streq0(nm_team_setting_config_get(a_priv->team_setting), - nm_team_setting_config_get(b_priv->team_setting)); - } - - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_team_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -static void -duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) -{ - _maybe_changed(NM_SETTING_TEAM(dst), - nm_team_setting_reset(NM_SETTING_TEAM_GET_PRIVATE(dst)->team_setting, - NM_SETTING_TEAM_GET_PRIVATE(src)->team_setting)); -} - -static gboolean -init_from_dbus(NMSetting * setting, - GHashTable * keys, - GVariant * setting_dict, - GVariant * connection_dict, - guint /* NMSettingParseFlags */ parse_flags, - GError ** error) -{ - guint32 changed = 0; - gboolean success; - - if (keys) - g_hash_table_remove(keys, "interface-name"); - - success = nm_team_setting_reset_from_dbus(NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, - setting_dict, - keys, - &changed, - parse_flags, - error); - _maybe_changed(NM_SETTING_TEAM(setting), changed); - return success; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingTeam * setting = NM_SETTING_TEAM(object); - NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(setting); - const GPtrArray * v_ptrarr; - - switch (prop_id) { - case NM_TEAM_ATTRIBUTE_CONFIG: - g_value_set_string(value, nm_team_setting_config_get(priv->team_setting)); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE: - g_value_set_boolean(value, nm_team_setting_value_get_bool(priv->team_setting, prop_id)); - break; - case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT: - case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL: - case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT: - case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS: - g_value_set_int(value, nm_team_setting_value_get_int32(priv->team_setting, prop_id)); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY: - g_value_set_string(value, nm_team_setting_value_get_string(priv->team_setting, prop_id)); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH: - v_ptrarr = priv->team_setting->d.master.runner_tx_hash; - g_value_take_boxed(value, - v_ptrarr ? _nm_utils_ptrarray_to_strv((GPtrArray *) v_ptrarr) : NULL); - break; - case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: - g_value_take_boxed(value, - _nm_utils_copy_array(priv->team_setting->d.link_watchers, - (NMUtilsCopyFunc) _nm_team_link_watcher_ref, - (GDestroyNotify) nm_team_link_watcher_unref)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingTeam * setting = NM_SETTING_TEAM(object); - NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(object); - guint32 changed; - const GPtrArray * v_ptrarr; - - switch (prop_id) { - case NM_TEAM_ATTRIBUTE_CONFIG: - changed = nm_team_setting_config_set(priv->team_setting, g_value_get_string(value)); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE: - changed = - nm_team_setting_value_set_bool(priv->team_setting, prop_id, g_value_get_boolean(value)); - break; - case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT: - case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL: - case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT: - case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS: - changed = - nm_team_setting_value_set_int32(priv->team_setting, prop_id, g_value_get_int(value)); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY: - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY: - changed = nm_team_setting_value_set_string(priv->team_setting, - prop_id, - g_value_get_string(value)); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH: - v_ptrarr = g_value_get_boxed(value); - changed = nm_team_setting_value_master_runner_tx_hash_set_list( - priv->team_setting, - v_ptrarr ? (const char *const *) v_ptrarr->pdata : NULL, - v_ptrarr ? v_ptrarr->len : 0u); - break; - case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: - v_ptrarr = g_value_get_boxed(value); - changed = nm_team_setting_value_link_watchers_set_list( - priv->team_setting, - v_ptrarr ? (const NMTeamLinkWatcher *const *) v_ptrarr->pdata : NULL, - v_ptrarr ? v_ptrarr->len : 0u); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - return; - } - - _maybe_changed(setting, changed & ~(((guint32) 1) << prop_id)); -} - -/*****************************************************************************/ - -static void -nm_setting_team_init(NMSettingTeam *setting) -{ - NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(setting); - - priv->team_setting = nm_team_setting_new(FALSE, NULL); -} - -/** - * nm_setting_team_new: - * - * Creates a new #NMSettingTeam object with default values. - * - * Returns: (transfer full): the new empty #NMSettingTeam object - **/ -NMSetting * -nm_setting_team_new(void) -{ - return g_object_new(NM_TYPE_SETTING_TEAM, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(object); - - nm_team_setting_free(priv->team_setting); - - G_OBJECT_CLASS(nm_setting_team_parent_class)->finalize(object); -} - -static void -nm_setting_team_class_init(NMSettingTeamClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingTeamPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - setting_class->duplicate_copy_properties = duplicate_copy_properties; - setting_class->init_from_dbus = init_from_dbus; - - /** - * NMSettingTeam:config: - * - * The JSON configuration for the team network interface. The property - * should contain raw JSON configuration data suitable for teamd, because - * the value is passed directly to teamd. If not specified, the default - * configuration is used. See man teamd.conf for the format details. - **/ - /* ---ifcfg-rh--- - * property: config - * variable: TEAM_CONFIG - * description: Team configuration in JSON. See man teamd.conf for details. - * ---end--- - */ - obj_properties[NM_TEAM_ATTRIBUTE_CONFIG] = g_param_spec_string( - NM_SETTING_TEAM_CONFIG, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_CONFIG], - &nm_sett_info_propert_type_team_s); - - /** - * NMSettingTeam:notify-peers-count: - * - * Corresponds to the teamd notify_peers.count. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT] = - g_param_spec_int(NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeam:notify-peers-interval: - * - * Corresponds to the teamd notify_peers.interval. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL] = - g_param_spec_int(NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeam:mcast-rejoin-count: - * - * Corresponds to the teamd mcast_rejoin.count. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT] = - g_param_spec_int(NM_SETTING_TEAM_MCAST_REJOIN_COUNT, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeam:mcast-rejoin-interval: - * - * Corresponds to the teamd mcast_rejoin.interval. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL] = - g_param_spec_int(NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeam:runner: - * - * Corresponds to the teamd runner.name. - * Permitted values are: "roundrobin", "broadcast", "activebackup", - * "loadbalance", "lacp", "random". - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER] = - g_param_spec_string(NM_SETTING_TEAM_RUNNER, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER], - &nm_sett_info_propert_type_team_s); - - /** - * NMSettingTeam:runner-hwaddr-policy: - * - * Corresponds to the teamd runner.hwaddr_policy. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY] = - g_param_spec_string(NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY], - &nm_sett_info_propert_type_team_s); - - /** - * NMSettingTeam:runner-tx-hash: - * - * Corresponds to the teamd runner.tx_hash. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH] = g_param_spec_boxed( - NM_SETTING_TEAM_RUNNER_TX_HASH, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH], - &nm_sett_info_propert_type_team_as); - - /** - * NMSettingTeam:runner-tx-balancer: - * - * Corresponds to the teamd runner.tx_balancer.name. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER] = - g_param_spec_string(NM_SETTING_TEAM_RUNNER_TX_BALANCER, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER], - &nm_sett_info_propert_type_team_s); - - /** - * NMSettingTeam:runner-tx-balancer-interval: - * - * Corresponds to the teamd runner.tx_balancer.interval. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL] = - g_param_spec_int(NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj( - properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeam:runner-active: - * - * Corresponds to the teamd runner.active. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE] = - g_param_spec_boolean(NM_SETTING_TEAM_RUNNER_ACTIVE, - "", - "", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE], - &nm_sett_info_propert_type_team_b); - - /** - * NMSettingTeam:runner-fast-rate: - * - * Corresponds to the teamd runner.fast_rate. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE] = - g_param_spec_boolean(NM_SETTING_TEAM_RUNNER_FAST_RATE, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE], - &nm_sett_info_propert_type_team_b); - - /** - * NMSettingTeam:runner-sys-prio: - * - * Corresponds to the teamd runner.sys_prio. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO] = - g_param_spec_int(NM_SETTING_TEAM_RUNNER_SYS_PRIO, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeam:runner-min-ports: - * - * Corresponds to the teamd runner.min_ports. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS] = - g_param_spec_int(NM_SETTING_TEAM_RUNNER_MIN_PORTS, - "", - "", - G_MININT32, - G_MAXINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS], - &nm_sett_info_propert_type_team_i); - - /** - * NMSettingTeam:runner-agg-select-policy: - * - * Corresponds to the teamd runner.agg_select_policy. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY] = - g_param_spec_string(NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY], - &nm_sett_info_propert_type_team_s); - - /** - * NMSettingTeam:link-watchers: (type GPtrArray(NMTeamLinkWatcher)) - * - * Link watchers configuration for the connection: each link watcher is - * defined by a dictionary, whose keys depend upon the selected link - * watcher. Available link watchers are 'ethtool', 'nsna_ping' and - * 'arp_ping' and it is specified in the dictionary with the key 'name'. - * Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; - * nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; - * arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', - * 'validate-inactive', 'send-always'. See teamd.conf man for more details. - * - * Since: 1.12 - **/ - obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS] = - g_param_spec_boxed(NM_SETTING_TEAM_LINK_WATCHERS, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], - &nm_sett_info_propert_type_team_link_watchers); - - /* ---dbus--- - * property: interface-name - * format: string - * description: Deprecated in favor of connection.interface-name, but can - * be used for backward-compatibility with older daemons, to set the - * team's interface name. - * ---end--- - */ - _nm_properties_override_dbus(properties_override, - "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); - - g_object_class_install_properties(object_class, G_N_ELEMENTS(obj_properties), obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_TEAM, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-team.h b/libnm-core/nm-setting-team.h deleted file mode 100644 index 3f40c8cb9b..0000000000 --- a/libnm-core/nm-setting-team.h +++ /dev/null @@ -1,226 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2013 Jiri Pirko - */ - -#ifndef __NM_SETTING_TEAM_H__ -#define __NM_SETTING_TEAM_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -/** - * NMTeamLinkWatcherArpPingFlags: - * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE: no one among the arp_ping link watcher - * boolean options ('validate_active', 'validate_inactive', 'send_always') is - * enabled (set to true). - * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE: the arp_ping link watcher - * option 'validate_active' is enabled (set to true). - * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE: the arp_ping link watcher - * option 'validate_inactive' is enabled (set to true). - * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS: the arp_ping link watcher option - * 'send_always' is enabled (set to true). - */ -typedef enum { /*< flags >*/ - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE = 0, /*< skip >*/ - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE = 0x2, - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE = 0x4, - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS = 0x8, -} NMTeamLinkWatcherArpPingFlags; - -#define NM_TEAM_LINK_WATCHER_ETHTOOL "ethtool" -#define NM_TEAM_LINK_WATCHER_ARP_PING "arp_ping" -#define NM_TEAM_LINK_WATCHER_NSNA_PING "nsna_ping" - -typedef struct NMTeamLinkWatcher NMTeamLinkWatcher; - -GType nm_team_link_watcher_get_type(void); - -NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_team_link_watcher_new_ethtool(int delay_up, int delay_down, GError **error); -NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_team_link_watcher_new_nsna_ping(int init_wait, - int interval, - int missed_max, - const char *target_host, - GError ** error); -NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping(int init_wait, - int interval, - int missed_max, - const char * target_host, - const char * source_host, - NMTeamLinkWatcherArpPingFlags flags, - GError ** error); -NM_AVAILABLE_IN_1_16 -NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping2(int init_wait, - int interval, - int missed_max, - int vlanid, - const char * target_host, - const char * source_host, - NMTeamLinkWatcherArpPingFlags flags, - GError ** error); -NM_AVAILABLE_IN_1_12 -void nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -void nm_team_link_watcher_unref(NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -gboolean nm_team_link_watcher_equal(const NMTeamLinkWatcher *watcher, - const NMTeamLinkWatcher *other); -NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_team_link_watcher_dup(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -const char *nm_team_link_watcher_get_name(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -int nm_team_link_watcher_get_delay_up(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -int nm_team_link_watcher_get_delay_down(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -int nm_team_link_watcher_get_init_wait(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -int nm_team_link_watcher_get_interval(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -int nm_team_link_watcher_get_missed_max(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -const char *nm_team_link_watcher_get_target_host(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -const char *nm_team_link_watcher_get_source_host(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags(const NMTeamLinkWatcher *watcher); -NM_AVAILABLE_IN_1_16 -int nm_team_link_watcher_get_vlanid(const NMTeamLinkWatcher *watcher); - -#define NM_TYPE_SETTING_TEAM (nm_setting_team_get_type()) -#define NM_SETTING_TEAM(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_TEAM, NMSettingTeam)) -#define NM_SETTING_TEAM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_TEAM, NMSettingTeamClass)) -#define NM_IS_SETTING_TEAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_TEAM)) -#define NM_IS_SETTING_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_TEAM)) -#define NM_SETTING_TEAM_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_TEAM, NMSettingTeamClass)) - -#define NM_SETTING_TEAM_SETTING_NAME "team" - -#define NM_SETTING_TEAM_CONFIG "config" -#define NM_SETTING_TEAM_NOTIFY_PEERS_COUNT "notify-peers-count" -#define NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL "notify-peers-interval" -#define NM_SETTING_TEAM_MCAST_REJOIN_COUNT "mcast-rejoin-count" -#define NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL "mcast-rejoin-interval" -#define NM_SETTING_TEAM_RUNNER "runner" -#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY "runner-hwaddr-policy" -#define NM_SETTING_TEAM_RUNNER_TX_HASH "runner-tx-hash" -#define NM_SETTING_TEAM_RUNNER_TX_BALANCER "runner-tx-balancer" -#define NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL "runner-tx-balancer-interval" -#define NM_SETTING_TEAM_RUNNER_ACTIVE "runner-active" -#define NM_SETTING_TEAM_RUNNER_FAST_RATE "runner-fast-rate" -#define NM_SETTING_TEAM_RUNNER_SYS_PRIO "runner-sys-prio" -#define NM_SETTING_TEAM_RUNNER_MIN_PORTS "runner-min-ports" -#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY "runner-agg-select-policy" -#define NM_SETTING_TEAM_LINK_WATCHERS "link-watchers" - -#define NM_SETTING_TEAM_RUNNER_BROADCAST "broadcast" -#define NM_SETTING_TEAM_RUNNER_ROUNDROBIN "roundrobin" -#define NM_SETTING_TEAM_RUNNER_RANDOM "random" -#define NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP "activebackup" -#define NM_SETTING_TEAM_RUNNER_LOADBALANCE "loadbalance" -#define NM_SETTING_TEAM_RUNNER_LACP "lacp" - -#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL "same_all" -#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE "by_active" -#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE "only_active" - -#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO "lacp_prio" -#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO_STABLE "lacp_prio_stable" -#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_BANDWIDTH "bandwidth" -#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_COUNT "count" -#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_PORT_CONFIG "port_config" - -#define NM_SETTING_TEAM_NOTIFY_PEERS_COUNT_ACTIVEBACKUP_DEFAULT 1 -#define NM_SETTING_TEAM_NOTIFY_MCAST_COUNT_ACTIVEBACKUP_DEFAULT 1 -#define NM_SETTING_TEAM_RUNNER_DEFAULT NM_SETTING_TEAM_RUNNER_ROUNDROBIN -#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_DEFAULT NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL -#define NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT 50 -#define NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT 65535 -#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT \ - NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO - -/** - * NMSettingTeam: - * - * Teaming Settings - */ -struct _NMSettingTeam { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingTeamClass; - -GType nm_setting_team_get_type(void); - -NMSetting *nm_setting_team_new(void); - -const char *nm_setting_team_get_config(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_get_notify_peers_count(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_get_notify_peers_interval(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_get_mcast_rejoin_count(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_get_mcast_rejoin_interval(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -const char *nm_setting_team_get_runner(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -const char *nm_setting_team_get_runner_hwaddr_policy(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -const char *nm_setting_team_get_runner_tx_balancer(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_get_runner_tx_balancer_interval(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_get_runner_active(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_get_runner_fast_rate(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_get_runner_sys_prio(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -int nm_setting_team_get_runner_min_ports(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -const char *nm_setting_team_get_runner_agg_select_policy(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_remove_runner_tx_hash_by_value(NMSettingTeam *setting, const char *txhash); -NM_AVAILABLE_IN_1_12 -guint nm_setting_team_get_num_runner_tx_hash(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -const char *nm_setting_team_get_runner_tx_hash(NMSettingTeam *setting, guint idx); -NM_AVAILABLE_IN_1_12 -void nm_setting_team_remove_runner_tx_hash(NMSettingTeam *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_add_runner_tx_hash(NMSettingTeam *setting, const char *txhash); -NM_AVAILABLE_IN_1_12 -guint nm_setting_team_get_num_link_watchers(NMSettingTeam *setting); -NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_setting_team_get_link_watcher(NMSettingTeam *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_add_link_watcher(NMSettingTeam *setting, NMTeamLinkWatcher *link_watcher); -NM_AVAILABLE_IN_1_12 -void nm_setting_team_remove_link_watcher(NMSettingTeam *setting, guint idx); -NM_AVAILABLE_IN_1_12 -gboolean nm_setting_team_remove_link_watcher_by_value(NMSettingTeam * setting, - NMTeamLinkWatcher *link_watcher); -NM_AVAILABLE_IN_1_12 -void nm_setting_team_clear_link_watchers(NMSettingTeam *setting); -G_END_DECLS - -#endif /* __NM_SETTING_TEAM_H__ */ diff --git a/libnm-core/nm-setting-tun.c b/libnm-core/nm-setting-tun.c deleted file mode 100644 index 1208a62bad..0000000000 --- a/libnm-core/nm-setting-tun.c +++ /dev/null @@ -1,397 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-tun.h" - -#include - -#include "nm-utils.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" -#include "nm-connection-private.h" - -/** - * SECTION:nm-setting-tun - * @short_description: Describes connection properties for TUN/TAP interfaces - * - * The #NMSettingTun object is a #NMSetting subclass that describes properties - * necessary for connection to TUN/TAP interfaces. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_MODE, - PROP_OWNER, - PROP_GROUP, - PROP_PI, - PROP_VNET_HDR, - PROP_MULTI_QUEUE, ); - -typedef struct { - char * owner; - char * group; - NMSettingTunMode mode; - bool pi : 1; - bool vnet_hdr : 1; - bool multi_queue : 1; -} NMSettingTunPrivate; - -G_DEFINE_TYPE(NMSettingTun, nm_setting_tun, NM_TYPE_SETTING) - -#define NM_SETTING_TUN_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_TUN, NMSettingTunPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_tun_get_mode: - * @setting: the #NMSettingTun - * - * Returns: the #NMSettingTun:mode property of the setting - * - * Since: 1.2 - **/ -NMSettingTunMode -nm_setting_tun_get_mode(NMSettingTun *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TUN(setting), NM_SETTING_TUN_MODE_TUN); - return NM_SETTING_TUN_GET_PRIVATE(setting)->mode; -} - -/** - * nm_setting_tun_get_owner: - * @setting: the #NMSettingTun - * - * Returns: the #NMSettingTun:owner property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_tun_get_owner(NMSettingTun *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TUN(setting), NULL); - return NM_SETTING_TUN_GET_PRIVATE(setting)->owner; -} - -/** - * nm_setting_tun_get_group: - * @setting: the #NMSettingTun - * - * Returns: the #NMSettingTun:group property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_tun_get_group(NMSettingTun *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TUN(setting), NULL); - return NM_SETTING_TUN_GET_PRIVATE(setting)->group; -} - -/** - * nm_setting_tun_get_pi: - * @setting: the #NMSettingTun - * - * Returns: the #NMSettingTun:pi property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_tun_get_pi(NMSettingTun *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TUN(setting), FALSE); - return NM_SETTING_TUN_GET_PRIVATE(setting)->pi; -} - -/** - * nm_setting_tun_get_vnet_hdr: - * @setting: the #NMSettingTun - * - * Returns: the #NMSettingTun:vnet_hdr property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_tun_get_vnet_hdr(NMSettingTun *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TUN(setting), FALSE); - return NM_SETTING_TUN_GET_PRIVATE(setting)->vnet_hdr; -} - -/** - * nm_setting_tun_get_multi_queue: - * @setting: the #NMSettingTun - * - * Returns: the #NMSettingTun:multi-queue property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_tun_get_multi_queue(NMSettingTun *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_TUN(setting), FALSE); - return NM_SETTING_TUN_GET_PRIVATE(setting)->multi_queue; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(setting); - - if (!NM_IN_SET(priv->mode, NM_SETTING_TUN_MODE_TUN, NM_SETTING_TUN_MODE_TAP)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%u': invalid mode"), - (unsigned) priv->mode); - g_prefix_error(error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_MODE); - return FALSE; - } - - if (priv->owner) { - if (_nm_utils_ascii_str_to_int64(priv->owner, 10, 0, G_MAXINT32, -1) == -1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s': invalid user ID"), - priv->owner); - g_prefix_error(error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_OWNER); - return FALSE; - } - } - - if (priv->group) { - if (_nm_utils_ascii_str_to_int64(priv->group, 10, 0, G_MAXINT32, -1) == -1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s': invalid group ID"), - priv->group); - g_prefix_error(error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_GROUP); - return FALSE; - } - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingTun * setting = NM_SETTING_TUN(object); - NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_MODE: - g_value_set_uint(value, priv->mode); - break; - case PROP_OWNER: - g_value_set_string(value, priv->owner); - break; - case PROP_GROUP: - g_value_set_string(value, priv->group); - break; - case PROP_PI: - g_value_set_boolean(value, priv->pi); - break; - case PROP_VNET_HDR: - g_value_set_boolean(value, priv->vnet_hdr); - break; - case PROP_MULTI_QUEUE: - g_value_set_boolean(value, priv->multi_queue); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingTun * setting = NM_SETTING_TUN(object); - NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_MODE: - priv->mode = g_value_get_uint(value); - break; - case PROP_OWNER: - g_free(priv->owner); - priv->owner = g_value_dup_string(value); - break; - case PROP_GROUP: - g_free(priv->group); - priv->group = g_value_dup_string(value); - break; - case PROP_PI: - priv->pi = g_value_get_boolean(value); - break; - case PROP_VNET_HDR: - priv->vnet_hdr = g_value_get_boolean(value); - break; - case PROP_MULTI_QUEUE: - priv->multi_queue = g_value_get_boolean(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} -/*****************************************************************************/ - -static void -nm_setting_tun_init(NMSettingTun *self) -{ - NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(self); - - priv->mode = NM_SETTING_TUN_MODE_TUN; -} - -/** - * nm_setting_tun_new: - * - * Creates a new #NMSettingTun object with default values. - * - * Returns: (transfer full): the new empty #NMSettingTun object - * - * Since: 1.2 - **/ -NMSetting * -nm_setting_tun_new(void) -{ - return g_object_new(NM_TYPE_SETTING_TUN, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingTun * setting = NM_SETTING_TUN(object); - NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(setting); - - g_free(priv->owner); - g_free(priv->group); - - G_OBJECT_CLASS(nm_setting_tun_parent_class)->finalize(object); -} - -static void -nm_setting_tun_class_init(NMSettingTunClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingTunPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingTun:mode: - * - * The operating mode of the virtual device. Allowed values are - * %NM_SETTING_TUN_MODE_TUN to create a layer 3 device and - * %NM_SETTING_TUN_MODE_TAP to create an Ethernet-like layer 2 - * one. - * - * Since: 1.2 - */ - obj_properties[PROP_MODE] = - g_param_spec_uint(NM_SETTING_TUN_MODE, - "", - "", - 0, - G_MAXUINT, - NM_SETTING_TUN_MODE_TUN, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingTun:owner: - * - * The user ID which will own the device. If set to %NULL everyone - * will be able to use the device. - * - * Since: 1.2 - */ - obj_properties[PROP_OWNER] = g_param_spec_string(NM_SETTING_TUN_OWNER, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingTun:group: - * - * The group ID which will own the device. If set to %NULL everyone - * will be able to use the device. - * - * Since: 1.2 - */ - obj_properties[PROP_GROUP] = g_param_spec_string(NM_SETTING_TUN_GROUP, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingTun:pi: - * - * If %TRUE the interface will prepend a 4 byte header describing the - * physical interface to the packets. - * - * Since: 1.2 - */ - obj_properties[PROP_PI] = g_param_spec_boolean(NM_SETTING_TUN_PI, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingTun:vnet-hdr: - * - * If %TRUE the IFF_VNET_HDR the tunnel packets will include a virtio - * network header. - * - * Since: 1.2 - */ - obj_properties[PROP_VNET_HDR] = g_param_spec_boolean( - NM_SETTING_TUN_VNET_HDR, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingTun:multi-queue: - * - * If the property is set to %TRUE, the interface will support - * multiple file descriptors (queues) to parallelize packet - * sending or receiving. Otherwise, the interface will only - * support a single queue. - * - * Since: 1.2 - */ - obj_properties[PROP_MULTI_QUEUE] = g_param_spec_boolean( - NM_SETTING_TUN_MULTI_QUEUE, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_TUN); -} diff --git a/libnm-core/nm-setting-tun.h b/libnm-core/nm-setting-tun.h deleted file mode 100644 index 3fbbf08253..0000000000 --- a/libnm-core/nm-setting-tun.h +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_TUN_H__ -#define __NM_SETTING_TUN_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_TUN (nm_setting_tun_get_type()) -#define NM_SETTING_TUN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_TUN, NMSettingTun)) -#define NM_SETTING_TUN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_TUNCONFIG, NMSettingTunClass)) -#define NM_IS_SETTING_TUN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_TUN)) -#define NM_IS_SETTING_TUN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_TUN)) -#define NM_SETTING_TUN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_TUN, NMSettingTunClass)) - -#define NM_SETTING_TUN_SETTING_NAME "tun" - -#define NM_SETTING_TUN_MODE "mode" -#define NM_SETTING_TUN_OWNER "owner" -#define NM_SETTING_TUN_GROUP "group" -#define NM_SETTING_TUN_PI "pi" -#define NM_SETTING_TUN_VNET_HDR "vnet-hdr" -#define NM_SETTING_TUN_MULTI_QUEUE "multi-queue" - -/** - * NMSettingTunMode: - * @NM_SETTING_TUN_MODE_UNKNOWN: an unknown device type - * @NM_SETTING_TUN_MODE_TUN: a TUN device - * @NM_SETTING_TUN_MODE_TAP: a TAP device - * - * #NMSettingTunMode values indicate the device type (TUN/TAP) - */ -typedef enum { - NM_SETTING_TUN_MODE_UNKNOWN = 0, - NM_SETTING_TUN_MODE_TUN = 1, - NM_SETTING_TUN_MODE_TAP = 2, -} NMSettingTunMode; - -/** - * NMSettingTun: - * - * Tunnel Settings - */ -struct _NMSettingTun { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingTunClass; - -NM_AVAILABLE_IN_1_2 -GType nm_setting_tun_get_type(void); -NM_AVAILABLE_IN_1_2 -NMSetting *nm_setting_tun_new(void); - -NM_AVAILABLE_IN_1_2 -NMSettingTunMode nm_setting_tun_get_mode(NMSettingTun *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_tun_get_owner(NMSettingTun *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_tun_get_group(NMSettingTun *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_tun_get_pi(NMSettingTun *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_tun_get_vnet_hdr(NMSettingTun *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_tun_get_multi_queue(NMSettingTun *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_TUN_H__ */ diff --git a/libnm-core/nm-setting-user.c b/libnm-core/nm-setting-user.c deleted file mode 100644 index f62b8babbc..0000000000 --- a/libnm-core/nm-setting-user.c +++ /dev/null @@ -1,594 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-user.h" - -#include "nm-setting.h" -#include "nm-setting-private.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-user - * @short_description: Describes user properties - * - * The #NMSettingUser object is a #NMSetting subclass that allow to attach - * arbitrary user data to #NMConnection objects. - **/ - -#define MAX_NUM_KEYS 256 - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingUser, PROP_DATA, ); - -typedef struct { - GHashTable * data; - GHashTable * data_invalid; - const char **keys; -} NMSettingUserPrivate; - -/** - * NMSettingUser: - * - * General User Profile Settings - */ -struct _NMSettingUser { - NMSetting parent; - NMSettingUserPrivate _priv; -}; - -struct _NMSettingUserClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingUser, nm_setting_user, NM_TYPE_SETTING) - -#define NM_SETTING_USER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMSettingUser, NM_IS_SETTING_USER) - -/*****************************************************************************/ - -static gboolean -_key_char_is_regular(char ch) -{ - /* allow words of printable characters, plus some - * special characters, for example to support base64 encoding. */ - return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') - || NM_IN_SET(ch, '-', '_', '+', '/', '='); -} - -/** - * nm_setting_user_check_key: - * @key: the key to check - * @error: a #GError, %NULL to ignore. - * - * Checks whether @key is a valid user data key. This means, - * key is not %NULL, not too large and valid ASCII. Also, - * only digits and numbers are allowed with a few special - * characters. The key must contain at least one '.' and - * look like a fully qualified DNS name. - * - * Since: 1.8 - * - * Returns: %TRUE if @key is a valid user data key. - */ -gboolean -nm_setting_user_check_key(const char *key, GError **error) -{ - gsize len; - gboolean has_dot; - char ch; - - g_return_val_if_fail(!error || !*error, FALSE); - - if (!key || !key[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing key")); - return FALSE; - } - len = strlen(key); - if (len > 255) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key is too long")); - return FALSE; - } - if (!g_utf8_validate(key, len, NULL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key must be UTF8")); - return FALSE; - } - - has_dot = FALSE; - while (TRUE) { - ch = (key++)[0]; - - /* Allow something that looks like a FQN, separating namespaces by a single '.' - * We want to print the keys nicely in nmcli requiring escaping. - * - * If a user really has to encode special values in the name, he may base64 encode it. */ - - if (!_key_char_is_regular(ch)) - break; - - while (_key_char_is_regular(key[0])) - key++; - - ch = key[0]; - if (ch == '\0') { - if (!has_dot) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key requires a '.' for a namespace")); - return FALSE; - } - return TRUE; - } - - if (ch != '.') - break; - - has_dot = TRUE; - ch = (++key)[0]; - if (ch == '.') { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key cannot contain \"..\"")); - return FALSE; - } - } - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key contains invalid characters")); - return FALSE; -} - -/** - * nm_setting_user_check_val: - * @val: the value to check - * @error: a #GError, %NULL to ignore. - * - * Checks whether @val is a valid user data value. This means, - * value is not %NULL, not too large and valid UTF-8. - * - * Since: 1.8 - * - * Returns: %TRUE if @val is a valid user data value. - */ -gboolean -nm_setting_user_check_val(const char *val, GError **error) -{ - gsize len; - - g_return_val_if_fail(!error || !*error, FALSE); - - if (!val) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value is missing")); - return FALSE; - } - - len = strlen(val); - if (len > 8 * 1024) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value is too large")); - return FALSE; - } - - if (!g_utf8_validate(val, len, NULL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("value is not valid UTF8")); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static GHashTable * -_create_data_hash(void) -{ - return g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); -} - -/** - * nm_setting_user_get_keys: - * @setting: the #NMSettingUser - * @out_len: (out): the length of the returned array - * - * Returns: (array length=out_len) (transfer none): a - * %NULL-terminated array containing each key from the table. - **/ -const char *const * -nm_setting_user_get_keys(NMSettingUser *setting, guint *out_len) -{ - NMSettingUser * self = setting; - NMSettingUserPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_USER(self), NULL); - - priv = NM_SETTING_USER_GET_PRIVATE(self); - - if (priv->keys) { - NM_SET_OUT(out_len, g_hash_table_size(priv->data)); - return priv->keys; - } - - priv->keys = nm_utils_strdict_get_keys(priv->data, TRUE, out_len); - - /* don't return %NULL, but hijack the @keys fields as a pseudo - * empty strv array. */ - return priv->keys ?: ((const char **) &priv->keys); -} - -/*****************************************************************************/ - -/** - * nm_setting_user_get_data: - * @setting: the #NMSettingUser instance - * @key: the key to lookup - * - * Since: 1.8 - * - * Returns: (transfer none): the value associated with @key or %NULL if no such - * value exists. - */ -const char * -nm_setting_user_get_data(NMSettingUser *setting, const char *key) -{ - NMSettingUser * self = setting; - NMSettingUserPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_USER(self), NULL); - g_return_val_if_fail(key, NULL); - - priv = NM_SETTING_USER_GET_PRIVATE(self); - - if (!priv->data) - return NULL; - - return g_hash_table_lookup(priv->data, key); -} - -/** - * nm_setting_user_set_data: - * @setting: the #NMSettingUser instance - * @key: the key to set - * @val: (allow-none): the value to set or %NULL to clear a key. - * @error: (allow-none): optional error argument - * - * Since: 1.8 - * - * Returns: %TRUE if the operation was successful. The operation - * can fail if @key or @val are not valid strings according - * to nm_setting_user_check_key() and nm_setting_user_check_val(). - */ -gboolean -nm_setting_user_set_data(NMSettingUser *setting, const char *key, const char *val, GError **error) -{ - NMSettingUser * self = setting; - NMSettingUserPrivate *priv; - gboolean changed = FALSE; - - g_return_val_if_fail(NM_IS_SETTING_USER(self), FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - if (!nm_setting_user_check_key(key, error)) - return FALSE; - - if (val && !nm_setting_user_check_val(val, error)) - return FALSE; - - priv = NM_SETTING_USER_GET_PRIVATE(self); - - if (!val) { - if (priv->data && g_hash_table_remove(priv->data, key)) { - nm_clear_g_free(&priv->keys); - changed = TRUE; - } - goto out; - } - - if (priv->data) { - const char *key2, *val2; - - if (g_hash_table_lookup_extended(priv->data, key, (gpointer *) &key2, (gpointer *) &val2)) { - if (nm_streq(val, val2)) - goto out; - } else { - if (g_hash_table_size(priv->data) >= MAX_NUM_KEYS) { - /* limit the number of valid keys */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("maximum number of user data entries reached")); - return FALSE; - } - - nm_clear_g_free(&priv->keys); - } - } else - priv->data = _create_data_hash(); - - g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); - changed = TRUE; - -out: - if (priv->data_invalid) { - /* setting a value purges all invalid values that were set - * via GObject property. */ - changed = TRUE; - nm_clear_pointer(&priv->data_invalid, g_hash_table_unref); - } - if (changed) - _notify(self, PROP_DATA); - return TRUE; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingUser * self = NM_SETTING_USER(setting); - NMSettingUserPrivate *priv = NM_SETTING_USER_GET_PRIVATE(self); - - if (priv->data_invalid) { - const char * key, *val; - GHashTableIter iter; - gs_free_error GError *local = NULL; - - g_hash_table_iter_init(&iter, priv->data_invalid); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - if (!nm_setting_user_check_key(key, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid key \"%s\": %s"), - key, - local->message); - } else if (!nm_setting_user_check_val(val, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid value for \"%s\": %s"), - key, - local->message); - } else { - nm_assert_not_reached(); - continue; - } - g_prefix_error(error, "%s.%s: ", NM_SETTING_USER_SETTING_NAME, NM_SETTING_USER_DATA); - return FALSE; - } - nm_assert_not_reached(); - } - - if (priv->data && g_hash_table_size(priv->data) > MAX_NUM_KEYS) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("maximum number of user data entries reached (%u instead of %u)"), - g_hash_table_size(priv->data), - (unsigned) MAX_NUM_KEYS); - g_prefix_error(error, "%s.%s: ", NM_SETTING_USER_SETTING_NAME, NM_SETTING_USER_DATA); - return FALSE; - } - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingUserPrivate *priv, *pri2; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_USER_DATA)) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) - return NM_TERNARY_DEFAULT; - - if (!set_b) - return TRUE; - - priv = NM_SETTING_USER_GET_PRIVATE(NM_SETTING_USER(set_a)); - pri2 = NM_SETTING_USER_GET_PRIVATE(NM_SETTING_USER(set_b)); - return nm_utils_hashtable_equal(priv->data, pri2->data, TRUE, g_str_equal) - && nm_utils_hashtable_equal(priv->data_invalid, - pri2->data_invalid, - TRUE, - g_str_equal); - } - - return NM_SETTING_CLASS(nm_setting_user_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingUser * self = NM_SETTING_USER(object); - NMSettingUserPrivate *priv = NM_SETTING_USER_GET_PRIVATE(self); - GHashTableIter iter; - GHashTable * data; - const char * key, *val; - - switch (prop_id) { - case PROP_DATA: - data = _create_data_hash(); - if (priv->data) { - g_hash_table_iter_init(&iter, priv->data); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) - g_hash_table_insert(data, g_strdup(key), g_strdup(val)); - } - if (priv->data_invalid) { - g_hash_table_iter_init(&iter, priv->data_invalid); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) - g_hash_table_insert(data, g_strdup(key), g_strdup(val)); - } - g_value_take_boxed(value, data); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingUser * self = NM_SETTING_USER(object); - NMSettingUserPrivate *priv = NM_SETTING_USER_GET_PRIVATE(self); - GHashTableIter iter; - GHashTable * data; - const char * key, *val; - - switch (prop_id) { - case PROP_DATA: - nm_clear_g_free(&priv->keys); - - data = g_value_get_boxed(value); - if (!data || !g_hash_table_size(data)) { - nm_clear_pointer(&priv->data, g_hash_table_unref); - nm_clear_pointer(&priv->data_invalid, g_hash_table_unref); - return; - } - - if (priv->data) - g_hash_table_remove_all(priv->data); - else - priv->data = _create_data_hash(); - - if (priv->data_invalid) - g_hash_table_remove_all(priv->data_invalid); - - g_hash_table_iter_init(&iter, data); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - if (nm_setting_user_check_key(key, NULL) && nm_setting_user_check_val(val, NULL)) - g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); - else { - if (!priv->data_invalid) - priv->data_invalid = _create_data_hash(); - g_hash_table_insert(priv->data_invalid, g_strdup(key), g_strdup(val)); - } - } - if (priv->data_invalid && !g_hash_table_size(priv->data_invalid)) - nm_clear_pointer(&priv->data_invalid, g_hash_table_unref); - - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_user_init(NMSettingUser *self) -{} - -/** - * nm_setting_user_new: - * - * Creates a new #NMSettingUser object with default values. - * - * Returns: the new empty #NMSettingUser object - **/ -NMSetting * -nm_setting_user_new(void) -{ - return g_object_new(NM_TYPE_SETTING_USER, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingUser * self = NM_SETTING_USER(object); - NMSettingUserPrivate *priv = NM_SETTING_USER_GET_PRIVATE(self); - - g_free(priv->keys); - if (priv->data) - g_hash_table_unref(priv->data); - if (priv->data_invalid) - g_hash_table_unref(priv->data_invalid); - - G_OBJECT_CLASS(nm_setting_user_parent_class)->finalize(object); -} - -static void -nm_setting_user_class_init(NMSettingUserClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - - /** - * NMSettingUser:data: (type GHashTable(utf8,utf8)) - * - * A dictionary of key/value pairs with user data. This data is ignored by NetworkManager - * and can be used at the users discretion. The keys only support a strict ascii format, - * but the values can be arbitrary UTF8 strings up to a certain length. - * - * Since: 1.8 - **/ - /* ---ifcfg-rh--- - * property: data - * variable: NM_USER_* - * description: each key/value pair is stored as a separate variable with - * name composed by concatenating NM_USER_ with the encoded key. The key is - * encoded by substituting lowercase letters with uppercase and prepending - * uppercase letters with an underscore. A dot is encoded as a double - * underscore. Remaining characters are encoded as underscore followed by a - * 3 digit octal representation of the character. - * example: NM_USER_FOO__BAR=something - * ---end--- - */ - obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_USER_DATA, - "", - "", - G_TYPE_HASH_TABLE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_DATA], - &nm_sett_info_propert_type_strdict); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_USER, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-user.h b/libnm-core/nm-setting-user.h deleted file mode 100644 index b151cd3ee6..0000000000 --- a/libnm-core/nm-setting-user.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_USER_H__ -#define __NM_SETTING_USER_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_USER (nm_setting_user_get_type()) -#define NM_SETTING_USER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_USER, NMSettingUser)) -#define NM_SETTING_USER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_USER, NMSettingUserClass)) -#define NM_IS_SETTING_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_USER)) -#define NM_IS_SETTING_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_USER)) -#define NM_SETTING_USER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_USER, NMSettingUserClass)) - -#define NM_SETTING_USER_SETTING_NAME "user" - -#define NM_SETTING_USER_DATA "data" - -typedef struct _NMSettingUserClass NMSettingUserClass; - -NM_AVAILABLE_IN_1_8 -GType nm_setting_user_get_type(void); - -NM_AVAILABLE_IN_1_8 -NMSetting *nm_setting_user_new(void); - -NM_AVAILABLE_IN_1_8 -const char *const *nm_setting_user_get_keys(NMSettingUser *setting, guint *out_len); - -NM_AVAILABLE_IN_1_8 -const char *nm_setting_user_get_data(NMSettingUser *setting, const char *key); -NM_AVAILABLE_IN_1_8 -gboolean -nm_setting_user_set_data(NMSettingUser *setting, const char *key, const char *val, GError **error); - -NM_AVAILABLE_IN_1_8 -gboolean nm_setting_user_check_key(const char *key, GError **error); -NM_AVAILABLE_IN_1_8 -gboolean nm_setting_user_check_val(const char *val, GError **error); - -G_END_DECLS - -#endif /* __NM_SETTING_USER_H__ */ diff --git a/libnm-core/nm-setting-veth.c b/libnm-core/nm-setting-veth.c deleted file mode 100644 index 6270afb38d..0000000000 --- a/libnm-core/nm-setting-veth.c +++ /dev/null @@ -1,194 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2020 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-veth.h" - -#include - -#include "nm-utils.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" -#include "nm-connection-private.h" - -/** - * SECTION:nm-setting-veth - * @short_description: Describes connection properties for veth interfaces - * - * The #NMSettingVeth object is a #NMSetting subclass that describes properties - * necessary for connection to veth interfaces. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PEER, ); - -typedef struct { - char *peer; -} NMSettingVethPrivate; - -/** - * NMSettingVeth: - * - * Veth Settings - */ -struct _NMSettingVeth { - NMSetting parent; - NMSettingVethPrivate _priv; -}; - -struct _NMSettingVethClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingVeth, nm_setting_veth, NM_TYPE_SETTING) - -#define NM_SETTING_VETH_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMSettingVeth, NM_IS_SETTING_VETH, NMSetting) - -/*****************************************************************************/ - -/** - * nm_setting_veth_get_peer: - * @setting: the #NMSettingVeth - * - * Returns: the #NMSettingVeth:peer property of the setting - * - * Since: 1.30 - **/ -const char * -nm_setting_veth_get_peer(NMSettingVeth *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VETH(setting), NULL); - return NM_SETTING_VETH_GET_PRIVATE(setting)->peer; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting); - - if (!priv->peer) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is not specified")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VETH_SETTING_NAME, NM_SETTING_VETH_PEER); - return FALSE; - } - - if (!nm_utils_ifname_valid(priv->peer, NMU_IFACE_KERNEL, NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid interface name"), - priv->peer); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VETH_SETTING_NAME, NM_SETTING_VETH_PEER); - return FALSE; - } - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingVeth * setting = NM_SETTING_VETH(object); - NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PEER: - g_value_set_string(value, priv->peer); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingVeth * setting = NM_SETTING_VETH(object); - NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PEER: - g_free(priv->peer); - priv->peer = g_value_dup_string(value); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_veth_init(NMSettingVeth *setting) -{} - -/** - * nm_setting_veth_new: - * - * Creates a new #NMSettingVeth object with default values. - * - * Returns: (transfer full): the new empty #NMSettingVeth object - * - * Since: 1.30 - **/ -NMSetting * -nm_setting_veth_new(void) -{ - return g_object_new(NM_TYPE_SETTING_VETH, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingVeth * setting = NM_SETTING_VETH(object); - NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting); - - g_free(priv->peer); - - G_OBJECT_CLASS(nm_setting_veth_parent_class)->finalize(object); -} - -static void -nm_setting_veth_class_init(NMSettingVethClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingVethPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingVeth:peer: - * - * This property specifies the peer interface name of the veth. This - * property is mandatory. - * - * Since: 1.30 - **/ - obj_properties[PROP_PEER] = g_param_spec_string(NM_SETTING_VETH_PEER, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_VETH); -} diff --git a/libnm-core/nm-setting-veth.h b/libnm-core/nm-setting-veth.h deleted file mode 100644 index 5dbc192742..0000000000 --- a/libnm-core/nm-setting-veth.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2020 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_VETH_H__ -#define __NM_SETTING_VETH_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_VETH (nm_setting_veth_get_type()) -#define NM_SETTING_VETH(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VETH, NMSettingVeth)) -#define NM_IS_SETTING_VETH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VETH)) -#define NM_IS_SETTING_VETH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VETH)) -#define NM_SETTING_VETH_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VETH, NMSettingVethClass)) - -#define NM_SETTING_VETH_SETTING_NAME "veth" - -#define NM_SETTING_VETH_PEER "peer" - -typedef struct _NMSettingVethClass NMSettingVethClass; - -NM_AVAILABLE_IN_1_30 -GType nm_setting_veth_get_type(void); -NM_AVAILABLE_IN_1_30 -NMSetting *nm_setting_veth_new(void); - -NM_AVAILABLE_IN_1_30 -const char *nm_setting_veth_get_peer(NMSettingVeth *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_VETH_H__ */ diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c deleted file mode 100644 index 123c11919c..0000000000 --- a/libnm-core/nm-setting-vlan.c +++ /dev/null @@ -1,983 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2014 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-vlan.h" - -#include - -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" -#include "nm-utils.h" -#include "nm-core-types-internal.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" -#include "nm-setting-wired.h" -#include "nm-connection-private.h" - -/** - * SECTION:nm-setting-vlan - * @short_description: Describes connection properties for VLAN interfaces - * - * The #NMSettingVlan object is a #NMSetting subclass that describes properties - * necessary for connection to VLAN interfaces. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingVlan, - PROP_PARENT, - PROP_ID, - PROP_FLAGS, - PROP_INGRESS_PRIORITY_MAP, - PROP_EGRESS_PRIORITY_MAP, ); - -typedef struct { - GSList *ingress_priority_map; - GSList *egress_priority_map; - char * parent; - guint32 id; - guint32 flags; -} NMSettingVlanPrivate; - -G_DEFINE_TYPE(NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING) - -#define NM_SETTING_VLAN_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_VLAN, NMSettingVlanPrivate)) - -/*****************************************************************************/ - -#define MAX_SKB_PRIO G_MAXUINT32 -#define MAX_8021P_PRIO 7 /* Max 802.1p priority */ - -/** - * nm_setting_vlan_get_parent: - * @setting: the #NMSettingVlan - * - * Returns: the #NMSettingVlan:parent property of the setting - **/ -const char * -nm_setting_vlan_get_parent(NMSettingVlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), NULL); - return NM_SETTING_VLAN_GET_PRIVATE(setting)->parent; -} - -/** - * nm_setting_vlan_get_id: - * @setting: the #NMSettingVlan - * - * Returns: the #NMSettingVlan:id property of the setting - **/ -guint32 -nm_setting_vlan_get_id(NMSettingVlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), 0); - return NM_SETTING_VLAN_GET_PRIVATE(setting)->id; -} - -/** - * nm_setting_vlan_get_flags: - * @setting: the #NMSettingVlan - * - * Returns: the #NMSettingVlan:flags property of the setting - **/ -guint32 -nm_setting_vlan_get_flags(NMSettingVlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), 0); - return NM_SETTING_VLAN_GET_PRIVATE(setting)->flags; -} - -static NMVlanQosMapping * -priority_map_new(guint32 from, guint32 to) -{ - NMVlanQosMapping *mapping; - - mapping = g_new(NMVlanQosMapping, 1); - *mapping = (NMVlanQosMapping){ - .from = from, - .to = to, - }; - return mapping; -} - -static NMVlanQosMapping * -priority_map_new_from_str(NMVlanPriorityMap map, const char *str) -{ - guint32 from, to; - - if (!nm_utils_vlan_priority_map_parse_str(map, str, FALSE, &from, &to, NULL)) - return NULL; - return priority_map_new(from, to); -} - -static void -priority_map_free(NMVlanQosMapping *map) -{ - nm_assert(map); - g_free(map); -} - -static GSList * -get_map(NMSettingVlan *self, NMVlanPriorityMap map) -{ - if (map == NM_VLAN_INGRESS_MAP) - return NM_SETTING_VLAN_GET_PRIVATE(self)->ingress_priority_map; - else if (map == NM_VLAN_EGRESS_MAP) - return NM_SETTING_VLAN_GET_PRIVATE(self)->egress_priority_map; - nm_assert_not_reached(); - return NULL; -} - -static int -prio_map_compare(gconstpointer p_a, gconstpointer p_b) -{ - const NMVlanQosMapping *a = p_a; - const NMVlanQosMapping *b = p_b; - - return a->from < b->from - ? -1 - : (a->from > b->from ? 1 : (a->to < b->to ? -1 : (a->to > b->to ? 1 : 0))); -} - -static void -set_map(NMSettingVlan *self, NMVlanPriorityMap map, GSList *list) -{ - /* Assert that the list is sorted */ -#if NM_MORE_ASSERTS >= 2 - { - GSList *iter, *last; - - last = list; - iter = list ? list->next : NULL; - while (iter) { - const NMVlanQosMapping *l = last->data; - const NMVlanQosMapping *m = iter->data; - - nm_assert(prio_map_compare(last->data, iter->data) < 0); - - /* Also reject duplicates (based on "from") */ - nm_assert(l->from < m->from); - - last = iter; - iter = iter->next; - } - } -#endif - - if (map == NM_VLAN_INGRESS_MAP) { - NM_SETTING_VLAN_GET_PRIVATE(self)->ingress_priority_map = list; - _notify(self, PROP_INGRESS_PRIORITY_MAP); - } else if (map == NM_VLAN_EGRESS_MAP) { - NM_SETTING_VLAN_GET_PRIVATE(self)->egress_priority_map = list; - _notify(self, PROP_EGRESS_PRIORITY_MAP); - } else - nm_assert_not_reached(); -} - -static gboolean -check_replace_duplicate_priority(GSList *list, guint32 from, guint32 to) -{ - GSList * iter; - NMVlanQosMapping *p; - - for (iter = list; iter; iter = g_slist_next(iter)) { - p = iter->data; - if (p->from == from) { - p->to = to; - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_vlan_add_priority_str: - * @setting: the #NMSettingVlan - * @map: the type of priority map - * @str: the string which contains a priority map, like "3:7" - * - * Adds a priority map entry into either the #NMSettingVlan:ingress_priority_map - * or the #NMSettingVlan:egress_priority_map properties. The priority map maps - * the Linux SKB priorities to 802.1p priorities. - * - * Returns: %TRUE if the entry was successfully added to the list, or it - * overwrote the old value, %FALSE if @str is not a valid mapping. - */ -gboolean -nm_setting_vlan_add_priority_str(NMSettingVlan *setting, NMVlanPriorityMap map, const char *str) -{ - GSList * list = NULL; - NMVlanQosMapping *item = NULL; - - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); - g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE); - g_return_val_if_fail(str && str[0], FALSE); - - item = priority_map_new_from_str(map, str); - if (!item) - return FALSE; - - list = get_map(setting, map); - - /* Duplicates get replaced */ - if (check_replace_duplicate_priority(list, item->from, item->to)) { - g_free(item); - if (map == NM_VLAN_INGRESS_MAP) - _notify(setting, PROP_INGRESS_PRIORITY_MAP); - else - _notify(setting, PROP_EGRESS_PRIORITY_MAP); - return TRUE; - } - - set_map(setting, map, g_slist_insert_sorted(list, item, prio_map_compare)); - return TRUE; -} - -/** - * nm_setting_vlan_get_num_priorities: - * @setting: the #NMSettingVlan - * @map: the type of priority map - * - * Returns the number of entries in the - * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map - * properties of this setting. - * - * Returns: return the number of ingress/egress priority entries. - **/ -gint32 -nm_setting_vlan_get_num_priorities(NMSettingVlan *setting, NMVlanPriorityMap map) -{ - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), -1); - g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, -1); - - return g_slist_length(get_map(setting, map)); -} - -/** - * nm_setting_vlan_get_priority: - * @setting: the #NMSettingVlan - * @map: the type of priority map - * @idx: the zero-based index of the ingress/egress priority map entry - * @out_from: (out) (allow-none): on return the value of the priority map's 'from' item - * @out_to: (out) (allow-none): on return the value of priority map's 'to' item - * - * Retrieve one of the entries of the #NMSettingVlan:ingress_priority_map - * or #NMSettingVlan:egress_priority_map properties of this setting. - * - * Returns: returns %TRUE if @idx is in range. Otherwise, %FALSE. - **/ -gboolean -nm_setting_vlan_get_priority(NMSettingVlan * setting, - NMVlanPriorityMap map, - guint32 idx, - guint32 * out_from, - guint32 * out_to) -{ - NMVlanQosMapping *item; - GSList * list; - - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); - g_return_val_if_fail(NM_IN_SET(map, NM_VLAN_INGRESS_MAP, NM_VLAN_EGRESS_MAP), FALSE); - - list = get_map(setting, map); - item = g_slist_nth_data(list, idx); - - if (!item) { - NM_SET_OUT(out_from, 0); - NM_SET_OUT(out_to, 0); - return FALSE; - } - - NM_SET_OUT(out_from, item->from); - NM_SET_OUT(out_to, item->to); - return TRUE; -} - -/** - * nm_setting_vlan_add_priority: - * @setting: the #NMSettingVlan - * @map: the type of priority map - * @from: the priority to map to @to - * @to: the priority to map @from to - * - * Adds a priority mapping to the #NMSettingVlan:ingress_priority_map or - * #NMSettingVlan:egress_priority_map properties of the setting. If @from is - * already in the given priority map, this function will overwrite the - * existing entry with the new @to. - * - * If @map is #NM_VLAN_INGRESS_MAP then @from is the incoming 802.1q VLAN - * Priority Code Point (PCP) value, and @to is the Linux SKB priority value. - * - * If @map is #NM_VLAN_EGRESS_MAP then @from is the Linux SKB priority value and - * @to is the outgoing 802.1q VLAN Priority Code Point (PCP) value. - * - * Returns: %TRUE. - */ -gboolean -nm_setting_vlan_add_priority(NMSettingVlan * setting, - NMVlanPriorityMap map, - guint32 from, - guint32 to) -{ - GSList * list = NULL; - NMVlanQosMapping *item; - - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); - g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE); - - list = get_map(setting, map); - if (check_replace_duplicate_priority(list, from, to)) { - if (map == NM_VLAN_INGRESS_MAP) - _notify(setting, PROP_INGRESS_PRIORITY_MAP); - else - _notify(setting, PROP_EGRESS_PRIORITY_MAP); - return TRUE; - } - - item = g_malloc0(sizeof(NMVlanQosMapping)); - item->from = from; - item->to = to; - set_map(setting, map, g_slist_insert_sorted(list, item, prio_map_compare)); - - return TRUE; -} - -gboolean -_nm_setting_vlan_set_priorities(NMSettingVlan * setting, - NMVlanPriorityMap map, - const NMVlanQosMapping *qos_map, - guint n_qos_map) -{ - gboolean has_changes = FALSE; - GSList * map_prev, *map_new; - guint i; - gint64 from_last; - - map_prev = get_map(setting, map); - - if (n_qos_map != g_slist_length(map_prev)) - has_changes = TRUE; - else { - const GSList *iter; - - iter = map_prev; - for (i = 0; i < n_qos_map; i++, iter = iter->next) { - const NMVlanQosMapping *m = iter->data; - - if (m->from != qos_map[i].from || m->to != qos_map[i].to) { - has_changes = TRUE; - break; - } - } - } - - if (!has_changes) - return FALSE; - - map_new = NULL; - from_last = G_MAXINT64; - for (i = n_qos_map; i > 0;) { - const NMVlanQosMapping *m = &qos_map[--i]; - NMVlanQosMapping * item; - - /* We require the array to be presorted. */ - if (m->from >= from_last) - g_return_val_if_reached(FALSE); - from_last = m->from; - - item = g_malloc0(sizeof(NMVlanQosMapping)); - item->from = m->from; - item->to = m->to; - map_new = g_slist_prepend(map_new, item); - } - - g_slist_free_full(map_prev, g_free); - set_map(setting, map, map_new); - - return TRUE; -} - -void -_nm_setting_vlan_get_priorities(NMSettingVlan * setting, - NMVlanPriorityMap map, - NMVlanQosMapping **out_qos_map, - guint * out_n_qos_map) -{ - GSList * list; - NMVlanQosMapping *qos_map = NULL; - guint n_qos_map, i; - - list = get_map(setting, map); - - n_qos_map = g_slist_length(list); - - if (n_qos_map > 0) { - qos_map = g_new(NMVlanQosMapping, n_qos_map); - - for (i = 0; list; i++, list = list->next) { - nm_assert(i < n_qos_map); - qos_map[i] = *((const NMVlanQosMapping *) list->data); - } - } - *out_qos_map = qos_map; - *out_n_qos_map = n_qos_map; -} - -/** - * nm_setting_vlan_remove_priority: - * @setting: the #NMSettingVlan - * @map: the type of priority map - * @idx: the zero-based index of the priority map to remove - * - * Removes the priority map at index @idx from the - * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map - * properties. - */ -void -nm_setting_vlan_remove_priority(NMSettingVlan *setting, NMVlanPriorityMap map, guint32 idx) -{ - GSList *list = NULL, *item = NULL; - - g_return_if_fail(NM_IS_SETTING_VLAN(setting)); - g_return_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP); - - list = get_map(setting, map); - g_return_if_fail(idx < g_slist_length(list)); - - item = g_slist_nth(list, idx); - priority_map_free((NMVlanQosMapping *) (item->data)); - set_map(setting, map, g_slist_delete_link(list, item)); -} - -static gboolean -priority_map_remove_by_value(NMSettingVlan * setting, - NMVlanPriorityMap map, - guint32 from, - guint32 to, - gboolean wildcard_to) -{ - GSList * list = NULL, *iter = NULL; - NMVlanQosMapping *item; - - nm_assert(NM_IS_SETTING_VLAN(setting)); - nm_assert(NM_IN_SET(map, NM_VLAN_INGRESS_MAP, NM_VLAN_EGRESS_MAP)); - - list = get_map(setting, map); - for (iter = list; iter; iter = g_slist_next(iter)) { - item = iter->data; - - if (item->from != from) - continue; - if (!wildcard_to && item->to != to) - continue; - - priority_map_free((NMVlanQosMapping *) (iter->data)); - set_map(setting, map, g_slist_delete_link(list, iter)); - return TRUE; - } - return FALSE; -} - -/** - * nm_setting_vlan_remove_priority_by_value: - * @setting: the #NMSettingVlan - * @map: the type of priority map - * @from: the priority to map to @to - * @to: the priority to map @from to - * - * Removes the priority map @form:@to from the #NMSettingVlan:ingress_priority_map - * or #NMSettingVlan:egress_priority_map (according to @map argument) - * properties. - * - * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not. - */ -gboolean -nm_setting_vlan_remove_priority_by_value(NMSettingVlan * setting, - NMVlanPriorityMap map, - guint32 from, - guint32 to) -{ - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); - g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE); - - return priority_map_remove_by_value(setting, map, from, to, FALSE); -} - -/** - * nm_setting_vlan_remove_priority_str_by_value: - * @setting: the #NMSettingVlan - * @map: the type of priority map - * @str: the string which contains a priority map, like "3:7" - * - * Removes the priority map @str from the #NMSettingVlan:ingress_priority_map - * or #NMSettingVlan:egress_priority_map (according to @map argument) - * properties. - * - * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not. - */ -gboolean -nm_setting_vlan_remove_priority_str_by_value(NMSettingVlan * setting, - NMVlanPriorityMap map, - const char * str) -{ - gboolean is_wildcard_to; - guint32 from, to; - - g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); - g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE); - - if (!nm_utils_vlan_priority_map_parse_str(map, str, TRUE, &from, &to, &is_wildcard_to)) - return FALSE; - return priority_map_remove_by_value(setting, map, from, to, is_wildcard_to); -} - -/** - * nm_setting_vlan_clear_priorities: - * @setting: the #NMSettingVlan - * @map: the type of priority map - * - * Clear all the entries from #NMSettingVlan:ingress_priority_map or - * #NMSettingVlan:egress_priority_map properties. - */ -void -nm_setting_vlan_clear_priorities(NMSettingVlan *setting, NMVlanPriorityMap map) -{ - GSList *list = NULL; - - g_return_if_fail(NM_IS_SETTING_VLAN(setting)); - g_return_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP); - - list = get_map(setting, map); - g_slist_free_full(list, g_free); - set_map(setting, map, NULL); -} - -/*****************************************************************************/ - -static int -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(setting); - NMSettingConnection * s_con; - NMSettingWired * s_wired; - - if (connection) { - s_con = nm_connection_get_setting_connection(connection); - s_wired = nm_connection_get_setting_wired(connection); - } else { - s_con = NULL; - s_wired = NULL; - } - - if (priv->parent) { - if (nm_utils_is_uuid(priv->parent)) { - /* If we have an NMSettingConnection:master with slave-type="vlan", - * then it must be the same UUID. - */ - if (s_con) { - const char *master = NULL, *slave_type = NULL; - - slave_type = nm_setting_connection_get_slave_type(s_con); - if (!g_strcmp0(slave_type, NM_SETTING_VLAN_SETTING_NAME)) - master = nm_setting_connection_get_master(s_con); - - if (master && g_strcmp0(priv->parent, master) != 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' value doesn't match '%s=%s'"), - priv->parent, - NM_SETTING_CONNECTION_MASTER, - master); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_VLAN_SETTING_NAME, - NM_SETTING_VLAN_PARENT); - return FALSE; - } - } - } else if (!nm_utils_ifname_valid_kernel(priv->parent, NULL)) { - /* parent must be either a UUID or an interface name */ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is neither an UUID nor an interface name"), - priv->parent); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT); - return FALSE; - } - } else { - /* If parent is NULL, the parent must be specified via - * NMSettingWired:mac-address. - */ - if (connection && (!s_wired || !nm_setting_wired_get_mac_address(s_wired))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is not specified and neither is '%s:%s'"), - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_MAC_ADDRESS); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT); - return FALSE; - } - } - - if (priv->id >= 4095) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the vlan id must be in range 0-4094 but is %u"), - priv->id); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_ID); - return FALSE; - } - - if (priv->flags & ~NM_VLAN_FLAGS_ALL) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("flags are invalid")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_FLAGS); - return FALSE; - } - - if (connection && !s_wired) { - /* technically, a VLAN setting does not require an ethernet setting. However, - * the ifcfg-rh reader always adds a ethernet setting when reading a vlan setting. - * Thus, in order to be consistent, always add one via normalization. */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_SETTING_NOT_FOUND, - _("vlan setting should have a ethernet setting as well")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_FLAGS); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - - return TRUE; -} - -static GVariant * -_override_flags_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - return g_variant_new_uint32(nm_setting_vlan_get_flags((NMSettingVlan *) setting)); -} - -static gboolean -_override_flags_not_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - NMSettingParseFlags parse_flags, - GError ** error) -{ - /* we changed the default value for FLAGS. When an older client - * doesn't serialize the property, we assume it is the old default. */ - g_object_set(G_OBJECT(setting), NM_SETTING_VLAN_FLAGS, (NMVlanFlags) 0, NULL); - return TRUE; -} - -static GSList * -priority_strv_to_maplist(NMVlanPriorityMap map, char **strv) -{ - GSList *list = NULL; - gsize i; - - for (i = 0; strv && strv[i]; i++) { - guint32 from, to; - - if (!nm_utils_vlan_priority_map_parse_str(map, strv[i], FALSE, &from, &to, NULL)) - continue; - if (check_replace_duplicate_priority(list, from, to)) - continue; - list = g_slist_prepend(list, priority_map_new(from, to)); - } - return g_slist_sort(list, prio_map_compare); -} - -static char ** -priority_maplist_to_strv(GSList *list) -{ - GSList * iter; - GPtrArray *strv; - - strv = g_ptr_array_new(); - - for (iter = list; iter; iter = g_slist_next(iter)) { - NMVlanQosMapping *item = iter->data; - - g_ptr_array_add(strv, g_strdup_printf("%d:%d", item->from, item->to)); - } - g_ptr_array_add(strv, NULL); - - return (char **) g_ptr_array_free(strv, FALSE); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingVlan * setting = NM_SETTING_VLAN(object); - NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_value_set_string(value, priv->parent); - break; - case PROP_ID: - g_value_set_uint(value, priv->id); - break; - case PROP_FLAGS: - g_value_set_flags(value, priv->flags); - break; - case PROP_INGRESS_PRIORITY_MAP: - g_value_take_boxed(value, priority_maplist_to_strv(priv->ingress_priority_map)); - break; - case PROP_EGRESS_PRIORITY_MAP: - g_value_take_boxed(value, priority_maplist_to_strv(priv->egress_priority_map)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingVlan * setting = NM_SETTING_VLAN(object); - NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_free(priv->parent); - priv->parent = g_value_dup_string(value); - break; - case PROP_ID: - priv->id = g_value_get_uint(value); - break; - case PROP_FLAGS: - priv->flags = g_value_get_flags(value); - break; - case PROP_INGRESS_PRIORITY_MAP: - g_slist_free_full(priv->ingress_priority_map, g_free); - priv->ingress_priority_map = - priority_strv_to_maplist(NM_VLAN_INGRESS_MAP, g_value_get_boxed(value)); - break; - case PROP_EGRESS_PRIORITY_MAP: - g_slist_free_full(priv->egress_priority_map, g_free); - priv->egress_priority_map = - priority_strv_to_maplist(NM_VLAN_EGRESS_MAP, g_value_get_boxed(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_vlan_init(NMSettingVlan *self) -{ - NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(self); - - priv->flags = NM_VLAN_FLAG_REORDER_HEADERS; -} - -/** - * nm_setting_vlan_new: - * - * Creates a new #NMSettingVlan object with default values. - * - * Returns: (transfer full): the new empty #NMSettingVlan object - **/ -NMSetting * -nm_setting_vlan_new(void) -{ - return g_object_new(NM_TYPE_SETTING_VLAN, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingVlan * setting = NM_SETTING_VLAN(object); - NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(setting); - - g_free(priv->parent); - g_slist_free_full(priv->ingress_priority_map, g_free); - g_slist_free_full(priv->egress_priority_map, g_free); - - G_OBJECT_CLASS(nm_setting_vlan_parent_class)->finalize(object); -} - -static void -nm_setting_vlan_class_init(NMSettingVlanClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingVlanPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingVlan:parent: - * - * If given, specifies the parent interface name or parent connection UUID - * from which this VLAN interface should be created. If this property is - * not specified, the connection must contain an #NMSettingWired setting - * with a #NMSettingWired:mac-address property. - **/ - /* ---ifcfg-rh--- - * property: parent - * variable: DEVICE or PHYSDEV - * description: Parent interface of the VLAN. - * ---end--- - */ - obj_properties[PROP_PARENT] = g_param_spec_string( - NM_SETTING_VLAN_PARENT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVlan:id: - * - * The VLAN identifier that the interface created by this connection should - * be assigned. The valid range is from 0 to 4094, without the reserved id 4095. - **/ - /* ---ifcfg-rh--- - * property: id - * variable: VLAN_ID or DEVICE - * description: VLAN identifier. - * ---end--- - */ - obj_properties[PROP_ID] = - g_param_spec_uint(NM_SETTING_VLAN_ID, - "", - "", - 0, - 4095, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVlan:flags: - * - * One or more flags which control the behavior and features of the VLAN - * interface. Flags include %NM_VLAN_FLAG_REORDER_HEADERS (reordering of - * output packet headers), %NM_VLAN_FLAG_GVRP (use of the GVRP protocol), - * and %NM_VLAN_FLAG_LOOSE_BINDING (loose binding of the interface to its - * master device's operating state). %NM_VLAN_FLAG_MVRP (use of the MVRP - * protocol). - * - * The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, - * but it used to be 0. To preserve backward compatibility, the default-value - * in the D-Bus API continues to be 0 and a missing property on D-Bus - * is still considered as 0. - **/ - /* ---ifcfg-rh--- - * property: flags - * variable: GVRP, MVRP, VLAN_FLAGS - * values: "yes or "no" for GVRP and MVRP; "LOOSE_BINDING" and "NO_REORDER_HDR" for VLAN_FLAGS - * description: VLAN flags. - * ---end--- - */ - obj_properties[PROP_FLAGS] = g_param_spec_flags(NM_SETTING_VLAN_FLAGS, - "", - "", - NM_TYPE_VLAN_FLAGS, - NM_VLAN_FLAG_REORDER_HEADERS, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj( - properties_override, - obj_properties[PROP_FLAGS], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT32, - .to_dbus_fcn = _override_flags_get, - .missing_from_dbus_fcn = _override_flags_not_set, )); - - /** - * NMSettingVlan:ingress-priority-map: - * - * For incoming packets, a list of mappings from 802.1p priorities to Linux - * SKB priorities. The mapping is given in the format "from:to" where both - * "from" and "to" are unsigned integers, ie "7:3". - **/ - /* ---ifcfg-rh--- - * property: ingress-priority-map - * variable: VLAN_INGRESS_PRIORITY_MAP - * description: Ingress priority mapping. - * example: VLAN_INGRESS_PRIORITY_MAP=4:2,3:5 - * ---end--- - */ - obj_properties[PROP_INGRESS_PRIORITY_MAP] = g_param_spec_boxed( - NM_SETTING_VLAN_INGRESS_PRIORITY_MAP, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVlan:egress-priority-map: - * - * For outgoing packets, a list of mappings from Linux SKB priorities to - * 802.1p priorities. The mapping is given in the format "from:to" where - * both "from" and "to" are unsigned integers, ie "7:3". - **/ - /* ---ifcfg-rh--- - * property: egress-priority-map - * variable: VLAN_EGRESS_PRIORITY_MAP - * description: Egress priority mapping. - * example: VLAN_EGRESS_PRIORITY_MAP=5:4,4:1,3:7 - * ---end--- - */ - obj_properties[PROP_EGRESS_PRIORITY_MAP] = g_param_spec_boxed( - NM_SETTING_VLAN_EGRESS_PRIORITY_MAP, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /* ---ifcfg-rh--- - * property: interface-name - * variable: PHYSDEV and VLAN_ID, or DEVICE - * description: VLAN interface name. - * If all variables are set, parent device from PHYSDEV takes precedence over DEVICE, - * but VLAN id from DEVICE takes precedence over VLAN_ID. - * example: PHYSDEV=eth0, VLAN_ID=12; or DEVICE=eth0.12 - * ---end--- - * ---dbus--- - * property: interface-name - * format: string - * description: Deprecated in favor of connection.interface-name, but can - * be used for backward-compatibility with older daemons, to set the - * vlan's interface name. - * ---end--- - */ - _nm_properties_override_dbus(properties_override, - "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_VLAN, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-vlan.h b/libnm-core/nm-setting-vlan.h deleted file mode 100644 index 4b2ca429cf..0000000000 --- a/libnm-core/nm-setting-vlan.h +++ /dev/null @@ -1,134 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2014 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_VLAN_H__ -#define __NM_SETTING_VLAN_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_VLAN (nm_setting_vlan_get_type()) -#define NM_SETTING_VLAN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VLAN, NMSettingVlan)) -#define NM_SETTING_VLAN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_VLANCONFIG, NMSettingVlanClass)) -#define NM_IS_SETTING_VLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VLAN)) -#define NM_IS_SETTING_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VLAN)) -#define NM_SETTING_VLAN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VLAN, NMSettingVlanClass)) - -#define NM_SETTING_VLAN_SETTING_NAME "vlan" - -#define NM_SETTING_VLAN_PARENT "parent" -#define NM_SETTING_VLAN_ID "id" -#define NM_SETTING_VLAN_FLAGS "flags" -#define NM_SETTING_VLAN_INGRESS_PRIORITY_MAP "ingress-priority-map" -#define NM_SETTING_VLAN_EGRESS_PRIORITY_MAP "egress-priority-map" - -/** - * NMSettingVlan: - * - * VLAN Settings - */ -struct _NMSettingVlan { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingVlanClass; - -/** - * NMVlanPriorityMap: - * @NM_VLAN_INGRESS_MAP: map for incoming data - * @NM_VLAN_EGRESS_MAP: map for outgoing data - * - * A selector for traffic priority maps; these map Linux SKB priorities - * to 802.1p priorities used in VLANs. - **/ -/* clang-format off */ -typedef enum { - NM_VLAN_INGRESS_MAP, - NM_VLAN_EGRESS_MAP -} NMVlanPriorityMap; -/* clang-format on */ - -/** - * NMVlanFlags: - * @NM_VLAN_FLAG_REORDER_HEADERS: indicates that this interface should reorder - * outgoing packet headers to look more like a non-VLAN Ethernet interface - * @NM_VLAN_FLAG_GVRP: indicates that this interface should use GVRP to register - * itself with its switch - * @NM_VLAN_FLAG_LOOSE_BINDING: indicates that this interface's operating - * state is tied to the underlying network interface but other details - * (like routing) are not. - * @NM_VLAN_FLAG_MVRP: indicates that this interface should use MVRP to register - * itself with its switch - * - * #NMVlanFlags values control the behavior of the VLAN interface. - **/ -typedef enum { /*< flags >*/ - NM_VLAN_FLAG_REORDER_HEADERS = 0x1, - NM_VLAN_FLAG_GVRP = 0x2, - NM_VLAN_FLAG_LOOSE_BINDING = 0x4, - NM_VLAN_FLAG_MVRP = 0x8, - - /* NOTE: if adding flags update nm-setting-vlan.c::verify() */ - - /* NOTE: these flags must correspond to the value from the kernel - * header files. */ -} NMVlanFlags; - -#define NM_VLAN_FLAGS_ALL \ - (NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP | NM_VLAN_FLAG_LOOSE_BINDING \ - | NM_VLAN_FLAG_MVRP) - -GType nm_setting_vlan_get_type(void); -NMSetting *nm_setting_vlan_new(void); - -const char *nm_setting_vlan_get_parent(NMSettingVlan *setting); -guint32 nm_setting_vlan_get_id(NMSettingVlan *setting); -guint32 nm_setting_vlan_get_flags(NMSettingVlan *setting); - -gint32 nm_setting_vlan_get_num_priorities(NMSettingVlan *setting, NMVlanPriorityMap map); - -gboolean nm_setting_vlan_get_priority(NMSettingVlan * setting, - NMVlanPriorityMap map, - guint32 idx, - guint32 * out_from, - guint32 * out_to); - -gboolean nm_setting_vlan_add_priority(NMSettingVlan * setting, - NMVlanPriorityMap map, - guint32 from, - guint32 to); - -void nm_setting_vlan_remove_priority(NMSettingVlan *setting, NMVlanPriorityMap map, guint32 idx); - -gboolean nm_setting_vlan_remove_priority_by_value(NMSettingVlan * setting, - NMVlanPriorityMap map, - guint32 from, - guint32 to); - -gboolean nm_setting_vlan_remove_priority_str_by_value(NMSettingVlan * setting, - NMVlanPriorityMap map, - const char * str); - -void nm_setting_vlan_clear_priorities(NMSettingVlan *setting, NMVlanPriorityMap map); - -gboolean -nm_setting_vlan_add_priority_str(NMSettingVlan *setting, NMVlanPriorityMap map, const char *str); - -G_END_DECLS - -#endif /* __NM_SETTING_VLAN_H__ */ diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c deleted file mode 100644 index 8ee5c2b972..0000000000 --- a/libnm-core/nm-setting-vpn.c +++ /dev/null @@ -1,1233 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-vpn.h" - -#include - -#include "nm-glib-aux/nm-secret-utils.h" -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-vpn - * @short_description: Describes connection properties for Virtual Private Networks - * - * The #NMSettingVpn object is a #NMSetting subclass that describes properties - * necessary for connection to Virtual Private Networks. NetworkManager uses - * a plugin architecture to allow easier use of new VPN types, and this - * setting abstracts the configuration for those plugins. Since the configuration - * options are only known to the VPN plugins themselves, the VPN configuration - * options are stored as key/value pairs of strings rather than GObject - * properties. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingVpn, - PROP_SERVICE_TYPE, - PROP_USER_NAME, - PROP_PERSISTENT, - PROP_DATA, - PROP_SECRETS, - PROP_TIMEOUT, ); - -typedef struct { - char *service_type; - - /* username of the user requesting this connection, thus - * it's really only valid for user connections, and it also - * should never be saved out to persistent config. - */ - char *user_name; - - /* Whether the VPN stays up across link changes, until the user - * explicitly disconnects it. - */ - gboolean persistent; - - /* The hash table is created at setting object - * init time and should not be replaced. It is - * a char * -> char * mapping, and both the key - * and value are owned by the hash table, and should - * be allocated with functions whose value can be - * freed with g_free(). Should not contain secrets. - */ - GHashTable *data; - - /* The hash table is created at setting object - * init time and should not be replaced. It is - * a char * -> char * mapping, and both the key - * and value are owned by the hash table, and should - * be allocated with functions whose value can be - * freed with g_free(). Should contain secrets only. - */ - GHashTable *secrets; - - /* Timeout for the VPN service to establish the connection */ - guint32 timeout; -} NMSettingVpnPrivate; - -G_DEFINE_TYPE(NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING) - -#define NM_SETTING_VPN_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_VPN, NMSettingVpnPrivate)) - -/*****************************************************************************/ - -static GHashTable * -_ensure_strdict(GHashTable **p_hash, gboolean for_secrets) -{ - if (!*p_hash) { - *p_hash = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - for_secrets ? (GDestroyNotify) nm_free_secret : g_free); - } - return *p_hash; -} - -/*****************************************************************************/ - -/** - * nm_setting_vpn_get_service_type: - * @setting: the #NMSettingVpn - * - * Returns the service name of the VPN, which identifies the specific VPN - * plugin that should be used to connect to this VPN. - * - * Returns: the VPN plugin's service name - **/ -const char * -nm_setting_vpn_get_service_type(NMSettingVpn *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); - - return NM_SETTING_VPN_GET_PRIVATE(setting)->service_type; -} - -/** - * nm_setting_vpn_get_user_name: - * @setting: the #NMSettingVpn - * - * Returns: the #NMSettingVpn:user-name property of the setting - **/ -const char * -nm_setting_vpn_get_user_name(NMSettingVpn *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); - - return NM_SETTING_VPN_GET_PRIVATE(setting)->user_name; -} - -/** - * nm_setting_vpn_get_persistent: - * @setting: the #NMSettingVpn - * - * Returns: the #NMSettingVpn:persistent property of the setting - **/ -gboolean -nm_setting_vpn_get_persistent(NMSettingVpn *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), FALSE); - - return NM_SETTING_VPN_GET_PRIVATE(setting)->persistent; -} - -/** - * nm_setting_vpn_get_num_data_items: - * @setting: the #NMSettingVpn - * - * Gets number of key/value pairs of VPN configuration data. - * - * Returns: the number of VPN plugin specific configuration data items - **/ -guint32 -nm_setting_vpn_get_num_data_items(NMSettingVpn *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), 0); - - return nm_g_hash_table_size(NM_SETTING_VPN_GET_PRIVATE(setting)->data); -} - -/** - * nm_setting_vpn_add_data_item: - * @setting: the #NMSettingVpn - * @key: a name that uniquely identifies the given value @item - * @item: (allow-none): the value to be referenced by @key - * - * Establishes a relationship between @key and @item internally in the - * setting which may be retrieved later. Should not be used to store passwords - * or other secrets, which is what nm_setting_vpn_add_secret() is for. - * - * Before 1.24, @item must not be %NULL and not an empty string. Since 1.24, - * @item can be set to an empty string. It can also be set to %NULL to unset - * the key. In that case, the behavior is as if calling nm_setting_vpn_remove_data_item(). - **/ -void -nm_setting_vpn_add_data_item(NMSettingVpn *setting, const char *key, const char *item) -{ - if (!item) { - nm_setting_vpn_remove_data_item(setting, key); - return; - } - - g_return_if_fail(NM_IS_SETTING_VPN(setting)); - g_return_if_fail(key && key[0]); - - g_hash_table_insert(_ensure_strdict(&NM_SETTING_VPN_GET_PRIVATE(setting)->data, FALSE), - g_strdup(key), - g_strdup(item)); - _notify(setting, PROP_DATA); -} - -/** - * nm_setting_vpn_get_data_item: - * @setting: the #NMSettingVpn - * @key: the name of the data item to retrieve - * - * Retrieves the data item of a key/value relationship previously established - * by nm_setting_vpn_add_data_item(). - * - * Returns: the data item, if any - **/ -const char * -nm_setting_vpn_get_data_item(NMSettingVpn *setting, const char *key) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); - g_return_val_if_fail(key && key[0], NULL); - - return nm_g_hash_table_lookup(NM_SETTING_VPN_GET_PRIVATE(setting)->data, key); -} - -/** - * nm_setting_vpn_get_data_keys: - * @setting: the #NMSettingVpn - * @out_length: (allow-none) (out): the length of the returned array - * - * Retrieves every data key inside @setting, as an array. - * - * Returns: (array length=out_length) (transfer container): a - * %NULL-terminated array containing each data key or %NULL if - * there are no data items. - * - * Since: 1.12 - */ -const char ** -nm_setting_vpn_get_data_keys(NMSettingVpn *setting, guint *out_length) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); - - return nm_utils_strdict_get_keys(NM_SETTING_VPN_GET_PRIVATE(setting)->data, TRUE, out_length); -} - -/** - * nm_setting_vpn_remove_data_item: - * @setting: the #NMSettingVpn - * @key: the name of the data item to remove - * - * Deletes a key/value relationship previously established by - * nm_setting_vpn_add_data_item(). - * - * Returns: %TRUE if the data item was found and removed from the internal list, - * %FALSE if it was not. - **/ -gboolean -nm_setting_vpn_remove_data_item(NMSettingVpn *setting, const char *key) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), FALSE); - g_return_val_if_fail(key && key[0], FALSE); - - if (nm_g_hash_table_remove(NM_SETTING_VPN_GET_PRIVATE(setting)->data, key)) { - _notify(setting, PROP_DATA); - return TRUE; - } - return FALSE; -} - -static void -foreach_item_helper(NMSettingVpn *self, GHashTable **p_hash, NMVpnIterFunc func, gpointer user_data) -{ - gs_unref_object NMSettingVpn *self_keep_alive = NULL; - gs_strfreev char ** keys = NULL; - guint i, len; - - nm_assert(NM_IS_SETTING_VPN(self)); - nm_assert(func); - - keys = nm_utils_strv_make_deep_copied(nm_utils_strdict_get_keys(*p_hash, TRUE, &len)); - if (len == 0u) { - nm_assert(!keys); - return; - } - - if (len > 1u) - self_keep_alive = g_object_ref(self); - - for (i = 0; i < len; i++) { - /* NOTE: note that we call the function with a clone of @key, - * not with the actual key from the dictionary. - * - * The @value on the other hand, is not cloned but retrieved before - * invoking @func(). That means, if @func() modifies the setting while - * being called, the values are as they currently are, but the - * keys (and their order) were pre-determined before starting to - * invoke the callbacks. - * - * The idea is to give some sensible, stable behavior in case the user - * modifies the settings. Whether this particular behavior is optimal - * is unclear. It's probably a bad idea to modify the settings while - * iterating the values. But at least, it's a safe thing to do and we - * do something sensible. */ - func(keys[i], nm_g_hash_table_lookup(*p_hash, keys[i]), user_data); - } -} - -/** - * nm_setting_vpn_foreach_data_item: - * @setting: a #NMSettingVpn - * @func: (scope call): an user provided function - * @user_data: data to be passed to @func - * - * Iterates all data items stored in this setting. It is safe to add, remove, - * and modify data items inside @func, though any additions or removals made - * during iteration will not be part of the iteration. - */ -void -nm_setting_vpn_foreach_data_item(NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data) -{ - g_return_if_fail(NM_IS_SETTING_VPN(setting)); - g_return_if_fail(func); - - foreach_item_helper(setting, &NM_SETTING_VPN_GET_PRIVATE(setting)->data, func, user_data); -} - -/** - * nm_setting_vpn_get_num_secrets: - * @setting: the #NMSettingVpn - * - * Gets number of VPN plugin specific secrets in the setting. - * - * Returns: the number of VPN plugin specific secrets - **/ -guint32 -nm_setting_vpn_get_num_secrets(NMSettingVpn *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), 0); - - return nm_g_hash_table_size(NM_SETTING_VPN_GET_PRIVATE(setting)->secrets); -} - -/** - * nm_setting_vpn_add_secret: - * @setting: the #NMSettingVpn - * @key: a name that uniquely identifies the given secret @secret - * @secret: (allow-none): the secret to be referenced by @key - * - * Establishes a relationship between @key and @secret internally in the - * setting which may be retrieved later. - * - * Before 1.24, @secret must not be %NULL and not an empty string. Since 1.24, - * @secret can be set to an empty string. It can also be set to %NULL to unset - * the key. In that case, the behavior is as if calling nm_setting_vpn_remove_secret(). - **/ -void -nm_setting_vpn_add_secret(NMSettingVpn *setting, const char *key, const char *secret) -{ - if (!secret) { - nm_setting_vpn_remove_secret(setting, key); - return; - } - - g_return_if_fail(NM_IS_SETTING_VPN(setting)); - g_return_if_fail(key && key[0]); - - g_hash_table_insert(_ensure_strdict(&NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, TRUE), - g_strdup(key), - g_strdup(secret)); - _notify(setting, PROP_SECRETS); -} - -/** - * nm_setting_vpn_get_secret: - * @setting: the #NMSettingVpn - * @key: the name of the secret to retrieve - * - * Retrieves the secret of a key/value relationship previously established - * by nm_setting_vpn_add_secret(). - * - * Returns: the secret, if any - **/ -const char * -nm_setting_vpn_get_secret(NMSettingVpn *setting, const char *key) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); - g_return_val_if_fail(key && key[0], NULL); - - return nm_g_hash_table_lookup(NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, key); -} - -/** - * nm_setting_vpn_get_secret_keys: - * @setting: the #NMSettingVpn - * @out_length: (allow-none) (out): the length of the returned array - * - * Retrieves every secret key inside @setting, as an array. - * - * Returns: (array length=out_length) (transfer container): a - * %NULL-terminated array containing each secret key or %NULL if - * there are no secrets. - * - * Since: 1.12 - */ -const char ** -nm_setting_vpn_get_secret_keys(NMSettingVpn *setting, guint *out_length) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); - - return nm_utils_strdict_get_keys(NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, - TRUE, - out_length); -} - -/** - * nm_setting_vpn_remove_secret: - * @setting: the #NMSettingVpn - * @key: the name of the secret to remove - * - * Deletes a key/value relationship previously established by - * nm_setting_vpn_add_secret(). - * - * Returns: %TRUE if the secret was found and removed from the internal list, - * %FALSE if it was not. - **/ -gboolean -nm_setting_vpn_remove_secret(NMSettingVpn *setting, const char *key) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), FALSE); - g_return_val_if_fail(key && key[0], FALSE); - - if (nm_g_hash_table_remove(NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, key)) { - _notify(setting, PROP_SECRETS); - return TRUE; - } - return FALSE; -} - -/** - * nm_setting_vpn_foreach_secret: - * @setting: a #NMSettingVpn - * @func: (scope call): an user provided function - * @user_data: data to be passed to @func - * - * Iterates all secrets stored in this setting. It is safe to add, remove, - * and modify secrets inside @func, though any additions or removals made during - * iteration will not be part of the iteration. - */ -void -nm_setting_vpn_foreach_secret(NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data) -{ - g_return_if_fail(NM_IS_SETTING_VPN(setting)); - g_return_if_fail(func); - - foreach_item_helper(setting, &NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, func, user_data); -} - -static gboolean -aggregate(NMSetting *setting, int type_i, gpointer arg) -{ - NMSettingVpnPrivate * priv = NM_SETTING_VPN_GET_PRIVATE(setting); - NMConnectionAggregateType type = type_i; - NMSettingSecretFlags secret_flags; - const char * key_name; - GHashTableIter iter; - - switch (type) { - case NM_CONNECTION_AGGREGATE_ANY_SECRETS: - if (nm_g_hash_table_size(priv->secrets) > 0u) { - *((gboolean *) arg) = TRUE; - return TRUE; - } - return FALSE; - - case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: - - if (priv->secrets) { - g_hash_table_iter_init(&iter, priv->secrets); - while (g_hash_table_iter_next(&iter, (gpointer *) &key_name, NULL)) { - if (!nm_setting_get_secret_flags(NM_SETTING(setting), - key_name, - &secret_flags, - NULL)) - nm_assert_not_reached(); - if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { - *((gboolean *) arg) = TRUE; - return TRUE; - } - } - } - - /* OK, we have no secrets with system-secret flags. - * But do we have any secret-flags (without secrets) that indicate system secrets? */ - if (priv->data) { - g_hash_table_iter_init(&iter, priv->data); - while (g_hash_table_iter_next(&iter, (gpointer *) &key_name, NULL)) { - gs_free char *secret_name = NULL; - - if (!NM_STR_HAS_SUFFIX(key_name, "-flags")) - continue; - secret_name = g_strndup(key_name, strlen(key_name) - NM_STRLEN("-flags")); - if (secret_name[0] == '\0') - continue; - if (!nm_setting_get_secret_flags(NM_SETTING(setting), - secret_name, - &secret_flags, - NULL)) - nm_assert_not_reached(); - if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { - *((gboolean *) arg) = TRUE; - return TRUE; - } - } - } - - return FALSE; - } - - g_return_val_if_reached(FALSE); -} - -/** - * nm_setting_vpn_get_timeout: - * @setting: the #NMSettingVpn - * - * Returns: the #NMSettingVpn:timeout property of the setting - * - * Since: 1.2 - **/ -guint32 -nm_setting_vpn_get_timeout(NMSettingVpn *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VPN(setting), 0); - - return NM_SETTING_VPN_GET_PRIVATE(setting)->timeout; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); - NMSettingConnection *s_con; - - if (!priv->service_type) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE); - return FALSE; - } - if (!priv->service_type[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE); - return FALSE; - } - - /* default username can be NULL, but can't be zero-length */ - if (priv->user_name && !priv->user_name[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_USER_NAME); - return FALSE; - } - - if (connection && (s_con = nm_connection_get_setting_connection(connection)) - && nm_setting_connection_get_multi_connect(s_con) != NM_CONNECTION_MULTI_CONNECT_DEFAULT) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("cannot set connection.multi-connect for VPN setting")); - return FALSE; - } - - return TRUE; -} - -static NMSettingUpdateSecretResult -update_secret_string(NMSetting *setting, const char *key, const char *value, GError **error) -{ - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); - - g_return_val_if_fail(key && key[0], NM_SETTING_UPDATE_SECRET_ERROR); - g_return_val_if_fail(value, NM_SETTING_UPDATE_SECRET_ERROR); - - if (nm_streq0(nm_g_hash_table_lookup(priv->secrets, key), value)) - return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - - g_hash_table_insert(_ensure_strdict(&priv->secrets, TRUE), g_strdup(key), g_strdup(value)); - return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; -} - -static NMSettingUpdateSecretResult -update_secret_dict(NMSetting *setting, GVariant *secrets, GError **error) -{ - NMSettingVpnPrivate * priv = NM_SETTING_VPN_GET_PRIVATE(setting); - GVariantIter iter; - const char * name, *value; - NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - - g_return_val_if_fail(secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR); - - /* Make sure the items are valid */ - g_variant_iter_init(&iter, secrets); - while (g_variant_iter_next(&iter, "{&s&s}", &name, &value)) { - if (!name[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("setting contained a secret with an empty name")); - g_prefix_error(error, "%s: ", NM_SETTING_VPN_SETTING_NAME); - return NM_SETTING_UPDATE_SECRET_ERROR; - } - } - - /* Now add the items to the settings' secrets list */ - g_variant_iter_init(&iter, secrets); - while (g_variant_iter_next(&iter, "{&s&s}", &name, &value)) { - if (nm_streq0(nm_g_hash_table_lookup(priv->secrets, name), value)) - continue; - - g_hash_table_insert(_ensure_strdict(&priv->secrets, TRUE), g_strdup(name), g_strdup(value)); - result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; - } - - return result; -} - -static int -update_one_secret(NMSetting *setting, const char *key, GVariant *value, GError **error) -{ - NMSettingUpdateSecretResult success = NM_SETTING_UPDATE_SECRET_ERROR; - - g_return_val_if_fail(key != NULL, NM_SETTING_UPDATE_SECRET_ERROR); - g_return_val_if_fail(value != NULL, NM_SETTING_UPDATE_SECRET_ERROR); - - if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { - /* Passing the string properties individually isn't correct, and won't - * produce the correct result, but for some reason that's how it used - * to be done. So even though it's not correct, keep the code around - * for compatibility's sake. - */ - success = update_secret_string(setting, key, g_variant_get_string(value, NULL), error); - } else if (g_variant_is_of_type(value, G_VARIANT_TYPE("a{ss}"))) { - if (!nm_streq(key, NM_SETTING_VPN_SECRETS)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, - _("not a secret property")); - g_prefix_error(error, "%s.%s ", NM_SETTING_VPN_SETTING_NAME, key); - } else - success = update_secret_dict(setting, value, error); - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("secret is not of correct type")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, key); - } - - if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) - _notify(NM_SETTING_VPN(setting), PROP_SECRETS); - - return success; -} - -static void -for_each_secret(NMSetting * setting, - const char * secret_name, - GVariant * val, - gboolean remove_non_secrets, - _NMConnectionForEachSecretFunc callback, - gpointer callback_data, - GVariantBuilder * setting_builder) -{ - GVariantBuilder vpn_secrets_builder; - GVariantIter vpn_secrets_iter; - const char * vpn_secret_name; - const char * secret; - - if (!nm_streq(secret_name, NM_SETTING_VPN_SECRETS)) { - NM_SETTING_CLASS(nm_setting_vpn_parent_class) - ->for_each_secret(setting, - secret_name, - val, - remove_non_secrets, - callback, - callback_data, - setting_builder); - return; - } - - if (!g_variant_is_of_type(val, G_VARIANT_TYPE("a{ss}"))) { - /* invalid type. Silently ignore the secrets as we cannot find out the - * secret-flags. */ - return; - } - - /* Iterate through each secret from the VPN dict in the overall secrets dict */ - g_variant_builder_init(&vpn_secrets_builder, G_VARIANT_TYPE("a{ss}")); - g_variant_iter_init(&vpn_secrets_iter, val); - while (g_variant_iter_next(&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) { - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - /* we ignore the return value of get_secret_flags. The function may determine - * that this is not a secret, based on having not secret-flags and no secrets. - * But we have the secret at hand. We know it would be a valid secret, if we - * only add it to the VPN settings. */ - nm_setting_get_secret_flags(setting, vpn_secret_name, &secret_flags, NULL); - - if (callback(secret_flags, callback_data)) - g_variant_builder_add(&vpn_secrets_builder, "{ss}", vpn_secret_name, secret); - } - - g_variant_builder_add(setting_builder, - "{sv}", - secret_name, - g_variant_builder_end(&vpn_secrets_builder)); -} - -static gboolean -get_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags *out_flags, - GError ** error) -{ - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); - gs_free char * flags_key_free = NULL; - const char * flags_key; - const char * flags_val; - gint64 i64; - - nm_assert(secret_name); - - if (!secret_name[0]) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, - _("secret name cannot be empty")); - return FALSE; - } - - flags_key = nm_construct_name_a("%s-flags", secret_name, &flags_key_free); - - if (!priv->data - || !g_hash_table_lookup_extended(priv->data, flags_key, NULL, (gpointer *) &flags_val)) { - NM_SET_OUT(out_flags, NM_SETTING_SECRET_FLAG_NONE); - - /* having no secret flag for the secret is fine, as long as there - * is the secret itself... */ - if (!nm_g_hash_table_lookup(priv->secrets, secret_name)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, - _("secret flags property not found")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, flags_key); - return FALSE; - } - return TRUE; - } - - i64 = _nm_utils_ascii_str_to_int64(flags_val, 10, 0, NM_SETTING_SECRET_FLAG_ALL, -1); - if (i64 == -1 || !_nm_setting_secret_flags_valid(i64)) { - /* The flags keys is set to an unexpected value. That is a configuration - * error. Note that keys named "*-flags" are reserved for secrets. The user - * must not use this for anything but secret flags. Hence, we cannot fail - * to read the secret, we pretend that the secret flag is set to the default - * NM_SETTING_SECRET_FLAG_NONE. */ - NM_SET_OUT(out_flags, NM_SETTING_SECRET_FLAG_NONE); - return TRUE; - } - - NM_SET_OUT(out_flags, (NMSettingSecretFlags) i64); - return TRUE; -} - -static gboolean -set_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags flags, - GError ** error) -{ - nm_assert(secret_name); - - if (!secret_name[0]) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, - _("secret name cannot be empty")); - return FALSE; - } - - g_hash_table_insert(_ensure_strdict(&NM_SETTING_VPN_GET_PRIVATE(setting)->data, FALSE), - g_strdup_printf("%s-flags", secret_name), - g_strdup_printf("%u", flags)); - _notify(NM_SETTING_VPN(setting), PROP_SECRETS); - return TRUE; -} - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - /* Assume that VPN connections need secrets since they almost always will */ - return g_ptr_array_sized_new(1); -} - -static NMTernary -compare_property_secrets(NMSettingVpn *a, NMSettingVpn *b, NMSettingCompareFlags flags) -{ - GHashTableIter iter; - const char * key, *val; - int run; - - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_FUZZY)) - return NM_TERNARY_DEFAULT; - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)) - return NM_TERNARY_DEFAULT; - - if (!b) - return TRUE; - - for (run = 0; run < 2; run++) { - NMSettingVpn * current_a = (run == 0) ? a : b; - NMSettingVpn * current_b = (run == 0) ? b : a; - NMSettingVpnPrivate *priv_a = NM_SETTING_VPN_GET_PRIVATE(current_a); - - if (!priv_a->secrets) - continue; - - g_hash_table_iter_init(&iter, priv_a->secrets); - while (g_hash_table_iter_next(&iter, (gpointer) &key, (gpointer) &val)) { - if (nm_streq0(val, nm_setting_vpn_get_secret(current_b, key))) - continue; - if (!_nm_setting_should_compare_secret_property(NM_SETTING(current_a), - NM_SETTING(current_b), - key, - flags)) - continue; - - return FALSE; - } - } - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_VPN_SECRETS)) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) - return NM_TERNARY_DEFAULT; - return compare_property_secrets(NM_SETTING_VPN(set_a), NM_SETTING_VPN(set_b), flags); - } - - return NM_SETTING_CLASS(nm_setting_vpn_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -static gboolean -clear_secrets(const NMSettInfoSetting * sett_info, - guint property_idx, - NMSetting * setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data) -{ - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); - GParamSpec * prop_spec = sett_info->property_infos[property_idx].param_spec; - GHashTableIter iter; - const char * secret; - gboolean changed = TRUE; - - if (!prop_spec || !NM_FLAGS_HAS(prop_spec->flags, NM_SETTING_PARAM_SECRET)) - return FALSE; - - nm_assert(nm_streq(prop_spec->name, NM_SETTING_VPN_SECRETS)); - - if (!priv->secrets) - return FALSE; - - g_hash_table_iter_init(&iter, priv->secrets); - while (g_hash_table_iter_next(&iter, (gpointer) &secret, NULL)) { - if (func) { - NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; - - if (!nm_setting_get_secret_flags(setting, secret, &flags, NULL)) - nm_assert_not_reached(); - - if (!func(setting, secret, flags, user_data)) - continue; - } else - nm_assert(nm_setting_get_secret_flags(setting, secret, NULL, NULL)); - - g_hash_table_iter_remove(&iter); - changed = TRUE; - } - - if (changed) - _notify(NM_SETTING_VPN(setting), PROP_SECRETS); - - return changed; -} - -static gboolean -vpn_secrets_from_dbus(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - NMSettingVpn * self = NM_SETTING_VPN(setting); - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(self); - gs_unref_hashtable GHashTable *hash_free = NULL; - GVariantIter iter; - const char * key; - const char * val; - - hash_free = g_steal_pointer(&priv->secrets); - - g_variant_iter_init(&iter, value); - while (g_variant_iter_next(&iter, "{&s&s}", &key, &val)) { - if (!key[0]) - continue; - g_hash_table_insert(_ensure_strdict(&priv->secrets, TRUE), g_strdup(key), g_strdup(val)); - } - - _notify(self, PROP_SECRETS); - return TRUE; -} - -static GVariant * -vpn_secrets_to_dbus(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); - GVariantBuilder builder; - gs_free const char **keys = NULL; - guint i, len; - - if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_NO_SECRETS)) - return NULL; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); - - keys = nm_utils_strdict_get_keys(priv->secrets, TRUE, &len); - for (i = 0; i < len; i++) { - const char * key = keys[i]; - NMSettingSecretFlags secret_flags; - - if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED)) { - if (!nm_setting_get_secret_flags(setting, key, &secret_flags, NULL) - || !NM_FLAGS_HAS(secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) - continue; - } - g_variant_builder_add(&builder, "{ss}", key, g_hash_table_lookup(priv->secrets, key)); - } - - return g_variant_builder_end(&builder); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingVpn * setting = NM_SETTING_VPN(object); - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_SERVICE_TYPE: - g_value_set_string(value, nm_setting_vpn_get_service_type(setting)); - break; - case PROP_USER_NAME: - g_value_set_string(value, nm_setting_vpn_get_user_name(setting)); - break; - case PROP_PERSISTENT: - g_value_set_boolean(value, priv->persistent); - break; - case PROP_DATA: - g_value_take_boxed(value, _nm_utils_copy_strdict(priv->data)); - break; - case PROP_SECRETS: - g_value_take_boxed(value, _nm_utils_copy_strdict(priv->secrets)); - break; - case PROP_TIMEOUT: - g_value_set_uint(value, nm_setting_vpn_get_timeout(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_SERVICE_TYPE: - g_free(priv->service_type); - priv->service_type = g_value_dup_string(value); - break; - case PROP_USER_NAME: - g_free(priv->user_name); - priv->user_name = g_value_dup_string(value); - break; - case PROP_PERSISTENT: - priv->persistent = g_value_get_boolean(value); - break; - case PROP_DATA: - case PROP_SECRETS: - { - gs_unref_hashtable GHashTable *hash_free = NULL; - GHashTable * src_hash = g_value_get_boxed(value); - GHashTable ** p_hash; - const gboolean is_secrets = (prop_id == PROP_SECRETS); - - if (is_secrets) - p_hash = &priv->secrets; - else - p_hash = &priv->data; - - hash_free = g_steal_pointer(p_hash); - - if (src_hash && g_hash_table_size(src_hash) > 0) { - GHashTableIter iter; - const char * key; - const char * val; - - g_hash_table_iter_init(&iter, src_hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - if (!key || !key[0] || !val) { - /* NULL keys/values and empty key are not allowed. Usually, we would reject them in verify(), but - * then our nm_setting_vpn_remove_data_item() also doesn't allow empty keys. So, if we failed - * it in verify(), it would be only fixable by setting PROP_DATA again. Instead, - * silently ignore them. */ - continue; - } - g_hash_table_insert(_ensure_strdict(p_hash, is_secrets), - g_strdup(key), - g_strdup(val)); - } - } - } break; - case PROP_TIMEOUT: - priv->timeout = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_vpn_init(NMSettingVpn *setting) -{} - -/** - * nm_setting_vpn_new: - * - * Creates a new #NMSettingVpn object with default values. - * - * Returns: (transfer full): the new empty #NMSettingVpn object - **/ -NMSetting * -nm_setting_vpn_new(void) -{ - return g_object_new(NM_TYPE_SETTING_VPN, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(object); - - g_free(priv->service_type); - g_free(priv->user_name); - if (priv->data) - g_hash_table_unref(priv->data); - if (priv->secrets) - g_hash_table_unref(priv->secrets); - - G_OBJECT_CLASS(nm_setting_vpn_parent_class)->finalize(object); -} - -static void -nm_setting_vpn_class_init(NMSettingVpnClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingVpnPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->update_one_secret = update_one_secret; - setting_class->for_each_secret = for_each_secret; - setting_class->get_secret_flags = get_secret_flags; - setting_class->set_secret_flags = set_secret_flags; - setting_class->need_secrets = need_secrets; - setting_class->compare_property = compare_property; - setting_class->clear_secrets = clear_secrets; - setting_class->aggregate = aggregate; - - /** - * NMSettingVpn:service-type: - * - * D-Bus service name of the VPN plugin that this setting uses to connect to - * its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc - * plugin. - **/ - obj_properties[PROP_SERVICE_TYPE] = - g_param_spec_string(NM_SETTING_VPN_SERVICE_TYPE, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVpn:user-name: - * - * If the VPN connection requires a user name for authentication, that name - * should be provided here. If the connection is available to more than one - * user, and the VPN requires each user to supply a different name, then - * leave this property empty. If this property is empty, NetworkManager - * will automatically supply the username of the user which requested the - * VPN connection. - **/ - obj_properties[PROP_USER_NAME] = - g_param_spec_string(NM_SETTING_VPN_USER_NAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVpn:persistent: - * - * If the VPN service supports persistence, and this property is %TRUE, - * the VPN will attempt to stay connected across link changes and outages, - * until explicitly disconnected. - **/ - obj_properties[PROP_PERSISTENT] = - g_param_spec_boolean(NM_SETTING_VPN_PERSISTENT, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVpn:data: (type GHashTable(utf8,utf8)): - * - * Dictionary of key/value pairs of VPN plugin specific data. Both keys and - * values must be strings. - **/ - /* ---keyfile--- - * property: data - * variable: separate variables named after keys of the dictionary - * description: The keys of the data dictionary are used as variable names directly - * under [vpn] section. - * example: remote=ovpn.corp.com cipher=AES-256-CBC username=joe - * ---end--- - */ - obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_VPN_DATA, - "", - "", - G_TYPE_HASH_TABLE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_DATA], - &nm_sett_info_propert_type_strdict); - - /** - * NMSettingVpn:secrets: (type GHashTable(utf8,utf8)): - * - * Dictionary of key/value pairs of VPN plugin specific secrets like - * passwords or private keys. Both keys and values must be strings. - **/ - /* ---keyfile--- - * property: secrets - * variable: separate variables named after keys of the dictionary - * description: The keys of the secrets dictionary are used as variable names directly - * under [vpn-secrets] section. - * example: password=Popocatepetl - * ---end--- - */ - obj_properties[PROP_SECRETS] = - g_param_spec_boxed(NM_SETTING_VPN_SECRETS, - "", - "", - G_TYPE_HASH_TABLE, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET - | NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj( - properties_override, - obj_properties[PROP_SECRETS], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("a{ss}"), - .to_dbus_fcn = vpn_secrets_to_dbus, - .from_dbus_fcn = vpn_secrets_from_dbus, )); - - /** - * NMSettingVpn:timeout: - * - * Timeout for the VPN service to establish the connection. Some services - * may take quite a long time to connect. - * Value of 0 means a default timeout, which is 60 seconds (unless overridden - * by vpn.timeout in configuration file). Values greater than zero mean - * timeout in seconds. - * - * Since: 1.2 - **/ - obj_properties[PROP_TIMEOUT] = g_param_spec_uint(NM_SETTING_VPN_TIMEOUT, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_VPN, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-vpn.h b/libnm-core/nm-setting-vpn.h deleted file mode 100644 index 9e5d6e4be3..0000000000 --- a/libnm-core/nm-setting-vpn.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2013 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_VPN_H__ -#define __NM_SETTING_VPN_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_VPN (nm_setting_vpn_get_type()) -#define NM_SETTING_VPN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VPN, NMSettingVpn)) -#define NM_SETTING_VPN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_VPN, NMSettingVpnClass)) -#define NM_IS_SETTING_VPN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VPN)) -#define NM_IS_SETTING_VPN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VPN)) -#define NM_SETTING_VPN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VPN, NMSettingVpnClass)) - -#define NM_SETTING_VPN_SETTING_NAME "vpn" - -#define NM_SETTING_VPN_SERVICE_TYPE "service-type" -#define NM_SETTING_VPN_USER_NAME "user-name" -#define NM_SETTING_VPN_PERSISTENT "persistent" -#define NM_SETTING_VPN_DATA "data" -#define NM_SETTING_VPN_SECRETS "secrets" -#define NM_SETTING_VPN_TIMEOUT "timeout" - -/** - * NMSettingVpn: - * - * VPN Settings - */ -struct _NMSettingVpn { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingVpnClass; - -/** - * NMVpnIterFunc: - * @key: the name of the data or secret item - * @value: the value of the data or secret item - * @user_data: User data passed to nm_setting_vpn_foreach_data_item() or - * nm_setting_vpn_foreach_secret() - **/ -typedef void (*NMVpnIterFunc)(const char *key, const char *value, gpointer user_data); - -GType nm_setting_vpn_get_type(void); - -NMSetting * nm_setting_vpn_new(void); -const char *nm_setting_vpn_get_service_type(NMSettingVpn *setting); -const char *nm_setting_vpn_get_user_name(NMSettingVpn *setting); -gboolean nm_setting_vpn_get_persistent(NMSettingVpn *setting); - -guint32 nm_setting_vpn_get_num_data_items(NMSettingVpn *setting); -void nm_setting_vpn_add_data_item(NMSettingVpn *setting, const char *key, const char *item); -const char *nm_setting_vpn_get_data_item(NMSettingVpn *setting, const char *key); -gboolean nm_setting_vpn_remove_data_item(NMSettingVpn *setting, const char *key); -void -nm_setting_vpn_foreach_data_item(NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data); -NM_AVAILABLE_IN_1_12 -const char **nm_setting_vpn_get_data_keys(NMSettingVpn *setting, guint *out_length); - -guint32 nm_setting_vpn_get_num_secrets(NMSettingVpn *setting); -void nm_setting_vpn_add_secret(NMSettingVpn *setting, const char *key, const char *secret); -const char *nm_setting_vpn_get_secret(NMSettingVpn *setting, const char *key); -gboolean nm_setting_vpn_remove_secret(NMSettingVpn *setting, const char *key); -void nm_setting_vpn_foreach_secret(NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data); -NM_AVAILABLE_IN_1_12 -const char **nm_setting_vpn_get_secret_keys(NMSettingVpn *setting, guint *out_length); - -NM_AVAILABLE_IN_1_2 -guint32 nm_setting_vpn_get_timeout(NMSettingVpn *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_VPN_H__ */ diff --git a/libnm-core/nm-setting-vrf.c b/libnm-core/nm-setting-vrf.c deleted file mode 100644 index d4198a7b78..0000000000 --- a/libnm-core/nm-setting-vrf.c +++ /dev/null @@ -1,164 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-vrf.h" - -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-vrf - * @short_description: Describes connection properties for vrf interfaces - * - * The #NMSettingVrf object is a #NMSetting subclass that describes properties - * necessary for connection to vrf devices - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_TABLE, ); - -/** - * NMSettingVrf: - * - * VRF settings - * - * Since: 1.24 - */ -struct _NMSettingVrf { - NMSetting parent; - guint32 table; -}; - -struct _NMSettingVrfClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingVrf, nm_setting_vrf, NM_TYPE_SETTING) - -/*****************************************************************************/ - -/** - * nm_setting_vrf_get_table: - * @setting: the #NMSettingVrf - * - * Returns: the routing table for the VRF - * - * Since: 1.24 - **/ -guint32 -nm_setting_vrf_get_table(NMSettingVrf *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VRF(setting), 0); - - return setting->table; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingVrf *self = NM_SETTING_VRF(setting); - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - if (self->table == 0) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("table cannot be zero")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VRF_SETTING_NAME, NM_SETTING_VRF_TABLE); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingVrf *self = NM_SETTING_VRF(object); - - switch (prop_id) { - case PROP_TABLE: - g_value_set_uint(value, self->table); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingVrf *self = NM_SETTING_VRF(object); - - switch (prop_id) { - case PROP_TABLE: - self->table = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_vrf_init(NMSettingVrf *setting) -{} - -/** - * nm_setting_vrf_new: - * - * Creates a new #NMSettingVrf object with default values. - * - * Returns: (transfer full): the new empty #NMSettingVrf object - * - * Since: 1.24 - **/ -NMSetting * -nm_setting_vrf_new(void) -{ - return g_object_new(NM_TYPE_SETTING_VRF, NULL); -} - -static void -nm_setting_vrf_class_init(NMSettingVrfClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - object_class->get_property = get_property; - object_class->set_property = set_property; - - setting_class->verify = verify; - - /** - * NMSettingVrf:table: - * - * The routing table for this VRF. - * - * Since: 1.24 - **/ - obj_properties[PROP_TABLE] = - g_param_spec_uint(NM_SETTING_VRF_TABLE, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_VRF); -} diff --git a/libnm-core/nm-setting-vrf.h b/libnm-core/nm-setting-vrf.h deleted file mode 100644 index afa044b830..0000000000 --- a/libnm-core/nm-setting-vrf.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#ifndef __NM_SETTING_VRF_H__ -#define __NM_SETTING_VRF_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_VRF (nm_setting_vrf_get_type()) -#define NM_SETTING_VRF(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VRF, NMSettingVrf)) -#define NM_SETTING_VRF_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_VRFCONFIG, NMSettingVrfClass)) -#define NM_IS_SETTING_VRF(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VRF)) -#define NM_IS_SETTING_VRF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VRF)) -#define NM_SETTING_VRF_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VRF, NMSettingVrfClass)) - -#define NM_SETTING_VRF_SETTING_NAME "vrf" - -#define NM_SETTING_VRF_TABLE "table" - -typedef struct _NMSettingVrfClass NMSettingVrfClass; - -NM_AVAILABLE_IN_1_24 -GType nm_setting_vrf_get_type(void); -NM_AVAILABLE_IN_1_24 -NMSetting *nm_setting_vrf_new(void); -NM_AVAILABLE_IN_1_24 -guint32 nm_setting_vrf_get_table(NMSettingVrf *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_VRF_H__ */ diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c deleted file mode 100644 index ea8d454681..0000000000 --- a/libnm-core/nm-setting-vxlan.c +++ /dev/null @@ -1,816 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-vxlan.h" - -#include - -#include "nm-utils.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-vxlan - * @short_description: Describes connection properties for VXLAN interfaces - * - * The #NMSettingVxlan object is a #NMSetting subclass that describes properties - * necessary for connection to VXLAN interfaces. - **/ - -#define DST_PORT_DEFAULT 8472 - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, - PROP_ID, - PROP_LOCAL, - PROP_REMOTE, - PROP_SOURCE_PORT_MIN, - PROP_SOURCE_PORT_MAX, - PROP_DESTINATION_PORT, - PROP_TOS, - PROP_TTL, - PROP_AGEING, - PROP_LIMIT, - PROP_LEARNING, - PROP_PROXY, - PROP_RSC, - PROP_L2_MISS, - PROP_L3_MISS, ); - -typedef struct { - char *parent; - char *local; - char *remote; - guint id; - guint source_port_min; - guint source_port_max; - guint destination_port; - guint tos; - guint ttl; - guint ageing; - guint limit; - bool learning : 1; - bool proxy : 1; - bool rsc : 1; - bool l2_miss : 1; - bool l3_miss : 1; -} NMSettingVxlanPrivate; - -G_DEFINE_TYPE(NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING) - -#define NM_SETTING_VXLAN_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_VXLAN, NMSettingVxlanPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_vxlan_get_parent: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:parent property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_vxlan_get_parent(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), NULL); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->parent; -} - -/** - * nm_setting_vxlan_get_id: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:id property of the setting - * - * Since: 1.2 - **/ -guint -nm_setting_vxlan_get_id(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->id; -} - -/** - * nm_setting_vxlan_get_local: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:local property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_vxlan_get_local(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), NULL); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->local; -} - -/** - * nm_setting_vxlan_get_remote: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:remote property of the setting - * - * Since: 1.2 - **/ -const char * -nm_setting_vxlan_get_remote(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), NULL); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->remote; -} - -/** - * nm_setting_vxlan_get_source_port_min: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:source-port-min property of the setting - * - * Since: 1.2 - **/ -guint -nm_setting_vxlan_get_source_port_min(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->source_port_min; -} - -/** - * nm_setting_vxlan_get_source_port_max: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:source-port-max property of the setting - * - * Since: 1.2 - **/ -guint -nm_setting_vxlan_get_source_port_max(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->source_port_max; -} - -/** - * nm_setting_vxlan_get_destination_port: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:destination-port property of the setting - * - * Since: 1.2 - **/ -guint -nm_setting_vxlan_get_destination_port(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), DST_PORT_DEFAULT); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->destination_port; -} - -/** - * nm_setting_vxlan_get_proxy: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:proxy property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_vxlan_get_proxy(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->proxy; -} - -/** - * nm_setting_vxlan_get_ageing: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:ageing property of the setting - * - * Since: 1.2 - **/ -guint -nm_setting_vxlan_get_ageing(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->ageing; -} - -/** - * nm_setting_vxlan_get_limit: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:limit property of the setting - * - * Since: 1.2 - **/ -guint -nm_setting_vxlan_get_limit(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->limit; -} - -/** - * nm_setting_vxlan_get_tos: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:tos property of the setting - * - * Since: 1.2 - **/ -guint -nm_setting_vxlan_get_tos(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->tos; -} - -/** - * nm_setting_vxlan_get_ttl: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:ttl property of the setting - * - * Since: 1.2 - **/ -guint -nm_setting_vxlan_get_ttl(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->ttl; -} - -/** - * nm_setting_vxlan_get_learning: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:learning property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_vxlan_get_learning(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->learning; -} - -/** - * nm_setting_vxlan_get_rsc: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:rsc property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_vxlan_get_rsc(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->rsc; -} - -/** - * nm_setting_vxlan_get_l2_miss: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:l2_miss property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_vxlan_get_l2_miss(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->l2_miss; -} - -/** - * nm_setting_vxlan_get_l3_miss: - * @setting: the #NMSettingVxlan - * - * Returns: the #NMSettingVxlan:l3_miss property of the setting - * - * Since: 1.2 - **/ -gboolean -nm_setting_vxlan_get_l3_miss(NMSettingVxlan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); - return NM_SETTING_VXLAN_GET_PRIVATE(setting)->l3_miss; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(setting); - int addr_family = AF_UNSPEC; - gboolean remote_is_valid = TRUE; - gboolean local_is_valid = TRUE; - - if (priv->remote && !nm_utils_parse_inaddr_bin(addr_family, priv->remote, &addr_family, NULL)) - remote_is_valid = FALSE; - if (priv->local && !nm_utils_parse_inaddr_bin(addr_family, priv->local, &addr_family, NULL)) - local_is_valid = FALSE; - - if (!remote_is_valid) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IP%s address"), - priv->remote, - addr_family == AF_UNSPEC ? "" : (addr_family == AF_INET ? "4" : "6")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VXLAN_SETTING_NAME, NM_SETTING_VXLAN_REMOTE); - return FALSE; - } - - if (!local_is_valid) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IP%s address"), - priv->local, - addr_family == AF_UNSPEC ? "" : (addr_family == AF_INET ? "4" : "6")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VXLAN_SETTING_NAME, NM_SETTING_VXLAN_LOCAL); - return FALSE; - } - - if (priv->parent && !nm_utils_ifname_valid_kernel(priv->parent, NULL) - && !nm_utils_is_uuid(priv->parent)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is neither an UUID nor an interface name"), - priv->parent); - g_prefix_error(error, "%s.%s: ", NM_SETTING_VXLAN_SETTING_NAME, NM_SETTING_VXLAN_PARENT); - return FALSE; - } - - if ((priv->source_port_min || priv->source_port_max) - && (priv->source_port_min > priv->source_port_max)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d is greater than local port max %d"), - priv->source_port_min, - priv->source_port_max); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_VXLAN_SETTING_NAME, - NM_SETTING_VXLAN_SOURCE_PORT_MIN); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -_addrstr_set(char **dst, const char *src) -{ - gs_free char *old = NULL; - - old = *dst; - if (!src) - *dst = NULL; - else if (!nm_utils_parse_inaddr(AF_UNSPEC, src, dst)) - *dst = g_strdup(src); -} -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingVxlan * setting = NM_SETTING_VXLAN(object); - NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_value_set_string(value, priv->parent); - break; - case PROP_ID: - g_value_set_uint(value, priv->id); - break; - case PROP_LOCAL: - g_value_set_string(value, priv->local); - break; - case PROP_REMOTE: - g_value_set_string(value, priv->remote); - break; - case PROP_SOURCE_PORT_MIN: - g_value_set_uint(value, priv->source_port_min); - break; - case PROP_SOURCE_PORT_MAX: - g_value_set_uint(value, priv->source_port_max); - break; - case PROP_DESTINATION_PORT: - g_value_set_uint(value, priv->destination_port); - break; - case PROP_TOS: - g_value_set_uint(value, priv->tos); - break; - case PROP_AGEING: - g_value_set_uint(value, priv->ageing); - break; - case PROP_LIMIT: - g_value_set_uint(value, priv->limit); - break; - case PROP_PROXY: - g_value_set_boolean(value, priv->proxy); - break; - case PROP_TTL: - g_value_set_uint(value, priv->ttl); - break; - case PROP_LEARNING: - g_value_set_boolean(value, priv->learning); - break; - case PROP_RSC: - g_value_set_boolean(value, priv->rsc); - break; - case PROP_L2_MISS: - g_value_set_boolean(value, priv->l2_miss); - break; - case PROP_L3_MISS: - g_value_set_boolean(value, priv->l3_miss); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingVxlan * setting = NM_SETTING_VXLAN(object); - NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_PARENT: - g_free(priv->parent); - priv->parent = g_value_dup_string(value); - break; - case PROP_ID: - priv->id = g_value_get_uint(value); - break; - case PROP_LOCAL: - _addrstr_set(&priv->local, g_value_get_string(value)); - break; - case PROP_REMOTE: - _addrstr_set(&priv->remote, g_value_get_string(value)); - break; - case PROP_SOURCE_PORT_MIN: - priv->source_port_min = g_value_get_uint(value); - break; - case PROP_SOURCE_PORT_MAX: - priv->source_port_max = g_value_get_uint(value); - break; - case PROP_DESTINATION_PORT: - priv->destination_port = g_value_get_uint(value); - break; - case PROP_TOS: - priv->tos = g_value_get_uint(value); - break; - case PROP_AGEING: - priv->ageing = g_value_get_uint(value); - break; - case PROP_LIMIT: - priv->limit = g_value_get_uint(value); - break; - case PROP_PROXY: - priv->proxy = g_value_get_boolean(value); - break; - case PROP_TTL: - priv->ttl = g_value_get_uint(value); - break; - case PROP_LEARNING: - priv->learning = g_value_get_boolean(value); - break; - case PROP_RSC: - priv->rsc = g_value_get_boolean(value); - break; - case PROP_L2_MISS: - priv->l2_miss = g_value_get_boolean(value); - break; - case PROP_L3_MISS: - priv->l3_miss = g_value_get_boolean(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_vxlan_init(NMSettingVxlan *self) -{ - NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(self); - - priv->destination_port = DST_PORT_DEFAULT; - priv->ageing = 300; - priv->learning = TRUE; -} - -/** - * nm_setting_vxlan_new: - * - * Creates a new #NMSettingVxlan object with default values. - * - * Returns: (transfer full): the new empty #NMSettingVxlan object - * - * Since: 1.2 - **/ -NMSetting * -nm_setting_vxlan_new(void) -{ - return g_object_new(NM_TYPE_SETTING_VXLAN, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingVxlan * setting = NM_SETTING_VXLAN(object); - NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(setting); - - g_free(priv->parent); - g_free(priv->local); - g_free(priv->remote); - - G_OBJECT_CLASS(nm_setting_vxlan_parent_class)->finalize(object); -} - -static void -nm_setting_vxlan_class_init(NMSettingVxlanClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingVxlanPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingVxlan:parent: - * - * If given, specifies the parent interface name or parent connection UUID. - * - * Since: 1.2 - **/ - obj_properties[PROP_PARENT] = g_param_spec_string( - NM_SETTING_VXLAN_PARENT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - /** - * NMSettingVxlan:id: - * - * Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to - * use. - * - * Since: 1.2 - **/ - obj_properties[PROP_ID] = - g_param_spec_uint(NM_SETTING_VXLAN_ID, - "", - "", - 0, - (1 << 24) - 1, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:local: - * - * If given, specifies the source IP address to use in outgoing packets. - * - * Since: 1.2 - **/ - obj_properties[PROP_LOCAL] = g_param_spec_string(NM_SETTING_VXLAN_LOCAL, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:remote: - * - * Specifies the unicast destination IP address to use in outgoing packets - * when the destination link layer address is not known in the VXLAN device - * forwarding database, or the multicast IP address to join. - * - * Since: 1.2 - **/ - obj_properties[PROP_REMOTE] = g_param_spec_string( - NM_SETTING_VXLAN_REMOTE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:source-port-min: - * - * Specifies the minimum UDP source port to communicate to the remote VXLAN - * tunnel endpoint. - * - * Since: 1.2 - **/ - obj_properties[PROP_SOURCE_PORT_MIN] = - g_param_spec_uint(NM_SETTING_VXLAN_SOURCE_PORT_MIN, - "", - "", - 0, - G_MAXUINT16, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:source-port-max: - * - * Specifies the maximum UDP source port to communicate to the remote VXLAN - * tunnel endpoint. - * - * Since: 1.2 - **/ - obj_properties[PROP_SOURCE_PORT_MAX] = - g_param_spec_uint(NM_SETTING_VXLAN_SOURCE_PORT_MAX, - "", - "", - 0, - G_MAXUINT16, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:destination-port: - * - * Specifies the UDP destination port to communicate to the remote VXLAN - * tunnel endpoint. - * - * Since: 1.2 - **/ - obj_properties[PROP_DESTINATION_PORT] = - g_param_spec_uint(NM_SETTING_VXLAN_DESTINATION_PORT, - "", - "", - 0, - G_MAXUINT16, - DST_PORT_DEFAULT, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:ageing: - * - * Specifies the lifetime in seconds of FDB entries learnt by the kernel. - * - * Since: 1.2 - **/ - obj_properties[PROP_AGEING] = - g_param_spec_uint(NM_SETTING_VXLAN_AGEING, - "", - "", - 0, - G_MAXUINT32, - 300, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:limit: - * - * Specifies the maximum number of FDB entries. A value of zero means that - * the kernel will store unlimited entries. - * - * Since: 1.2 - **/ - obj_properties[PROP_LIMIT] = - g_param_spec_uint(NM_SETTING_VXLAN_LIMIT, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:tos: - * - * Specifies the TOS value to use in outgoing packets. - * - * Since: 1.2 - **/ - obj_properties[PROP_TOS] = - g_param_spec_uint(NM_SETTING_VXLAN_TOS, - "", - "", - 0, - 255, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:ttl: - * - * Specifies the time-to-live value to use in outgoing packets. - * - * Since: 1.2 - **/ - obj_properties[PROP_TTL] = - g_param_spec_uint(NM_SETTING_VXLAN_TTL, - "", - "", - 0, - 255, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:proxy: - * - * Specifies whether ARP proxy is turned on. - * - * Since: 1.2 - **/ - obj_properties[PROP_PROXY] = g_param_spec_boolean( - NM_SETTING_VXLAN_PROXY, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:learning: - * - * Specifies whether unknown source link layer addresses and IP addresses - * are entered into the VXLAN device forwarding database. - * - * Since: 1.2 - **/ - obj_properties[PROP_LEARNING] = g_param_spec_boolean( - NM_SETTING_VXLAN_LEARNING, - "", - "", - TRUE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - /** - * NMSettingVxlan:rsc: - * - * Specifies whether route short circuit is turned on. - * - * Since: 1.2 - **/ - obj_properties[PROP_RSC] = g_param_spec_boolean(NM_SETTING_VXLAN_RSC, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE - | G_PARAM_STATIC_STRINGS); - /** - * NMSettingVxlan:l2-miss: - * - * Specifies whether netlink LL ADDR miss notifications are generated. - * - * Since: 1.2 - **/ - obj_properties[PROP_L2_MISS] = g_param_spec_boolean( - NM_SETTING_VXLAN_L2_MISS, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingVxlan:l3-miss: - * - * Specifies whether netlink IP ADDR miss notifications are generated. - * - * Since: 1.2 - **/ - obj_properties[PROP_L3_MISS] = g_param_spec_boolean( - NM_SETTING_VXLAN_L3_MISS, - "", - "", - FALSE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_VXLAN); -} diff --git a/libnm-core/nm-setting-vxlan.h b/libnm-core/nm-setting-vxlan.h deleted file mode 100644 index 9b987b660c..0000000000 --- a/libnm-core/nm-setting-vxlan.h +++ /dev/null @@ -1,101 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_VXLAN_H__ -#define __NM_SETTING_VXLAN_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_VXLAN (nm_setting_vxlan_get_type()) -#define NM_SETTING_VXLAN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VXLAN, NMSettingVxlan)) -#define NM_SETTING_VXLAN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_VXLANCONFIG, NMSettingVxlanClass)) -#define NM_IS_SETTING_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VXLAN)) -#define NM_IS_SETTING_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VXLAN)) -#define NM_SETTING_VXLAN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VXLAN, NMSettingVxlanClass)) - -#define NM_SETTING_VXLAN_SETTING_NAME "vxlan" - -#define NM_SETTING_VXLAN_PARENT "parent" -#define NM_SETTING_VXLAN_ID "id" -#define NM_SETTING_VXLAN_LOCAL "local" -#define NM_SETTING_VXLAN_REMOTE "remote" -#define NM_SETTING_VXLAN_SOURCE_PORT_MIN "source-port-min" -#define NM_SETTING_VXLAN_SOURCE_PORT_MAX "source-port-max" -#define NM_SETTING_VXLAN_DESTINATION_PORT "destination-port" -#define NM_SETTING_VXLAN_TOS "tos" -#define NM_SETTING_VXLAN_TTL "ttl" -#define NM_SETTING_VXLAN_AGEING "ageing" -#define NM_SETTING_VXLAN_LIMIT "limit" -#define NM_SETTING_VXLAN_PROXY "proxy" -#define NM_SETTING_VXLAN_LEARNING "learning" -#define NM_SETTING_VXLAN_RSC "rsc" -#define NM_SETTING_VXLAN_L2_MISS "l2-miss" -#define NM_SETTING_VXLAN_L3_MISS "l3-miss" - -/** - * NMSettingVxlan: - * - * VXLAN Settings - */ -struct _NMSettingVxlan { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingVxlanClass; - -NM_AVAILABLE_IN_1_2 -GType nm_setting_vxlan_get_type(void); -NM_AVAILABLE_IN_1_2 -NMSetting *nm_setting_vxlan_new(void); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_vxlan_get_parent(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_vxlan_get_id(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_vxlan_get_local(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -const char *nm_setting_vxlan_get_remote(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_vxlan_get_source_port_min(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_vxlan_get_source_port_max(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_vxlan_get_destination_port(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_vxlan_get_tos(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_vxlan_get_ttl(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_vxlan_get_ageing(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -guint nm_setting_vxlan_get_limit(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_vxlan_get_proxy(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_vxlan_get_learning(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_vxlan_get_rsc(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_vxlan_get_l2_miss(NMSettingVxlan *setting); -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_vxlan_get_l3_miss(NMSettingVxlan *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_VXLAN_H__ */ diff --git a/libnm-core/nm-setting-wifi-p2p.c b/libnm-core/nm-setting-wifi-p2p.c deleted file mode 100644 index e026cb8fbb..0000000000 --- a/libnm-core/nm-setting-wifi-p2p.c +++ /dev/null @@ -1,304 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-wifi-p2p.h" - -#include - -#include "nm-utils.h" -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-wifi-p2p - * @short_description: Describes connection properties for 802.11 Wi-Fi P2P networks - * - * The #NMSettingWifiP2P object is a #NMSetting subclass that describes properties - * necessary for connection to 802.11 Wi-Fi P2P networks (aka Wi-Fi Direct). - **/ - -/** - * NMSettingWifiP2P: - * - * Wi-Fi P2P Settings - * - * Since: 1.16 - */ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PEER, PROP_WPS_METHOD, PROP_WFD_IES, ); - -typedef struct { - char * peer_mac_address; - GBytes *wfd_ies; - - NMSettingWirelessSecurityWpsMethod wps_method; -} NMSettingWifiP2PPrivate; - -struct _NMSettingWifiP2P { - NMSetting parent; - NMSettingWifiP2PPrivate _priv; -}; - -struct _NMSettingWifiP2PClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingWifiP2P, nm_setting_wifi_p2p, NM_TYPE_SETTING) - -#define NM_SETTING_WIFI_P2P_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMSettingWifiP2P, NM_IS_SETTING_WIFI_P2P, NMSetting) - -/*****************************************************************************/ - -/** - * nm_setting_wifi_p2p_get_peer: - * @setting: the #NMSettingWifiP2P - * - * Returns: the #NMSettingWifiP2P:peer property of the setting - * - * Since: 1.16 - **/ -const char * -nm_setting_wifi_p2p_get_peer(NMSettingWifiP2P *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIFI_P2P(setting), NULL); - - return NM_SETTING_WIFI_P2P_GET_PRIVATE(setting)->peer_mac_address; -} - -/** - * nm_setting_wifi_p2p_get_wps_method: - * @setting: the #NMSettingWifiP2P - * - * Returns: the #NMSettingWifiP2P:wps-method property of the setting - * - * Since: 1.16 - **/ -NMSettingWirelessSecurityWpsMethod -nm_setting_wifi_p2p_get_wps_method(NMSettingWifiP2P *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIFI_P2P(setting), - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT); - - return NM_SETTING_WIFI_P2P_GET_PRIVATE(setting)->wps_method; -} - -/** - * nm_setting_wifi_p2p_get_wfd_ies: - * @setting: the #NMSettingWiFiP2P - * - * Returns: (transfer none): the #NMSettingWiFiP2P:wfd-ies property of the setting - * - * Since: 1.16 - **/ -GBytes * -nm_setting_wifi_p2p_get_wfd_ies(NMSettingWifiP2P *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIFI_P2P(setting), NULL); - - return NM_SETTING_WIFI_P2P_GET_PRIVATE(setting)->wfd_ies; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWifiP2PPrivate *priv = NM_SETTING_WIFI_P2P_GET_PRIVATE(setting); - - if (!priv->peer_mac_address) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIFI_P2P_SETTING_NAME, - NM_SETTING_WIFI_P2P_PEER); - return FALSE; - } - - if (!nm_utils_hwaddr_valid(priv->peer_mac_address, ETH_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIFI_P2P_SETTING_NAME, - NM_SETTING_WIFI_P2P_PEER); - return FALSE; - } - - if (!_nm_utils_wps_method_validate(priv->wps_method, - NM_SETTING_WIFI_P2P_SETTING_NAME, - NM_SETTING_WIFI_P2P_WPS_METHOD, - TRUE, - error)) - return FALSE; - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingWifiP2P *setting = NM_SETTING_WIFI_P2P(object); - - switch (prop_id) { - case PROP_PEER: - g_value_set_string(value, nm_setting_wifi_p2p_get_peer(setting)); - break; - case PROP_WPS_METHOD: - g_value_set_uint(value, nm_setting_wifi_p2p_get_wps_method(setting)); - break; - case PROP_WFD_IES: - g_value_set_boxed(value, nm_setting_wifi_p2p_get_wfd_ies(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingWifiP2PPrivate *priv = NM_SETTING_WIFI_P2P_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_PEER: - g_free(priv->peer_mac_address); - priv->peer_mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); - break; - case PROP_WPS_METHOD: - priv->wps_method = g_value_get_uint(value); - break; - case PROP_WFD_IES: - nm_clear_pointer(&priv->wfd_ies, g_bytes_unref); - priv->wfd_ies = g_value_dup_boxed(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_wifi_p2p_init(NMSettingWifiP2P *setting) -{} - -/** - * nm_setting_wifi_p2p_new: - * - * Creates a new #NMSettingWifiP2P object with default values. - * - * Returns: (transfer full): the new empty #NMSettingWifiP2P object - * - * Since: 1.16 - **/ -NMSetting * -nm_setting_wifi_p2p_new(void) -{ - return g_object_new(NM_TYPE_SETTING_WIFI_P2P, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingWifiP2PPrivate *priv = NM_SETTING_WIFI_P2P_GET_PRIVATE(object); - - g_free(priv->peer_mac_address); - g_bytes_unref(priv->wfd_ies); - - G_OBJECT_CLASS(nm_setting_wifi_p2p_parent_class)->finalize(object); -} - -static void -nm_setting_wifi_p2p_class_init(NMSettingWifiP2PClass *setting_wifi_p2p_class) -{ - GObjectClass * object_class = G_OBJECT_CLASS(setting_wifi_p2p_class); - NMSettingClass *setting_class = NM_SETTING_CLASS(setting_wifi_p2p_class); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingWifiP2P:peer: - * - * The P2P device that should be connected to. Currently, this is the only - * way to create or join a group. - * - * Since: 1.16 - */ - /* ---keyfile--- - * property: peer - * format: usual hex-digits-and-colons notation - * description: MAC address in traditional hex-digits-and-colons notation - * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) - * (e.g. 0;34;104;18;121;162). - * ---end--- - */ - obj_properties[PROP_PEER] = g_param_spec_string(NM_SETTING_WIFI_P2P_PEER, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWifiP2P:wps-method: - * - * Flags indicating which mode of WPS is to be used. - * - * There's little point in changing the default setting as NetworkManager will - * automatically determine the best method to use. - * - * Since: 1.16 - */ - obj_properties[PROP_WPS_METHOD] = g_param_spec_uint( - NM_SETTING_WIFI_P2P_WPS_METHOD, - "", - "", - 0, - G_MAXUINT32, - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWifiP2P:wfd-ies: - * - * The Wi-Fi Display (WFD) Information Elements (IEs) to set. - * - * Wi-Fi Display requires a protocol specific information element to be - * set in certain Wi-Fi frames. These can be specified here for the - * purpose of establishing a connection. - * This setting is only useful when implementing a Wi-Fi Display client. - * - * Since: 1.16 - */ - obj_properties[PROP_WFD_IES] = g_param_spec_boxed( - NM_SETTING_WIFI_P2P_WFD_IES, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_WIFI_P2P); -} diff --git a/libnm-core/nm-setting-wifi-p2p.h b/libnm-core/nm-setting-wifi-p2p.h deleted file mode 100644 index 029b75f065..0000000000 --- a/libnm-core/nm-setting-wifi-p2p.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_WIFI_P2P_H__ -#define __NM_SETTING_WIFI_P2P_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" -#include "nm-setting-wireless-security.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_WIFI_P2P (nm_setting_wifi_p2p_get_type()) -#define NM_SETTING_WIFI_P2P(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIFI_P2P, NMSettingWifiP2P)) -#define NM_SETTING_WIFI_P2P_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIFI_P2P, NMSettingWifiP2PClass)) -#define NM_IS_SETTING_WIFI_P2P(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIFI_P2P)) -#define NM_IS_SETTING_WIFI_P2P_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIFI_P2P)) -#define NM_SETTING_WIFI_P2P_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIFI_P2P, NMSettingWifiP2PClass)) - -#define NM_SETTING_WIFI_P2P_SETTING_NAME "wifi-p2p" - -/** - * NM_SETTING_WIFI_P2P_PEER: - * - * The mac address of the peer to connect to. - */ -#define NM_SETTING_WIFI_P2P_PEER "peer" -#define NM_SETTING_WIFI_P2P_WPS_METHOD "wps-method" -#define NM_SETTING_WIFI_P2P_WFD_IES "wfd-ies" - -typedef struct _NMSettingWifiP2PClass NMSettingWifiP2PClass; - -NM_AVAILABLE_IN_1_16 -GType nm_setting_wifi_p2p_get_type(void); - -NM_AVAILABLE_IN_1_16 -NMSetting *nm_setting_wifi_p2p_new(void); - -NM_AVAILABLE_IN_1_16 -const char *nm_setting_wifi_p2p_get_peer(NMSettingWifiP2P *setting); - -NM_AVAILABLE_IN_1_16 -NMSettingWirelessSecurityWpsMethod nm_setting_wifi_p2p_get_wps_method(NMSettingWifiP2P *setting); - -NM_AVAILABLE_IN_1_16 -GBytes *nm_setting_wifi_p2p_get_wfd_ies(NMSettingWifiP2P *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_WIFI_P2P_H__ */ diff --git a/libnm-core/nm-setting-wimax.c b/libnm-core/nm-setting-wimax.c deleted file mode 100644 index dcb59412f4..0000000000 --- a/libnm-core/nm-setting-wimax.c +++ /dev/null @@ -1,255 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011 - 2013 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-wimax.h" - -#include - -#include "nm-setting-private.h" -#include "nm-utils.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-wimax - * @short_description: Describes 802.16e Mobile WiMAX connection properties - * - * The #NMSettingWimax object is a #NMSetting subclass that describes properties - * necessary for connection to 802.16e Mobile WiMAX networks. - * - * NetworkManager no longer supports WiMAX; while this API remains available for - * backward-compatibility reasons, it serves no real purpose, since WiMAX - * connections cannot be activated. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_NETWORK_NAME, PROP_MAC_ADDRESS, ); - -typedef struct { - char *network_name; - char *mac_address; -} NMSettingWimaxPrivate; - -G_DEFINE_TYPE(NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING) - -#define NM_SETTING_WIMAX_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_wimax_get_network_name: - * @setting: the #NMSettingWimax - * - * Returns the WiMAX NSP name (ex "Sprint" or "CLEAR") which identifies the - * specific WiMAX network this setting describes a connection to. - * - * Returns: the WiMAX NSP name - * - * Deprecated: 1.2: WiMAX is no longer supported. - **/ -const char * -nm_setting_wimax_get_network_name(NMSettingWimax *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIMAX(setting), NULL); - - return NM_SETTING_WIMAX_GET_PRIVATE(setting)->network_name; -} - -/** - * nm_setting_wimax_get_mac_address: - * @setting: the #NMSettingWimax - * - * Returns the MAC address of a WiMAX device which this connection is locked - * to. - * - * Returns: the MAC address - * - * Deprecated: 1.2: WiMAX is no longer supported. - **/ -const char * -nm_setting_wimax_get_mac_address(NMSettingWimax *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIMAX(setting), NULL); - - return NM_SETTING_WIMAX_GET_PRIVATE(setting)->mac_address; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE(setting); - - if (!priv->network_name) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIMAX_SETTING_NAME, - NM_SETTING_WIMAX_NETWORK_NAME); - return FALSE; - } - - if (!strlen(priv->network_name)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIMAX_SETTING_NAME, - NM_SETTING_WIMAX_NETWORK_NAME); - return FALSE; - } - - if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, ETH_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIMAX_SETTING_NAME, - NM_SETTING_WIMAX_MAC_ADDRESS); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingWimax *setting = NM_SETTING_WIMAX(object); - - switch (prop_id) { - case PROP_NETWORK_NAME: - g_value_set_string(value, nm_setting_wimax_get_network_name(setting)); - break; - case PROP_MAC_ADDRESS: - g_value_set_string(value, nm_setting_wimax_get_mac_address(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_NETWORK_NAME: - g_free(priv->network_name); - priv->network_name = g_value_dup_string(value); - break; - case PROP_MAC_ADDRESS: - g_free(priv->mac_address); - priv->mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_wimax_init(NMSettingWimax *setting) -{} - -/** - * nm_setting_wimax_new: - * - * Creates a new #NMSettingWimax object with default values. - * - * Returns: the new empty #NMSettingWimax object - * - * Deprecated: 1.2: WiMAX is no longer supported. - **/ -NMSetting * -nm_setting_wimax_new(void) -{ - return g_object_new(NM_TYPE_SETTING_WIMAX, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE(object); - - g_free(priv->network_name); - g_free(priv->mac_address); - - G_OBJECT_CLASS(nm_setting_wimax_parent_class)->finalize(object); -} - -static void -nm_setting_wimax_class_init(NMSettingWimaxClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingWimaxPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingWimax:network-name: - * - * Network Service Provider (NSP) name of the WiMAX network this connection - * should use. - * - * Deprecated: 1.2: WiMAX is no longer supported. - **/ - obj_properties[PROP_NETWORK_NAME] = - g_param_spec_string(NM_SETTING_WIMAX_NETWORK_NAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWimax:mac-address: - * - * If specified, this connection will only apply to the WiMAX device whose - * MAC address matches. This property does not change the MAC address of the - * device (known as MAC spoofing). - * - * Deprecated: 1.2: WiMAX is no longer supported. - **/ - obj_properties[PROP_MAC_ADDRESS] = - g_param_spec_string(NM_SETTING_WIMAX_MAC_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_MAC_ADDRESS], - &nm_sett_info_propert_type_mac_address); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_WIMAX, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-wimax.h b/libnm-core/nm-setting-wimax.h deleted file mode 100644 index 7279e043b5..0000000000 --- a/libnm-core/nm-setting-wimax.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef __NM_SETTING_WIMAX_H__ -#define __NM_SETTING_WIMAX_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_WIMAX (nm_setting_wimax_get_type()) -#define NM_SETTING_WIMAX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimax)) -#define NM_SETTING_WIMAX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass)) -#define NM_IS_SETTING_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIMAX)) -#define NM_IS_SETTING_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIMAX)) -#define NM_SETTING_WIMAX_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass)) - -#define NM_SETTING_WIMAX_SETTING_NAME "wimax" - -#define NM_SETTING_WIMAX_NETWORK_NAME "network-name" -#define NM_SETTING_WIMAX_MAC_ADDRESS "mac-address" - -/** - * NMSettingWimax: - * - * WiMax Settings - */ -struct _NMSettingWimax { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingWimaxClass; - -NM_DEPRECATED_IN_1_2 -GType nm_setting_wimax_get_type(void); - -NM_DEPRECATED_IN_1_2 -NMSetting *nm_setting_wimax_new(void); -NM_DEPRECATED_IN_1_2 -const char *nm_setting_wimax_get_network_name(NMSettingWimax *setting); -NM_DEPRECATED_IN_1_2 -const char *nm_setting_wimax_get_mac_address(NMSettingWimax *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_WIMAX_H__ */ diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c deleted file mode 100644 index 857f11b1f9..0000000000 --- a/libnm-core/nm-setting-wired.c +++ /dev/null @@ -1,1647 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-wired.h" - -#include - -#include "nm-utils.h" -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-wired - * @short_description: Describes connection properties for Ethernet-based networks - * - * The #NMSettingWired object is a #NMSetting subclass that describes properties - * necessary for connection to Ethernet networks. - **/ - -/*****************************************************************************/ - -G_STATIC_ASSERT(NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS - == (NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT | NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE)); - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingWired, - PROP_PORT, - PROP_SPEED, - PROP_DUPLEX, - PROP_AUTO_NEGOTIATE, - PROP_MAC_ADDRESS, - PROP_CLONED_MAC_ADDRESS, - PROP_GENERATE_MAC_ADDRESS_MASK, - PROP_MAC_ADDRESS_BLACKLIST, - PROP_MTU, - PROP_S390_SUBCHANNELS, - PROP_S390_NETTYPE, - PROP_S390_OPTIONS, - PROP_WAKE_ON_LAN, - PROP_WAKE_ON_LAN_PASSWORD, ); - -typedef struct { - struct { - NMUtilsNamedValue *arr; - guint len; - guint n_alloc; - } s390_options; - GArray * mac_address_blacklist; - char ** s390_subchannels; - char * port; - char * duplex; - char * device_mac_address; - char * cloned_mac_address; - char * generate_mac_address_mask; - char * s390_nettype; - char * wol_password; - NMSettingWiredWakeOnLan wol; - guint32 speed; - guint32 mtu; - bool auto_negotiate : 1; -} NMSettingWiredPrivate; - -G_DEFINE_TYPE(NMSettingWired, nm_setting_wired, NM_TYPE_SETTING) - -#define NM_SETTING_WIRED_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate)) - -/*****************************************************************************/ - -static const char *valid_s390_opts[] = { - "broadcast_mode", - "buffer_count", - "canonical_macaddr", - "checksumming", - "ctcprot", - "fake_broadcast", - "inter", - "inter_jumbo", - "ipato_add4", - "ipato_add6", - "ipato_enable", - "ipato_invert4", - "ipato_invert6", - "isolation", - "lancmd_timeout", - "large_send", - "layer2", - "portname", - "portno", - "priority_queueing", - "protocol", - "route4", - "route6", - "rxip_add4", - "rxip_add6", - "sniffer", - "total", - "vipa_add4", - "vipa_add6", - NULL, -}; - -static gboolean -valid_s390_opts_check(const char *option) -{ -#if NM_MORE_ASSERTS > 5 - nm_assert(NM_PTRARRAY_LEN(valid_s390_opts) + 1 == G_N_ELEMENTS(valid_s390_opts)); - { - gsize i; - - for (i = 0; i < G_N_ELEMENTS(valid_s390_opts); i++) { - if (i == G_N_ELEMENTS(valid_s390_opts) - 1) - nm_assert(!valid_s390_opts[i]); - else { - nm_assert(valid_s390_opts[i]); - nm_assert(valid_s390_opts[i][0] != '\0'); - if (i > 0) - g_assert(strcmp(valid_s390_opts[i - 1], valid_s390_opts[i]) < 0); - } - } - } -#endif - - return option - && (nm_utils_array_find_binary_search(valid_s390_opts, - sizeof(const char *), - G_N_ELEMENTS(valid_s390_opts) - 1, - &option, - nm_strcmp_p_with_data, - NULL) - >= 0); -} - -/** - * nm_setting_wired_get_port: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:port property of the setting - **/ -const char * -nm_setting_wired_get_port(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->port; -} - -/** - * nm_setting_wired_get_speed: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:speed property of the setting - **/ -guint32 -nm_setting_wired_get_speed(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), 0); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->speed; -} - -/** - * nm_setting_wired_get_duplex: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:duplex property of the setting - **/ -const char * -nm_setting_wired_get_duplex(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->duplex; -} - -/** - * nm_setting_wired_get_auto_negotiate: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:auto-negotiate property of the setting - **/ -gboolean -nm_setting_wired_get_auto_negotiate(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->auto_negotiate; -} - -/** - * nm_setting_wired_get_mac_address: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:mac-address property of the setting - **/ -const char * -nm_setting_wired_get_mac_address(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->device_mac_address; -} - -/** - * nm_setting_wired_get_cloned_mac_address: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:cloned-mac-address property of the setting - **/ -const char * -nm_setting_wired_get_cloned_mac_address(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->cloned_mac_address; -} - -/** - * nm_setting_wired_get_generate_mac_address_mask: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:generate-mac-address-mask property of the setting - * - * Since: 1.4 - **/ -const char * -nm_setting_wired_get_generate_mac_address_mask(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->generate_mac_address_mask; -} - -/** - * nm_setting_wired_get_mac_address_blacklist: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:mac-address-blacklist property of the setting - **/ -const char *const * -nm_setting_wired_get_mac_address_blacklist(NMSettingWired *setting) -{ - NMSettingWiredPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - return (const char *const *) priv->mac_address_blacklist->data; -} - -/** - * nm_setting_wired_get_num_mac_blacklist_items: - * @setting: the #NMSettingWired - * - * Returns: the number of blacklisted MAC addresses - **/ -guint32 -nm_setting_wired_get_num_mac_blacklist_items(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), 0); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->mac_address_blacklist->len; -} - -/** - * nm_setting_wired_get_mac_blacklist_item: - * @setting: the #NMSettingWired - * @idx: the zero-based index of the MAC address entry - * - * Returns: the blacklisted MAC address string (hex-digits-and-colons notation) - * at index @idx - **/ -const char * -nm_setting_wired_get_mac_blacklist_item(NMSettingWired *setting, guint32 idx) -{ - NMSettingWiredPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - g_return_val_if_fail(idx <= priv->mac_address_blacklist->len, NULL); - - return g_array_index(priv->mac_address_blacklist, const char *, idx); -} - -/** - * nm_setting_wired_add_mac_blacklist_item: - * @setting: the #NMSettingWired - * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist - * - * Adds a new MAC address to the #NMSettingWired:mac-address-blacklist property. - * - * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address - * is invalid or was already present - **/ -gboolean -nm_setting_wired_add_mac_blacklist_item(NMSettingWired *setting, const char *mac) -{ - NMSettingWiredPrivate *priv; - const char * candidate; - int i; - - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); - g_return_val_if_fail(mac != NULL, FALSE); - - if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) - return FALSE; - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - for (i = 0; i < priv->mac_address_blacklist->len; i++) { - candidate = g_array_index(priv->mac_address_blacklist, char *, i); - if (nm_utils_hwaddr_matches(mac, -1, candidate, -1)) - return FALSE; - } - - mac = nm_utils_hwaddr_canonical(mac, ETH_ALEN); - g_array_append_val(priv->mac_address_blacklist, mac); - _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); - return TRUE; -} - -/** - * nm_setting_wired_remove_mac_blacklist_item: - * @setting: the #NMSettingWired - * @idx: index number of the MAC address - * - * Removes the MAC address at index @idx from the blacklist. - **/ -void -nm_setting_wired_remove_mac_blacklist_item(NMSettingWired *setting, guint32 idx) -{ - NMSettingWiredPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_WIRED(setting)); - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - g_return_if_fail(idx < priv->mac_address_blacklist->len); - - g_array_remove_index(priv->mac_address_blacklist, idx); - _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); -} - -/** - * nm_setting_wired_remove_mac_blacklist_item_by_value: - * @setting: the #NMSettingWired - * @mac: the MAC address string (hex-digits-and-colons notation) to remove from - * the blacklist - * - * Removes the MAC address @mac from the blacklist. - * - * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_wired_remove_mac_blacklist_item_by_value(NMSettingWired *setting, const char *mac) -{ - NMSettingWiredPrivate *priv; - const char * candidate; - int i; - - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); - g_return_val_if_fail(mac != NULL, FALSE); - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - for (i = 0; i < priv->mac_address_blacklist->len; i++) { - candidate = g_array_index(priv->mac_address_blacklist, char *, i); - if (!nm_utils_hwaddr_matches(mac, -1, candidate, -1)) { - g_array_remove_index(priv->mac_address_blacklist, i); - _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_wired_clear_mac_blacklist_items: - * @setting: the #NMSettingWired - * - * Removes all blacklisted MAC addresses. - **/ -void -nm_setting_wired_clear_mac_blacklist_items(NMSettingWired *setting) -{ - g_return_if_fail(NM_IS_SETTING_WIRED(setting)); - - g_array_set_size(NM_SETTING_WIRED_GET_PRIVATE(setting)->mac_address_blacklist, 0); - _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); -} - -/** - * nm_setting_wired_get_mtu: - * @setting: the #NMSettingWired - * - * Returns: the #NMSettingWired:mtu property of the setting - **/ -guint32 -nm_setting_wired_get_mtu(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), 0); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->mtu; -} - -/** - * nm_setting_wired_get_s390_subchannels: - * @setting: the #NMSettingWired - * - * Return the list of s390 subchannels that identify the device that this - * connection is applicable to. The connection should only be used in - * conjunction with that device. - * - * Returns: (transfer none) (element-type utf8): array of strings, each specifying - * one subchannel the s390 device uses to communicate to the host. - **/ -const char *const * -nm_setting_wired_get_s390_subchannels(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - return (const char *const *) NM_SETTING_WIRED_GET_PRIVATE(setting)->s390_subchannels; -} - -/** - * nm_setting_wired_get_s390_nettype: - * @setting: the #NMSettingWired - * - * Returns the s390 device type this connection should apply to. Will be one - * of 'qeth', 'lcs', or 'ctc'. - * - * Returns: the s390 device type - **/ -const char * -nm_setting_wired_get_s390_nettype(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->s390_nettype; -} - -/** - * nm_setting_wired_get_num_s390_options: - * @setting: the #NMSettingWired - * - * Returns the number of s390-specific options that should be set for this - * device when it is activated. This can be used to retrieve each s390 - * option individually using nm_setting_wired_get_s390_option(). - * - * Returns: the number of s390-specific device options - **/ -guint32 -nm_setting_wired_get_num_s390_options(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), 0); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->s390_options.len; -} - -/** - * nm_setting_wired_get_s390_option: - * @setting: the #NMSettingWired - * @idx: index of the desired option, from 0 to - * nm_setting_wired_get_num_s390_options() - 1 - * @out_key: (out) (transfer none): on return, the key name of the s390 specific - * option; this value is owned by the setting and should not be modified - * @out_value: (out) (transfer none): on return, the value of the key of the - * s390 specific option; this value is owned by the setting and should not be - * modified - * - * Given an index, return the value of the s390 option at that index. indexes - * are *not* guaranteed to be static across modifications to options done by - * nm_setting_wired_add_s390_option() and nm_setting_wired_remove_s390_option(), - * and should not be used to refer to options except for short periods of time - * such as during option iteration. - * - * Returns: %TRUE on success if the index was valid and an option was found, - * %FALSE if the index was invalid (ie, greater than the number of options - * currently held by the setting) - **/ -gboolean -nm_setting_wired_get_s390_option(NMSettingWired *setting, - guint32 idx, - const char ** out_key, - const char ** out_value) -{ - NMSettingWiredPrivate *priv; - - /* with LTO and optimization, the compiler complains that the - * output variables are not initialized. In practice, the function - * only sets the output on success. But make the compiler happy. - */ - NM_SET_OUT(out_key, NULL); - NM_SET_OUT(out_value, NULL); - - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - - g_return_val_if_fail(idx < priv->s390_options.len, FALSE); - - NM_SET_OUT(out_key, priv->s390_options.arr[idx].name); - NM_SET_OUT(out_value, priv->s390_options.arr[idx].value_str); - return TRUE; -} - -/** - * nm_setting_wired_get_s390_option_by_key: - * @setting: the #NMSettingWired - * @key: the key for which to retrieve the value - * - * Returns the value associated with the s390-specific option specified by - * @key, if it exists. - * - * Returns: the value, or %NULL if the key/value pair was never added to the - * setting; the value is owned by the setting and must not be modified - **/ -const char * -nm_setting_wired_get_s390_option_by_key(NMSettingWired *setting, const char *key) -{ - NMSettingWiredPrivate *priv; - gssize idx; - - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - g_return_val_if_fail(key && key[0], NULL); - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - - idx = nm_utils_named_value_list_find(priv->s390_options.arr, priv->s390_options.len, key, TRUE); - if (idx < 0) - return NULL; - return priv->s390_options.arr[idx].value_str; -} - -/** - * nm_setting_wired_add_s390_option: - * @setting: the #NMSettingWired - * @key: key name for the option - * @value: value for the option - * - * Add an option to the table. The option is compared to an internal list - * of allowed options. Key names may contain only alphanumeric characters - * (ie [a-zA-Z0-9]). Adding a new key replaces any existing key/value pair that - * may already exist. - * - * Returns: %TRUE if the option was valid and was added to the internal option - * list, %FALSE if it was not. - **/ -gboolean -nm_setting_wired_add_s390_option(NMSettingWired *setting, const char *key, const char *value) -{ - NMSettingWiredPrivate *priv; - gssize idx; - NMUtilsNamedValue * v; - - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); - g_return_val_if_fail(value, FALSE); - - if (!valid_s390_opts_check(key)) { - g_return_val_if_fail(key, FALSE); - return FALSE; - } - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - - idx = nm_utils_named_value_list_find(priv->s390_options.arr, priv->s390_options.len, key, TRUE); - if (idx < 0) { - gsize dst_idx = ~idx; - - if (priv->s390_options.n_alloc < priv->s390_options.len + 1) { - priv->s390_options.n_alloc = NM_MAX(4, (priv->s390_options.len + 1) * 2); - priv->s390_options.arr = - g_realloc(priv->s390_options.arr, - priv->s390_options.n_alloc * sizeof(NMUtilsNamedValue)); - } - if (dst_idx < priv->s390_options.len) { - memmove(&priv->s390_options.arr[dst_idx + 1], - &priv->s390_options.arr[dst_idx], - (priv->s390_options.len - dst_idx) * sizeof(NMUtilsNamedValue)); - } - priv->s390_options.arr[dst_idx] = (NMUtilsNamedValue){ - .name = g_strdup(key), - .value_str = g_strdup(value), - }; - priv->s390_options.len++; - } else { - v = &priv->s390_options.arr[idx]; - if (nm_streq(value, v->value_str)) - return TRUE; - g_free((char *) v->value_str); - v->value_str = g_strdup(value); - } - - _notify(setting, PROP_S390_OPTIONS); - return TRUE; -} - -/** - * nm_setting_wired_remove_s390_option: - * @setting: the #NMSettingWired - * @key: key name for the option to remove - * - * Remove the s390-specific option referenced by @key from the internal option - * list. - * - * Returns: %TRUE if the option was found and removed from the internal option - * list, %FALSE if it was not. - **/ -gboolean -nm_setting_wired_remove_s390_option(NMSettingWired *setting, const char *key) -{ - NMSettingWiredPrivate *priv; - gsize dst_idx; - gssize idx; - - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); - g_return_val_if_fail(key, FALSE); - - priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - - idx = nm_utils_named_value_list_find(priv->s390_options.arr, priv->s390_options.len, key, TRUE); - if (idx < 0) - return FALSE; - - dst_idx = idx; - - g_free((char *) priv->s390_options.arr[dst_idx].name); - g_free((char *) priv->s390_options.arr[dst_idx].value_str); - if (dst_idx + 1 != priv->s390_options.len) { - memmove(&priv->s390_options.arr[dst_idx], - &priv->s390_options.arr[dst_idx + 1], - (priv->s390_options.len - dst_idx - 1) * sizeof(NMUtilsNamedValue)); - } - - priv->s390_options.len--; - - _notify(setting, PROP_S390_OPTIONS); - return TRUE; -} - -static void -_s390_options_clear(NMSettingWiredPrivate *priv) -{ - guint i; - - for (i = 0; i < priv->s390_options.len; i++) { - g_free((char *) priv->s390_options.arr[i].name); - g_free((char *) priv->s390_options.arr[i].value_str); - } - nm_clear_g_free(&priv->s390_options.arr); - priv->s390_options.len = 0; - priv->s390_options.n_alloc = 0; -} - -void -_nm_setting_wired_clear_s390_options(NMSettingWired *setting) -{ - g_return_if_fail(NM_IS_SETTING_WIRED(setting)); - - _s390_options_clear(NM_SETTING_WIRED_GET_PRIVATE(setting)); -} - -/** - * nm_setting_wired_get_valid_s390_options: - * @setting: (allow-none): the #NMSettingWired. This argument is unused - * and you may pass %NULL. - * - * Returns a list of valid s390 options. - * - * The @setting argument is unused and %NULL may be passed instead. - * - * Returns: (transfer none): a %NULL-terminated array of strings of valid s390 options. - **/ -const char ** -nm_setting_wired_get_valid_s390_options(NMSettingWired *setting) -{ - return valid_s390_opts; -} - -/** - * nm_setting_wired_get_wake_on_lan: - * @setting: the #NMSettingWired - * - * Returns the Wake-on-LAN options enabled for the connection - * - * Returns: the Wake-on-LAN options - * - * Since: 1.2 - */ -NMSettingWiredWakeOnLan -nm_setting_wired_get_wake_on_lan(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NM_SETTING_WIRED_WAKE_ON_LAN_NONE); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->wol; -} - -/** - * nm_setting_wired_get_wake_on_lan_password: - * @setting: the #NMSettingWired - * - * Returns the Wake-on-LAN password. This only applies to - * %NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC. - * - * Returns: the Wake-on-LAN setting password, or %NULL if there is no password. - * - * Since: 1.2 - */ -const char * -nm_setting_wired_get_wake_on_lan_password(NMSettingWired *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); - - return NM_SETTING_WIRED_GET_PRIVATE(setting)->wol_password; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - GError * local = NULL; - guint i; - - if (!NM_IN_STRSET(priv->port, NULL, "tp", "aui", "bnc", "mii")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid Ethernet port value"), - priv->port); - g_prefix_error(error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_PORT); - return FALSE; - } - - if (!NM_IN_STRSET(priv->duplex, NULL, "half", "full")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid duplex value"), - priv->duplex); - g_prefix_error(error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_DUPLEX); - return FALSE; - } - - if (priv->device_mac_address && !nm_utils_hwaddr_valid(priv->device_mac_address, ETH_ALEN)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid MAC address"), - priv->device_mac_address); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_MAC_ADDRESS); - return FALSE; - } - - for (i = 0; i < priv->mac_address_blacklist->len; i++) { - const char *mac = g_array_index(priv->mac_address_blacklist, const char *, i); - - if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid MAC address"), - mac); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST); - return FALSE; - } - } - - if (priv->s390_subchannels) { - guint len = g_strv_length(priv->s390_subchannels); - - if (len != 2 && len != 3) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_S390_SUBCHANNELS); - return FALSE; - } - } - - if (!NM_IN_STRSET(priv->s390_nettype, NULL, "qeth", "lcs", "ctc")) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_S390_NETTYPE); - return FALSE; - } - - for (i = 0; i < priv->s390_options.len; i++) { - const NMUtilsNamedValue *v = &priv->s390_options.arr[i]; - - nm_assert(v->name); - - if (!valid_s390_opts_check(v->name) || v->value_str[0] == '\0' - || strlen(v->value_str) > 200) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid '%s' or its value '%s'"), - v->name, - v->value_str); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_S390_OPTIONS); - return FALSE; - } - } - - if (priv->cloned_mac_address && !NM_CLONED_MAC_IS_SPECIAL(priv->cloned_mac_address) - && !nm_utils_hwaddr_valid(priv->cloned_mac_address, ETH_ALEN)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid MAC address"), - priv->cloned_mac_address); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_CLONED_MAC_ADDRESS); - return FALSE; - } - - /* generate-mac-address-mask only makes sense with cloned-mac-address "random" or - * "stable". Still, let's not be so strict about that and accept the value - * even if it is unused. */ - if (!_nm_utils_generate_mac_address_mask_parse(priv->generate_mac_address_mask, - NULL, - NULL, - NULL, - &local)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - local->message); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK); - g_error_free(local); - return FALSE; - } - - if (NM_FLAGS_ANY(priv->wol, NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS) - && !nm_utils_is_power_of_two(priv->wol)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Wake-on-LAN mode 'default' and 'ignore' are exclusive flags")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_WAKE_ON_LAN); - return FALSE; - } - - if (priv->wol_password && !NM_FLAGS_HAS(priv->wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Wake-on-LAN password can only be used with magic packet mode")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD); - return FALSE; - } - - if (priv->wol_password && !nm_utils_hwaddr_valid(priv->wol_password, ETH_ALEN)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid MAC address"), - priv->wol_password); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD); - return FALSE; - } - - /* Normalizable properties - just return NM_SETTING_VERIFY_NORMALIZABLE for compatibility - * with legacy nm-connection-editor which used to save "full" duplex connection as default - */ - - if (((priv->speed) && (!priv->duplex)) || ((!priv->speed) && (priv->duplex))) { - g_set_error_literal( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - priv->auto_negotiate - ? _("both speed and duplex should have a valid value or both should be unset") - : _("both speed and duplex are required for static link configuration")); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - if (nm_streq(sett_info->property_infos[property_idx].name, - NM_SETTING_WIRED_CLONED_MAC_ADDRESS)) { - return !set_b - || nm_streq0(NM_SETTING_WIRED_GET_PRIVATE(set_a)->cloned_mac_address, - NM_SETTING_WIRED_GET_PRIVATE(set_b)->cloned_mac_address); - } - - return NM_SETTING_CLASS(nm_setting_wired_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -static GVariant * -_override_autoneg_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - return g_variant_new_boolean(nm_setting_wired_get_auto_negotiate((NMSettingWired *) setting)); -} - -/*****************************************************************************/ - -static void -clear_blacklist_item(char **item_p) -{ - g_free(*item_p); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingWired * setting = NM_SETTING_WIRED(object); - NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - GHashTable * hash; - guint i; - - switch (prop_id) { - case PROP_PORT: - g_value_set_string(value, nm_setting_wired_get_port(setting)); - break; - case PROP_SPEED: - g_value_set_uint(value, nm_setting_wired_get_speed(setting)); - break; - case PROP_DUPLEX: - g_value_set_string(value, nm_setting_wired_get_duplex(setting)); - break; - case PROP_AUTO_NEGOTIATE: - g_value_set_boolean(value, nm_setting_wired_get_auto_negotiate(setting)); - break; - case PROP_MAC_ADDRESS: - g_value_set_string(value, nm_setting_wired_get_mac_address(setting)); - break; - case PROP_CLONED_MAC_ADDRESS: - g_value_set_string(value, nm_setting_wired_get_cloned_mac_address(setting)); - break; - case PROP_GENERATE_MAC_ADDRESS_MASK: - g_value_set_string(value, nm_setting_wired_get_generate_mac_address_mask(setting)); - break; - case PROP_MAC_ADDRESS_BLACKLIST: - g_value_set_boxed(value, (char **) priv->mac_address_blacklist->data); - break; - case PROP_MTU: - g_value_set_uint(value, nm_setting_wired_get_mtu(setting)); - break; - case PROP_S390_SUBCHANNELS: - g_value_set_boxed(value, priv->s390_subchannels); - break; - case PROP_S390_NETTYPE: - g_value_set_string(value, nm_setting_wired_get_s390_nettype(setting)); - break; - case PROP_S390_OPTIONS: - hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); - for (i = 0; i < priv->s390_options.len; i++) { - g_hash_table_insert(hash, - g_strdup(priv->s390_options.arr[i].name), - g_strdup(priv->s390_options.arr[i].value_str)); - } - g_value_take_boxed(value, hash); - break; - case PROP_WAKE_ON_LAN: - g_value_set_uint(value, priv->wol); - break; - case PROP_WAKE_ON_LAN_PASSWORD: - g_value_set_string(value, priv->wol_password); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(object); - const char *const * blacklist; - const char * mac; - - switch (prop_id) { - case PROP_PORT: - g_free(priv->port); - priv->port = g_value_dup_string(value); - break; - case PROP_SPEED: - priv->speed = g_value_get_uint(value); - break; - case PROP_DUPLEX: - g_free(priv->duplex); - priv->duplex = g_value_dup_string(value); - break; - case PROP_AUTO_NEGOTIATE: - priv->auto_negotiate = g_value_get_boolean(value); - break; - case PROP_MAC_ADDRESS: - g_free(priv->device_mac_address); - priv->device_mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); - break; - case PROP_CLONED_MAC_ADDRESS: - g_free(priv->cloned_mac_address); - priv->cloned_mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); - break; - case PROP_GENERATE_MAC_ADDRESS_MASK: - g_free(priv->generate_mac_address_mask); - priv->generate_mac_address_mask = g_value_dup_string(value); - break; - case PROP_MAC_ADDRESS_BLACKLIST: - blacklist = g_value_get_boxed(value); - g_array_set_size(priv->mac_address_blacklist, 0); - if (blacklist && *blacklist) { - guint i; - - for (i = 0; blacklist[i]; i++) { - mac = _nm_utils_hwaddr_canonical_or_invalid(blacklist[i], ETH_ALEN); - g_array_append_val(priv->mac_address_blacklist, mac); - } - } - break; - case PROP_MTU: - priv->mtu = g_value_get_uint(value); - break; - case PROP_S390_SUBCHANNELS: - if (priv->s390_subchannels) - g_strfreev(priv->s390_subchannels); - priv->s390_subchannels = g_value_dup_boxed(value); - break; - case PROP_S390_NETTYPE: - g_free(priv->s390_nettype); - priv->s390_nettype = g_value_dup_string(value); - break; - case PROP_S390_OPTIONS: - { - GHashTable *hash; - - _s390_options_clear(priv); - - hash = g_value_get_boxed(value); - - priv->s390_options.n_alloc = hash ? g_hash_table_size(hash) : 0u; - - if (priv->s390_options.n_alloc > 0) { - gboolean invalid_content = FALSE; - GHashTableIter iter; - const char * key; - const char * val; - guint i, j; - - priv->s390_options.arr = g_new(NMUtilsNamedValue, priv->s390_options.n_alloc); - g_hash_table_iter_init(&iter, hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - if (!key || !val) { - invalid_content = TRUE; - continue; - } - nm_assert(priv->s390_options.len < priv->s390_options.n_alloc); - priv->s390_options.arr[priv->s390_options.len] = (NMUtilsNamedValue){ - .name = g_strdup(key), - .value_str = g_strdup(val), - }; - priv->s390_options.len++; - } - if (priv->s390_options.len > 1) { - nm_utils_named_value_list_sort(priv->s390_options.arr, - priv->s390_options.len, - NULL, - NULL); - /* prune duplicate keys. This is only possible if @hash does not use - * g_str_equal() as compare function (which would be a bug). - * Still, handle this, because we use later binary sort and rely - * on unique names. One bug here, should not bork the remainder - * of the program. */ - j = 1; - for (i = 1; i < priv->s390_options.len; i++) { - if (nm_streq(priv->s390_options.arr[j - 1].name, - priv->s390_options.arr[i].name)) { - g_free((char *) priv->s390_options.arr[i].name); - g_free((char *) priv->s390_options.arr[i].value_str); - invalid_content = TRUE; - continue; - } - priv->s390_options.arr[j++] = priv->s390_options.arr[i]; - } - priv->s390_options.len = j; - } - - g_return_if_fail(!invalid_content); - } - } break; - case PROP_WAKE_ON_LAN: - priv->wol = g_value_get_uint(value); - break; - case PROP_WAKE_ON_LAN_PASSWORD: - g_free(priv->wol_password); - priv->wol_password = g_value_dup_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_wired_init(NMSettingWired *setting) -{ - NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - - /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */ - priv->mac_address_blacklist = g_array_new(TRUE, FALSE, sizeof(char *)); - g_array_set_clear_func(priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item); - - priv->wol = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT; -} - -/** - * nm_setting_wired_new: - * - * Creates a new #NMSettingWired object with default values. - * - * Returns: (transfer full): the new empty #NMSettingWired object - **/ -NMSetting * -nm_setting_wired_new(void) -{ - return g_object_new(NM_TYPE_SETTING_WIRED, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(object); - - g_free(priv->port); - g_free(priv->duplex); - g_free(priv->s390_nettype); - - _s390_options_clear(priv); - - g_free(priv->device_mac_address); - g_free(priv->cloned_mac_address); - g_free(priv->generate_mac_address_mask); - g_array_unref(priv->mac_address_blacklist); - - if (priv->s390_subchannels) - g_strfreev(priv->s390_subchannels); - - g_free(priv->wol_password); - - G_OBJECT_CLASS(nm_setting_wired_parent_class)->finalize(object); -} - -static void -nm_setting_wired_class_init(NMSettingWiredClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingWiredPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->compare_property = compare_property; - - /** - * NMSettingWired:port: - * - * Specific port type to use if the device supports multiple - * attachment methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit - * Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface). - * If the device supports only one port type, this setting is ignored. - **/ - /* ---ifcfg-rh--- - * property: port - * variable: (none) - * description: The property is not saved by the plugin. - * ---end--- - */ - obj_properties[PROP_PORT] = g_param_spec_string(NM_SETTING_WIRED_PORT, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:speed: - * - * When a value greater than 0 is set, configures the device to use - * the specified speed. If "auto-negotiate" is "yes" the specified - * speed will be the only one advertised during link negotiation: - * this works only for BASE-T 802.3 specifications and is useful for - * enforcing gigabit speeds, as in this case link negotiation is - * mandatory. - * If the value is unset (0, the default), the link configuration will be - * either skipped (if "auto-negotiate" is "no", the default) or will - * be auto-negotiated (if "auto-negotiate" is "yes") and the local device - * will advertise all the supported speeds. - * In Mbit/s, ie 100 == 100Mbit/s. - * Must be set together with the "duplex" property when non-zero. - * Before specifying a speed value be sure your device supports it. - **/ - /* ---ifcfg-rh--- - * property: speed - * variable: ETHTOOL_OPTS - * description: Fixed speed for the ethernet link. It is added as "speed" - * parameter in the ETHTOOL_OPTS variable. - * ---end--- - */ - obj_properties[PROP_SPEED] = g_param_spec_uint(NM_SETTING_WIRED_SPEED, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:duplex: - * - * When a value is set, either "half" or "full", configures the device - * to use the specified duplex mode. If "auto-negotiate" is "yes" the - * specified duplex mode will be the only one advertised during link - * negotiation: this works only for BASE-T 802.3 specifications and is - * useful for enforcing gigabits modes, as in these cases link negotiation - * is mandatory. - * If the value is unset (the default), the link configuration will be - * either skipped (if "auto-negotiate" is "no", the default) or will - * be auto-negotiated (if "auto-negotiate" is "yes") and the local device - * will advertise all the supported duplex modes. - * Must be set together with the "speed" property if specified. - * Before specifying a duplex mode be sure your device supports it. - **/ - /* ---ifcfg-rh--- - * property: duplex - * variable: ETHTOOL_OPTS - * description: Fixed duplex mode for the ethernet link. It is added as - * "duplex" parameter in the ETHOOL_OPTS variable. - * ---end--- - */ - obj_properties[PROP_DUPLEX] = g_param_spec_string(NM_SETTING_WIRED_DUPLEX, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:auto-negotiate: - * - * When %TRUE, enforce auto-negotiation of speed and duplex mode. - * If "speed" and "duplex" properties are both specified, only that - * single mode will be advertised and accepted during the link - * auto-negotiation process: this works only for BASE-T 802.3 specifications - * and is useful for enforcing gigabits modes, as in these cases link - * negotiation is mandatory. - * When %FALSE, "speed" and "duplex" properties should be both set or - * link configuration will be skipped. - **/ - /* ---ifcfg-rh--- - * property: auto-negotiate - * variable: ETHTOOL_OPTS - * description: Whether link speed and duplex autonegotiation is enabled. - * It is not saved only if disabled and no values are provided for the - * "speed" and "duplex" parameters (skips link configuration). - * ---end--- - */ - obj_properties[PROP_AUTO_NEGOTIATE] = - g_param_spec_boolean(NM_SETTING_WIRED_AUTO_NEGOTIATE, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_AUTO_NEGOTIATE], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BOOLEAN, - .to_dbus_fcn = _override_autoneg_get, )); - - /** - * NMSettingWired:mac-address: - * - * If specified, this connection will only apply to the Ethernet device - * whose permanent MAC address matches. This property does not change the - * MAC address of the device (i.e. MAC spoofing). - **/ - /* ---keyfile--- - * property: mac-address - * format: usual hex-digits-and-colons notation - * description: MAC address in traditional hex-digits-and-colons notation - * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) - * (e.g. 0;34;104;18;121;162) - * ---end--- - * ---ifcfg-rh--- - * property: mac-address - * variable: HWADDR - * description: Hardware address of the device in traditional hex-digits-and-colons - * notation (e.g. 00:22:68:14:5A:05). - * Note that for initscripts this is the current MAC address of the device as found - * during ifup. For NetworkManager this is the permanent MAC address. Or in case no - * permanent MAC address exists, the MAC address initially configured on the device. - * ---end--- - */ - obj_properties[PROP_MAC_ADDRESS] = g_param_spec_string( - NM_SETTING_WIRED_MAC_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_MAC_ADDRESS], - &nm_sett_info_propert_type_mac_address); - - /** - * NMSettingWired:cloned-mac-address: - * - * If specified, request that the device use this MAC address instead. - * This is known as MAC cloning or spoofing. - * - * Beside explicitly specifying a MAC address, the special values "preserve", "permanent", - * "random" and "stable" are supported. - * "preserve" means not to touch the MAC address on activation. - * "permanent" means to use the permanent hardware address if the device - * has one (otherwise this is treated as "preserve"). - * "random" creates a random MAC address on each connect. - * "stable" creates a hashed MAC address based on connection.stable-id and a - * machine dependent key. - * - * If unspecified, the value can be overwritten via global defaults, see manual - * of NetworkManager.conf. If still unspecified, it defaults to "preserve" - * (older versions of NetworkManager may use a different default value). - * - * On D-Bus, this field is expressed as "assigned-mac-address" or the deprecated - * "cloned-mac-address". - **/ - /* ---keyfile--- - * property: cloned-mac-address - * format: usual hex-digits-and-colons notation - * description: Cloned MAC address in traditional hex-digits-and-colons notation - * (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete) - * (e.g. 0;34;104;18;121;178). - * ---end--- - * ---ifcfg-rh--- - * property: cloned-mac-address - * variable: MACADDR - * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons - * notation (e.g. 00:22:68:14:5A:99). - * ---end--- - * ---dbus--- - * property: cloned-mac-address - * format: byte array - * description: This D-Bus field is deprecated in favor of "assigned-mac-address" - * which is more flexible and allows specifying special variants like "random". - * For libnm and nmcli, this field is called "cloned-mac-address". - * ---end--- - */ - obj_properties[PROP_CLONED_MAC_ADDRESS] = g_param_spec_string( - NM_SETTING_WIRED_CLONED_MAC_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_CLONED_MAC_ADDRESS], - &nm_sett_info_propert_type_cloned_mac_address); - - /* ---dbus--- - * property: assigned-mac-address - * format: string - * description: The new field for the cloned MAC address. It can be either - * a hardware address in ASCII representation, or one of the special values - * "preserve", "permanent", "random" or "stable". - * This field replaces the deprecated "cloned-mac-address" on D-Bus, which - * can only contain explicit hardware addresses. Note that this property - * only exists in D-Bus API. libnm and nmcli continue to call this property - * "cloned-mac-address". - * ---end--- - */ - _nm_properties_override_dbus(properties_override, - "assigned-mac-address", - &nm_sett_info_propert_type_assigned_mac_address); - - /** - * NMSettingWired:generate-mac-address-mask: - * - * With #NMSettingWired:cloned-mac-address setting "random" or "stable", - * by default all bits of the MAC address are scrambled and a locally-administered, - * unicast MAC address is created. This property allows to specify that certain bits - * are fixed. Note that the least significant bit of the first MAC address will - * always be unset to create a unicast MAC address. - * - * If the property is %NULL, it is eligible to be overwritten by a default - * connection setting. If the value is still %NULL or an empty string, the - * default is to create a locally-administered, unicast MAC address. - * - * If the value contains one MAC address, this address is used as mask. The set - * bits of the mask are to be filled with the current MAC address of the device, - * while the unset bits are subject to randomization. - * Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address - * and only randomize the lower 3 bytes using the "random" or "stable" algorithm. - * - * If the value contains one additional MAC address after the mask, - * this address is used instead of the current MAC address to fill the bits - * that shall not be randomized. For example, a value of - * "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address - * to 68:F7:28, while the lower bits are randomized. A value of - * "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled - * globally-administered, burned-in MAC address. - * - * If the value contains more than one additional MAC addresses, one of - * them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" - * will create a fully scrambled MAC address, randomly locally or globally - * administered. - **/ - /* ---ifcfg-rh--- - * property: generate-mac-address-mask - * variable: GENERATE_MAC_ADDRESS_MASK(+) - * description: the MAC address mask for generating randomized and stable - * cloned-mac-address. - * ---end--- - */ - obj_properties[PROP_GENERATE_MAC_ADDRESS_MASK] = g_param_spec_string( - NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:mac-address-blacklist: - * - * If specified, this connection will never apply to the Ethernet device - * whose permanent MAC address matches an address in the list. Each MAC - * address is in the standard hex-digits-and-colons notation - * (00:11:22:33:44:55). - **/ - /* ---keyfile--- - * property: mac-address-blacklist - * format: list of MACs (separated with semicolons) - * description: MAC address blacklist. - * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78 - * ---end--- - * ---ifcfg-rh--- - * property: mac-address-blacklist - * variable: HWADDR_BLACKLIST(+) - * description: It denies usage of the connection for any device whose address - * is listed. - * example: HWADDR_BLACKLIST="00:22:68:11:69:08 00:11:22:11:44:55" - * ---end--- - */ - obj_properties[PROP_MAC_ADDRESS_BLACKLIST] = g_param_spec_boxed( - NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:mtu: - * - * If non-zero, only transmit packets of the specified size or smaller, - * breaking larger packets up into multiple Ethernet frames. - **/ - /* ---ifcfg-rh--- - * property: mtu - * variable: MTU - * description: MTU of the interface. - * ---end--- - */ - obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_WIRED_MTU, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:s390-subchannels: - * - * Identifies specific subchannels that this network device uses for - * communication with z/VM or s390 host. Like the - * #NMSettingWired:mac-address property for non-z/VM devices, this property - * can be used to ensure this connection only applies to the network device - * that uses these subchannels. The list should contain exactly 3 strings, - * and each string may only be composed of hexadecimal characters and the - * period (.) character. - **/ - /* ---ifcfg-rh--- - * property: s390-subchannels - * variable: SUBCHANNELS - * description: Subchannels for IBM S390 hosts. - * example: SUBCHANNELS=0.0.b00a,0.0.b00b,0.0.b00c - * ---end--- - */ - obj_properties[PROP_S390_SUBCHANNELS] = g_param_spec_boxed( - NM_SETTING_WIRED_S390_SUBCHANNELS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:s390-nettype: - * - * s390 network device type; one of "qeth", "lcs", or "ctc", representing - * the different types of virtual network devices available on s390 systems. - **/ - /* ---ifcfg-rh--- - * property: s390-nettype - * variable: NETTYPE - * values: "qeth", "lcs" or "ctc" - * description: Network type of the S390 host. - * example: NETTYPE=qeth - * ---end--- - */ - obj_properties[PROP_S390_NETTYPE] = g_param_spec_string( - NM_SETTING_WIRED_S390_NETTYPE, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:s390-options: (type GHashTable(utf8,utf8)): - * - * Dictionary of key/value pairs of s390-specific device options. Both keys - * and values must be strings. Allowed keys include "portno", "layer2", - * "portname", "protocol", among others. Key names must contain only - * alphanumeric characters (ie, [a-zA-Z0-9]). - **/ - /* ---ifcfg-rh--- - * property: s390-options - * variable: OPTIONS and PORTNAME, CTCPROTO, - * description: S390 device options. All options go to OPTIONS, except for - * "portname" and "ctcprot" that have their own variables. - * ---end--- - */ - obj_properties[PROP_S390_OPTIONS] = g_param_spec_boxed( - NM_SETTING_WIRED_S390_OPTIONS, - "", - "", - G_TYPE_HASH_TABLE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_S390_OPTIONS], - &nm_sett_info_propert_type_strdict); - - /** - * NMSettingWired:wake-on-lan: - * - * The #NMSettingWiredWakeOnLan options to enable. Not all devices support all options. - * May be any combination of %NM_SETTING_WIRED_WAKE_ON_LAN_PHY, - * %NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST, %NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST, - * %NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST, %NM_SETTING_WIRED_WAKE_ON_LAN_ARP, - * %NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC or the special values - * %NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (to use global settings) and - * %NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (to disable management of Wake-on-LAN in - * NetworkManager). - * - * Since: 1.2 - **/ - obj_properties[PROP_WAKE_ON_LAN] = - g_param_spec_uint(NM_SETTING_WIRED_WAKE_ON_LAN, - "", - "", - 0, - G_MAXUINT32, - NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWired:wake-on-lan-password: - * - * If specified, the password used with magic-packet-based - * Wake-on-LAN, represented as an Ethernet MAC address. If %NULL, - * no password will be required. - * - * Since: 1.2 - **/ - obj_properties[PROP_WAKE_ON_LAN_PASSWORD] = - g_param_spec_string(NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_WIRED, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-wired.h b/libnm-core/nm-setting-wired.h deleted file mode 100644 index acabd70646..0000000000 --- a/libnm-core/nm-setting-wired.h +++ /dev/null @@ -1,142 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_WIRED_H__ -#define __NM_SETTING_WIRED_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_WIRED (nm_setting_wired_get_type()) -#define NM_SETTING_WIRED(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIRED, NMSettingWired)) -#define NM_SETTING_WIRED_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIRED, NMSettingWiredClass)) -#define NM_IS_SETTING_WIRED(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIRED)) -#define NM_IS_SETTING_WIRED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIRED)) -#define NM_SETTING_WIRED_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIRED, NMSettingWiredClass)) - -#define NM_SETTING_WIRED_SETTING_NAME "802-3-ethernet" - -/** - * NMSettingWiredWakeOnLan: - * @NM_SETTING_WIRED_WAKE_ON_LAN_NONE: Wake-on-LAN disabled - * @NM_SETTING_WIRED_WAKE_ON_LAN_PHY: Wake on PHY activity - * @NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST: Wake on unicast messages - * @NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST: Wake on multicast messages - * @NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST: Wake on broadcast messages - * @NM_SETTING_WIRED_WAKE_ON_LAN_ARP: Wake on ARP - * @NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC: Wake on magic packet - * @NM_SETTING_WIRED_WAKE_ON_LAN_ALL: Wake on all events. This does not - * include the exclusive flags @NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT or - * @NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE. - * @NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT: Use the default value - * @NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE: Don't change configured settings - * @NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS: Mask of flags that are - * incompatible with other flags - * - * Options for #NMSettingWired:wake-on-lan. Note that not all options - * are supported by all devices. - * - * Since: 1.2 - */ -typedef enum { /*< flags >*/ - NM_SETTING_WIRED_WAKE_ON_LAN_NONE = 0, /*< skip >*/ - NM_SETTING_WIRED_WAKE_ON_LAN_PHY = 0x2, - NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST = 0x4, - NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST = 0x8, - NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST = 0x10, - NM_SETTING_WIRED_WAKE_ON_LAN_ARP = 0x20, - NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC = 0x40, - - NM_SETTING_WIRED_WAKE_ON_LAN_ALL = 0x7E, /*< skip >*/ - - NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT = 0x1, - NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE = 0x8000, - NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS = 0x8001, /*< skip >*/ -} NMSettingWiredWakeOnLan; - -#define NM_SETTING_WIRED_PORT "port" -#define NM_SETTING_WIRED_SPEED "speed" -#define NM_SETTING_WIRED_DUPLEX "duplex" -#define NM_SETTING_WIRED_AUTO_NEGOTIATE "auto-negotiate" -#define NM_SETTING_WIRED_MAC_ADDRESS "mac-address" -#define NM_SETTING_WIRED_CLONED_MAC_ADDRESS "cloned-mac-address" -#define NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK "generate-mac-address-mask" -#define NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST "mac-address-blacklist" -#define NM_SETTING_WIRED_MTU "mtu" -#define NM_SETTING_WIRED_S390_SUBCHANNELS "s390-subchannels" -#define NM_SETTING_WIRED_S390_NETTYPE "s390-nettype" -#define NM_SETTING_WIRED_S390_OPTIONS "s390-options" -#define NM_SETTING_WIRED_WAKE_ON_LAN "wake-on-lan" -#define NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD "wake-on-lan-password" - -/** - * NMSettingWired: - * - * Wired Ethernet Settings - */ -struct _NMSettingWired { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingWiredClass; - -GType nm_setting_wired_get_type(void); - -NMSetting * nm_setting_wired_new(void); -const char *nm_setting_wired_get_port(NMSettingWired *setting); -guint32 nm_setting_wired_get_speed(NMSettingWired *setting); -const char *nm_setting_wired_get_duplex(NMSettingWired *setting); -gboolean nm_setting_wired_get_auto_negotiate(NMSettingWired *setting); -const char *nm_setting_wired_get_mac_address(NMSettingWired *setting); -const char *nm_setting_wired_get_cloned_mac_address(NMSettingWired *setting); - -NM_AVAILABLE_IN_1_4 -const char *nm_setting_wired_get_generate_mac_address_mask(NMSettingWired *setting); - -const char *const *nm_setting_wired_get_mac_address_blacklist(NMSettingWired *setting); -guint32 nm_setting_wired_get_num_mac_blacklist_items(NMSettingWired *setting); -const char * nm_setting_wired_get_mac_blacklist_item(NMSettingWired *setting, guint32 idx); -gboolean nm_setting_wired_add_mac_blacklist_item(NMSettingWired *setting, const char *mac); -void nm_setting_wired_remove_mac_blacklist_item(NMSettingWired *setting, guint32 idx); -gboolean nm_setting_wired_remove_mac_blacklist_item_by_value(NMSettingWired *setting, - const char * mac); -void nm_setting_wired_clear_mac_blacklist_items(NMSettingWired *setting); - -guint32 nm_setting_wired_get_mtu(NMSettingWired *setting); - -const char *const *nm_setting_wired_get_s390_subchannels(NMSettingWired *setting); -const char * nm_setting_wired_get_s390_nettype(NMSettingWired *setting); - -guint32 nm_setting_wired_get_num_s390_options(NMSettingWired *setting); -gboolean nm_setting_wired_get_s390_option(NMSettingWired *setting, - guint32 idx, - const char ** out_key, - const char ** out_value); -const char *nm_setting_wired_get_s390_option_by_key(NMSettingWired *setting, const char *key); -gboolean -nm_setting_wired_add_s390_option(NMSettingWired *setting, const char *key, const char *value); -gboolean nm_setting_wired_remove_s390_option(NMSettingWired *setting, const char *key); -const char **nm_setting_wired_get_valid_s390_options(NMSettingWired *setting); - -NMSettingWiredWakeOnLan nm_setting_wired_get_wake_on_lan(NMSettingWired *setting); -const char * nm_setting_wired_get_wake_on_lan_password(NMSettingWired *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_WIRED_H__ */ diff --git a/libnm-core/nm-setting-wireguard.c b/libnm-core/nm-setting-wireguard.c deleted file mode 100644 index 3a36dabafb..0000000000 --- a/libnm-core/nm-setting-wireguard.c +++ /dev/null @@ -1,2591 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 - 2019 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-wireguard.h" - -#include "nm-setting-private.h" -#include "nm-utils-private.h" -#include "nm-connection-private.h" -#include "nm-glib-aux/nm-secret-utils.h" - -/*****************************************************************************/ - -/** - * SECTION:nm-setting-wireguard - * @short_description: Describes connection properties for wireguard related options - * - * The #NMSettingWireGuard object is a #NMSetting subclass that contains settings - * for configuring WireGuard. - **/ - -/*****************************************************************************/ - -static NMWireGuardPeer *_wireguard_peer_dup(const NMWireGuardPeer *self); - -G_DEFINE_BOXED_TYPE(NMWireGuardPeer, - nm_wireguard_peer, - _wireguard_peer_dup, - nm_wireguard_peer_unref) - -/* NMWireGuardPeer can also track invalid allowed-ip settings, and only reject - * them later during is_valid(). Such values are marked by a leading 'X' character - * in the @allowed_ips. It is expected, that such values are the exception, and - * commonly not present. */ -#define ALLOWED_IP_INVALID_X 'X' -#define ALLOWED_IP_INVALID_X_STR "X" - -/** - * NMWireGuardPeer: - * - * The settings of one WireGuard peer. - * - * Since: 1.16 - */ -struct _NMWireGuardPeer { - NMSockAddrEndpoint * endpoint; - char * public_key; - char * preshared_key; - GPtrArray * allowed_ips; - guint refcount; - NMSettingSecretFlags preshared_key_flags; - guint16 persistent_keepalive; - bool public_key_valid : 1; - bool preshared_key_valid : 1; - bool sealed : 1; -}; - -static gboolean -NM_IS_WIREGUARD_PEER(const NMWireGuardPeer *self, gboolean also_sealed) -{ - return self && self->refcount > 0 && (also_sealed || !self->sealed); -} - -/** - * nm_wireguard_peer_new: - * - * Returns: (transfer full): a new, default, unsealed #NMWireGuardPeer instance. - * - * Since: 1.16 - */ -NMWireGuardPeer * -nm_wireguard_peer_new(void) -{ - NMWireGuardPeer *self; - - self = g_slice_new(NMWireGuardPeer); - *self = (NMWireGuardPeer){ - .refcount = 1, - .preshared_key_flags = NM_SETTING_SECRET_FLAG_NOT_REQUIRED, - }; - return self; -} - -/** - * nm_wireguard_peer_new_clone: - * @self: the #NMWireGuardPeer instance to copy. - * @with_secrets: if %TRUE, the preshared-key secrets are copied - * as well. Otherwise, they will be removed. - * - * Returns: (transfer full): a clone of @self. This instance - * is always unsealed. - * - * Since: 1.16 - */ -NMWireGuardPeer * -nm_wireguard_peer_new_clone(const NMWireGuardPeer *self, gboolean with_secrets) -{ - NMWireGuardPeer *new; - guint i; - - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - - new = g_slice_new(NMWireGuardPeer); - *new = (NMWireGuardPeer){ - .refcount = 1, - .public_key = g_strdup(self->public_key), - .public_key_valid = self->public_key_valid, - .preshared_key = with_secrets ? g_strdup(self->preshared_key) : NULL, - .preshared_key_valid = self->preshared_key_valid, - .preshared_key_flags = self->preshared_key_flags, - .endpoint = nm_sock_addr_endpoint_ref(self->endpoint), - .persistent_keepalive = self->persistent_keepalive, - }; - if (self->allowed_ips && self->allowed_ips->len > 0) { - new->allowed_ips = g_ptr_array_new_full(self->allowed_ips->len, g_free); - for (i = 0; i < self->allowed_ips->len; i++) { - g_ptr_array_add(new->allowed_ips, g_strdup(self->allowed_ips->pdata[i])); - } - } - return new; -} - -/** - * nm_wireguard_peer_ref: - * @self: (allow-none): the #NMWireGuardPeer instance - * - * This is not thread-safe. - * - * Returns: returns the input argument @self after incrementing - * the reference count. - * - * Since: 1.16 - */ -NMWireGuardPeer * -nm_wireguard_peer_ref(NMWireGuardPeer *self) -{ - if (!self) - return NULL; - - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - - nm_assert(self->refcount < G_MAXUINT); - - self->refcount++; - return self; -} - -/** - * nm_wireguard_peer_unref: - * @self: (allow-none): the #NMWireGuardPeer instance - * - * Drop a reference to @self. If the last reference is dropped, - * the instance is freed and all associate data released. - * - * This is not thread-safe. - * - * Since: 1.16 - */ -void -nm_wireguard_peer_unref(NMWireGuardPeer *self) -{ - if (!self) - return; - - g_return_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE)); - - if (--self->refcount > 0) - return; - - nm_sock_addr_endpoint_unref(self->endpoint); - if (self->allowed_ips) - g_ptr_array_unref(self->allowed_ips); - g_free(self->public_key); - nm_free_secret(self->preshared_key); - g_slice_free(NMWireGuardPeer, self); -} - -/** - * _wireguard_peer_dup: - * @self: the #NMWireGuardPeer instance - * - * Duplicates the #NMWireGuardPeer instance. Note that if @self - * is already sealed, this increments the reference count and - * returns it. If the instance is still unsealed, it is copied. - * - * Returns: (transfer full): a duplicate of @self, or (if the - * instance is sealed and thus immutable) a reference to @self. - * As such, the instance will be sealed if and only if @self is - * sealed. - */ -static NMWireGuardPeer * -_wireguard_peer_dup(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - - if (self->sealed) - return nm_wireguard_peer_ref((NMWireGuardPeer *) self); - return nm_wireguard_peer_new_clone(self, TRUE); -} - -/** - * nm_wireguard_peer_seal: - * @self: the #NMWireGuardPeer instance - * - * Seal the #NMWireGuardPeer instance. Afterwards, it is a bug - * to call all functions that modify the instance (except ref/unref). - * A sealed instance cannot be unsealed again, but you can create - * an unsealed copy with nm_wireguard_peer_new_clone(). - * - * Since: 1.16 - */ -void -nm_wireguard_peer_seal(NMWireGuardPeer *self) -{ - g_return_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE)); - - self->sealed = TRUE; - - if (self->allowed_ips) { - if (self->allowed_ips->len == 0) - nm_clear_pointer(&self->allowed_ips, g_ptr_array_unref); - } -} - -/** - * nm_wireguard_peer_is_sealed: - * @self: the #NMWireGuardPeer instance - * - * Returns: whether @self is sealed or not. - * - * Since: 1.16 - */ -gboolean -nm_wireguard_peer_is_sealed(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), FALSE); - - return self->sealed; -} - -/** - * nm_wireguard_peer_get_public_key: - * @self: the #NMWireGuardPeer instance - * - * Returns: (transfer none): the public key or %NULL if unset. - * - * Since: 1.16 - */ -const char * -nm_wireguard_peer_get_public_key(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - - return self->public_key; -} - -/** - * nm_wireguard_peer_set_public_key: - * @self: the unsealed #NMWireGuardPeer instance - * @public_key: (allow-none) (transfer none): the new public - * key or %NULL to clear the public key. - * @accept_invalid: if %TRUE and @public_key is not %NULL and - * invalid, then do not modify the instance. - * - * Reset the public key. Note that if the public key is valid, it - * will be normalized (which may or may not modify the set value). - * - * It is a bug trying to modify a sealed #NMWireGuardPeer instance. - * - * Returns: %TRUE if the key was valid or %NULL. Returns - * %FALSE for invalid keys. Depending on @accept_invalid - * will an invalid key be set or not. - * - * Since: 1.16 - */ -gboolean -nm_wireguard_peer_set_public_key(NMWireGuardPeer *self, - const char * public_key, - gboolean accept_invalid) -{ - char * public_key_normalized = NULL; - gboolean is_valid; - - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); - - if (!public_key) { - nm_clear_g_free(&self->public_key); - return TRUE; - } - - is_valid = nm_utils_base64secret_normalize(public_key, - NM_WIREGUARD_PUBLIC_KEY_LEN, - &public_key_normalized); - nm_assert(is_valid == (public_key_normalized != NULL)); - - if (!is_valid && !accept_invalid) - return FALSE; - - self->public_key_valid = is_valid; - g_free(self->public_key); - self->public_key = public_key_normalized ?: g_strdup(public_key); - return is_valid; -} - -void -_nm_wireguard_peer_set_public_key_bin(NMWireGuardPeer *self, - const guint8 public_key[static NM_WIREGUARD_PUBLIC_KEY_LEN]) -{ - g_return_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE)); - - nm_clear_g_free(&self->public_key); - - if (!public_key) - return; - - self->public_key = g_base64_encode(public_key, NM_WIREGUARD_PUBLIC_KEY_LEN); - self->public_key_valid = TRUE; -} - -/** - * nm_wireguard_peer_get_preshared_key: - * @self: the #NMWireGuardPeer instance - * - * Returns: (transfer none): the preshared key or %NULL if unset. - * - * Since: 1.16 - */ -const char * -nm_wireguard_peer_get_preshared_key(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - - return self->preshared_key; -} - -/** - * nm_wireguard_peer_set_preshared_key: - * @self: the unsealed #NMWireGuardPeer instance - * @preshared_key: (allow-none) (transfer none): the new preshared - * key or %NULL to clear the preshared key. - * @accept_invalid: whether to allow setting the key to an invalid - * value. If %FALSE, @self is unchanged if the key is invalid - * and if %FALSE is returned. - * - * Reset the preshared key. Note that if the preshared key is valid, it - * will be normalized (which may or may not modify the set value). - * - * Note that the preshared-key is a secret and consequently has corresponding - * preshared-key-flags property. This is so that secrets can be optional - * and requested on demand from a secret-agent. Also, an invalid preshared-key - * may optionally cause nm_wireguard_peer_is_valid() to fail or it may - * be accepted. - * - * It is a bug trying to modify a sealed #NMWireGuardPeer instance. - * - * Returns: %TRUE if the preshared-key is valid, otherwise %FALSE. - * %NULL is considered a valid value. - * If the key is invalid, it depends on @accept_invalid whether the - * previous value was reset. - * - * Since: 1.16 - */ -gboolean -nm_wireguard_peer_set_preshared_key(NMWireGuardPeer *self, - const char * preshared_key, - gboolean accept_invalid) -{ - char * preshared_key_normalized = NULL; - gboolean is_valid; - - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); - - if (!preshared_key) { - nm_clear_pointer(&self->preshared_key, nm_free_secret); - return TRUE; - } - - is_valid = nm_utils_base64secret_normalize(preshared_key, - NM_WIREGUARD_SYMMETRIC_KEY_LEN, - &preshared_key_normalized); - nm_assert(is_valid == (preshared_key_normalized != NULL)); - - if (!is_valid && !accept_invalid) - return FALSE; - - self->preshared_key_valid = is_valid; - nm_free_secret(self->preshared_key); - self->preshared_key = preshared_key_normalized ?: g_strdup(preshared_key); - return is_valid; -} - -/** - * nm_wireguard_peer_get_preshared_key_flags: - * @self: the #NMWireGuardPeer instance - * - * Returns: get the secret flags for the preshared-key. - * - * Since: 1.16 - */ -NMSettingSecretFlags -nm_wireguard_peer_get_preshared_key_flags(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), 0); - - return self->preshared_key_flags; -} - -/** - * nm_wireguard_peer_set_preshared_key_flags: - * @self: the unsealed #NMWireGuardPeer instance - * @preshared_key_flags: the secret flags to set. - * - * It is a bug trying to modify a sealed #NMWireGuardPeer instance. - * - * Since: 1.16 - */ -void -nm_wireguard_peer_set_preshared_key_flags(NMWireGuardPeer * self, - NMSettingSecretFlags preshared_key_flags) -{ - g_return_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE)); - - self->preshared_key_flags = preshared_key_flags; -} - -/** - * nm_wireguard_peer_get_persistent_keepalive: - * @self: the #NMWireGuardPeer instance - * - * Returns: get the persistent-keepalive setting in seconds. Set to zero to disable - * keep-alive. - * - * Since: 1.16 - */ -guint16 -nm_wireguard_peer_get_persistent_keepalive(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), 0); - - return self->persistent_keepalive; -} - -/** - * nm_wireguard_peer_set_persistent_keepalive: - * @self: the unsealed #NMWireGuardPeer instance - * @persistent_keepalive: the keep-alive value to set. - * - * It is a bug trying to modify a sealed #NMWireGuardPeer instance. - * - * Since: 1.16 - */ -void -nm_wireguard_peer_set_persistent_keepalive(NMWireGuardPeer *self, guint16 persistent_keepalive) -{ - g_return_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE)); - - self->persistent_keepalive = persistent_keepalive; -} - -NMSockAddrEndpoint * -_nm_wireguard_peer_get_endpoint(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - - return self->endpoint; -} - -/** - * nm_wireguard_peer_get_endpoint: - * @self: the #NMWireGuardPeer instance - * - * Returns: (transfer none): the endpoint or %NULL if none was set. - * - * Since: 1.16 - */ -const char * -nm_wireguard_peer_get_endpoint(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - - return self->endpoint ? nm_sock_addr_endpoint_get_endpoint(self->endpoint) : NULL; -} - -void -_nm_wireguard_peer_set_endpoint(NMWireGuardPeer *self, NMSockAddrEndpoint *endpoint) -{ - NMSockAddrEndpoint *old; - - nm_assert(NM_IS_WIREGUARD_PEER(self, FALSE)); - - old = self->endpoint; - self->endpoint = nm_sock_addr_endpoint_ref(endpoint); - nm_sock_addr_endpoint_unref(old); -} - -/** - * nm_wireguard_peer_set_endpoint: - * @self: the unsealed #NMWireGuardPeer instance - * @endpoint: the socket address endpoint to set or %NULL. - * @allow_invalid: if %TRUE, also invalid values are set. - * If %FALSE, the function does nothing for invalid @endpoint - * arguments. - * - * Sets or clears the endpoint of @self. - * - * It is a bug trying to modify a sealed #NMWireGuardPeer instance. - * - * Returns: %TRUE if the endpoint is %NULL or valid. For an - * invalid @endpoint argument, %FALSE is returned. Depending - * on @allow_invalid, the instance will be modified. - * - * Since: 1.16 - */ -gboolean -nm_wireguard_peer_set_endpoint(NMWireGuardPeer *self, const char *endpoint, gboolean allow_invalid) -{ - NMSockAddrEndpoint *old; - NMSockAddrEndpoint *new; - gboolean is_valid; - - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); - - if (!endpoint) { - nm_clear_pointer(&self->endpoint, nm_sock_addr_endpoint_unref); - return TRUE; - } - - new = nm_sock_addr_endpoint_new(endpoint); - - is_valid = (nm_sock_addr_endpoint_get_host(new) != NULL); - - if (!allow_invalid && !is_valid) { - nm_sock_addr_endpoint_unref(new); - return FALSE; - } - - old = self->endpoint; - self->endpoint = new; - nm_sock_addr_endpoint_unref(old); - return is_valid; -} - -/** - * nm_wireguard_peer_get_allowed_ips_len: - * @self: the #NMWireGuardPeer instance - * - * Returns: the number of allowed-ips entries. - * - * Since: 1.16 - */ -guint -nm_wireguard_peer_get_allowed_ips_len(const NMWireGuardPeer *self) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), 0); - - return self->allowed_ips ? self->allowed_ips->len : 0u; -} - -/** - * nm_wireguard_peer_get_allowed_ip: - * @self: the #NMWireGuardPeer instance - * @idx: the index from zero to (allowed-ips-len - 1) to - * retrieve. - * @out_is_valid: (allow-none): %TRUE if the returned value is a valid allowed-ip - * setting. - * - * Returns: (transfer none): the allowed-ip setting at index @idx. - * If @idx is out of range, %NULL will be returned. - * - * Since: 1.16 - */ -const char * -nm_wireguard_peer_get_allowed_ip(const NMWireGuardPeer *self, guint idx, gboolean *out_is_valid) -{ - const char *s; - - /* With LTO, the compiler might warn about the g_return_val_if_fail() - * code path not initializing the output argument. Workaround that by - * always setting the out argument. */ - NM_SET_OUT(out_is_valid, FALSE); - - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - - if (!self->allowed_ips || idx >= self->allowed_ips->len) - return NULL; - - s = self->allowed_ips->pdata[idx]; - NM_SET_OUT(out_is_valid, s[0] != ALLOWED_IP_INVALID_X); - return s[0] == ALLOWED_IP_INVALID_X ? &s[1] : s; -} - -/** - * nm_wireguard_peer_clear_allowed_ips: - * @self: the unsealed #NMWireGuardPeer instance - * - * Removes all allowed-ip entries. - * - * It is a bug trying to modify a sealed #NMWireGuardPeer instance. - * - * Since: 1.16 - */ -void -nm_wireguard_peer_clear_allowed_ips(NMWireGuardPeer *self) -{ - g_return_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE)); - - if (self->allowed_ips) - g_ptr_array_set_size(self->allowed_ips, 0); -} - -static gboolean -_peer_append_allowed_ip(NMWireGuardPeer *self, const char *allowed_ip, gboolean accept_invalid) -{ - int addr_family; - int prefix; - NMIPAddr addrbin; - char * str; - gboolean is_valid = TRUE; - - nm_assert(NM_IS_WIREGUARD_PEER(self, FALSE)); - nm_assert(allowed_ip); - - /* normalize the address (if it is valid. Otherwise, take it - * as-is (it will render the instance invalid). */ - if (!nm_utils_parse_inaddr_prefix_bin(AF_UNSPEC, allowed_ip, &addr_family, &addrbin, &prefix)) { - if (!accept_invalid) - return FALSE; - /* mark the entry as invalid by having a "X" prefix. */ - str = g_strconcat(ALLOWED_IP_INVALID_X_STR, allowed_ip, NULL); - is_valid = FALSE; - } else { - char addrstr[NM_UTILS_INET_ADDRSTRLEN]; - - nm_assert_addr_family(addr_family); - - nm_utils_inet_ntop(addr_family, &addrbin, addrstr); - if (prefix >= 0) - str = g_strdup_printf("%s/%d", addrstr, prefix); - else - str = g_strdup(addrstr); - nm_assert(str[0] != ALLOWED_IP_INVALID_X); - } - - if (!self->allowed_ips) - self->allowed_ips = g_ptr_array_new_with_free_func(g_free); - - g_ptr_array_add(self->allowed_ips, str); - return is_valid; -} - -/** - * nm_wireguard_peer_append_allowed_ip: - * @self: the unsealed #NMWireGuardPeer instance - * @allowed_ip: the allowed-ip entry to set. - * @accept_invalid: if %TRUE, also invalid @allowed_ip value - * will be appended. Otherwise, the function does nothing - * in face of invalid values and returns %FALSE. - * - * Appends @allowed_ip setting to the list. This does not check - * for duplicates and always appends @allowed_ip to the end of the - * list. If @allowed_ip is valid, it will be normalized and a modified - * for might be appended. If @allowed_ip is invalid, it will still be - * appended, but later verification will fail. - * - * It is a bug trying to modify a sealed #NMWireGuardPeer instance. - * - * Returns: %TRUE if the value is a valid allowed-ips value, %FALSE otherwise. - * Depending on @accept_invalid, also invalid values are added. - * - * Since: 1.16 - */ -gboolean -nm_wireguard_peer_append_allowed_ip(NMWireGuardPeer *self, - const char * allowed_ip, - gboolean accept_invalid) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); - g_return_val_if_fail(allowed_ip, FALSE); - - return _peer_append_allowed_ip(self, allowed_ip, accept_invalid); -} - -/** - * nm_wireguard_peer_remove_allowed_ip: - * @self: the unsealed #NMWireGuardPeer instance - * @idx: the index from zero to (allowed-ips-len - 1) to - * retrieve. If the index is out of range, %FALSE is returned - * and nothing is done. - * - * Removes the allowed-ip at the given @idx. This shifts all - * following entries one index down. - * - * It is a bug trying to modify a sealed #NMWireGuardPeer instance. - * - * Returns: %TRUE if @idx was valid and the allowed-ip was removed. - * %FALSE otherwise, and the peer will not be changed. - * - * Since: 1.16 - */ -gboolean -nm_wireguard_peer_remove_allowed_ip(NMWireGuardPeer *self, guint idx) -{ - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); - - if (!self->allowed_ips || idx >= self->allowed_ips->len) - return FALSE; - - g_ptr_array_remove_index(self->allowed_ips, idx); - return TRUE; -} - -/** - * nm_wireguard_peer_is_valid: - * @self: the #NMWireGuardPeer instance - * @check_secrets: if %TRUE, non-secret properties are validated. - * Otherwise, they are ignored for this purpose. - * @check_non_secrets: if %TRUE, secret properties are validated. - * Otherwise, they are ignored for this purpose. - * @error: the #GError location for returning the failure reason. - * - * Returns: %TRUE if the peer is valid or fails with an error - * reason. - * - * Since: 1.16 - */ -gboolean -nm_wireguard_peer_is_valid(const NMWireGuardPeer *self, - gboolean check_non_secrets, - gboolean check_secrets, - GError ** error) -{ - guint i; - - g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - if (check_non_secrets) { - if (!self->public_key) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("missing public-key for peer")); - return FALSE; - } else if (!self->public_key_valid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid public-key for peer")); - return FALSE; - } - } - - if (check_secrets) { - if (self->preshared_key && !self->preshared_key_valid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid preshared-key for peer")); - return FALSE; - } - } - - if (check_non_secrets) { - if (!_nm_utils_secret_flags_validate(self->preshared_key_flags, - NULL, - NULL, - NM_SETTING_SECRET_FLAG_NONE, - error)) - return FALSE; - } - - if (check_non_secrets) { - if (self->endpoint && !nm_sock_addr_endpoint_get_host(self->endpoint)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid endpoint for peer")); - return FALSE; - } - - if (self->allowed_ips) { - for (i = 0; i < self->allowed_ips->len; i++) { - const char *s = self->allowed_ips->pdata[i]; - - if (s[0] == ALLOWED_IP_INVALID_X) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid IP address \"%s\" for allowed-ip of peer"), - &s[1]); - return FALSE; - } - } - } - - if (!_nm_setting_secret_flags_valid(self->preshared_key_flags)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid preshared-key-flags for peer")); - return FALSE; - } - } - - return TRUE; -} - -/** - * nm_wireguard_peer_cmp: - * @a: (allow-none): the #NMWireGuardPeer to compare. - * @b: (allow-none): the other #NMWireGuardPeer to compare. - * @compare_flags: #NMSettingCompareFlags to affect the comparison. - * - * Returns: zero of the two instances are equivalent or - * a non-zero integer otherwise. This defines a total ordering - * over the peers. Whether a peer is sealed or not, does not - * affect the comparison. - * - * Since: 1.16 - */ -int -nm_wireguard_peer_cmp(const NMWireGuardPeer *a, - const NMWireGuardPeer *b, - NMSettingCompareFlags compare_flags) -{ - guint i, n; - - NM_CMP_SELF(a, b); - - /* regardless of the @compare_flags, the public-key is the ID of the peer. It must - * always be compared. */ - NM_CMP_FIELD_BOOL(a, b, public_key_valid); - NM_CMP_FIELD_STR0(a, b, public_key); - - if (NM_FLAGS_ANY(compare_flags, - NM_SETTING_COMPARE_FLAG_INFERRABLE | NM_SETTING_COMPARE_FLAG_FUZZY)) - return 0; - - NM_CMP_FIELD_BOOL(a, b, endpoint); - if (a->endpoint) { - NM_CMP_DIRECT_STRCMP0(nm_sock_addr_endpoint_get_endpoint(a->endpoint), - nm_sock_addr_endpoint_get_endpoint(b->endpoint)); - } - - NM_CMP_FIELD(a, b, persistent_keepalive); - - NM_CMP_DIRECT((n = (a->allowed_ips ? a->allowed_ips->len : 0u)), - (b->allowed_ips ? b->allowed_ips->len : 0u)); - for (i = 0; i < n; i++) - NM_CMP_DIRECT_STRCMP0(a->allowed_ips->pdata[i], b->allowed_ips->pdata[i]); - - NM_CMP_FIELD(a, b, preshared_key_flags); - - if (!NM_FLAGS_HAS(compare_flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)) { - if (NM_FLAGS_HAS(compare_flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) - && NM_FLAGS_HAS(a->preshared_key_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) { - /* pass */ - } else if (NM_FLAGS_HAS(compare_flags, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) - && NM_FLAGS_HAS(a->preshared_key_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)) { - /* pass */ - } else { - NM_CMP_FIELD_BOOL(a, b, preshared_key_valid); - NM_CMP_FIELD_STR0(a, b, preshared_key); - } - } - - return 0; -} - -/*****************************************************************************/ - -typedef struct { - const char * public_key; - NMWireGuardPeer *peer; - guint idx; -} PeerData; - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_FWMARK, - PROP_IP4_AUTO_DEFAULT_ROUTE, - PROP_IP6_AUTO_DEFAULT_ROUTE, - PROP_LISTEN_PORT, - PROP_MTU, - PROP_PEER_ROUTES, - PROP_PRIVATE_KEY, - PROP_PRIVATE_KEY_FLAGS, ); - -typedef struct { - char * private_key; - GPtrArray * peers_arr; - GHashTable * peers_hash; - NMSettingSecretFlags private_key_flags; - NMTernary ip4_auto_default_route; - NMTernary ip6_auto_default_route; - guint32 fwmark; - guint32 mtu; - guint16 listen_port; - bool private_key_valid : 1; - bool peer_routes : 1; -} NMSettingWireGuardPrivate; - -/** - * NMSettingWireGuard: - * - * WireGuard Settings - * - * Since: 1.16 - */ -struct _NMSettingWireGuard { - NMSetting parent; - NMSettingWireGuardPrivate _priv; -}; - -struct _NMSettingWireGuardClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingWireGuard, nm_setting_wireguard, NM_TYPE_SETTING) - -#define NM_SETTING_WIREGUARD_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMSettingWireGuard, NM_IS_SETTING_WIREGUARD, NMSetting) - -/*****************************************************************************/ - -#define peers_psk_get_secret_name_a(public_key, to_free) \ - nm_construct_name_a(NM_SETTING_WIREGUARD_PEERS ".%s." NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, \ - (public_key), \ - (to_free)) - -#define peers_psk_get_secret_name_dup(public_key) \ - g_strdup_printf(NM_SETTING_WIREGUARD_PEERS ".%s." NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, \ - (public_key)) - -#define peers_psk_get_secret_parse_a(secret_public_key, public_key_free) \ - ({ \ - const char *_secret_public_key = (secret_public_key); \ - char ** _public_key_free = (public_key_free); \ - const char *_public_key = NULL; \ - \ - nm_assert(_public_key_free && !*_public_key_free); \ - \ - if (NM_STR_HAS_PREFIX(_secret_public_key, NM_SETTING_WIREGUARD_PEERS ".")) { \ - _secret_public_key += NM_STRLEN(NM_SETTING_WIREGUARD_PEERS "."); \ - if (NM_STR_HAS_SUFFIX(_secret_public_key, "." NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)) { \ - _public_key = \ - nm_strndup_a(300, \ - _secret_public_key, \ - strlen(_secret_public_key) \ - - NM_STRLEN("." NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY), \ - _public_key_free); \ - } \ - } \ - \ - _public_key; \ - }) - -/*****************************************************************************/ - -/** - * nm_setting_wireguard_get_private_key: - * @self: the #NMSettingWireGuard instance - * - * Returns: (transfer none): the set private-key or %NULL. - * - * Since: 1.16 - */ -const char * -nm_setting_wireguard_get_private_key(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NULL); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->private_key; -} - -/** - * nm_setting_wireguard_get_private_key_flags: - * @self: the #NMSettingWireGuard instance - * - * Returns: the secret-flags for #NMSettingWireGuard:private-key. - * - * Since: 1.16 - */ -NMSettingSecretFlags -nm_setting_wireguard_get_private_key_flags(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->private_key_flags; -} - -/** - * nm_setting_wireguard_get_fwmark: - * @self: the #NMSettingWireGuard instance - * - * Returns: the set firewall mark. - * - * Since: 1.16 - */ -guint32 -nm_setting_wireguard_get_fwmark(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->fwmark; -} - -/** - * nm_setting_wireguard_get_listen_port: - * @self: the #NMSettingWireGuard instance - * - * Returns: the set UDP listen port. - * - * Since: 1.16 - */ -guint16 -nm_setting_wireguard_get_listen_port(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->listen_port; -} - -/** - * nm_setting_wireguard_get_peer_routes: - * @self: the #NMSettingWireGuard instance - * - * Returns: whether automatically add peer routes. - * - * Since: 1.16 - */ -gboolean -nm_setting_wireguard_get_peer_routes(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), TRUE); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->peer_routes; -} - -/** - * nm_setting_wireguard_get_mtu: - * @self: the #NMSettingWireGuard instance - * - * Returns: the MTU of the setting. - * - * Since: 1.16 - */ -guint32 -nm_setting_wireguard_get_mtu(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->mtu; -} - -/** - * nm_setting_wireguard_get_ip4_auto_default_route: - * @self: the #NMSettingWireGuard setting. - * - * Returns: the "ip4-auto-default-route" property of the setting. - * - * Since: 1.20 - */ -NMTernary -nm_setting_wireguard_get_ip4_auto_default_route(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NM_TERNARY_DEFAULT); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->ip4_auto_default_route; -} - -/** - * nm_setting_wireguard_get_ip6_auto_default_route: - * @self: the #NMSettingWireGuard setting. - * - * Returns: the "ip6-auto-default-route" property of the setting. - * - * Since: 1.20 - */ -NMTernary -nm_setting_wireguard_get_ip6_auto_default_route(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NM_TERNARY_DEFAULT); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->ip6_auto_default_route; -} - -/*****************************************************************************/ - -static void -_peer_free(PeerData *pd) -{ - nm_assert(pd); - - nm_wireguard_peer_unref(pd->peer); - g_slice_free(PeerData, pd); -} - -/*****************************************************************************/ - -static void -_peers_notify(gpointer self) -{ - _nm_setting_emit_property_changed(self); -} - -static PeerData * -_peers_get(NMSettingWireGuardPrivate *priv, guint idx) -{ - PeerData *pd; - - nm_assert(priv); - nm_assert(idx < priv->peers_arr->len); - - pd = priv->peers_arr->pdata[idx]; - - nm_assert(pd); - nm_assert(pd->idx == idx); - nm_assert(NM_IS_WIREGUARD_PEER(pd->peer, TRUE)); - nm_assert(nm_wireguard_peer_is_sealed(pd->peer)); - nm_assert(pd->public_key == nm_wireguard_peer_get_public_key(pd->peer)); - nm_assert(g_hash_table_lookup(priv->peers_hash, pd) == pd); - - return pd; -} - -static PeerData * -_peers_get_by_public_key(NMSettingWireGuardPrivate *priv, - const char * public_key, - gboolean try_with_normalized_key) -{ - gs_free char *public_key_normalized = NULL; - PeerData * pd; - -again: - nm_assert(priv); - nm_assert(public_key); - - pd = g_hash_table_lookup(priv->peers_hash, &public_key); - if (pd) { - nm_assert(_peers_get(priv, pd->idx) == pd); - return pd; - } - if (try_with_normalized_key - && nm_utils_base64secret_normalize(public_key, - NM_WIREGUARD_PUBLIC_KEY_LEN, - &public_key_normalized)) { - public_key = public_key_normalized; - try_with_normalized_key = FALSE; - goto again; - } - return NULL; -} - -static void -_peers_remove(NMSettingWireGuardPrivate *priv, PeerData *pd, gboolean do_free) -{ - guint i; - - nm_assert(pd); - nm_assert(_peers_get(priv, pd->idx) == pd); - - for (i = pd->idx + 1; i < priv->peers_arr->len; i++) - _peers_get(priv, i)->idx--; - - g_ptr_array_remove_index(priv->peers_arr, pd->idx); - if (!g_hash_table_remove(priv->peers_hash, pd)) - nm_assert_not_reached(); - if (do_free) - _peer_free(pd); -} - -/** - * nm_setting_wireguard_get_peers_len: - * @self: the #NMSettingWireGuard instance - * - * Returns: the number of registered peers. - * - * Since: 1.16 - */ -guint -nm_setting_wireguard_get_peers_len(NMSettingWireGuard *self) -{ - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); - - return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->peers_arr->len; -} - -/** - * nm_setting_wireguard_get_peer: - * @self: the #NMSettingWireGuard instance - * @idx: the index to lookup. - * - * Returns: (transfer none): the #NMWireGuardPeer entry at - * index @idx. If the index is out of range, %NULL is returned. - * - * Since: 1.16 - */ -NMWireGuardPeer * -nm_setting_wireguard_get_peer(NMSettingWireGuard *self, guint idx) -{ - NMSettingWireGuardPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NULL); - - priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); - - if (idx >= priv->peers_arr->len) - return NULL; - - return _peers_get(priv, idx)->peer; -} - -/** - * nm_setting_wireguard_get_peer_by_public_key: - * @self: the #NMSettingWireGuard instance - * @public_key: the public key for looking up the - * peer. - * @out_idx: (out) (allow-none): optional output argument - * for the index of the found peer. If no index is found, - * this is set to the nm_setting_wireguard_get_peers_len(). - * - * Returns: (transfer none): the #NMWireGuardPeer instance with a - * matching public key. If no such peer exists, %NULL is returned. - * - * Since: 1.16 - */ -NMWireGuardPeer * -nm_setting_wireguard_get_peer_by_public_key(NMSettingWireGuard *self, - const char * public_key, - guint * out_idx) -{ - NMSettingWireGuardPrivate *priv; - PeerData * pd; - - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NULL); - g_return_val_if_fail(public_key, NULL); - - priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); - - pd = _peers_get_by_public_key(priv, public_key, TRUE); - if (!pd) { - NM_SET_OUT(out_idx, priv->peers_arr->len); - return NULL; - } - NM_SET_OUT(out_idx, pd->idx); - return pd->peer; -} - -static gboolean -_peers_set(NMSettingWireGuardPrivate *priv, - NMWireGuardPeer * peer, - guint idx, - gboolean check_same_key) -{ - PeerData * pd_same_key = NULL; - PeerData * pd_idx = NULL; - const char *public_key; - - nm_assert(idx <= priv->peers_arr->len); - - public_key = nm_wireguard_peer_get_public_key(peer); - - if (idx < priv->peers_arr->len) { - pd_idx = _peers_get(priv, idx); - - if (pd_idx->peer == peer) - return FALSE; - - if (check_same_key && nm_streq(public_key, nm_wireguard_peer_get_public_key(pd_idx->peer))) - check_same_key = FALSE; - } - - nm_wireguard_peer_seal(peer); - nm_wireguard_peer_ref(peer); - - if (check_same_key) { - pd_same_key = _peers_get_by_public_key(priv, public_key, FALSE); - if (pd_same_key) { - if (pd_idx) { - nm_assert(pd_same_key != pd_idx); - _peers_remove(priv, pd_same_key, TRUE); - pd_same_key = NULL; - } else { - if (pd_same_key->peer == peer && pd_same_key->idx == priv->peers_arr->len - 1) { - nm_wireguard_peer_unref(peer); - return FALSE; - } - _peers_remove(priv, pd_same_key, FALSE); - nm_wireguard_peer_unref(pd_same_key->peer); - } - } - } else - nm_assert(_peers_get_by_public_key(priv, public_key, FALSE) == pd_idx); - - if (pd_idx) { - g_hash_table_remove(priv->peers_hash, pd_idx); - nm_wireguard_peer_unref(pd_idx->peer); - pd_idx->public_key = public_key; - pd_idx->peer = peer; - g_hash_table_add(priv->peers_hash, pd_idx); - return TRUE; - } - - if (!pd_same_key) - pd_same_key = g_slice_new(PeerData); - - *pd_same_key = (PeerData){ - .peer = peer, - .public_key = public_key, - .idx = priv->peers_arr->len, - }; - - g_ptr_array_add(priv->peers_arr, pd_same_key); - if (!nm_g_hash_table_add(priv->peers_hash, pd_same_key)) - nm_assert_not_reached(); - - nm_assert(_peers_get(priv, pd_same_key->idx) == pd_same_key); - - return TRUE; -} - -static gboolean -_peers_append(NMSettingWireGuardPrivate *priv, NMWireGuardPeer *peer, gboolean check_same_key) -{ - return _peers_set(priv, peer, priv->peers_arr->len, check_same_key); -} - -/** - * nm_setting_wireguard_set_peer: - * @self: the #NMSettingWireGuard instance - * @peer: the #NMWireGuardPeer instance to set. - * This seals @peer and keeps a reference on the - * instance. - * @idx: the index, in the range of 0 to the number of - * peers (including). That means, if @idx is one past - * the end of the number of peers, this is the same as - * nm_setting_wireguard_append_peer(). Otherwise, the - * peer at this index is replaced. - * - * If @idx is one past the last peer, the behavior is the same - * as nm_setting_wireguard_append_peer(). - * Otherwise, the peer will be at @idx and replace the peer - * instance at that index. Note that if a peer with the same - * public-key exists on another index, then that peer will also - * be replaced. In that case, the number of peers will shrink - * by one (because the one at @idx got replace and then one - * with the same public-key got removed). This also means, - * that the resulting index afterwards may be one less than - * @idx (if another peer with a lower index was dropped). - * - * Since: 1.16 - */ -void -nm_setting_wireguard_set_peer(NMSettingWireGuard *self, NMWireGuardPeer *peer, guint idx) -{ - NMSettingWireGuardPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_WIREGUARD(self)); - g_return_if_fail(NM_IS_WIREGUARD_PEER(peer, TRUE)); - - priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); - - g_return_if_fail(idx <= priv->peers_arr->len); - - if (_peers_set(priv, peer, idx, TRUE)) - _peers_notify(self); -} - -/** - * nm_setting_wireguard_append_peer: - * @self: the #NMSettingWireGuard instance - * @peer: the #NMWireGuardPeer instance to append. - * This seals @peer and keeps a reference on the - * instance. - * - * If a peer with the same public-key already exists, that - * one is replaced by @peer. The new @peer is always appended - * (or moved to) the end, so in case a peer is replaced, the - * indexes are shifted and the number of peers stays unchanged. - * - * Since: 1.16 - */ -void -nm_setting_wireguard_append_peer(NMSettingWireGuard *self, NMWireGuardPeer *peer) -{ - g_return_if_fail(NM_IS_SETTING_WIREGUARD(self)); - g_return_if_fail(NM_IS_WIREGUARD_PEER(peer, TRUE)); - - if (_peers_append(NM_SETTING_WIREGUARD_GET_PRIVATE(self), peer, TRUE)) - _peers_notify(self); -} - -/** - * nm_setting_wireguard_remove_peer - * @self: the #NMSettingWireGuard instance - * @idx: the index to remove. - * - * Returns: %TRUE if @idx was in range and a peer - * was removed. Otherwise, @self is unchanged. - * - * Since: 1.16 - */ -gboolean -nm_setting_wireguard_remove_peer(NMSettingWireGuard *self, guint idx) -{ - NMSettingWireGuardPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), FALSE); - - priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); - - if (idx >= priv->peers_arr->len) - return FALSE; - - _peers_remove(priv, _peers_get(priv, idx), TRUE); - _peers_notify(self); - return TRUE; -} - -static guint -_peers_clear(NMSettingWireGuardPrivate *priv) -{ - guint l; - - l = priv->peers_arr->len; - while (priv->peers_arr->len > 0) { - _peers_remove(priv, _peers_get(priv, priv->peers_arr->len - 1), TRUE); - } - return l; -} - -/** - * nm_setting_wireguard_: - * @self: the #NMSettingWireGuard instance - * - * Returns: the number of cleared peers. - * - * Since: 1.16 - */ -guint -nm_setting_wireguard_clear_peers(NMSettingWireGuard *self) -{ - guint l; - - g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); - - l = _peers_clear(NM_SETTING_WIREGUARD_GET_PRIVATE(self)); - if (l > 0) - _peers_notify(self); - return l; -} - -/*****************************************************************************/ - -static GVariant * -_peers_dbus_only_synth(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMSettingWireGuard * self = NM_SETTING_WIREGUARD(setting); - NMSettingWireGuardPrivate *priv; - gboolean any_peers = FALSE; - GVariantBuilder peers_builder; - guint i_peer, n_peers; - guint i; - - n_peers = nm_setting_wireguard_get_peers_len(self); - if (n_peers == 0) - return NULL; - - priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); - - for (i_peer = 0; i_peer < n_peers; i_peer++) { - const NMWireGuardPeer *peer = _peers_get(priv, i_peer)->peer; - GVariantBuilder builder; - - if (!peer->public_key) - continue; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - - g_variant_builder_add(&builder, - "{sv}", - NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY, - g_variant_new_string(peer->public_key)); - - if (!NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS) && peer->endpoint) - g_variant_builder_add( - &builder, - "{sv}", - NM_WIREGUARD_PEER_ATTR_ENDPOINT, - g_variant_new_string(nm_sock_addr_endpoint_get_endpoint(peer->endpoint))); - - if (_nm_connection_serialize_secrets(flags, peer->preshared_key_flags) - && peer->preshared_key) - g_variant_builder_add(&builder, - "{sv}", - NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, - g_variant_new_string(peer->preshared_key)); - - if (!NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - && peer->preshared_key_flags != NM_SETTING_SECRET_FLAG_NOT_REQUIRED) - g_variant_builder_add(&builder, - "{sv}", - NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS, - g_variant_new_uint32(peer->preshared_key_flags)); - - if (!NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - && peer->persistent_keepalive != 0) - g_variant_builder_add(&builder, - "{sv}", - NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE, - g_variant_new_uint32(peer->persistent_keepalive)); - - if (!NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS) && peer->allowed_ips - && peer->allowed_ips->len > 0) { - const char *const * strv = (const char *const *) peer->allowed_ips->pdata; - gs_free const char **strv_fixed = NULL; - - for (i = 0; i < peer->allowed_ips->len; i++) { - if (strv[i][0] != ALLOWED_IP_INVALID_X) - continue; - if (!strv_fixed) { - strv_fixed = nm_memdup(strv, sizeof(strv[0]) * peer->allowed_ips->len); - strv = strv_fixed; - } - ((const char **) strv)[i]++; - } - g_variant_builder_add(&builder, - "{sv}", - NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS, - g_variant_new_strv(strv, peer->allowed_ips->len)); - } - - if (!any_peers) { - g_variant_builder_init(&peers_builder, G_VARIANT_TYPE("aa{sv}")); - any_peers = TRUE; - } - g_variant_builder_add(&peers_builder, "a{sv}", &builder); - } - - return any_peers ? g_variant_builder_end(&peers_builder) : NULL; -} - -static gboolean -_peers_dbus_only_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GVariantIter iter_peers; - GVariant * peer_var; - guint i_peer; - gboolean success = FALSE; - gboolean peers_changed = FALSE; - - nm_assert(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}"))); - - g_variant_iter_init(&iter_peers, value); - - i_peer = 0; - while (g_variant_iter_next(&iter_peers, "@a{sv}", &peer_var)) { - _nm_unused gs_unref_variant GVariant *peer_var_unref = peer_var; - nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; - const char * cstr; - guint32 u32; - GVariant * var; - - i_peer++; - - if (!g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY, "&s", &cstr)) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("peer #%u has no public-key"), - i_peer); - goto out; - } - continue; - } - - peer = nm_wireguard_peer_new(); - if (!nm_wireguard_peer_set_public_key(peer, cstr, TRUE)) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("peer #%u has invalid public-key"), - i_peer); - goto out; - } - continue; - } - - if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_ENDPOINT, "&s", &cstr)) { - nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL; - - ep = nm_sock_addr_endpoint_new(cstr); - if (!nm_sock_addr_endpoint_get_host(ep)) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("peer #%u has invalid endpoint"), - i_peer); - goto out; - } - } else - _nm_wireguard_peer_set_endpoint(peer, ep); - } - - if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, "&s", &cstr)) - nm_wireguard_peer_set_preshared_key(peer, cstr, TRUE); - - if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS, "u", &u32)) - nm_wireguard_peer_set_preshared_key_flags(peer, u32); - - if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE, "u", &u32)) - nm_wireguard_peer_set_persistent_keepalive(peer, u32); - - if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS, "@as", &var)) { - _nm_unused gs_unref_variant GVariant *var_free = var; - gs_free const char ** allowed_ips = NULL; - gsize i, l; - - allowed_ips = g_variant_get_strv(var, &l); - if (allowed_ips) { - for (i = 0; i < l; i++) { - if (_peer_append_allowed_ip(peer, allowed_ips[i], FALSE)) - continue; - if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) - continue; - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("peer #%u has invalid allowed-ips setting"), - i_peer); - goto out; - } - } - } - - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - gs_free_error GError *local = NULL; - - if (!nm_wireguard_peer_is_valid(peer, TRUE, FALSE, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("peer #%u is invalid: %s"), - i_peer, - local->message); - goto out; - } - } - - /* we could easily reject duplicate peers (by public-key) or duplicate GVariant attributes. - * However, don't do that. In case of duplicate values, the latter peer overwrite the earlier - * and GVariant attributes are ignored by g_variant_lookup() above. */ - if (_peers_append(NM_SETTING_WIREGUARD_GET_PRIVATE(setting), peer, TRUE)) - peers_changed = TRUE; - } - - success = TRUE; - -out: - if (peers_changed) - _peers_notify(setting); - return success; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWireGuard * s_wg = NM_SETTING_WIREGUARD(setting); - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - guint i; - - if (!_nm_connection_verify_required_interface_name(connection, error)) - return FALSE; - - if (!_nm_utils_secret_flags_validate(nm_setting_wireguard_get_private_key_flags(s_wg), - NM_SETTING_WIREGUARD_SETTING_NAME, - NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, - NM_SETTING_SECRET_FLAG_NOT_REQUIRED, - error)) - return FALSE; - - for (i = 0; i < priv->peers_arr->len; i++) { - NMWireGuardPeer *peer = _peers_get(priv, i)->peer; - - if (!nm_wireguard_peer_is_valid(peer, TRUE, FALSE, error)) { - g_prefix_error(error, - "%s.%s[%u]: ", - NM_SETTING_WIREGUARD_SETTING_NAME, - NM_SETTING_WIREGUARD_PEERS, - i); - return FALSE; - } - } - - if (connection) { - NMSettingIPConfig *s_ip4; - NMSettingIPConfig *s_ip6; - const char * method; - - /* WireGuard is Layer 3 only. For the moment, we only support a restricted set of - * IP methods. We may relax that later, once we fix the implementations so they - * actually work. */ - - if ((s_ip4 = nm_connection_get_setting_ip4_config(connection)) - && (method = nm_setting_ip_config_get_method(s_ip4)) - && !NM_IN_STRSET(method, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("method \"%s\" is not supported for WireGuard"), - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_METHOD); - return FALSE; - } - - if ((s_ip6 = nm_connection_get_setting_ip6_config(connection)) - && (method = nm_setting_ip_config_get_method(s_ip6)) - && !NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_IGNORE, - NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, - NM_SETTING_IP6_CONFIG_METHOD_MANUAL, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("method \"%s\" is not supported for WireGuard"), - method); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_METHOD); - return FALSE; - } - } - - /* private-key is a secret, hence we cannot verify it like a regular property. */ - return TRUE; -} - -static gboolean -verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - guint i; - - if (priv->private_key && !priv->private_key_valid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("key must be 32 bytes base64 encoded")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIREGUARD_SETTING_NAME, - NM_SETTING_WIREGUARD_PRIVATE_KEY); - return FALSE; - } - - for (i = 0; i < priv->peers_arr->len; i++) { - NMWireGuardPeer *peer = _peers_get(priv, i)->peer; - - if (!nm_wireguard_peer_is_valid(peer, FALSE, TRUE, error)) { - g_prefix_error(error, - "%s.%s[%u]: ", - NM_SETTING_WIREGUARD_SETTING_NAME, - NM_SETTING_WIREGUARD_PEERS, - i); - return FALSE; - } - } - - return TRUE; -} - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - GPtrArray * secrets = NULL; - guint i; - - if (!priv->private_key || !priv->private_key_valid) { - secrets = g_ptr_array_new_full(1, g_free); - g_ptr_array_add(secrets, g_strdup(NM_SETTING_WIREGUARD_PRIVATE_KEY)); - } - - for (i = 0; i < priv->peers_arr->len; i++) { - NMWireGuardPeer *peer = _peers_get(priv, i)->peer; - - if (NM_FLAGS_HAS(peer->preshared_key_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) - continue; - - if (peer->preshared_key_valid) - continue; - - if (!peer->public_key_valid) - continue; - - if (!secrets) - secrets = g_ptr_array_new_full(1, g_free); - g_ptr_array_add(secrets, peers_psk_get_secret_name_dup(peer->public_key)); - } - - return secrets; -} - -static gboolean -clear_secrets(const NMSettInfoSetting * sett_info, - guint property_idx, - NMSetting * setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data) -{ - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_WIREGUARD_PEERS)) { - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - gboolean peers_changed = FALSE; - guint i, j; - - j = 0; - for (i = 0; i < priv->peers_arr->len; i++) { - NMWireGuardPeer *peer = _peers_get(priv, i)->peer; - - if (!peer->preshared_key) - continue; - - if (func) { - gs_free char *name_free = NULL; - const char * name; - - /* only stack-allocate (alloca) a few times. */ - if (j++ < 5) - name = peers_psk_get_secret_name_a(peer->public_key, &name_free); - else { - name_free = peers_psk_get_secret_name_dup(peer->public_key); - name = name_free; - } - - if (!func(setting, name, peer->preshared_key_flags, user_data)) - continue; - } - - { - nm_auto_unref_wgpeer NMWireGuardPeer *peer2 = NULL; - - peer2 = nm_wireguard_peer_new_clone(peer, FALSE); - - if (_peers_set(priv, peer2, i, FALSE)) - peers_changed = TRUE; - } - } - - if (peers_changed) - _peers_notify(setting); - return peers_changed; - } - - return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) - ->clear_secrets(sett_info, property_idx, setting, func, user_data); -} - -static int -update_one_secret(NMSetting *setting, const char *key, GVariant *value, GError **error) -{ - NMSettingWireGuard * self = NM_SETTING_WIREGUARD(setting); - NMSettingWireGuardPrivate *priv; - gboolean has_changes = FALSE; - gboolean has_error = FALSE; - GVariantIter iter_peers; - GVariant * peer_var; - guint i_peer; - - if (!nm_streq(key, NM_SETTING_WIREGUARD_PEERS)) { - return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) - ->update_one_secret(setting, key, value, error); - } - - if (!g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}"))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, - _("invalid peer secrets")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIREGUARD_SETTING_NAME, - NM_SETTING_WIREGUARD_PEERS); - return NM_SETTING_UPDATE_SECRET_ERROR; - } - - priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); - - g_variant_iter_init(&iter_peers, value); - - i_peer = 0; - while (g_variant_iter_next(&iter_peers, "@a{sv}", &peer_var)) { - _nm_unused gs_unref_variant GVariant *peer_var_unref = peer_var; - nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; - PeerData * pd; - const char * cstr; - - i_peer++; - - if (!g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY, "&s", &cstr)) { - if (!has_error) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, - _("peer #%u lacks public-key"), - i_peer - 1); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIREGUARD_SETTING_NAME, - NM_SETTING_WIREGUARD_PEERS); - has_error = TRUE; - } - continue; - } - - pd = _peers_get_by_public_key(priv, cstr, TRUE); - if (!pd) { - if (!has_error) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, - _("non-existing peer '%s'"), - cstr); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIREGUARD_SETTING_NAME, - NM_SETTING_WIREGUARD_PEERS); - has_error = TRUE; - } - continue; - } - - if (!g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, "&s", &cstr)) { - /* no preshared-key. Ignore the rest. - * - * In particular, we don't reject all unknown fields. */ - continue; - } - - if (nm_streq0(cstr, nm_wireguard_peer_get_preshared_key(pd->peer))) - continue; - - peer = nm_wireguard_peer_new_clone(pd->peer, FALSE); - nm_wireguard_peer_set_preshared_key(peer, cstr, TRUE); - - if (!_peers_set(priv, peer, pd->idx, FALSE)) - nm_assert_not_reached(); - has_changes = TRUE; - } - - if (has_error) - return NM_SETTING_UPDATE_SECRET_ERROR; - if (has_changes) - return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; - return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingWireGuardPrivate *a_priv; - NMSettingWireGuardPrivate *b_priv; - guint i; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_WIREGUARD_PEERS)) { - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) - return NM_TERNARY_DEFAULT; - - if (!set_b) - return TRUE; - - a_priv = NM_SETTING_WIREGUARD_GET_PRIVATE(set_a); - b_priv = NM_SETTING_WIREGUARD_GET_PRIVATE(set_b); - - if (a_priv->peers_arr->len != b_priv->peers_arr->len) - return FALSE; - for (i = 0; i < a_priv->peers_arr->len; i++) { - NMWireGuardPeer *a_peer = _peers_get(a_priv, i)->peer; - NMWireGuardPeer *b_peer = _peers_get(b_priv, i)->peer; - - if (nm_wireguard_peer_cmp(a_peer, b_peer, flags) != 0) - return FALSE; - } - - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -static void -duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) -{ - NMSettingWireGuardPrivate *priv_src = NM_SETTING_WIREGUARD_GET_PRIVATE(src); - NMSettingWireGuardPrivate *priv_dst = NM_SETTING_WIREGUARD_GET_PRIVATE(dst); - guint i; - gboolean peers_changed = FALSE; - - NM_SETTING_CLASS(nm_setting_wireguard_parent_class) - ->duplicate_copy_properties(sett_info, src, dst); - - /* We don't bother comparing the existing peers with what we are about to set. - * Always reset all. */ - if (_peers_clear(priv_dst) > 0) - peers_changed = TRUE; - for (i = 0; i < priv_src->peers_arr->len; i++) { - if (_peers_append(priv_dst, _peers_get(priv_src, i)->peer, FALSE)) - peers_changed = TRUE; - } - if (peers_changed) - _peers_notify(dst); -} - -static void -enumerate_values(const NMSettInfoProperty *property_info, - NMSetting * setting, - NMSettingValueIterFn func, - gpointer user_data) -{ - if (nm_streq(property_info->name, NM_SETTING_WIREGUARD_PEERS)) { - NMSettingWireGuardPrivate * priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - nm_auto_unset_gvalue GValue value = G_VALUE_INIT; - GPtrArray * ptr = NULL; - guint i; - - if (priv->peers_arr && priv->peers_arr->len > 0) { - ptr = g_ptr_array_new_with_free_func((GDestroyNotify) nm_wireguard_peer_unref); - for (i = 0; i < priv->peers_arr->len; i++) - g_ptr_array_add(ptr, nm_wireguard_peer_ref(_peers_get(priv, i)->peer)); - } - g_value_init(&value, G_TYPE_PTR_ARRAY); - g_value_take_boxed(&value, ptr); - func(setting, property_info->name, &value, 0, user_data); - return; - } - - NM_SETTING_CLASS(nm_setting_wireguard_parent_class) - ->enumerate_values(property_info, setting, func, user_data); -} - -static gboolean -aggregate(NMSetting *setting, int type_i, gpointer arg) -{ - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - NMConnectionAggregateType type = type_i; - NMSettingSecretFlags secret_flags; - guint i; - - nm_assert(NM_IN_SET(type, - NM_CONNECTION_AGGREGATE_ANY_SECRETS, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS)); - - switch (type) { - case NM_CONNECTION_AGGREGATE_ANY_SECRETS: - if (priv->private_key) - goto out_done; - for (i = 0; i < priv->peers_arr->len; i++) { - if (nm_wireguard_peer_get_preshared_key(_peers_get(priv, i)->peer)) - goto out_done; - } - break; - - case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: -#if NM_MORE_ASSERTS - if (!nm_setting_get_secret_flags(setting, - NM_SETTING_WIREGUARD_PRIVATE_KEY, - &secret_flags, - NULL)) - nm_assert_not_reached(); - nm_assert(secret_flags == priv->private_key_flags); -#endif - if (priv->private_key_flags == NM_SETTING_SECRET_FLAG_NONE) - goto out_done; - for (i = 0; i < priv->peers_arr->len; i++) { - secret_flags = nm_wireguard_peer_get_preshared_key_flags(_peers_get(priv, i)->peer); - if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) - goto out_done; - } - break; - } - - return FALSE; - -out_done: - *((gboolean *) arg) = TRUE; - return TRUE; -} - -static gboolean -get_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags *out_flags, - GError ** error) -{ - if (NM_STR_HAS_PREFIX(secret_name, NM_SETTING_WIREGUARD_PEERS ".")) { - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - gs_free char * public_key_free = NULL; - const char * public_key; - PeerData * pd; - - public_key = peers_psk_get_secret_parse_a(secret_name, &public_key_free); - if (public_key && (pd = _peers_get_by_public_key(priv, public_key, FALSE))) { - NM_SET_OUT(out_flags, nm_wireguard_peer_get_preshared_key_flags(pd->peer)); - return TRUE; - } - } - - return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) - ->get_secret_flags(setting, secret_name, out_flags, error); -} - -static gboolean -set_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags flags, - GError ** error) -{ - if (NM_STR_HAS_PREFIX(secret_name, NM_SETTING_WIREGUARD_PEERS ".")) { - NMSettingWireGuard * self = NM_SETTING_WIREGUARD(setting); - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); - gs_free char * public_key_free = NULL; - const char * public_key; - PeerData * pd; - - public_key = peers_psk_get_secret_parse_a(secret_name, &public_key_free); - if (public_key && (pd = _peers_get_by_public_key(priv, public_key, FALSE))) { - if (nm_wireguard_peer_get_preshared_key_flags(pd->peer) != flags) { - nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; - - peer = nm_wireguard_peer_new_clone(pd->peer, TRUE); - peer->preshared_key_flags = flags; - if (_peers_set(priv, peer, pd->idx, FALSE)) - _peers_notify(self); - } - - return TRUE; - } - } - - return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) - ->set_secret_flags(setting, secret_name, flags, error); -} - -static void -for_each_secret(NMSetting * setting, - const char * data_key, - GVariant * data_val, - gboolean remove_non_secrets, - _NMConnectionForEachSecretFunc callback, - gpointer callback_data, - GVariantBuilder * setting_builder) -{ - NMSettingWireGuard * s_wg; - NMSettingWireGuardPrivate *priv; - GVariantBuilder peers_builder; - GVariantIter * peer_iter; - GVariantIter data_iter; - const char * key; - - if (!nm_streq(data_key, NM_SETTING_WIREGUARD_PEERS)) { - NM_SETTING_CLASS(nm_setting_wireguard_parent_class) - ->for_each_secret(setting, - data_key, - data_val, - remove_non_secrets, - callback, - callback_data, - setting_builder); - return; - } - - if (!g_variant_is_of_type(data_val, G_VARIANT_TYPE("aa{sv}"))) { - /* invalid type. Silently ignore content as we cannot find secret-keys - * here. */ - return; - } - - s_wg = NM_SETTING_WIREGUARD(setting); - priv = NM_SETTING_WIREGUARD_GET_PRIVATE(s_wg); - - g_variant_builder_init(&peers_builder, G_VARIANT_TYPE("aa{sv}")); - g_variant_iter_init(&data_iter, data_val); - while (g_variant_iter_next(&data_iter, "a{sv}", &peer_iter)) { - _nm_unused nm_auto_free_variant_iter GVariantIter *peer_iter_free = peer_iter; - gs_unref_variant GVariant *preshared_key = NULL; - PeerData * pd = NULL; - NMSettingSecretFlags secret_flags; - GVariant * val; - GVariantBuilder peer_builder; - - g_variant_builder_init(&peer_builder, G_VARIANT_TYPE("a{sv}")); - - while (g_variant_iter_next(peer_iter, "{&sv}", &key, &val)) { - _nm_unused gs_unref_variant GVariant *val_free = val; - - if (nm_streq(key, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)) { - if (!preshared_key && g_variant_is_of_type(val, G_VARIANT_TYPE_STRING)) - preshared_key = g_variant_ref(val); - continue; - } - - if (nm_streq(key, NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY)) { - if (!pd && g_variant_is_of_type(val, G_VARIANT_TYPE_STRING)) - pd = _peers_get_by_public_key(priv, g_variant_get_string(val, NULL), TRUE); - } else if (remove_non_secrets) - continue; - - g_variant_builder_add(&peer_builder, "{sv}", key, val); - } - - if (pd && preshared_key) { - /* without specifying a public-key of an existing peer, the secret is - * ignored. */ - secret_flags = nm_wireguard_peer_get_preshared_key_flags(pd->peer); - if (callback(secret_flags, callback_data)) - g_variant_builder_add(&peer_builder, - "{sv}", - NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, - preshared_key); - } - - g_variant_builder_add(&peers_builder, "a{sv}", &peer_builder); - } - - g_variant_builder_add(setting_builder, - "{sv}", - NM_SETTING_WIREGUARD_PEERS, - g_variant_builder_end(&peers_builder)); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingWireGuard * setting = NM_SETTING_WIREGUARD(object); - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_FWMARK: - g_value_set_uint(value, priv->fwmark); - break; - case PROP_IP4_AUTO_DEFAULT_ROUTE: - g_value_set_enum(value, priv->ip4_auto_default_route); - break; - case PROP_IP6_AUTO_DEFAULT_ROUTE: - g_value_set_enum(value, priv->ip6_auto_default_route); - break; - case PROP_LISTEN_PORT: - g_value_set_uint(value, priv->listen_port); - break; - case PROP_MTU: - g_value_set_uint(value, priv->mtu); - break; - case PROP_PEER_ROUTES: - g_value_set_boolean(value, priv->peer_routes); - break; - case PROP_PRIVATE_KEY: - g_value_set_string(value, priv->private_key); - break; - case PROP_PRIVATE_KEY_FLAGS: - g_value_set_flags(value, priv->private_key_flags); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(object); - const char * str; - - switch (prop_id) { - case PROP_FWMARK: - priv->fwmark = g_value_get_uint(value); - break; - case PROP_IP4_AUTO_DEFAULT_ROUTE: - priv->ip4_auto_default_route = g_value_get_enum(value); - break; - case PROP_IP6_AUTO_DEFAULT_ROUTE: - priv->ip6_auto_default_route = g_value_get_enum(value); - break; - case PROP_LISTEN_PORT: - priv->listen_port = g_value_get_uint(value); - break; - case PROP_MTU: - priv->mtu = g_value_get_uint(value); - break; - case PROP_PEER_ROUTES: - priv->peer_routes = g_value_get_boolean(value); - break; - case PROP_PRIVATE_KEY: - nm_clear_pointer(&priv->private_key, nm_free_secret); - str = g_value_get_string(value); - if (str) { - if (nm_utils_base64secret_normalize(str, - NM_WIREGUARD_PUBLIC_KEY_LEN, - &priv->private_key)) - priv->private_key_valid = TRUE; - else { - priv->private_key = g_strdup(str); - priv->private_key_valid = FALSE; - } - } - break; - case PROP_PRIVATE_KEY_FLAGS: - priv->private_key_flags = g_value_get_flags(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_wireguard_init(NMSettingWireGuard *setting) -{ - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); - - priv->peers_arr = g_ptr_array_new(); - priv->peers_hash = g_hash_table_new(nm_pstr_hash, nm_pstr_equal); - priv->peer_routes = TRUE; - priv->ip4_auto_default_route = NM_TERNARY_DEFAULT; - priv->ip6_auto_default_route = NM_TERNARY_DEFAULT; -} - -/** - * nm_setting_wireguard_new: - * - * Creates a new #NMSettingWireGuard object with default values. - * - * Returns: (transfer full): the new empty #NMSettingWireGuard object - * - * Since: 1.16 - **/ -NMSetting * -nm_setting_wireguard_new(void) -{ - return g_object_new(NM_TYPE_SETTING_WIREGUARD, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(object); - - nm_free_secret(priv->private_key); - - _peers_clear(priv); - g_ptr_array_unref(priv->peers_arr); - g_hash_table_unref(priv->peers_hash); - - G_OBJECT_CLASS(nm_setting_wireguard_parent_class)->finalize(object); -} - -static void -nm_setting_wireguard_class_init(NMSettingWireGuardClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->verify_secrets = verify_secrets; - setting_class->need_secrets = need_secrets; - setting_class->clear_secrets = clear_secrets; - setting_class->update_one_secret = update_one_secret; - setting_class->compare_property = compare_property; - setting_class->duplicate_copy_properties = duplicate_copy_properties; - setting_class->enumerate_values = enumerate_values; - setting_class->aggregate = aggregate; - setting_class->get_secret_flags = get_secret_flags; - setting_class->set_secret_flags = set_secret_flags; - setting_class->for_each_secret = for_each_secret; - - /** - * NMSettingWireGuard:private-key: - * - * The 256 bit private-key in base64 encoding. - * - * Since: 1.16 - **/ - obj_properties[PROP_PRIVATE_KEY] = - g_param_spec_string(NM_SETTING_WIREGUARD_PRIVATE_KEY, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireGuard:private-key-flags: - * - * Flags indicating how to handle the #NMSettingWirelessSecurity:private-key - * property. - * - * Since: 1.16 - **/ - obj_properties[PROP_PRIVATE_KEY_FLAGS] = - g_param_spec_flags(NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireGuard:fwmark: - * - * The use of fwmark is optional and is by default off. Setting it to 0 - * disables it. Otherwise, it is a 32-bit fwmark for outgoing packets. - * - * Note that "ip4-auto-default-route" or "ip6-auto-default-route" enabled, - * implies to automatically choose a fwmark. - * - * Since: 1.16 - **/ - obj_properties[PROP_FWMARK] = - g_param_spec_uint(NM_SETTING_WIREGUARD_FWMARK, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireGuard:listen-port: - * - * The listen-port. If listen-port is not specified, the port will be chosen - * randomly when the interface comes up. - * - * Since: 1.16 - **/ - obj_properties[PROP_LISTEN_PORT] = - g_param_spec_uint(NM_SETTING_WIREGUARD_LISTEN_PORT, - "", - "", - 0, - 65535, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireGuard:peer-routes: - * - * Whether to automatically add routes for the AllowedIPs ranges - * of the peers. If %TRUE (the default), NetworkManager will automatically - * add routes in the routing tables according to ipv4.route-table and - * ipv6.route-table. Usually you want this automatism enabled. - * If %FALSE, no such routes are added automatically. In this case, the - * user may want to configure static routes in ipv4.routes and ipv6.routes, - * respectively. - * - * Note that if the peer's AllowedIPs is "0.0.0.0/0" or "::/0" and the profile's - * ipv4.never-default or ipv6.never-default setting is enabled, the peer route for - * this peer won't be added automatically. - * - * Since: 1.16 - **/ - obj_properties[PROP_PEER_ROUTES] = g_param_spec_boolean( - NM_SETTING_WIREGUARD_PEER_ROUTES, - "", - "", - TRUE, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireGuard:mtu: - * - * If non-zero, only transmit packets of the specified size or smaller, - * breaking larger packets up into multiple fragments. - * - * If zero a default MTU is used. Note that contrary to wg-quick's MTU - * setting, this does not take into account the current routes at the - * time of activation. - * - * Since: 1.16 - **/ - obj_properties[PROP_MTU] = - g_param_spec_uint(NM_SETTING_WIREGUARD_MTU, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireGuard:ip4-auto-default-route: - * - * Whether to enable special handling of the IPv4 default route. - * If enabled, the IPv4 default route from wireguard.peer-routes - * will be placed to a dedicated routing-table and two policy routing rules - * will be added. The fwmark number is also used as routing-table for the default-route, - * and if fwmark is zero, an unused fwmark/table is chosen automatically. - * This corresponds to what wg-quick does with Table=auto and what WireGuard - * calls "Improved Rule-based Routing". - * - * Note that for this automatism to work, you usually don't want to set - * ipv4.gateway, because that will result in a conflicting default route. - * - * Leaving this at the default will enable this option automatically - * if ipv4.never-default is not set and there are any peers that use - * a default-route as allowed-ips. - * - * Since: 1.20 - **/ - obj_properties[PROP_IP4_AUTO_DEFAULT_ROUTE] = g_param_spec_enum( - NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE, - "", - "", - NM_TYPE_TERNARY, - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireGuard:ip6-auto-default-route: - * - * Like ip4-auto-default-route, but for the IPv6 default route. - * - * Since: 1.20 - **/ - obj_properties[PROP_IP6_AUTO_DEFAULT_ROUTE] = g_param_spec_enum( - NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE, - "", - "", - NM_TYPE_TERNARY, - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /* ---dbus--- - * property: peers - * format: array of 'a{sv}' - * description: Array of dictionaries for the WireGuard peers. - * ---end--- - */ - _nm_properties_override_dbus( - properties_override, - NM_SETTING_WIREGUARD_PEERS, - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _peers_dbus_only_synth, - .from_dbus_fcn = _peers_dbus_only_set, )); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_WIREGUARD, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-wireguard.h b/libnm-core/nm-setting-wireguard.h deleted file mode 100644 index 3f046fc713..0000000000 --- a/libnm-core/nm-setting-wireguard.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 - 2019 Red Hat, Inc. - */ - -#ifndef __NM_SETTING_WIREGUARD_H__ -#define __NM_SETTING_WIREGUARD_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" -#include "nm-utils.h" - -G_BEGIN_DECLS - -/*****************************************************************************/ - -#define NM_WIREGUARD_PUBLIC_KEY_LEN 32 -#define NM_WIREGUARD_SYMMETRIC_KEY_LEN 32 - -/*****************************************************************************/ - -typedef struct _NMWireGuardPeer NMWireGuardPeer; - -NM_AVAILABLE_IN_1_16 -GType nm_wireguard_peer_get_type(void); - -NM_AVAILABLE_IN_1_16 -NMWireGuardPeer *nm_wireguard_peer_new(void); - -NM_AVAILABLE_IN_1_16 -NMWireGuardPeer *nm_wireguard_peer_new_clone(const NMWireGuardPeer *self, gboolean with_secrets); - -NM_AVAILABLE_IN_1_16 -NMWireGuardPeer *nm_wireguard_peer_ref(NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -void nm_wireguard_peer_unref(NMWireGuardPeer *self); - -NM_AVAILABLE_IN_1_16 -void nm_wireguard_peer_seal(NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -gboolean nm_wireguard_peer_is_sealed(const NMWireGuardPeer *self); - -NM_AVAILABLE_IN_1_16 -const char *nm_wireguard_peer_get_public_key(const NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -gboolean nm_wireguard_peer_set_public_key(NMWireGuardPeer *self, - const char * public_key, - gboolean accept_invalid); - -NM_AVAILABLE_IN_1_16 -const char *nm_wireguard_peer_get_preshared_key(const NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -gboolean nm_wireguard_peer_set_preshared_key(NMWireGuardPeer *self, - const char * preshared_key, - gboolean accept_invalid); - -NM_AVAILABLE_IN_1_16 -NMSettingSecretFlags nm_wireguard_peer_get_preshared_key_flags(const NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -void nm_wireguard_peer_set_preshared_key_flags(NMWireGuardPeer * self, - NMSettingSecretFlags preshared_key_flags); - -NM_AVAILABLE_IN_1_16 -guint16 nm_wireguard_peer_get_persistent_keepalive(const NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -void nm_wireguard_peer_set_persistent_keepalive(NMWireGuardPeer *self, - guint16 persistent_keepalive); - -NM_AVAILABLE_IN_1_16 -const char *nm_wireguard_peer_get_endpoint(const NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -gboolean -nm_wireguard_peer_set_endpoint(NMWireGuardPeer *self, const char *endpoint, gboolean allow_invalid); - -NM_AVAILABLE_IN_1_16 -guint nm_wireguard_peer_get_allowed_ips_len(const NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -const char * -nm_wireguard_peer_get_allowed_ip(const NMWireGuardPeer *self, guint idx, gboolean *out_is_valid); -NM_AVAILABLE_IN_1_16 -void nm_wireguard_peer_clear_allowed_ips(NMWireGuardPeer *self); -NM_AVAILABLE_IN_1_16 -gboolean nm_wireguard_peer_append_allowed_ip(NMWireGuardPeer *self, - const char * allowed_ip, - gboolean accept_invalid); -NM_AVAILABLE_IN_1_16 -gboolean nm_wireguard_peer_remove_allowed_ip(NMWireGuardPeer *self, guint idx); - -NM_AVAILABLE_IN_1_16 -gboolean nm_wireguard_peer_is_valid(const NMWireGuardPeer *self, - gboolean check_non_secrets, - gboolean check_secrets, - GError ** error); - -NM_AVAILABLE_IN_1_16 -int nm_wireguard_peer_cmp(const NMWireGuardPeer *a, - const NMWireGuardPeer *b, - NMSettingCompareFlags compare_flags); - -/*****************************************************************************/ - -#define NM_TYPE_SETTING_WIREGUARD (nm_setting_wireguard_get_type()) -#define NM_SETTING_WIREGUARD(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuard)) -#define NM_SETTING_WIREGUARD_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuardClass)) -#define NM_IS_SETTING_WIREGUARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIREGUARD)) -#define NM_IS_SETTING_WIREGUARD_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIREGUARD)) -#define NM_SETTING_WIREGUARD_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuardClass)) - -#define NM_SETTING_WIREGUARD_SETTING_NAME "wireguard" - -#define NM_SETTING_WIREGUARD_FWMARK "fwmark" -#define NM_SETTING_WIREGUARD_LISTEN_PORT "listen-port" -#define NM_SETTING_WIREGUARD_PRIVATE_KEY "private-key" -#define NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS "private-key-flags" - -#define NM_SETTING_WIREGUARD_PEERS "peers" - -#define NM_SETTING_WIREGUARD_MTU "mtu" -#define NM_SETTING_WIREGUARD_PEER_ROUTES "peer-routes" -#define NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE "ip4-auto-default-route" -#define NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE "ip6-auto-default-route" - -#define NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS "allowed-ips" -#define NM_WIREGUARD_PEER_ATTR_ENDPOINT "endpoint" -#define NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE "persistent-keepalive" -#define NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY "preshared-key" -#define NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS "preshared-key-flags" -#define NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY "public-key" - -/*****************************************************************************/ - -typedef struct _NMSettingWireGuardClass NMSettingWireGuardClass; - -NM_AVAILABLE_IN_1_16 -GType nm_setting_wireguard_get_type(void); - -NM_AVAILABLE_IN_1_16 -NMSetting *nm_setting_wireguard_new(void); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_16 -const char *nm_setting_wireguard_get_private_key(NMSettingWireGuard *self); - -NM_AVAILABLE_IN_1_16 -NMSettingSecretFlags nm_setting_wireguard_get_private_key_flags(NMSettingWireGuard *self); - -NM_AVAILABLE_IN_1_16 -guint16 nm_setting_wireguard_get_listen_port(NMSettingWireGuard *self); - -NM_AVAILABLE_IN_1_16 -guint32 nm_setting_wireguard_get_fwmark(NMSettingWireGuard *self); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_16 -guint nm_setting_wireguard_get_peers_len(NMSettingWireGuard *self); - -NM_AVAILABLE_IN_1_16 -NMWireGuardPeer *nm_setting_wireguard_get_peer(NMSettingWireGuard *self, guint idx); - -NM_AVAILABLE_IN_1_16 -NMWireGuardPeer *nm_setting_wireguard_get_peer_by_public_key(NMSettingWireGuard *self, - const char * public_key, - guint * out_idx); - -NM_AVAILABLE_IN_1_16 -void nm_setting_wireguard_set_peer(NMSettingWireGuard *self, NMWireGuardPeer *peer, guint idx); - -NM_AVAILABLE_IN_1_16 -void nm_setting_wireguard_append_peer(NMSettingWireGuard *self, NMWireGuardPeer *peer); - -NM_AVAILABLE_IN_1_16 -gboolean nm_setting_wireguard_remove_peer(NMSettingWireGuard *self, guint idx); - -NM_AVAILABLE_IN_1_16 -guint nm_setting_wireguard_clear_peers(NMSettingWireGuard *self); - -NM_AVAILABLE_IN_1_16 -gboolean nm_setting_wireguard_get_peer_routes(NMSettingWireGuard *self); - -NM_AVAILABLE_IN_1_16 -guint32 nm_setting_wireguard_get_mtu(NMSettingWireGuard *self); - -NM_AVAILABLE_IN_1_20 -NMTernary nm_setting_wireguard_get_ip4_auto_default_route(NMSettingWireGuard *self); - -NM_AVAILABLE_IN_1_20 -NMTernary nm_setting_wireguard_get_ip6_auto_default_route(NMSettingWireGuard *self); - -/*****************************************************************************/ - -G_END_DECLS - -#endif /* __NM_SETTING_WIREGUARD_H__ */ diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c deleted file mode 100644 index 162f92202c..0000000000 --- a/libnm-core/nm-setting-wireless-security.c +++ /dev/null @@ -1,1967 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2017 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-wireless-security.h" - -#include "nm-setting-8021x.h" -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" -#include "nm-setting-wireless.h" -#include "nm-glib-aux/nm-secret-utils.h" - -/** - * SECTION:nm-setting-wireless-security - * @short_description: Describes connection properties for Wi-Fi networks that - * use WEP, LEAP, WPA or WPA2/RSN security - * - * The #NMSettingWirelessSecurity object is a #NMSetting subclass that describes - * properties necessary for connection to encrypted Wi-Fi networks. - * - * It's a good idea to read up on wpa_supplicant configuration before using this - * setting extensively, since most of the options here correspond closely with - * the relevant wpa_supplicant configuration options. To get a better overview - * of how Wi-Fi security works, you may want to get copies of the following books. - * - * 802.11 Wireless Networks: The Definitive Guide, Second Edition - * Author: Matthew Gast - * ISBN: 978-0596100520 - * - * Cisco Wireless LAN Security - * Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky - * ISBN: 978-1587051548 - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingWirelessSecurity, - PROP_KEY_MGMT, - PROP_WEP_TX_KEYIDX, - PROP_AUTH_ALG, - PROP_PROTO, - PROP_PAIRWISE, - PROP_GROUP, - PROP_PMF, - PROP_LEAP_USERNAME, - PROP_WEP_KEY0, - PROP_WEP_KEY1, - PROP_WEP_KEY2, - PROP_WEP_KEY3, - PROP_WEP_KEY_FLAGS, - PROP_WEP_KEY_TYPE, - PROP_PSK, - PROP_PSK_FLAGS, - PROP_LEAP_PASSWORD, - PROP_LEAP_PASSWORD_FLAGS, - PROP_WPS_METHOD, - PROP_FILS, ); - -typedef struct { - GSList * proto; /* GSList of strings */ - GSList * pairwise; /* GSList of strings */ - GSList * group; /* GSList of strings */ - char * key_mgmt; - char * auth_alg; - char * leap_username; - char * leap_password; - char * wep_key0; - char * wep_key1; - char * wep_key2; - char * wep_key3; - char * psk; - NMSettingSecretFlags leap_password_flags; - NMSettingSecretFlags wep_key_flags; - NMSettingSecretFlags psk_flags; - NMSettingWirelessSecurityPmf pmf; - NMWepKeyType wep_key_type; - NMSettingWirelessSecurityWpsMethod wps_method; - NMSettingWirelessSecurityFils fils; - guint32 wep_tx_keyidx; -} NMSettingWirelessSecurityPrivate; - -G_DEFINE_TYPE(NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING) - -#define NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - NM_TYPE_SETTING_WIRELESS_SECURITY, \ - NMSettingWirelessSecurityPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_wireless_security_get_key_mgmt: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:key-mgmt property of the setting - **/ -const char * -nm_setting_wireless_security_get_key_mgmt(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->key_mgmt; -} - -/** - * nm_setting_wireless_security_get_num_protos: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the number of security protocols this connection allows when - * connecting to secure Wi-Fi networks - **/ -guint32 -nm_setting_wireless_security_get_num_protos(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); - - return g_slist_length(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->proto); -} - -/** - * nm_setting_wireless_security_get_proto: - * @setting: the #NMSettingWirelessSecurity - * @i: an index into the protocol list - * - * Returns: the protocol at index @i - **/ -const char * -nm_setting_wireless_security_get_proto(NMSettingWirelessSecurity *setting, guint32 i) -{ - NMSettingWirelessSecurityPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - g_return_val_if_fail(i <= g_slist_length(priv->proto), NULL); - - return (const char *) g_slist_nth_data(priv->proto, i); -} - -/** - * nm_setting_wireless_security_add_proto: - * @setting: the #NMSettingWirelessSecurity - * @proto: the protocol to add, one of "wpa" or "rsn" - * - * Adds a Wi-Fi security protocol (one of "wpa" or "rsn") to the allowed list; - * only protocols in this list will be used when finding and connecting to - * the Wi-Fi network specified by this connection. For example, if the - * protocol list contains only "wpa" but the access point for the SSID specified - * by this connection only supports WPA2/RSN, the connection cannot be used - * with the access point. - * - * Returns: %TRUE if the protocol was new and was added to the allowed - * protocol list, or %FALSE if it was already in the list - **/ -gboolean -nm_setting_wireless_security_add_proto(NMSettingWirelessSecurity *setting, const char *proto) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); - g_return_val_if_fail(proto != NULL, FALSE); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - for (iter = priv->proto; iter; iter = g_slist_next(iter)) { - if (g_ascii_strcasecmp(proto, (char *) iter->data) == 0) - return FALSE; - } - - priv->proto = g_slist_append(priv->proto, g_ascii_strdown(proto, -1)); - _notify(setting, PROP_PROTO); - return TRUE; -} - -/** - * nm_setting_wireless_security_remove_proto: - * @setting: the #NMSettingWirelessSecurity - * @i: index of the protocol to remove - * - * Removes a protocol from the allowed protocol list. - **/ -void -nm_setting_wireless_security_remove_proto(NMSettingWirelessSecurity *setting, guint32 i) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * elt; - - g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - elt = g_slist_nth(priv->proto, i); - g_return_if_fail(elt != NULL); - - g_free(elt->data); - priv->proto = g_slist_delete_link(priv->proto, elt); - _notify(setting, PROP_PROTO); -} - -/** - * nm_setting_wireless_security_remove_proto_by_value: - * @setting: the #NMSettingWirelessSecurity - * @proto: the protocol to remove, one of "wpa" or "rsn" - * - * Removes a protocol from the allowed protocol list. - * - * Returns: %TRUE if the protocol was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_wireless_security_remove_proto_by_value(NMSettingWirelessSecurity *setting, - const char * proto) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); - g_return_val_if_fail(proto != NULL, FALSE); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - for (iter = priv->proto; iter; iter = g_slist_next(iter)) { - if (g_ascii_strcasecmp(proto, (char *) iter->data) == 0) { - priv->proto = g_slist_delete_link(priv->proto, iter); - _notify(setting, PROP_PROTO); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_wireless_security_clear_protos: - * @setting: the #NMSettingWirelessSecurity - * - * Removes all protocols from the allowed list. If there are no protocols - * specified then all protocols are allowed. - **/ -void -nm_setting_wireless_security_clear_protos(NMSettingWirelessSecurity *setting) -{ - NMSettingWirelessSecurityPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - g_slist_free_full(priv->proto, g_free); - priv->proto = NULL; - _notify(setting, PROP_PROTO); -} - -/** - * nm_setting_wireless_security_get_num_pairwise: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the number of pairwise encryption algorithms in the allowed list - **/ -guint32 -nm_setting_wireless_security_get_num_pairwise(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); - - return g_slist_length(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->pairwise); -} - -/** - * nm_setting_wireless_security_get_pairwise: - * @setting: the #NMSettingWirelessSecurity - * @i: index of an item in the allowed pairwise encryption algorithm list - * - * Returns the allowed pairwise encryption algorithm from allowed algorithm - * list. - * - * Returns: the pairwise encryption algorithm at index @i - **/ -const char * -nm_setting_wireless_security_get_pairwise(NMSettingWirelessSecurity *setting, guint32 i) -{ - NMSettingWirelessSecurityPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - g_return_val_if_fail(i <= g_slist_length(priv->pairwise), NULL); - - return (const char *) g_slist_nth_data(priv->pairwise, i); -} - -/** - * nm_setting_wireless_security_add_pairwise: - * @setting: the #NMSettingWirelessSecurity - * @pairwise: the encryption algorithm to add, one of "tkip" or "ccmp" - * - * Adds an encryption algorithm to the list of allowed pairwise encryption - * algorithms. If the list is not empty, then only access points that support - * one or more of the encryption algorithms in the list will be considered - * compatible with this connection. - * - * Returns: %TRUE if the algorithm was added to the list, %FALSE if it was - * already in the list - **/ -gboolean -nm_setting_wireless_security_add_pairwise(NMSettingWirelessSecurity *setting, const char *pairwise) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); - g_return_val_if_fail(pairwise != NULL, FALSE); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - for (iter = priv->pairwise; iter; iter = g_slist_next(iter)) { - if (g_ascii_strcasecmp(pairwise, (char *) iter->data) == 0) - return FALSE; - } - - priv->pairwise = g_slist_append(priv->pairwise, g_ascii_strdown(pairwise, -1)); - _notify(setting, PROP_PAIRWISE); - return TRUE; -} - -/** - * nm_setting_wireless_security_remove_pairwise: - * @setting: the #NMSettingWirelessSecurity - * @i: the index of an item in the allowed pairwise encryption algorithm list - * - * Removes an encryption algorithm from the allowed pairwise encryption - * algorithm list. - **/ -void -nm_setting_wireless_security_remove_pairwise(NMSettingWirelessSecurity *setting, guint32 i) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * elt; - - g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - elt = g_slist_nth(priv->pairwise, i); - g_return_if_fail(elt != NULL); - - g_free(elt->data); - priv->pairwise = g_slist_delete_link(priv->pairwise, elt); - _notify(setting, PROP_PAIRWISE); -} - -/** - * nm_setting_wireless_security_remove_pairwise_by_value: - * @setting: the #NMSettingWirelessSecurity - * @pairwise: the encryption algorithm to remove, one of "tkip" or "ccmp" - * - * Removes an encryption algorithm from the allowed pairwise encryption - * algorithm list. - * - * Returns: %TRUE if the encryption algorithm was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_wireless_security_remove_pairwise_by_value(NMSettingWirelessSecurity *setting, - const char * pairwise) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); - g_return_val_if_fail(pairwise != NULL, FALSE); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - for (iter = priv->pairwise; iter; iter = g_slist_next(iter)) { - if (g_ascii_strcasecmp(pairwise, (char *) iter->data) == 0) { - priv->pairwise = g_slist_delete_link(priv->pairwise, iter); - _notify(setting, PROP_PAIRWISE); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_wireless_security_clear_pairwise: - * @setting: the #NMSettingWirelessSecurity - * - * Removes all algorithms from the allowed list. If there are no algorithms - * specified then all pairwise encryption algorithms are allowed. - **/ -void -nm_setting_wireless_security_clear_pairwise(NMSettingWirelessSecurity *setting) -{ - NMSettingWirelessSecurityPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - g_slist_free_full(priv->pairwise, g_free); - priv->pairwise = NULL; - _notify(setting, PROP_PAIRWISE); -} - -/** - * nm_setting_wireless_security_get_num_groups: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the number of groupwise encryption algorithms in the allowed list - **/ -guint32 -nm_setting_wireless_security_get_num_groups(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); - - return g_slist_length(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->group); -} - -/** - * nm_setting_wireless_security_get_group: - * @setting: the #NMSettingWirelessSecurity - * @i: index of an item in the allowed groupwise encryption algorithm list - * - * Returns the allowed groupwise encryption algorithm from allowed algorithm - * list. - * - * Returns: the groupwise encryption algorithm at index @i - **/ -const char * -nm_setting_wireless_security_get_group(NMSettingWirelessSecurity *setting, guint32 i) -{ - NMSettingWirelessSecurityPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - g_return_val_if_fail(i <= g_slist_length(priv->group), NULL); - - return (const char *) g_slist_nth_data(priv->group, i); -} - -/** - * nm_setting_wireless_security_add_group: - * @setting: the #NMSettingWirelessSecurity - * @group: the encryption algorithm to add, one of "wep40", "wep104", - * "tkip", or "ccmp" - * - * Adds an encryption algorithm to the list of allowed groupwise encryption - * algorithms. If the list is not empty, then only access points that support - * one or more of the encryption algorithms in the list will be considered - * compatible with this connection. - * - * Returns: %TRUE if the algorithm was added to the list, %FALSE if it was - * already in the list - **/ -gboolean -nm_setting_wireless_security_add_group(NMSettingWirelessSecurity *setting, const char *group) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); - g_return_val_if_fail(group != NULL, FALSE); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - for (iter = priv->group; iter; iter = g_slist_next(iter)) { - if (g_ascii_strcasecmp(group, (char *) iter->data) == 0) - return FALSE; - } - - priv->group = g_slist_append(priv->group, g_ascii_strdown(group, -1)); - _notify(setting, PROP_GROUP); - return TRUE; -} - -/** - * nm_setting_wireless_security_remove_group: - * @setting: the #NMSettingWirelessSecurity - * @i: the index of an item in the allowed groupwise encryption algorithm list - * - * Removes an encryption algorithm from the allowed groupwise encryption - * algorithm list. - **/ -void -nm_setting_wireless_security_remove_group(NMSettingWirelessSecurity *setting, guint32 i) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * elt; - - g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - elt = g_slist_nth(priv->group, i); - g_return_if_fail(elt != NULL); - - g_free(elt->data); - priv->group = g_slist_delete_link(priv->group, elt); - _notify(setting, PROP_GROUP); -} - -/** - * nm_setting_wireless_security_remove_group_by_value: - * @setting: the #NMSettingWirelessSecurity - * @group: the encryption algorithm to remove, one of "wep40", "wep104", - * "tkip", or "ccmp" - * - * Removes an encryption algorithm from the allowed groupwise encryption - * algorithm list. - * - * Returns: %TRUE if the algorithm was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_wireless_security_remove_group_by_value(NMSettingWirelessSecurity *setting, - const char * group) -{ - NMSettingWirelessSecurityPrivate *priv; - GSList * iter; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); - g_return_val_if_fail(group != NULL, FALSE); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - for (iter = priv->group; iter; iter = g_slist_next(iter)) { - if (g_ascii_strcasecmp(group, (char *) iter->data) == 0) { - priv->group = g_slist_delete_link(priv->group, iter); - _notify(setting, PROP_GROUP); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_wireless_security_clear_groups: - * @setting: the #NMSettingWirelessSecurity - * - * Removes all algorithms from the allowed list. If there are no algorithms - * specified then all groupwise encryption algorithms are allowed. - **/ -void -nm_setting_wireless_security_clear_groups(NMSettingWirelessSecurity *setting) -{ - NMSettingWirelessSecurityPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - g_slist_free_full(priv->group, g_free); - priv->group = NULL; - _notify(setting, PROP_GROUP); -} - -/* - * nm_setting_wireless_security_get_pmf: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:pmf property of the setting - * - * Since: 1.10 - **/ -NMSettingWirelessSecurityPmf -nm_setting_wireless_security_get_pmf(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->pmf; -} - -/** - * nm_setting_wireless_security_get_psk: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:psk property of the setting - **/ -const char * -nm_setting_wireless_security_get_psk(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->psk; -} - -/** - * nm_setting_wireless_security_get_psk_flags: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSettingWirelessSecurity:psk - **/ -NMSettingSecretFlags -nm_setting_wireless_security_get_psk_flags(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->psk_flags; -} - -/** - * nm_setting_wireless_security_get_leap_username: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:leap-username property of the setting - **/ -const char * -nm_setting_wireless_security_get_leap_username(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->leap_username; -} - -/** - * nm_setting_wireless_security_get_leap_password: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:leap-password property of the setting - **/ -const char * -nm_setting_wireless_security_get_leap_password(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->leap_password; -} - -/** - * nm_setting_wireless_security_get_leap_password_flags: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingSecretFlags pertaining to the - * #NMSettingWirelessSecurity:leap-password - **/ -NMSettingSecretFlags -nm_setting_wireless_security_get_leap_password_flags(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->leap_password_flags; -} - -/** - * nm_setting_wireless_security_get_wep_key: - * @setting: the #NMSettingWirelessSecurity - * @idx: the WEP key index (0..3 inclusive) - * - * Returns: the WEP key at the given index - **/ -const char * -nm_setting_wireless_security_get_wep_key(NMSettingWirelessSecurity *setting, guint32 idx) -{ - NMSettingWirelessSecurityPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - g_return_val_if_fail(idx < 4, NULL); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - if (idx == 0) - return priv->wep_key0; - else if (idx == 1) - return priv->wep_key1; - else if (idx == 2) - return priv->wep_key2; - else if (idx == 3) - return priv->wep_key3; - - g_assert_not_reached(); - return NULL; -} - -/** - * nm_setting_wireless_security_set_wep_key: - * @setting: the #NMSettingWirelessSecurity - * @idx: the index of the key (0..3 inclusive) - * @key: the WEP key as a string, in either hexadecimal, ASCII, or passphrase - * form as determined by the value of the #NMSettingWirelessSecurity:wep-key-type - * property. - * - * Sets a WEP key in the given index. - **/ -void -nm_setting_wireless_security_set_wep_key(NMSettingWirelessSecurity *setting, - guint32 idx, - const char * key) -{ - NMSettingWirelessSecurityPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); - g_return_if_fail(idx < 4); - - priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - switch (idx) { - case 0: - g_free(priv->wep_key0); - priv->wep_key0 = g_strdup(key); - _notify(setting, PROP_WEP_KEY0); - break; - case 1: - g_free(priv->wep_key1); - priv->wep_key1 = g_strdup(key); - _notify(setting, PROP_WEP_KEY1); - break; - case 2: - g_free(priv->wep_key2); - priv->wep_key2 = g_strdup(key); - _notify(setting, PROP_WEP_KEY2); - break; - case 3: - g_free(priv->wep_key3); - priv->wep_key3 = g_strdup(key); - _notify(setting, PROP_WEP_KEY3); - break; - default: - g_assert_not_reached(); - } -} - -/** - * nm_setting_wireless_security_get_wep_tx_keyidx: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:wep-tx-keyidx property of the setting - **/ -guint32 -nm_setting_wireless_security_get_wep_tx_keyidx(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wep_tx_keyidx; -} - -/** - * nm_setting_wireless_security_get_auth_alg: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:auth-alg property of the setting - **/ -const char * -nm_setting_wireless_security_get_auth_alg(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->auth_alg; -} - -/** - * nm_setting_wireless_security_get_wep_key_flags: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingSecretFlags pertaining to the all WEP keys - **/ -NMSettingSecretFlags -nm_setting_wireless_security_get_wep_key_flags(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NM_SETTING_SECRET_FLAG_NONE); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wep_key_flags; -} - -/** - * nm_setting_wireless_security_get_wep_key_type: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:wep-key-type property of the setting - **/ -NMWepKeyType -nm_setting_wireless_security_get_wep_key_type(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wep_key_type; -} - -/** - * nm_setting_wireless_security_get_wps_method: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:wps-method property of the setting - * - * Since: 1.10 - **/ -NMSettingWirelessSecurityWpsMethod -nm_setting_wireless_security_get_wps_method(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wps_method; -} - -/* - * nm_setting_wireless_security_get_fils: - * @setting: the #NMSettingWirelessSecurity - * - * Returns: the #NMSettingWirelessSecurity:fils property of the setting - * - * Since: 1.12 - **/ -NMSettingWirelessSecurityFils -nm_setting_wireless_security_get_fils(NMSettingWirelessSecurity *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); - - return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->fils; -} - -static GPtrArray * -need_secrets(NMSetting *setting) -{ - NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(setting); - NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); - GPtrArray * secrets; - - secrets = g_ptr_array_sized_new(4); - - g_assert(priv->key_mgmt); - - /* Static WEP */ - if (strcmp(priv->key_mgmt, "none") == 0) { - if ((priv->wep_tx_keyidx == 0) - && !nm_utils_wep_key_valid(priv->wep_key0, priv->wep_key_type)) { - g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0); - return secrets; - } - if ((priv->wep_tx_keyidx == 1) - && !nm_utils_wep_key_valid(priv->wep_key1, priv->wep_key_type)) { - g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1); - return secrets; - } - if ((priv->wep_tx_keyidx == 2) - && !nm_utils_wep_key_valid(priv->wep_key2, priv->wep_key_type)) { - g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2); - return secrets; - } - if ((priv->wep_tx_keyidx == 3) - && !nm_utils_wep_key_valid(priv->wep_key3, priv->wep_key_type)) { - g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3); - return secrets; - } - goto no_secrets; - } - - /* WPA-PSK infrastructure */ - if (strcmp(priv->key_mgmt, "wpa-psk") == 0) { - if (!nm_utils_wpa_psk_valid(priv->psk)) { - g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_PSK); - return secrets; - } - goto no_secrets; - } - - /* SAE, used in MESH and WPA3-Personal */ - if (strcmp(priv->key_mgmt, "sae") == 0) { - if (!priv->psk || !*priv->psk) { - g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_PSK); - return secrets; - } - goto no_secrets; - } - - /* LEAP */ - if (priv->auth_alg && !strcmp(priv->auth_alg, "leap") && !strcmp(priv->key_mgmt, "ieee8021x")) { - if (!priv->leap_password || !*priv->leap_password) { - g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD); - return secrets; - } - goto no_secrets; - } - - if (NM_IN_STRSET(priv->key_mgmt, "ieee8021x", "wpa-eap", "owe", "wpa-eap-suite-b-192")) { - /* Let caller check the 802.1x setting for secrets */ - goto no_secrets; - } - - g_assert_not_reached(); - return secrets; - -no_secrets: - if (secrets) - g_ptr_array_free(secrets, TRUE); - return NULL; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(setting); - NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); - const char * valid_key_mgmt[] = - {"none", "ieee8021x", "wpa-psk", "wpa-eap", "wpa-eap-suite-b-192", "sae", "owe", NULL}; - const char * valid_auth_algs[] = {"open", "shared", "leap", NULL}; - const char * valid_protos[] = {"wpa", "rsn", NULL}; - const char * valid_pairwise[] = {"tkip", "ccmp", NULL}; - const char * valid_groups[] = {"wep40", "wep104", "tkip", "ccmp", NULL}; - NMSettingWireless *s_wifi; - const char * wifi_mode; - - s_wifi = connection ? nm_connection_get_setting_wireless(connection) : NULL; - wifi_mode = s_wifi ? nm_setting_wireless_get_mode(s_wifi) : NULL; - - if (!priv->key_mgmt) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); - return FALSE; - } - - if (g_strcmp0(wifi_mode, NM_SETTING_WIRELESS_MODE_MESH) == 0) { - if ((strcmp(priv->key_mgmt, "none") == 0) || (strcmp(priv->key_mgmt, "sae") == 0)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for '%s' mode connections"), - priv->key_mgmt, - NM_SETTING_WIRELESS_MODE_MESH); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); - return FALSE; - } - } else { - if (!g_strv_contains(valid_key_mgmt, priv->key_mgmt)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid value for the property"), - priv->key_mgmt); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); - return FALSE; - } - } - - if (priv->auth_alg && !strcmp(priv->auth_alg, "leap")) { - /* LEAP must use ieee8021x key management */ - if (strcmp(priv->key_mgmt, "ieee8021x")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' security requires '%s=%s'"), - "leap", - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "ieee8021x"); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); - return FALSE; - } - if (!priv->leap_username) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME); - return FALSE; - } - } else { - if (nm_streq(priv->key_mgmt, "ieee8021x") || nm_streq(priv->key_mgmt, "wpa-eap") - || nm_streq(priv->key_mgmt, "wpa-eap-suite-b-192")) { - /* Need an 802.1x setting too */ - if (connection && !nm_connection_get_setting_802_1x(connection)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("'%s' security requires '%s' setting presence"), - priv->key_mgmt, - NM_SETTING_802_1X_SETTING_NAME); - g_prefix_error(error, "%s: ", NM_SETTING_802_1X_SETTING_NAME); - return FALSE; - } - } - } - - if (priv->leap_username && !strlen(priv->leap_username)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME); - return FALSE; - } - - if (priv->wep_tx_keyidx > 3) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%d' value is out of range <0-3>"), - priv->wep_tx_keyidx); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX); - return FALSE; - } - - if (priv->wep_key_type > NM_WEP_KEY_TYPE_LAST) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE); - return FALSE; - } - - if (priv->auth_alg && !g_strv_contains(valid_auth_algs, priv->auth_alg)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); - return FALSE; - } - - if (priv->proto && !_nm_utils_string_slist_validate(priv->proto, valid_protos)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_PROTO); - return FALSE; - } - - if (priv->pairwise) { - if (!_nm_utils_string_slist_validate(priv->pairwise, valid_pairwise)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_PAIRWISE); - return FALSE; - } - } - - if (priv->group && !_nm_utils_string_slist_validate(priv->group, valid_groups)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_GROUP); - return FALSE; - } - - /* Shared Key auth can only be used with WEP */ - if (priv->auth_alg && !strcmp(priv->auth_alg, "shared")) { - if (priv->key_mgmt && strcmp(priv->key_mgmt, "none")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' can only be used with '%s=%s' (WEP)"), - "shared", - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "none"); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); - return FALSE; - } - } - - G_STATIC_ASSERT_EXPR(((NMSettingWirelessSecurityPmf) -1) > 0); - if (priv->pmf > NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_PMF); - return FALSE; - } - - if (NM_IN_SET(priv->pmf, - NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL, - NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) - && !NM_IN_STRSET(priv->key_mgmt, - "wpa-eap", - "wpa-eap-suite-b-192", - "wpa-psk", - "sae", - "owe")) { - g_set_error( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' can only be used with 'wpa-eap', 'wpa-eap-suite-b-192', 'wpa-psk' or 'sae' key " - "management "), - priv->pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL ? "optional" : "required"); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_PMF); - return FALSE; - } - - if (!_nm_utils_wps_method_validate(priv->wps_method, - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, - FALSE, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -_verify_wep_key(const char * wep_key, - NMWepKeyType wep_key_type, - const char * property, - GError ** error) -{ - if (wep_key && !nm_utils_wep_key_valid(wep_key, wep_key_type)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, property); - return FALSE; - } - return TRUE; -} - -static gboolean -verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(setting); - NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); - - /* LEAP */ - if (priv->auth_alg && !strcmp(priv->auth_alg, "leap") && !strcmp(priv->key_mgmt, "ieee8021x")) { - if (!_nm_setting_verify_secret_string(priv->leap_password, - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, - error)) - return FALSE; - } - - /* WEP */ - if (!_verify_wep_key(priv->wep_key0, - priv->wep_key_type, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, - error)) - return FALSE; - if (!_verify_wep_key(priv->wep_key1, - priv->wep_key_type, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, - error)) - return FALSE; - if (!_verify_wep_key(priv->wep_key2, - priv->wep_key_type, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, - error)) - return FALSE; - if (!_verify_wep_key(priv->wep_key3, - priv->wep_key_type, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, - error)) - return FALSE; - - /* WPA-PSK */ - if (priv->psk && strcmp(priv->key_mgmt, "sae") != 0 && !nm_utils_wpa_psk_valid(priv->psk)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_PSK); - return FALSE; - } - - return TRUE; -} - -static gboolean -get_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags *out_flags, - GError ** error) -{ - NMSettingSecretFlags flags; - - if (NM_IN_STRSET(secret_name, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY3)) { - /* There's only one 'flags' property for WEP keys, so alias all the WEP key - * property names to that flags property. */ - nm_assert(_nm_setting_property_is_regular_secret(setting, secret_name)); - nm_assert(_nm_setting_property_is_regular_secret_flags( - setting, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS)); - - g_object_get(G_OBJECT(setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, &flags, NULL); - NM_SET_OUT(out_flags, flags); - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_wireless_security_parent_class) - ->get_secret_flags(setting, secret_name, out_flags, error); -} - -static gboolean -set_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags flags, - GError ** error) -{ - if (NM_IN_STRSET(secret_name, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY3)) { - /* There's only one 'flags' property for WEP keys, so alias all the WEP key - * property names to that flags property. */ - nm_assert(_nm_setting_property_is_regular_secret(setting, secret_name)); - nm_assert(_nm_setting_property_is_regular_secret_flags( - setting, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS)); - - if (!nm_g_object_set_property_flags(G_OBJECT(setting), - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, - NM_TYPE_SETTING_SECRET_FLAGS, - flags, - error)) - g_return_val_if_reached(FALSE); - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_wireless_security_parent_class) - ->set_secret_flags(setting, secret_name, flags, error); -} - -/* NMSettingWirelessSecurity:wep-key-type is an enum, but needs to be marshalled - * as 'u', not 'i', for backward-compatibility. - */ -static GVariant * -wep_key_type_to_dbus(const GValue *from) -{ - return g_variant_new_uint32(g_value_get_enum(from)); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingWirelessSecurity * setting = NM_SETTING_WIRELESS_SECURITY(object); - NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_KEY_MGMT: - g_value_set_string(value, priv->key_mgmt); - break; - case PROP_WEP_TX_KEYIDX: - g_value_set_uint(value, priv->wep_tx_keyidx); - break; - case PROP_AUTH_ALG: - g_value_set_string(value, priv->auth_alg); - break; - case PROP_PROTO: - g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->proto, TRUE)); - break; - case PROP_PAIRWISE: - g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->pairwise, TRUE)); - break; - case PROP_GROUP: - g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->group, TRUE)); - break; - case PROP_PMF: - g_value_set_int(value, nm_setting_wireless_security_get_pmf(setting)); - break; - case PROP_LEAP_USERNAME: - g_value_set_string(value, priv->leap_username); - break; - case PROP_WEP_KEY0: - g_value_set_string(value, priv->wep_key0); - break; - case PROP_WEP_KEY1: - g_value_set_string(value, priv->wep_key1); - break; - case PROP_WEP_KEY2: - g_value_set_string(value, priv->wep_key2); - break; - case PROP_WEP_KEY3: - g_value_set_string(value, priv->wep_key3); - break; - case PROP_WEP_KEY_FLAGS: - g_value_set_flags(value, priv->wep_key_flags); - break; - case PROP_PSK: - g_value_set_string(value, priv->psk); - break; - case PROP_PSK_FLAGS: - g_value_set_flags(value, priv->psk_flags); - break; - case PROP_LEAP_PASSWORD: - g_value_set_string(value, priv->leap_password); - break; - case PROP_LEAP_PASSWORD_FLAGS: - g_value_set_flags(value, priv->leap_password_flags); - break; - case PROP_WEP_KEY_TYPE: - g_value_set_enum(value, priv->wep_key_type); - break; - case PROP_WPS_METHOD: - g_value_set_uint(value, priv->wps_method); - break; - case PROP_FILS: - g_value_set_int(value, nm_setting_wireless_security_get_fils(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingWirelessSecurity * setting = NM_SETTING_WIRELESS_SECURITY(object); - NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); - const char * str; - - switch (prop_id) { - case PROP_KEY_MGMT: - g_free(priv->key_mgmt); - str = g_value_get_string(value); - priv->key_mgmt = str ? g_ascii_strdown(str, -1) : NULL; - break; - case PROP_WEP_TX_KEYIDX: - priv->wep_tx_keyidx = g_value_get_uint(value); - break; - case PROP_AUTH_ALG: - g_free(priv->auth_alg); - str = g_value_get_string(value); - priv->auth_alg = str ? g_ascii_strdown(str, -1) : NULL; - break; - case PROP_PROTO: - g_slist_free_full(priv->proto, g_free); - priv->proto = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); - break; - case PROP_PAIRWISE: - g_slist_free_full(priv->pairwise, g_free); - priv->pairwise = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); - break; - case PROP_GROUP: - g_slist_free_full(priv->group, g_free); - priv->group = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); - break; - case PROP_PMF: - priv->pmf = g_value_get_int(value); - break; - case PROP_LEAP_USERNAME: - g_free(priv->leap_username); - priv->leap_username = g_value_dup_string(value); - break; - case PROP_WEP_KEY0: - nm_free_secret(priv->wep_key0); - priv->wep_key0 = g_value_dup_string(value); - break; - case PROP_WEP_KEY1: - nm_free_secret(priv->wep_key1); - priv->wep_key1 = g_value_dup_string(value); - break; - case PROP_WEP_KEY2: - nm_free_secret(priv->wep_key2); - priv->wep_key2 = g_value_dup_string(value); - break; - case PROP_WEP_KEY3: - nm_free_secret(priv->wep_key3); - priv->wep_key3 = g_value_dup_string(value); - break; - case PROP_WEP_KEY_FLAGS: - priv->wep_key_flags = g_value_get_flags(value); - break; - case PROP_PSK: - nm_free_secret(priv->psk); - priv->psk = g_value_dup_string(value); - break; - case PROP_PSK_FLAGS: - priv->psk_flags = g_value_get_flags(value); - break; - case PROP_LEAP_PASSWORD: - nm_free_secret(priv->leap_password); - priv->leap_password = g_value_dup_string(value); - break; - case PROP_LEAP_PASSWORD_FLAGS: - priv->leap_password_flags = g_value_get_flags(value); - break; - case PROP_WEP_KEY_TYPE: - priv->wep_key_type = g_value_get_enum(value); - break; - case PROP_WPS_METHOD: - priv->wps_method = g_value_get_uint(value); - break; - case PROP_FILS: - priv->fils = g_value_get_int(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_wireless_security_init(NMSettingWirelessSecurity *self) -{ - nm_assert(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self)->wep_key_type - == NM_WEP_KEY_TYPE_UNKNOWN); - nm_assert(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self)->wps_method - == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT); -} - -/** - * nm_setting_wireless_security_new: - * - * Creates a new #NMSettingWirelessSecurity object with default values. - * - * Returns: (transfer full): the new empty #NMSettingWirelessSecurity object - **/ -NMSetting * -nm_setting_wireless_security_new(void) -{ - return g_object_new(NM_TYPE_SETTING_WIRELESS_SECURITY, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(object); - NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); - - g_free(priv->key_mgmt); - g_free(priv->auth_alg); - g_free(priv->leap_username); - nm_free_secret(priv->wep_key0); - nm_free_secret(priv->wep_key1); - nm_free_secret(priv->wep_key2); - nm_free_secret(priv->wep_key3); - nm_free_secret(priv->psk); - nm_free_secret(priv->leap_password); - - g_slist_free_full(priv->proto, g_free); - g_slist_free_full(priv->pairwise, g_free); - g_slist_free_full(priv->group, g_free); - - G_OBJECT_CLASS(nm_setting_wireless_security_parent_class)->finalize(object); -} - -static void -nm_setting_wireless_security_class_init(NMSettingWirelessSecurityClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingWirelessSecurityPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->verify_secrets = verify_secrets; - setting_class->need_secrets = need_secrets; - setting_class->get_secret_flags = get_secret_flags; - setting_class->set_secret_flags = set_secret_flags; - - /** - * NMSettingWirelessSecurity:key-mgmt: - * - * Key management used for the connection. One of "none" (WEP), - * "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" - * (SAE), "owe" (Opportunistic Wireless Encryption), "wpa-eap" - * (WPA-Enterprise) or "wpa-eap-suite-b-192" (WPA3-Enterprise Suite B). - * This property must be set for any Wi-Fi connection that uses security. - **/ - /* ---ifcfg-rh--- - * property: key-mgmt - * variable: KEY_MGMT(+) - * values: IEEE8021X, WPA-PSK, WPA-EAP, WPA-EAP-SUITE-B-192 - * description: Key management menthod. - * ---end--- - */ - obj_properties[PROP_KEY_MGMT] = - g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_REQUIRED | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:wep-tx-keyidx: - * - * When static WEP is used (ie, key-mgmt = "none") and a non-default WEP key - * index is used by the AP, put that WEP key index here. Valid values are 0 - * (default key) through 3. Note that some consumer access points (like the - * Linksys WRT54G) number the keys 1 - 4. - **/ - /* ---ifcfg-rh--- - * property: wep-tx-keyidx - * variable: DEFAULTKEY - * values: 1, 2, 3, 4 - * default: 1 - * description: Index of active WEP key. - * ---end--- - */ - obj_properties[PROP_WEP_TX_KEYIDX] = - g_param_spec_uint(NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, - "", - "", - 0, - 3, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:auth-alg: - * - * When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the - * 802.11 authentication algorithm required by the AP here. One of "open" - * for Open System, "shared" for Shared Key, or "leap" for Cisco LEAP. When - * using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the - * "leap-username" and "leap-password" properties must be specified. - **/ - /* ---ifcfg-rh--- - * property: auth-alg - * variable: SECURITYMODE(+) - * values: restricted, open, leap - * description: Authentication algorithm for WEP. - * ---end--- - */ - obj_properties[PROP_AUTH_ALG] = g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:proto: - * - * List of strings specifying the allowed WPA protocol versions to use. - * Each element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN). If - * not specified, both WPA and RSN connections are allowed. - **/ - /* ---ifcfg-rh--- - * property: proto - * variable: WPA_ALLOW_WPA(+), WPA_ALLOW_WPA2(+) - * values: yes, no - * default: no - * description: Allowed WPA protocols, WPA and WPA2 (RSN). - * ---end--- - */ - obj_properties[PROP_PROTO] = g_param_spec_boxed(NM_SETTING_WIRELESS_SECURITY_PROTO, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:pairwise: - * - * A list of pairwise encryption algorithms which prevents connections to - * Wi-Fi networks that do not utilize one of the algorithms in the list. - * For maximum compatibility leave this property empty. Each list element - * may be one of "tkip" or "ccmp". - **/ - /* ---ifcfg-rh--- - * property: pairwise - * variable: CIPHER_PAIRWISE(+) - * values: CCMP, TKIP - * description: Restrict pairwise encryption algorithms, specified as a space - * separated list. - * ---end--- - */ - obj_properties[PROP_PAIRWISE] = g_param_spec_boxed(NM_SETTING_WIRELESS_SECURITY_PAIRWISE, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:group: - * - * A list of group/broadcast encryption algorithms which prevents - * connections to Wi-Fi networks that do not utilize one of the algorithms - * in the list. For maximum compatibility leave this property empty. Each - * list element may be one of "wep40", "wep104", "tkip", or "ccmp". - **/ - /* ---ifcfg-rh--- - * property: group - * variable: CIPHER_GROUP(+) - * values: CCMP, TKIP, WEP40, WEP104 - * description: Restrict group/broadcast encryption algorithms, specified as a space - * separated list. - * ---end--- - */ - obj_properties[PROP_GROUP] = g_param_spec_boxed(NM_SETTING_WIRELESS_SECURITY_GROUP, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:pmf: - * - * Indicates whether Protected Management Frames (802.11w) must be enabled - * for the connection. One of %NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT - * (use global default value), %NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE - * (disable PMF), %NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (enable PMF if - * the supplicant and the access point support it) or - * %NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (enable PMF and fail if not - * supported). When set to %NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT and no - * global default is set, PMF will be optionally enabled. - * - * Since: 1.10 - **/ - /* ---ifcfg-rh--- - * property: pmf - * variable: PMF(+) - * values: default, disable, optional, required - * description: Enables or disables PMF (802.11w) - * example: PMF=required - * ---end--- - */ - obj_properties[PROP_PMF] = g_param_spec_int(NM_SETTING_WIRELESS_SECURITY_PMF, - "", - "", - G_MININT32, - G_MAXINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:leap-username: - * - * The login username for legacy LEAP connections (ie, key-mgmt = - * "ieee8021x" and auth-alg = "leap"). - **/ - /* ---ifcfg-rh--- - * property: leap-username - * variable: IEEE_8021X_IDENTITY(+) - * description: Login name for LEAP. - * ---end--- - */ - obj_properties[PROP_LEAP_USERNAME] = - g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:wep-key0: - * - * Index 0 WEP key. This is the WEP key used in most networks. See the - * "wep-key-type" property for a description of how this key is interpreted. - **/ - /* ---ifcfg-rh--- - * property: wep-key0 - * variable: KEY1, KEY_PASSPHRASE1(+) - * description: The first WEP key (used in most networks). See also DEFAULTKEY for key index. - * ---end--- - */ - obj_properties[PROP_WEP_KEY0] = - g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:wep-key1: - * - * Index 1 WEP key. This WEP index is not used by most networks. See the - * "wep-key-type" property for a description of how this key is interpreted. - **/ - /* ---ifcfg-rh--- - * property: wep-key1 - * variable: KEY2, KEY_PASSPHRASE2(+) - * description: WEP key with index 1. See also DEFAULTKEY for key index. - * ---end--- - */ - obj_properties[PROP_WEP_KEY1] = - g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:wep-key2: - * - * Index 2 WEP key. This WEP index is not used by most networks. See the - * "wep-key-type" property for a description of how this key is interpreted. - **/ - /* ---ifcfg-rh--- - * property: wep-key2 - * variable: KEY3, KEY_PASSPHRASE3(+) - * description: WEP key with index 2. See also DEFAULTKEY for key index. - * ---end--- - */ - obj_properties[PROP_WEP_KEY2] = - g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:wep-key3: - * - * Index 3 WEP key. This WEP index is not used by most networks. See the - * "wep-key-type" property for a description of how this key is interpreted. - **/ - /* ---ifcfg-rh--- - * property: wep-key3 - * variable: KEY4, KEY_PASSPHRASE4(+) - * description: WEP key with index 3. See also DEFAULTKEY for key index. - * ---end--- - */ - obj_properties[PROP_WEP_KEY3] = - g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:wep-key-flags: - * - * Flags indicating how to handle the #NMSettingWirelessSecurity:wep-key0, - * #NMSettingWirelessSecurity:wep-key1, #NMSettingWirelessSecurity:wep-key2, - * and #NMSettingWirelessSecurity:wep-key3 properties. - **/ - /* ---ifcfg-rh--- - * property: wep-key-flags - * variable: WEP_KEY_FLAGS(+) - * format: NMSettingSecretFlags - * description: Password flags for KEY, KEY_PASSPHRASE password. - * ---end--- - */ - obj_properties[PROP_WEP_KEY_FLAGS] = - g_param_spec_flags(NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:psk: - * - * Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII - * passphrase of 8 to 63 characters that is (as specified in the 802.11i - * standard) hashed to derive the actual key, or the key in form of 64 - * hexadecimal character. The WPA3-Personal networks use a passphrase - * of any length for SAE authentication. - **/ - /* ---ifcfg-rh--- - * property: psk - * variable: WPA_PSK - * description: Pre-Shared-Key for WPA networks. - * ---end--- - */ - obj_properties[PROP_PSK] = - g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_PSK, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:psk-flags: - * - * Flags indicating how to handle the #NMSettingWirelessSecurity:psk - * property. - **/ - /* ---ifcfg-rh--- - * property: psk-flags - * variable: WPA_PSK_FLAGS(+) - * format: NMSettingSecretFlags - * description: Password flags for WPA_PSK_FLAGS. - * example: WPA_PSK_FLAGS=user - * ---end--- - */ - obj_properties[PROP_PSK_FLAGS] = g_param_spec_flags(NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:leap-password: - * - * The login password for legacy LEAP connections (ie, key-mgmt = - * "ieee8021x" and auth-alg = "leap"). - **/ - /* ---ifcfg-rh--- - * property: leap-password - * variable: IEEE_8021X_PASSWORD(+) - * description: Password for LEAP. It can also go to "key-" - * lookaside file, or it can be owned by a secret agent. - * ---end--- - */ - obj_properties[PROP_LEAP_PASSWORD] = - g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:leap-password-flags: - * - * Flags indicating how to handle the - * #NMSettingWirelessSecurity:leap-password property. - **/ - /* ---ifcfg-rh--- - * property: leap-password-flags - * variable: IEEE_8021X_PASSWORD_FLAGS(+) - * format: NMSettingSecretFlags - * description: Password flags for IEEE_8021X_PASSWORD_FLAGS. - * ---end--- - */ - obj_properties[PROP_LEAP_PASSWORD_FLAGS] = - g_param_spec_flags(NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, - "", - "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:wep-key-type: - * - * Controls the interpretation of WEP keys. Allowed values are - * %NM_WEP_KEY_TYPE_KEY, in which case the key is either a 10- or - * 26-character hexadecimal string, or a 5- or 13-character ASCII password; - * or %NM_WEP_KEY_TYPE_PASSPHRASE, in which case the passphrase is provided - * as a string and will be hashed using the de-facto MD5 method to derive - * the actual WEP key. - **/ - /* ---ifcfg-rh--- - * property: wep-key-type - * variable: KEY or KEY_PASSPHRASE(+); KEY_TYPE(+) - * description: KEY is used for "key" type (10 or 26 hexadecimal characters, - * or 5 or 13 character string prefixed with "s:"). KEY_PASSPHRASE is used - * for WEP passphrases. KEY_TYPE specifies the key type and can be either - * 'key' or 'passphrase'. KEY_TYPE is redundant and can be omitted. - * example: KEY1=s:ahoj, KEY1=0a1c45bc02, KEY_PASSPHRASE1=mysupersecretkey - * ---end--- - */ - obj_properties[PROP_WEP_KEY_TYPE] = - g_param_spec_enum(NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, - "", - "", - NM_TYPE_WEP_KEY_TYPE, - NM_WEP_KEY_TYPE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj( - properties_override, - obj_properties[PROP_WEP_KEY_TYPE], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT32, - .gprop_to_dbus_fcn = wep_key_type_to_dbus, )); - - /** - * NMSettingWirelessSecurity:wps-method: - * - * Flags indicating which mode of WPS is to be used if any. - * - * There's little point in changing the default setting as NetworkManager will - * automatically determine whether it's feasible to start WPS enrollment from - * the Access Point capabilities. - * - * WPS can be disabled by setting this property to a value of 1. - * - * Since: 1.10 - **/ - /* ---ifcfg-rh--- - * property: wps-method - * variable: WPS_METHOD - * description: Used to control the WPS methods to be used - * Valid values are "default", "auto", "disabled", "pin" and "pbc". - * If omitted, whatver the AP announces is used. - * example: WPS_METHOD=disabled, WPS_METHOD="pin pbc" - * ---end--- - */ - obj_properties[PROP_WPS_METHOD] = g_param_spec_uint( - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, - "", - "", - 0, - G_MAXUINT32, - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWirelessSecurity:fils: - * - * Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for - * the connection. One of %NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (use - * global default value), %NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE - * (disable FILS), %NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (enable FILS - * if the supplicant and the access point support it) or - * %NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (enable FILS and fail if not - * supported). When set to %NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT and - * no global default is set, FILS will be optionally enabled. - * - * Since: 1.12 - **/ - /* ---ifcfg-rh--- - * property: fils - * variable: FILS(+) - * values: default, disable, optional, required - * description: Enables or disables FILS (802.11ai) - * example: FILS=required - * ---end--- - */ - obj_properties[PROP_FILS] = g_param_spec_int(NM_SETTING_WIRELESS_SECURITY_FILS, - "", - "", - G_MININT32, - G_MAXINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_WIRELESS_SECURITY, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-wireless-security.h b/libnm-core/nm-setting-wireless-security.h deleted file mode 100644 index 62a3c6e526..0000000000 --- a/libnm-core/nm-setting-wireless-security.h +++ /dev/null @@ -1,239 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2017 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_WIRELESS_SECURITY_H__ -#define __NM_SETTING_WIRELESS_SECURITY_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_get_type()) -#define NM_SETTING_WIRELESS_SECURITY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), \ - NM_TYPE_SETTING_WIRELESS_SECURITY, \ - NMSettingWirelessSecurity)) -#define NM_SETTING_WIRELESS_SECURITY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), \ - NM_TYPE_SETTING_WIRELESS_SECURITY, \ - NMSettingWirelessSecurityClass)) -#define NM_IS_SETTING_WIRELESS_SECURITY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIRELESS_SECURITY)) -#define NM_IS_SETTING_WIRELESS_SECURITY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIRELESS_SECURITY)) -#define NM_SETTING_WIRELESS_SECURITY_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), \ - NM_TYPE_SETTING_WIRELESS_SECURITY, \ - NMSettingWirelessSecurityClass)) - -#define NM_SETTING_WIRELESS_SECURITY_SETTING_NAME "802-11-wireless-security" - -/** - * NMWepKeyType: - * @NM_WEP_KEY_TYPE_UNKNOWN: unknown WEP key type - * @NM_WEP_KEY_TYPE_KEY: indicates a hexadecimal or ASCII formatted WEP key. - * Hex keys are either 10 or 26 hexadecimal characters (ie "5f782f2f5f" or - * "732f2d712e4a394a375d366931"), while ASCII keys are either 5 or 13 ASCII - * characters (ie "abcde" or "blahblah99$*1"). - * @NM_WEP_KEY_TYPE_PASSPHRASE: indicates a WEP passphrase (ex "I bought a duck - * on my way back from the market 235Q&^%^*%") instead of a hexadecimal or ASCII - * key. Passphrases are between 8 and 64 characters inclusive and are hashed - * the actual WEP key using the MD5 hash algorithm. - * @NM_WEP_KEY_TYPE_LAST: placeholder value for bounds-checking - * - * The #NMWepKeyType values specify how any WEP keys present in the setting - * are interpreted. There are no standards governing how to hash the various WEP - * key/passphrase formats into the actual WEP key. Unfortunately some WEP keys - * can be interpreted in multiple ways, requiring the setting to specify how to - * interpret the any WEP keys. For example, the key "732f2d712e4a394a375d366931" - * is both a valid Hexadecimal WEP key and a WEP passphrase. Further, many - * ASCII keys are also valid WEP passphrases, but since passphrases and ASCII - * keys are hashed differently to determine the actual WEP key the type must be - * specified. - */ -typedef enum { - NM_WEP_KEY_TYPE_UNKNOWN = 0, - NM_WEP_KEY_TYPE_KEY = 1, /* Hex or ASCII */ - NM_WEP_KEY_TYPE_PASSPHRASE = 2, /* 104/128-bit Passphrase */ - - NM_WEP_KEY_TYPE_LAST = NM_WEP_KEY_TYPE_PASSPHRASE, /*< skip >*/ -} NMWepKeyType; - -/** - * NMSettingWirelessSecurityPmf: - * @NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT: use the default value - * @NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE: disable PMF - * @NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL: enable PMF if the supplicant and the AP support it - * @NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED: require PMF and fail if not available - * - * These flags indicate whether PMF must be enabled. - **/ -typedef enum { - NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT = 0, - NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE = 1, - NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL = 2, - NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED = 3, - _NM_SETTING_WIRELESS_SECURITY_PMF_NUM, /*< skip >*/ - NM_SETTING_WIRELESS_SECURITY_PMF_LAST = _NM_SETTING_WIRELESS_SECURITY_PMF_NUM - 1, /*< skip >*/ -} NMSettingWirelessSecurityPmf; - -/** - * NMSettingWirelessSecurityWpsMethod: - * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT: Attempt whichever method AP supports - * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED: WPS can not be used. - * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO: Use WPS, any method - * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC: use WPS push-button method - * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN: use PIN method - * - * Configure the use of WPS by a connection while it activates. - * - * Note: prior to 1.16, this was a GEnum type instead of a GFlags type - * although, with the same numeric values. - * - * Since: 1.10 - **/ -typedef enum { /*< flags >*/ - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT = 0x00000000, - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED = 0x00000001, - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO = 0x00000002, - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC = 0x00000004, - NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN = 0x00000008, -} NMSettingWirelessSecurityWpsMethod; - -/** - * NMSettingWirelessSecurityFils: - * @NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT: use the default value - * @NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE: disable FILS - * @NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL: enable FILS if the supplicant and the AP support it - * @NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED: require FILS and fail if not available - * @_NM_SETTING_WIRELESS_SECURITY_FILS_NUM: placeholder value for bounds-checking - * @NM_SETTING_WIRELESS_SECURITY_FILS_LAST: placeholder value for bounds-checking - * - * These flags indicate whether FILS must be enabled. - * - * Since: 1.12 - **/ -/* clang-format off */ -typedef enum { - NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT = 0, - NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE = 1, - NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL = 2, - NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED = 3, - _NM_SETTING_WIRELESS_SECURITY_FILS_NUM, /*< skip >*/ - NM_SETTING_WIRELESS_SECURITY_FILS_LAST = _NM_SETTING_WIRELESS_SECURITY_FILS_NUM - 1, /*< skip >*/ -} NMSettingWirelessSecurityFils; -/* clang-format on */ - -#define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt" -#define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx" -#define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg" -#define NM_SETTING_WIRELESS_SECURITY_PROTO "proto" -#define NM_SETTING_WIRELESS_SECURITY_PAIRWISE "pairwise" -#define NM_SETTING_WIRELESS_SECURITY_GROUP "group" -#define NM_SETTING_WIRELESS_SECURITY_PMF "pmf" -#define NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME "leap-username" -#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY0 "wep-key0" -#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY1 "wep-key1" -#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY2 "wep-key2" -#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY3 "wep-key3" -#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS "wep-key-flags" -#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE "wep-key-type" -#define NM_SETTING_WIRELESS_SECURITY_PSK "psk" -#define NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS "psk-flags" -#define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD "leap-password" -#define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS "leap-password-flags" -#define NM_SETTING_WIRELESS_SECURITY_WPS_METHOD "wps-method" -#define NM_SETTING_WIRELESS_SECURITY_FILS "fils" - -/** - * NMSettingWirelessSecurity: - * - * Wi-Fi Security Settings - */ -struct _NMSettingWirelessSecurity { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingWirelessSecurityClass; - -GType nm_setting_wireless_security_get_type(void); - -NMSetting *nm_setting_wireless_security_new(void); - -const char *nm_setting_wireless_security_get_key_mgmt(NMSettingWirelessSecurity *setting); - -guint32 nm_setting_wireless_security_get_num_protos(NMSettingWirelessSecurity *setting); -const char *nm_setting_wireless_security_get_proto(NMSettingWirelessSecurity *setting, guint32 i); -gboolean nm_setting_wireless_security_add_proto(NMSettingWirelessSecurity *setting, - const char * proto); -void nm_setting_wireless_security_remove_proto(NMSettingWirelessSecurity *setting, guint32 i); -gboolean nm_setting_wireless_security_remove_proto_by_value(NMSettingWirelessSecurity *setting, - const char * proto); -void nm_setting_wireless_security_clear_protos(NMSettingWirelessSecurity *setting); - -guint32 nm_setting_wireless_security_get_num_pairwise(NMSettingWirelessSecurity *setting); -const char *nm_setting_wireless_security_get_pairwise(NMSettingWirelessSecurity *setting, - guint32 i); -gboolean nm_setting_wireless_security_add_pairwise(NMSettingWirelessSecurity *setting, - const char * pairwise); -void nm_setting_wireless_security_remove_pairwise(NMSettingWirelessSecurity *setting, guint32 i); -gboolean nm_setting_wireless_security_remove_pairwise_by_value(NMSettingWirelessSecurity *setting, - const char * pairwise); -void nm_setting_wireless_security_clear_pairwise(NMSettingWirelessSecurity *setting); - -guint32 nm_setting_wireless_security_get_num_groups(NMSettingWirelessSecurity *setting); -const char *nm_setting_wireless_security_get_group(NMSettingWirelessSecurity *setting, guint32 i); -gboolean nm_setting_wireless_security_add_group(NMSettingWirelessSecurity *setting, - const char * group); -void nm_setting_wireless_security_remove_group(NMSettingWirelessSecurity *setting, guint32 i); -gboolean nm_setting_wireless_security_remove_group_by_value(NMSettingWirelessSecurity *setting, - const char * group); -void nm_setting_wireless_security_clear_groups(NMSettingWirelessSecurity *setting); - -NM_AVAILABLE_IN_1_10 -NMSettingWirelessSecurityPmf -nm_setting_wireless_security_get_pmf(NMSettingWirelessSecurity *setting); - -const char * nm_setting_wireless_security_get_psk(NMSettingWirelessSecurity *setting); -NMSettingSecretFlags nm_setting_wireless_security_get_psk_flags(NMSettingWirelessSecurity *setting); - -const char *nm_setting_wireless_security_get_leap_username(NMSettingWirelessSecurity *setting); -const char *nm_setting_wireless_security_get_leap_password(NMSettingWirelessSecurity *setting); -NMSettingSecretFlags -nm_setting_wireless_security_get_leap_password_flags(NMSettingWirelessSecurity *setting); - -const char *nm_setting_wireless_security_get_wep_key(NMSettingWirelessSecurity *setting, - guint32 idx); -void nm_setting_wireless_security_set_wep_key(NMSettingWirelessSecurity *setting, - guint32 idx, - const char * key); -guint32 nm_setting_wireless_security_get_wep_tx_keyidx(NMSettingWirelessSecurity *setting); -const char *nm_setting_wireless_security_get_auth_alg(NMSettingWirelessSecurity *setting); - -NMSettingSecretFlags - nm_setting_wireless_security_get_wep_key_flags(NMSettingWirelessSecurity *setting); -NMWepKeyType nm_setting_wireless_security_get_wep_key_type(NMSettingWirelessSecurity *setting); - -NM_AVAILABLE_IN_1_10 -NMSettingWirelessSecurityWpsMethod -nm_setting_wireless_security_get_wps_method(NMSettingWirelessSecurity *setting); - -NM_AVAILABLE_IN_1_12 -NMSettingWirelessSecurityFils -nm_setting_wireless_security_get_fils(NMSettingWirelessSecurity *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_WIRELESS_SECURITY_H__ */ diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c deleted file mode 100644 index 232bc7a05d..0000000000 --- a/libnm-core/nm-setting-wireless.c +++ /dev/null @@ -1,1932 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-wireless.h" - -#include - -#include "nm-utils.h" -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" - -/** - * SECTION:nm-setting-wireless - * @short_description: Describes connection properties for 802.11 Wi-Fi networks - * - * The #NMSettingWireless object is a #NMSetting subclass that describes properties - * necessary for connection to 802.11 Wi-Fi networks. - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingWireless, - PROP_SSID, - PROP_MODE, - PROP_BAND, - PROP_CHANNEL, - PROP_BSSID, - PROP_RATE, - PROP_TX_POWER, - PROP_MAC_ADDRESS, - PROP_CLONED_MAC_ADDRESS, - PROP_GENERATE_MAC_ADDRESS_MASK, - PROP_MAC_ADDRESS_BLACKLIST, - PROP_MTU, - PROP_SEEN_BSSIDS, - PROP_HIDDEN, - PROP_POWERSAVE, - PROP_MAC_ADDRESS_RANDOMIZATION, - PROP_WAKE_ON_WLAN, - PROP_AP_ISOLATION, ); - -typedef struct { - GBytes * ssid; - GArray * mac_address_blacklist; - GPtrArray * seen_bssids; - char * mode; - char * band; - char * bssid; - char * device_mac_address; - char * cloned_mac_address; - char * generate_mac_address_mask; - NMSettingMacRandomization mac_address_randomization; - NMTernary ap_isolation; - guint32 channel; - guint32 rate; - guint32 tx_power; - guint32 mtu; - guint32 powersave; - guint32 wowl; - bool hidden : 1; -} NMSettingWirelessPrivate; - -G_DEFINE_TYPE(NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING) - -#define NM_SETTING_WIRELESS_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate)) - -/*****************************************************************************/ - -static gboolean -match_cipher(const char *cipher, - const char *expected, - guint32 wpa_flags, - guint32 rsn_flags, - guint32 flag) -{ - if (strcmp(cipher, expected) != 0) - return FALSE; - - if (!(wpa_flags & flag) && !(rsn_flags & flag)) - return FALSE; - - return TRUE; -} - -/** - * nm_setting_wireless_ap_security_compatible: - * @s_wireless: a #NMSettingWireless - * @s_wireless_sec: a #NMSettingWirelessSecurity or %NULL - * @ap_flags: the %NM80211ApFlags of the given access point - * @ap_wpa: the %NM80211ApSecurityFlags of the given access point's WPA - * capabilities - * @ap_rsn: the %NM80211ApSecurityFlags of the given access point's WPA2/RSN - * capabilities - * @ap_mode: the 802.11 mode of the AP, either Ad-Hoc or Infrastructure - * - * Given a #NMSettingWireless and an optional #NMSettingWirelessSecurity, - * determine if the configuration given by the settings is compatible with - * the security of an access point using that access point's capability flags - * and mode. Useful for clients that wish to filter a set of connections - * against a set of access points and determine which connections are - * compatible with which access points. - * - * Returns: %TRUE if the given settings are compatible with the access point's - * security flags and mode, %FALSE if they are not. - */ -gboolean -nm_setting_wireless_ap_security_compatible(NMSettingWireless * s_wireless, - NMSettingWirelessSecurity *s_wireless_sec, - NM80211ApFlags ap_flags, - NM80211ApSecurityFlags ap_wpa, - NM80211ApSecurityFlags ap_rsn, - NM80211Mode ap_mode) -{ - const char *key_mgmt = NULL, *cipher; - guint32 num, i; - gboolean found = FALSE; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(s_wireless), FALSE); - - if (!s_wireless_sec) { - if ((ap_flags & NM_802_11_AP_FLAGS_PRIVACY) || (ap_wpa != NM_802_11_AP_SEC_NONE) - || (ap_rsn != NM_802_11_AP_SEC_NONE)) - return FALSE; - return TRUE; - } - - key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wireless_sec); - if (!key_mgmt) - return FALSE; - - /* Static WEP */ - if (!strcmp(key_mgmt, "none")) { - if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY) || (ap_wpa != NM_802_11_AP_SEC_NONE) - || (ap_rsn != NM_802_11_AP_SEC_NONE)) - return FALSE; - return TRUE; - } - - /* Adhoc WPA2 (ie, RSN IBSS) */ - if (ap_mode == NM_802_11_MODE_ADHOC) { - if (strcmp(key_mgmt, "wpa-psk")) - return FALSE; - - /* Ensure the AP has RSN PSK capability */ - if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK)) - return FALSE; - - /* Fall through and check ciphers in generic WPA-PSK code */ - } - - /* Dynamic WEP or LEAP */ - if (!strcmp(key_mgmt, "ieee8021x")) { - if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) - return FALSE; - - /* If the AP is advertising a WPA IE, make sure it supports WEP ciphers */ - if (ap_wpa != NM_802_11_AP_SEC_NONE) { - if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return FALSE; - - /* quick check; can't use AP if it doesn't support at least one - * WEP cipher in both pairwise and group suites. - */ - if (!(ap_wpa & (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104)) - || !(ap_wpa & (NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104))) - return FALSE; - - /* Match at least one pairwise cipher with AP's capability if the - * wireless-security setting explicitly lists pairwise ciphers - */ - num = nm_setting_wireless_security_get_num_pairwise(s_wireless_sec); - for (i = 0, found = FALSE; i < num; i++) { - cipher = nm_setting_wireless_security_get_pairwise(s_wireless_sec, i); - if ((found = match_cipher(cipher, - "wep40", - ap_wpa, - ap_wpa, - NM_802_11_AP_SEC_PAIR_WEP40))) - break; - if ((found = match_cipher(cipher, - "wep104", - ap_wpa, - ap_wpa, - NM_802_11_AP_SEC_PAIR_WEP104))) - break; - } - if (!found && num) - return FALSE; - - /* Match at least one group cipher with AP's capability if the - * wireless-security setting explicitly lists group ciphers - */ - num = nm_setting_wireless_security_get_num_groups(s_wireless_sec); - for (i = 0, found = FALSE; i < num; i++) { - cipher = nm_setting_wireless_security_get_group(s_wireless_sec, i); - if ((found = match_cipher(cipher, - "wep40", - ap_wpa, - ap_wpa, - NM_802_11_AP_SEC_GROUP_WEP40))) - break; - if ((found = match_cipher(cipher, - "wep104", - ap_wpa, - ap_wpa, - NM_802_11_AP_SEC_GROUP_WEP104))) - break; - } - if (!found && num) - return FALSE; - } - return TRUE; - } - - /* WPA[2]-PSK and WPA[2] Enterprise */ - if (!strcmp(key_mgmt, "wpa-psk") || !strcmp(key_mgmt, "wpa-eap") || !strcmp(key_mgmt, "sae") - || !strcmp(key_mgmt, "owe")) { - if (!strcmp(key_mgmt, "wpa-psk")) { - if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) - && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK)) - return FALSE; - } else if (!strcmp(key_mgmt, "wpa-eap")) { - if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X) - && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return FALSE; - } else if (!strcmp(key_mgmt, "sae")) { - if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_SAE) - && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE)) - return FALSE; - } else if (!strcmp(key_mgmt, "owe")) { - if (!NM_FLAGS_ANY(ap_wpa, - NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM) - && !NM_FLAGS_ANY(ap_rsn, - NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) - return FALSE; - } - - // FIXME: should handle WPA and RSN separately here to ensure that - // if the Connection only uses WPA we don't match a cipher against - // the AP's RSN IE instead - - /* Match at least one pairwise cipher with AP's capability if the - * wireless-security setting explicitly lists pairwise ciphers - */ - num = nm_setting_wireless_security_get_num_pairwise(s_wireless_sec); - for (i = 0, found = FALSE; i < num; i++) { - cipher = nm_setting_wireless_security_get_pairwise(s_wireless_sec, i); - if ((found = match_cipher(cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_TKIP))) - break; - if ((found = match_cipher(cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_CCMP))) - break; - } - if (!found && num) - return FALSE; - - /* Match at least one group cipher with AP's capability if the - * wireless-security setting explicitly lists group ciphers - */ - num = nm_setting_wireless_security_get_num_groups(s_wireless_sec); - for (i = 0, found = FALSE; i < num; i++) { - cipher = nm_setting_wireless_security_get_group(s_wireless_sec, i); - - if ((found = - match_cipher(cipher, "wep40", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP40))) - break; - if ((found = - match_cipher(cipher, "wep104", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP104))) - break; - if ((found = match_cipher(cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_TKIP))) - break; - if ((found = match_cipher(cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_CCMP))) - break; - } - if (!found && num) - return FALSE; - - return TRUE; - } - - return FALSE; -} - -/** - * nm_setting_wireless_get_ssid: - * @setting: the #NMSettingWireless - * - * Returns: (transfer none): the #NMSettingWireless:ssid property of the setting - **/ -GBytes * -nm_setting_wireless_get_ssid(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->ssid; -} - -/** - * nm_setting_wireless_get_mode: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:mode property of the setting - **/ -const char * -nm_setting_wireless_get_mode(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mode; -} - -/** - * nm_setting_wireless_get_band: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:band property of the setting - **/ -const char * -nm_setting_wireless_get_band(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->band; -} - -/** - * nm_setting_wireless_get_channel: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:channel property of the setting - **/ -guint32 -nm_setting_wireless_get_channel(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->channel; -} - -/** - * nm_setting_wireless_get_bssid: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:bssid property of the setting - **/ -const char * -nm_setting_wireless_get_bssid(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->bssid; -} - -/** - * nm_setting_wireless_get_rate: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:rate property of the setting - **/ -guint32 -nm_setting_wireless_get_rate(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->rate; -} - -/** - * nm_setting_wireless_get_tx_power: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:tx-power property of the setting - **/ -guint32 -nm_setting_wireless_get_tx_power(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->tx_power; -} - -/** - * nm_setting_wireless_get_mac_address: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:mac-address property of the setting - **/ -const char * -nm_setting_wireless_get_mac_address(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->device_mac_address; -} - -/** - * nm_setting_wireless_get_cloned_mac_address: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:cloned-mac-address property of the setting - **/ -const char * -nm_setting_wireless_get_cloned_mac_address(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->cloned_mac_address; -} - -/** - * nm_setting_wireless_get_generate_mac_address_mask: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:generate-mac-address-mask property of the setting - * - * Since: 1.4 - **/ -const char * -nm_setting_wireless_get_generate_mac_address_mask(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->generate_mac_address_mask; -} - -/** - * nm_setting_wireless_get_mac_address_blacklist: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:mac-address-blacklist property of the setting - **/ -const char *const * -nm_setting_wireless_get_mac_address_blacklist(NMSettingWireless *setting) -{ - NMSettingWirelessPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - return (const char *const *) priv->mac_address_blacklist->data; -} - -/** - * nm_setting_wireless_get_num_mac_blacklist_items: - * @setting: the #NMSettingWireless - * - * Returns: the number of blacklisted MAC addresses - **/ -guint32 -nm_setting_wireless_get_num_mac_blacklist_items(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mac_address_blacklist->len; -} - -/** - * nm_setting_wireless_get_mac_blacklist_item: - * @setting: the #NMSettingWireless - * @idx: the zero-based index of the MAC address entry - * - * Returns: the blacklisted MAC address string (hex-digits-and-colons notation) - * at index @idx - **/ -const char * -nm_setting_wireless_get_mac_blacklist_item(NMSettingWireless *setting, guint32 idx) -{ - NMSettingWirelessPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - g_return_val_if_fail(idx <= priv->mac_address_blacklist->len, NULL); - - return g_array_index(priv->mac_address_blacklist, const char *, idx); -} - -/** - * nm_setting_wireless_add_mac_blacklist_item: - * @setting: the #NMSettingWireless - * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist - * - * Adds a new MAC address to the #NMSettingWireless:mac-address-blacklist property. - * - * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address - * is invalid or was already present - **/ -gboolean -nm_setting_wireless_add_mac_blacklist_item(NMSettingWireless *setting, const char *mac) -{ - NMSettingWirelessPrivate *priv; - const char * candidate; - int i; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), FALSE); - g_return_val_if_fail(mac != NULL, FALSE); - - if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) - return FALSE; - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - for (i = 0; i < priv->mac_address_blacklist->len; i++) { - candidate = g_array_index(priv->mac_address_blacklist, char *, i); - if (nm_utils_hwaddr_matches(mac, -1, candidate, -1)) - return FALSE; - } - - mac = nm_utils_hwaddr_canonical(mac, ETH_ALEN); - g_array_append_val(priv->mac_address_blacklist, mac); - _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); - return TRUE; -} - -/** - * nm_setting_wireless_remove_mac_blacklist_item: - * @setting: the #NMSettingWireless - * @idx: index number of the MAC address - * - * Removes the MAC address at index @idx from the blacklist. - **/ -void -nm_setting_wireless_remove_mac_blacklist_item(NMSettingWireless *setting, guint32 idx) -{ - NMSettingWirelessPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_WIRELESS(setting)); - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - g_return_if_fail(idx < priv->mac_address_blacklist->len); - - g_array_remove_index(priv->mac_address_blacklist, idx); - _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); -} - -/** - * nm_setting_wireless_remove_mac_blacklist_item_by_value: - * @setting: the #NMSettingWireless - * @mac: the MAC address string (hex-digits-and-colons notation) to remove from - * the blacklist - * - * Removes the MAC address @mac from the blacklist. - * - * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_wireless_remove_mac_blacklist_item_by_value(NMSettingWireless *setting, const char *mac) -{ - NMSettingWirelessPrivate *priv; - const char * candidate; - int i; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), FALSE); - g_return_val_if_fail(mac != NULL, FALSE); - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - for (i = 0; i < priv->mac_address_blacklist->len; i++) { - candidate = g_array_index(priv->mac_address_blacklist, char *, i); - if (!nm_utils_hwaddr_matches(mac, -1, candidate, -1)) { - g_array_remove_index(priv->mac_address_blacklist, i); - _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_wireless_clear_mac_blacklist_items: - * @setting: the #NMSettingWireless - * - * Removes all blacklisted MAC addresses. - **/ -void -nm_setting_wireless_clear_mac_blacklist_items(NMSettingWireless *setting) -{ - g_return_if_fail(NM_IS_SETTING_WIRELESS(setting)); - - g_array_set_size(NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mac_address_blacklist, 0); - _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); -} - -/** - * nm_setting_wireless_get_mtu: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:mtu property of the setting - **/ -guint32 -nm_setting_wireless_get_mtu(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mtu; -} - -/** - * nm_setting_wireless_get_hidden: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:hidden property of the setting - **/ -gboolean -nm_setting_wireless_get_hidden(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), FALSE); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->hidden; -} - -/** - * nm_setting_wireless_get_powersave: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:powersave property of the setting - * - * Since: 1.2 - **/ -guint32 -nm_setting_wireless_get_powersave(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->powersave; -} - -/** - * nm_setting_wireless_get_mac_address_randomization: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:mac-address-randomization property of the - * setting - * - * Since: 1.2 - **/ -NMSettingMacRandomization -nm_setting_wireless_get_mac_address_randomization(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mac_address_randomization; -} - -/** - * nm_setting_wireless_add_seen_bssid: - * @setting: the #NMSettingWireless - * @bssid: the new BSSID to add to the list - * - * Adds a new Wi-Fi AP's BSSID to the previously seen BSSID list of the setting. - * NetworkManager now tracks previously seen BSSIDs internally so this function - * no longer has much use. Actually, changes you make using this function will - * not be preserved. - * - * Returns: %TRUE if @bssid was already known, %FALSE if not - **/ -gboolean -nm_setting_wireless_add_seen_bssid(NMSettingWireless *setting, const char *bssid) -{ - NMSettingWirelessPrivate *priv; - gs_free char * lower_bssid = NULL; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), FALSE); - g_return_val_if_fail(bssid != NULL, FALSE); - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - - lower_bssid = g_ascii_strdown(bssid, -1); - - if (!priv->seen_bssids) { - priv->seen_bssids = g_ptr_array_new_with_free_func(g_free); - } else { - if (nm_utils_strv_find_first((char **) priv->seen_bssids->pdata, - priv->seen_bssids->len, - lower_bssid) - >= 0) - return FALSE; - } - - g_ptr_array_add(priv->seen_bssids, g_steal_pointer(&lower_bssid)); - _notify(setting, PROP_SEEN_BSSIDS); - return TRUE; -} - -/** - * nm_setting_wireless_get_num_seen_bssids: - * @setting: the #NMSettingWireless - * - * Returns: the number of BSSIDs in the previously seen BSSID list - **/ -guint32 -nm_setting_wireless_get_num_seen_bssids(NMSettingWireless *setting) -{ - NMSettingWirelessPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - - return priv->seen_bssids ? priv->seen_bssids->len : 0u; -} - -/** - * nm_setting_wireless_get_seen_bssid: - * @setting: the #NMSettingWireless - * @i: index of a BSSID in the previously seen BSSID list - * - * Returns: the BSSID at index @i - **/ -const char * -nm_setting_wireless_get_seen_bssid(NMSettingWireless *setting, guint32 i) -{ - NMSettingWirelessPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - - if (!priv->seen_bssids || i >= priv->seen_bssids->len) - return NULL; - - return priv->seen_bssids->pdata[i]; -} - -static GVariant * -_to_dbus_fcn_seen_bssids(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMSettingWirelessPrivate *priv; - - if (options && options->seen_bssids) { - return options->seen_bssids[0] ? g_variant_new_strv(options->seen_bssids, -1) : NULL; - } - - priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - - if (!priv->seen_bssids || priv->seen_bssids->len == 0) - return NULL; - - return g_variant_new_strv((const char *const *) priv->seen_bssids->pdata, - priv->seen_bssids->len); -} - -/** - * nm_setting_wireless_get_ap_isolation: - * @setting: the #NMSettingWireless - * - * Returns: the #NMSettingWireless:ap-isolation property of the setting - * - * Since: 1.28 - */ -NMTernary -nm_setting_wireless_get_ap_isolation(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NM_TERNARY_DEFAULT); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->ap_isolation; -} - -/*****************************************************************************/ - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - const char * valid_modes[] = {NM_SETTING_WIRELESS_MODE_INFRA, - NM_SETTING_WIRELESS_MODE_ADHOC, - NM_SETTING_WIRELESS_MODE_AP, - NM_SETTING_WIRELESS_MODE_MESH, - NULL}; - const char * valid_bands[] = {"a", "bg", NULL}; - guint i; - gsize length; - GError * local = NULL; - - if (!priv->ssid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_SSID); - return FALSE; - } - - length = g_bytes_get_size(priv->ssid); - if (length == 0 || length > 32) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("SSID length is out of range <1-32> bytes")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_SSID); - return FALSE; - } - - if (priv->mode && !g_strv_contains(valid_modes, priv->mode)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid Wi-Fi mode"), - priv->mode); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MODE); - return FALSE; - } - - if (priv->band && !g_strv_contains(valid_bands, priv->band)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid band"), - priv->band); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_BAND); - return FALSE; - } - - if (priv->channel && !priv->band) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("'%s' requires setting '%s' property"), - NM_SETTING_WIRELESS_CHANNEL, - NM_SETTING_WIRELESS_BAND); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_BAND); - return FALSE; - } - - if (priv->channel) { - if (!nm_utils_wifi_is_channel_valid(priv->channel, priv->band)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%d' is not a valid channel"), - priv->channel); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_CHANNEL); - return FALSE; - } - } - - if ((g_strcmp0(priv->mode, NM_SETTING_WIRELESS_MODE_MESH) == 0) - && !(priv->channel && priv->band)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("'%s' requires '%s' and '%s' property"), - priv->mode, - NM_SETTING_WIRELESS_BAND, - NM_SETTING_WIRELESS_CHANNEL); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MODE); - return FALSE; - } - - if (priv->bssid && !nm_utils_hwaddr_valid(priv->bssid, ETH_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_BSSID); - return FALSE; - } - - if (priv->device_mac_address && !nm_utils_hwaddr_valid(priv->device_mac_address, ETH_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MAC_ADDRESS); - return FALSE; - } - - if (priv->cloned_mac_address && !NM_CLONED_MAC_IS_SPECIAL(priv->cloned_mac_address) - && !nm_utils_hwaddr_valid(priv->cloned_mac_address, ETH_ALEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS); - return FALSE; - } - - /* generate-mac-address-mask only makes sense with cloned-mac-address "random" or - * "stable". Still, let's not be so strict about that and accept the value - * even if it is unused. */ - if (!_nm_utils_generate_mac_address_mask_parse(priv->generate_mac_address_mask, - NULL, - NULL, - NULL, - &local)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - local->message); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK); - g_error_free(local); - return FALSE; - } - - for (i = 0; i < priv->mac_address_blacklist->len; i++) { - const char *mac = g_array_index(priv->mac_address_blacklist, const char *, i); - - if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid MAC address"), - mac); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST); - return FALSE; - } - } - - if (priv->seen_bssids) { - for (i = 0; i < priv->seen_bssids->len; i++) { - const char *b; - - b = priv->seen_bssids->pdata[i]; - if (!nm_utils_hwaddr_valid(b, ETH_ALEN)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid MAC address"), - b); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_SEEN_BSSIDS); - return FALSE; - } - } - } - - if (!NM_IN_SET(priv->mac_address_randomization, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, - NM_SETTING_MAC_RANDOMIZATION_NEVER, - NM_SETTING_MAC_RANDOMIZATION_ALWAYS)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid value")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION); - return FALSE; - } - - if (NM_FLAGS_ANY(priv->wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS)) { - if (!nm_utils_is_power_of_two(priv->wowl)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Wake-on-WLAN mode 'default' and 'ignore' are exclusive flags")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_WAKE_ON_WLAN); - return FALSE; - } - } else if (NM_FLAGS_ANY(priv->wowl, ~NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Wake-on-WLAN trying to set unknown flag")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_WAKE_ON_WLAN); - return FALSE; - } - - if (priv->ap_isolation != NM_TERNARY_DEFAULT - && !nm_streq0(priv->mode, NM_SETTING_WIRELESS_MODE_AP)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("AP isolation can be set only in AP mode")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_AP_ISOLATION); - return FALSE; - } - - /* from here on, check for NM_SETTING_VERIFY_NORMALIZABLE conditions. */ - - if (priv->cloned_mac_address) { - if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS - && nm_streq(priv->cloned_mac_address, "random")) - goto mac_addr_rand_ok; - if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_NEVER - && nm_streq(priv->cloned_mac_address, "permanent")) - goto mac_addr_rand_ok; - if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) - goto mac_addr_rand_ok; - } else if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) - goto mac_addr_rand_ok; - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("conflicting value of mac-address-randomization and cloned-mac-address")); - g_prefix_error(error, - "%s.%s: ", - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS); - return NM_SETTING_VERIFY_NORMALIZABLE; -mac_addr_rand_ok: - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - if (nm_streq(sett_info->property_infos[property_idx].name, - NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) { - return !set_b - || nm_streq0(NM_SETTING_WIRELESS_GET_PRIVATE(set_a)->cloned_mac_address, - NM_SETTING_WIRELESS_GET_PRIVATE(set_b)->cloned_mac_address); - } - - return NM_SETTING_CLASS(nm_setting_wireless_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -static GVariant * -nm_setting_wireless_get_security(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - return NULL; - - if (!connection) - return NULL; - - if (!nm_connection_get_setting_wireless_security(connection)) - return NULL; - - return g_variant_new_string(NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); -} - -/** - * nm_setting_wireless_get_wake_on_wlan: - * @setting: the #NMSettingWireless - * - * Returns the Wake-on-WLAN options enabled for the connection - * - * Returns: the Wake-on-WLAN options - * - * Since: 1.12 - */ -NMSettingWirelessWakeOnWLan -nm_setting_wireless_get_wake_on_wlan(NMSettingWireless *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE); - - return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->wowl; -} - -static void -clear_blacklist_item(char **item_p) -{ - g_free(*item_p); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingWireless * setting = NM_SETTING_WIRELESS(object); - NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_SSID: - g_value_set_boxed(value, nm_setting_wireless_get_ssid(setting)); - break; - case PROP_MODE: - g_value_set_string(value, nm_setting_wireless_get_mode(setting)); - break; - case PROP_BAND: - g_value_set_string(value, nm_setting_wireless_get_band(setting)); - break; - case PROP_CHANNEL: - g_value_set_uint(value, nm_setting_wireless_get_channel(setting)); - break; - case PROP_BSSID: - g_value_set_string(value, nm_setting_wireless_get_bssid(setting)); - break; - case PROP_RATE: - g_value_set_uint(value, nm_setting_wireless_get_rate(setting)); - break; - case PROP_TX_POWER: - g_value_set_uint(value, nm_setting_wireless_get_tx_power(setting)); - break; - case PROP_MAC_ADDRESS: - g_value_set_string(value, nm_setting_wireless_get_mac_address(setting)); - break; - case PROP_CLONED_MAC_ADDRESS: - g_value_set_string(value, nm_setting_wireless_get_cloned_mac_address(setting)); - break; - case PROP_GENERATE_MAC_ADDRESS_MASK: - g_value_set_string(value, nm_setting_wireless_get_generate_mac_address_mask(setting)); - break; - case PROP_MAC_ADDRESS_BLACKLIST: - g_value_set_boxed(value, (char **) priv->mac_address_blacklist->data); - break; - case PROP_MTU: - g_value_set_uint(value, nm_setting_wireless_get_mtu(setting)); - break; - case PROP_SEEN_BSSIDS: - g_value_take_boxed(value, - priv->seen_bssids ? nm_utils_strv_dup((char **) priv->seen_bssids->pdata, - priv->seen_bssids->len, - TRUE) - : NULL); - break; - case PROP_HIDDEN: - g_value_set_boolean(value, nm_setting_wireless_get_hidden(setting)); - break; - case PROP_POWERSAVE: - g_value_set_uint(value, nm_setting_wireless_get_powersave(setting)); - break; - case PROP_MAC_ADDRESS_RANDOMIZATION: - g_value_set_uint(value, nm_setting_wireless_get_mac_address_randomization(setting)); - break; - case PROP_WAKE_ON_WLAN: - g_value_set_uint(value, nm_setting_wireless_get_wake_on_wlan(setting)); - break; - case PROP_AP_ISOLATION: - g_value_set_enum(value, priv->ap_isolation); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(object); - const char *const * blacklist; - const char * mac; - gboolean bool_val; - - switch (prop_id) { - case PROP_SSID: - if (priv->ssid) - g_bytes_unref(priv->ssid); - priv->ssid = g_value_dup_boxed(value); - break; - case PROP_MODE: - g_free(priv->mode); - priv->mode = g_value_dup_string(value); - break; - case PROP_BAND: - g_free(priv->band); - priv->band = g_value_dup_string(value); - break; - case PROP_CHANNEL: - priv->channel = g_value_get_uint(value); - break; - case PROP_BSSID: - g_free(priv->bssid); - priv->bssid = g_value_dup_string(value); - break; - case PROP_RATE: - priv->rate = g_value_get_uint(value); - break; - case PROP_TX_POWER: - priv->tx_power = g_value_get_uint(value); - break; - case PROP_MAC_ADDRESS: - g_free(priv->device_mac_address); - priv->device_mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); - break; - case PROP_CLONED_MAC_ADDRESS: - bool_val = !!priv->cloned_mac_address; - g_free(priv->cloned_mac_address); - priv->cloned_mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); - if (bool_val && !priv->cloned_mac_address) { - /* cloned-mac-address was set before but was now explicitly cleared. - * In this case, we also clear mac-address-randomization flag */ - if (priv->mac_address_randomization != NM_SETTING_MAC_RANDOMIZATION_DEFAULT) { - priv->mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_DEFAULT; - _notify(NM_SETTING_WIRELESS(object), PROP_MAC_ADDRESS_RANDOMIZATION); - } - } - break; - case PROP_GENERATE_MAC_ADDRESS_MASK: - g_free(priv->generate_mac_address_mask); - priv->generate_mac_address_mask = g_value_dup_string(value); - break; - case PROP_MAC_ADDRESS_BLACKLIST: - blacklist = g_value_get_boxed(value); - g_array_set_size(priv->mac_address_blacklist, 0); - if (blacklist && blacklist[0]) { - gsize i; - - for (i = 0; blacklist[i]; i++) { - mac = _nm_utils_hwaddr_canonical_or_invalid(blacklist[i], ETH_ALEN); - g_array_append_val(priv->mac_address_blacklist, mac); - } - } - break; - case PROP_MTU: - priv->mtu = g_value_get_uint(value); - break; - case PROP_SEEN_BSSIDS: - { - gs_unref_ptrarray GPtrArray *arr_old = NULL; - const char *const * strv; - - arr_old = g_steal_pointer(&priv->seen_bssids); - - strv = g_value_get_boxed(value); - if (strv && strv[0]) { - gsize i, l; - - l = NM_PTRARRAY_LEN(strv); - priv->seen_bssids = g_ptr_array_new_full(l, g_free); - for (i = 0; i < l; i++) - g_ptr_array_add(priv->seen_bssids, g_strdup(strv[i])); - } - break; - } - case PROP_HIDDEN: - priv->hidden = g_value_get_boolean(value); - break; - case PROP_POWERSAVE: - priv->powersave = g_value_get_uint(value); - break; - case PROP_MAC_ADDRESS_RANDOMIZATION: - priv->mac_address_randomization = g_value_get_uint(value); - break; - case PROP_WAKE_ON_WLAN: - priv->wowl = g_value_get_uint(value); - break; - case PROP_AP_ISOLATION: - priv->ap_isolation = g_value_get_enum(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_wireless_init(NMSettingWireless *setting) -{ - NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - - /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */ - priv->mac_address_blacklist = g_array_new(TRUE, FALSE, sizeof(char *)); - g_array_set_clear_func(priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item); - - priv->wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT; - priv->ap_isolation = NM_TERNARY_DEFAULT; -} - -/** - * nm_setting_wireless_new: - * - * Creates a new #NMSettingWireless object with default values. - * - * Returns: (transfer full): the new empty #NMSettingWireless object - **/ -NMSetting * -nm_setting_wireless_new(void) -{ - return g_object_new(NM_TYPE_SETTING_WIRELESS, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(object); - - g_free(priv->mode); - g_free(priv->band); - - if (priv->ssid) - g_bytes_unref(priv->ssid); - g_free(priv->bssid); - g_free(priv->device_mac_address); - g_free(priv->cloned_mac_address); - g_free(priv->generate_mac_address_mask); - g_array_unref(priv->mac_address_blacklist); - nm_clear_pointer(&priv->seen_bssids, g_ptr_array_unref); - - G_OBJECT_CLASS(nm_setting_wireless_parent_class)->finalize(object); -} - -static void -nm_setting_wireless_class_init(NMSettingWirelessClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - GArray * properties_override = _nm_sett_info_property_override_create_array(); - - g_type_class_add_private(klass, sizeof(NMSettingWirelessPrivate)); - - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->compare_property = compare_property; - - /** - * NMSettingWireless:ssid: - * - * SSID of the Wi-Fi network. Must be specified. - **/ - /* ---keyfile--- - * property: ssid - * format: string (or decimal-byte list - obsolete) - * description: SSID of Wi-Fi network. - * example: ssid=Quick Net - * ---end--- - * ---ifcfg-rh--- - * property: ssid - * variable: ESSID - * description: SSID of Wi-Fi network. - * example: ESSID="Quick Net" - * ---end--- - */ - obj_properties[PROP_SSID] = g_param_spec_boxed(NM_SETTING_WIRELESS_SSID, - "", - "", - G_TYPE_BYTES, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:mode: - * - * Wi-Fi network mode; one of "infrastructure", "mesh", "adhoc" or "ap". If blank, - * infrastructure is assumed. - **/ - /* ---ifcfg-rh--- - * property: mode - * variable: MODE - * values: Ad-Hoc, Managed (Auto) [case insensitive] - * description: Wi-Fi network mode. - * ---end--- - */ - obj_properties[PROP_MODE] = g_param_spec_string(NM_SETTING_WIRELESS_MODE, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:band: - * - * 802.11 frequency band of the network. One of "a" for 5GHz 802.11a or - * "bg" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network - * to the specific band, i.e. if "a" is specified, the device will not - * associate with the same network in the 2.4GHz band even if the network's - * settings are compatible. This setting depends on specific driver - * capability and may not work with all drivers. - **/ - /* ---ifcfg-rh--- - * property: band - * variable: BAND(+) - * values: a, bg - * description: BAND alone is honored, but CHANNEL overrides BAND since it - * implies a band. - * example: BAND=bg - * ---end--- - */ - obj_properties[PROP_BAND] = g_param_spec_string(NM_SETTING_WIRELESS_BAND, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:channel: - * - * Wireless channel to use for the Wi-Fi connection. The device will only - * join (or create for Ad-Hoc networks) a Wi-Fi network on the specified - * channel. Because channel numbers overlap between bands, this property - * also requires the "band" property to be set. - **/ - /* ---ifcfg-rh--- - * property: channel - * variable: CHANNEL - * description: Channel used for the Wi-Fi communication. - * Channels greater than 14 mean "a" band, otherwise the - * band is "bg". - * example: CHANNEL=6 - * ---end--- - */ - obj_properties[PROP_CHANNEL] = g_param_spec_uint(NM_SETTING_WIRELESS_CHANNEL, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:bssid: - * - * If specified, directs the device to only associate with the given access - * point. This capability is highly driver dependent and not supported by - * all devices. Note: this property does not control the BSSID used when - * creating an Ad-Hoc network and is unlikely to in the future. - **/ - /* ---ifcfg-rh--- - * property: bssid - * variable: BSSID(+) - * description: Restricts association only to a single AP. - * example: BSSID=00:1E:BD:64:83:21 - * ---end--- - */ - obj_properties[PROP_BSSID] = g_param_spec_string(NM_SETTING_WIRELESS_BSSID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_BSSID], - &nm_sett_info_propert_type_mac_address); - - /** - * NMSettingWireless:rate: - * - * If non-zero, directs the device to only use the specified bitrate for - * communication with the access point. Units are in Kb/s, ie 5500 = 5.5 - * Mbit/s. This property is highly driver dependent and not all devices - * support setting a static bitrate. - **/ - /* ---ifcfg-rh--- - * property: rate - * variable: (none) - * description: This property is not handled by ifcfg-rh plugin. - * ---end--- - */ - obj_properties[PROP_RATE] = g_param_spec_uint(NM_SETTING_WIRELESS_RATE, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:tx-power: - * - * If non-zero, directs the device to use the specified transmit power. - * Units are dBm. This property is highly driver dependent and not all - * devices support setting a static transmit power. - **/ - /* ---ifcfg-rh--- - * property: tx-power - * variable: (none) - * description: This property is not handled by ifcfg-rh plugin. - * ---end--- - */ - obj_properties[PROP_TX_POWER] = g_param_spec_uint( - NM_SETTING_WIRELESS_TX_POWER, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:mac-address: - * - * If specified, this connection will only apply to the Wi-Fi device whose - * permanent MAC address matches. This property does not change the MAC - * address of the device (i.e. MAC spoofing). - **/ - /* ---keyfile--- - * property: mac-address - * format: usual hex-digits-and-colons notation - * description: MAC address in traditional hex-digits-and-colons notation - * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) - * (e.g. 0;34;104;18;121;162). - * ---end--- - * ---ifcfg-rh--- - * property: mac-address - * variable: HWADDR - * description: Hardware address of the device in traditional hex-digits-and-colons - * notation (e.g. 00:22:68:14:5A:05). - * Note that for initscripts this is the current MAC address of the device as found - * during ifup. For NetworkManager this is the permanent MAC address. Or in case no - * permanent MAC address exists, the MAC address initially configured on the device. - * ---end--- - */ - obj_properties[PROP_MAC_ADDRESS] = - g_param_spec_string(NM_SETTING_WIRELESS_MAC_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_MAC_ADDRESS], - &nm_sett_info_propert_type_mac_address); - - /** - * NMSettingWireless:cloned-mac-address: - * - * If specified, request that the device use this MAC address instead. - * This is known as MAC cloning or spoofing. - * - * Beside explicitly specifying a MAC address, the special values "preserve", "permanent", - * "random" and "stable" are supported. - * "preserve" means not to touch the MAC address on activation. - * "permanent" means to use the permanent hardware address of the device. - * "random" creates a random MAC address on each connect. - * "stable" creates a hashed MAC address based on connection.stable-id and a - * machine dependent key. - * - * If unspecified, the value can be overwritten via global defaults, see manual - * of NetworkManager.conf. If still unspecified, it defaults to "preserve" - * (older versions of NetworkManager may use a different default value). - * - * On D-Bus, this field is expressed as "assigned-mac-address" or the deprecated - * "cloned-mac-address". - **/ - /* ---keyfile--- - * property: cloned-mac-address - * format: usual hex-digits-and-colons notation - * description: Cloned MAC address in traditional hex-digits-and-colons notation - * (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete) - * (e.g. 0;34;104;18;121;178). - * ---end--- - * ---ifcfg-rh--- - * property: cloned-mac-address - * variable: MACADDR - * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons - * notation (e.g. 00:22:68:14:5A:99). - * ---end--- - * ---dbus--- - * property: cloned-mac-address - * format: byte array - * description: This D-Bus field is deprecated in favor of "assigned-mac-address" - * which is more flexible and allows specifying special variants like "random". - * For libnm and nmcli, this field is called "cloned-mac-address". - * ---end--- - */ - obj_properties[PROP_CLONED_MAC_ADDRESS] = g_param_spec_string( - NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_CLONED_MAC_ADDRESS], - &nm_sett_info_propert_type_cloned_mac_address); - - /* ---dbus--- - * property: assigned-mac-address - * format: string - * description: The new field for the cloned MAC address. It can be either - * a hardware address in ASCII representation, or one of the special values - * "preserve", "permanent", "random" or "stable". - * This field replaces the deprecated "cloned-mac-address" on D-Bus, which - * can only contain explicit hardware addresses. Note that this property - * only exists in D-Bus API. libnm and nmcli continue to call this property - * "cloned-mac-address". - * ---end--- - */ - _nm_properties_override_dbus(properties_override, - "assigned-mac-address", - &nm_sett_info_propert_type_assigned_mac_address); - - /** - * NMSettingWireless:generate-mac-address-mask: - * - * With #NMSettingWireless:cloned-mac-address setting "random" or "stable", - * by default all bits of the MAC address are scrambled and a locally-administered, - * unicast MAC address is created. This property allows to specify that certain bits - * are fixed. Note that the least significant bit of the first MAC address will - * always be unset to create a unicast MAC address. - * - * If the property is %NULL, it is eligible to be overwritten by a default - * connection setting. If the value is still %NULL or an empty string, the - * default is to create a locally-administered, unicast MAC address. - * - * If the value contains one MAC address, this address is used as mask. The set - * bits of the mask are to be filled with the current MAC address of the device, - * while the unset bits are subject to randomization. - * Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address - * and only randomize the lower 3 bytes using the "random" or "stable" algorithm. - * - * If the value contains one additional MAC address after the mask, - * this address is used instead of the current MAC address to fill the bits - * that shall not be randomized. For example, a value of - * "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address - * to 68:F7:28, while the lower bits are randomized. A value of - * "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled - * globally-administered, burned-in MAC address. - * - * If the value contains more than one additional MAC addresses, one of - * them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" - * will create a fully scrambled MAC address, randomly locally or globally - * administered. - **/ - /* ---ifcfg-rh--- - * property: generate-mac-address-mask - * variable: GENERATE_MAC_ADDRESS_MASK(+) - * description: the MAC address mask for generating randomized and stable - * cloned-mac-address. - * ---end--- - */ - obj_properties[PROP_GENERATE_MAC_ADDRESS_MASK] = g_param_spec_string( - NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:mac-address-blacklist: - * - * A list of permanent MAC addresses of Wi-Fi devices to which this - * connection should never apply. Each MAC address should be given in the - * standard hex-digits-and-colons notation (eg "00:11:22:33:44:55"). - **/ - /* ---keyfile--- - * property: mac-address-blacklist - * format: list of MACs (separated with semicolons) - * description: MAC address blacklist. - * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78 - * ---end--- - * ---ifcfg-rh--- - * property: mac-address-blacklist - * variable: HWADDR_BLACKLIST(+) - * description: It denies usage of the connection for any device whose address - * is listed. - * ---end--- - */ - obj_properties[PROP_MAC_ADDRESS_BLACKLIST] = g_param_spec_boxed( - NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:seen-bssids: - * - * A list of BSSIDs (each BSSID formatted as a MAC address like - * "00:11:22:33:44:55") that have been detected as part of the Wi-Fi - * network. NetworkManager internally tracks previously seen BSSIDs. The - * property is only meant for reading and reflects the BSSID list of - * NetworkManager. The changes you make to this property will not be - * preserved. - **/ - /* ---ifcfg-rh--- - * property: seen-bssids - * variable: (none) - * description: This property is not handled by ifcfg-rh plugin. - * ---end--- - */ - obj_properties[PROP_SEEN_BSSIDS] = g_param_spec_boxed( - NM_SETTING_WIRELESS_SEEN_BSSIDS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj( - properties_override, - obj_properties[PROP_SEEN_BSSIDS], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING_ARRAY, - .to_dbus_fcn = _to_dbus_fcn_seen_bssids, )); - - /** - * NMSettingWireless:mtu: - * - * If non-zero, only transmit packets of the specified size or smaller, - * breaking larger packets up into multiple Ethernet frames. - **/ - /* ---ifcfg-rh--- - * property: mtu - * variable: MTU - * description: MTU of the wireless interface. - * ---end--- - */ - obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_WIRELESS_MTU, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:hidden: - * - * If %TRUE, indicates that the network is a non-broadcasting network that - * hides its SSID. This works both in infrastructure and AP mode. - * - * In infrastructure mode, various workarounds are used for a more reliable - * discovery of hidden networks, such as probe-scanning the SSID. However, - * these workarounds expose inherent insecurities with hidden SSID networks, - * and thus hidden SSID networks should be used with caution. - * - * In AP mode, the created network does not broadcast its SSID. - * - * Note that marking the network as hidden may be a privacy issue for you - * (in infrastructure mode) or client stations (in AP mode), as the explicit - * probe-scans are distinctly recognizable on the air. - * - **/ - /* ---ifcfg-rh--- - * property: hidden - * variable: SSID_HIDDEN(+) - * description: Whether the network hides the SSID. - * ---end--- - */ - obj_properties[PROP_HIDDEN] = g_param_spec_boolean(NM_SETTING_WIRELESS_HIDDEN, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:powersave: - * - * One of %NM_SETTING_WIRELESS_POWERSAVE_DISABLE (disable Wi-Fi power - * saving), %NM_SETTING_WIRELESS_POWERSAVE_ENABLE (enable Wi-Fi power - * saving), %NM_SETTING_WIRELESS_POWERSAVE_IGNORE (don't touch currently - * configure setting) or %NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (use the - * globally configured value). All other values are reserved. - * - * Since: 1.2 - **/ - /* ---ifcfg-rh--- - * property: powersave - * variable: POWERSAVE(+) - * values: default, ignore, enable, disable - * description: Enables or disables Wi-Fi power saving. - * example: POWERSAVE=enable - * ---end--- - */ - obj_properties[PROP_POWERSAVE] = g_param_spec_uint(NM_SETTING_WIRELESS_POWERSAVE, - "", - "", - 0, - G_MAXUINT32, - NM_SETTING_WIRELESS_POWERSAVE_DEFAULT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:mac-address-randomization: - * - * One of %NM_SETTING_MAC_RANDOMIZATION_DEFAULT (never randomize unless - * the user has set a global default to randomize and the supplicant - * supports randomization), %NM_SETTING_MAC_RANDOMIZATION_NEVER (never - * randomize the MAC address), or %NM_SETTING_MAC_RANDOMIZATION_ALWAYS - * (always randomize the MAC address). This property is deprecated for - * 'cloned-mac-address'. - * - * Since: 1.2 - * Deprecated: 1.4: Deprecated by NMSettingWireless:cloned-mac-address property. - **/ - /* ---ifcfg-rh--- - * property: mac-address-randomization - * variable: MAC_ADDRESS_RANDOMIZATION(+) - * values: default, never, always - * description: Enables or disables Wi-Fi MAC address randomization. - * example: MAC_ADDRESS_RANDOMIZATION=always - * ---end--- - */ - obj_properties[PROP_MAC_ADDRESS_RANDOMIZATION] = - g_param_spec_uint(NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, - "", - "", - 0, - G_MAXUINT32, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /* Compatibility for deprecated property */ - /* ---ifcfg-rh--- - * property: security - * variable: (none) - * description: This property is deprecated and not handled by ifcfg-rh-plugin. - * ---end--- - * ---dbus--- - * property: security - * description: This property is deprecated, but can be set to the value - * '802-11-wireless-security' when a wireless security setting is also - * present in the connection dictionary, for compatibility with very old - * NetworkManager daemons. - * ---end--- - */ - _nm_properties_override_dbus( - properties_override, - "security", - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING, - .to_dbus_fcn = nm_setting_wireless_get_security, )); - - /** - * NMSettingWireless:wake-on-wlan: - * - * The #NMSettingWirelessWakeOnWLan options to enable. Not all devices support all options. - * May be any combination of %NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY, - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT, - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC, - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE, - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST, - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE, - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE, - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP or the special values - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT (to use global settings) and - * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE (to disable management of Wake-on-LAN in - * NetworkManager). - * - * Since: 1.12 - **/ - obj_properties[PROP_WAKE_ON_WLAN] = - g_param_spec_uint(NM_SETTING_WIRELESS_WAKE_ON_WLAN, - "", - "", - 0, - G_MAXUINT32, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWireless:ap-isolation - * - * Configures AP isolation, which prevents communication between - * wireless devices connected to this AP. This property can be set - * to a value different from %NM_TERNARY_DEFAULT only when the - * interface is configured in AP mode. - * - * If set to %NM_TERNARY_TRUE, devices are not able to communicate - * with each other. This increases security because it protects - * devices against attacks from other clients in the network. At - * the same time, it prevents devices to access resources on the - * same wireless networks as file shares, printers, etc. - * - * If set to %NM_TERNARY_FALSE, devices can talk to each other. - * - * When set to %NM_TERNARY_DEFAULT, the global default is used; in - * case the global default is unspecified it is assumed to be - * %NM_TERNARY_FALSE. - * - * Since: 1.28 - **/ - /* ---ifcfg-rh--- - * property: ap-isolation - * variable: AP_ISOLATION(+) - * values: "yes", "no" - * default: missing variable means global default - * description: Whether AP isolation is enabled - * ---end--- - */ - obj_properties[PROP_AP_ISOLATION] = g_param_spec_enum( - NM_SETTING_WIRELESS_AP_ISOLATION, - "", - "", - NM_TYPE_TERNARY, - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_WIRELESS, - NULL, - properties_override); -} diff --git a/libnm-core/nm-setting-wireless.h b/libnm-core/nm-setting-wireless.h deleted file mode 100644 index f97e236ce7..0000000000 --- a/libnm-core/nm-setting-wireless.h +++ /dev/null @@ -1,216 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_WIRELESS_H__ -#define __NM_SETTING_WIRELESS_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" -#include "nm-setting-wireless-security.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_WIRELESS (nm_setting_wireless_get_type()) -#define NM_SETTING_WIRELESS(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIRELESS, NMSettingWireless)) -#define NM_SETTING_WIRELESS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessClass)) -#define NM_IS_SETTING_WIRELESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIRELESS)) -#define NM_IS_SETTING_WIRELESS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIRELESS)) -#define NM_SETTING_WIRELESS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessClass)) - -#define NM_SETTING_WIRELESS_SETTING_NAME "802-11-wireless" - -/** - * NMSettingWirelessWakeOnWLan: - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE: Wake-on-WLAN disabled - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY: Wake on any activity - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT: Wake on disconnect - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC: Wake on magic packet - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE: Wake on GTK rekey failure - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST: Wake on EAP identity request - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE: Wake on 4way handshake - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE: Wake on rfkill release - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL: Wake on all events. This does not - * include the exclusive flags @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT or - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE. - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT: Use the default value - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE: Don't change configured settings - * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS: Mask of flags that are - * incompatible with other flags - * - * Options for #NMSettingWireless:wake-on-wlan. Note that not all options - * are supported by all devices. - * - * Since: 1.12 - */ -/* clang-format off */ -typedef enum { /*< flags >*/ - NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE = 0, /*< skip >*/ - NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY = 0x2, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT = 0x4, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC = 0x8, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE = 0x10, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST = 0x20, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE = 0x40, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE = 0x80, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP = 0x100, - - NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL = 0x1FE, - - NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT = 0x1, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE = 0x8000, - - NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS = NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT | NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE, /*< skip >*/ -} NMSettingWirelessWakeOnWLan; -/* clang-format on */ - -#define NM_SETTING_WIRELESS_SSID "ssid" -#define NM_SETTING_WIRELESS_MODE "mode" -#define NM_SETTING_WIRELESS_BAND "band" -#define NM_SETTING_WIRELESS_CHANNEL "channel" -#define NM_SETTING_WIRELESS_BSSID "bssid" -#define NM_SETTING_WIRELESS_RATE "rate" -#define NM_SETTING_WIRELESS_TX_POWER "tx-power" -#define NM_SETTING_WIRELESS_MAC_ADDRESS "mac-address" -#define NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS "cloned-mac-address" -#define NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK "generate-mac-address-mask" -#define NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST "mac-address-blacklist" -#define NM_SETTING_WIRELESS_MTU "mtu" -#define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids" -#define NM_SETTING_WIRELESS_HIDDEN "hidden" -#define NM_SETTING_WIRELESS_POWERSAVE "powersave" -#define NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION "mac-address-randomization" -#define NM_SETTING_WIRELESS_WAKE_ON_WLAN "wake-on-wlan" -#define NM_SETTING_WIRELESS_AP_ISOLATION "ap-isolation" - -/** - * NM_SETTING_WIRELESS_MODE_ADHOC: - * - * Indicates Ad-Hoc mode where no access point is expected to be present. - */ -#define NM_SETTING_WIRELESS_MODE_ADHOC "adhoc" - -/** - * NM_SETTING_WIRELESS_MODE_AP: - * - * Indicates AP/master mode where the wireless device is started as an access - * point/hotspot. - */ -#define NM_SETTING_WIRELESS_MODE_AP "ap" - -/** - * NM_SETTING_WIRELESS_MODE_INFRA: - * - * Indicates infrastructure mode where an access point is expected to be present - * for this connection. - */ -#define NM_SETTING_WIRELESS_MODE_INFRA "infrastructure" - -/** - * NM_SETTING_WIRELESS_MODE_MESH: - * - * Indicates that the connection should create a mesh point. - * - * Since: 1.20 - */ -#define NM_SETTING_WIRELESS_MODE_MESH "mesh" - -/** - * NMSettingWirelessPowersave: - * @NM_SETTING_WIRELESS_POWERSAVE_DEFAULT: use the default value - * @NM_SETTING_WIRELESS_POWERSAVE_IGNORE: don't touch existing setting - * @NM_SETTING_WIRELESS_POWERSAVE_DISABLE: disable powersave - * @NM_SETTING_WIRELESS_POWERSAVE_ENABLE: enable powersave - * - * These flags indicate whether wireless powersave must be enabled. - **/ -typedef enum { - NM_SETTING_WIRELESS_POWERSAVE_DEFAULT = 0, - NM_SETTING_WIRELESS_POWERSAVE_IGNORE = 1, - NM_SETTING_WIRELESS_POWERSAVE_DISABLE = 2, - NM_SETTING_WIRELESS_POWERSAVE_ENABLE = 3, - _NM_SETTING_WIRELESS_POWERSAVE_NUM, /*< skip >*/ - NM_SETTING_WIRELESS_POWERSAVE_LAST = _NM_SETTING_WIRELESS_POWERSAVE_NUM - 1, /*< skip >*/ -} NMSettingWirelessPowersave; - -/** - * NMSettingWireless: - * - * Wi-Fi Settings - */ -struct _NMSettingWireless { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingWirelessClass; - -GType nm_setting_wireless_get_type(void); - -NMSetting *nm_setting_wireless_new(void); - -GBytes * nm_setting_wireless_get_ssid(NMSettingWireless *setting); -const char *nm_setting_wireless_get_mode(NMSettingWireless *setting); -const char *nm_setting_wireless_get_band(NMSettingWireless *setting); -guint32 nm_setting_wireless_get_channel(NMSettingWireless *setting); -const char *nm_setting_wireless_get_bssid(NMSettingWireless *setting); -guint32 nm_setting_wireless_get_rate(NMSettingWireless *setting); -guint32 nm_setting_wireless_get_tx_power(NMSettingWireless *setting); -const char *nm_setting_wireless_get_mac_address(NMSettingWireless *setting); -const char *nm_setting_wireless_get_cloned_mac_address(NMSettingWireless *setting); - -NM_AVAILABLE_IN_1_4 -const char *nm_setting_wireless_get_generate_mac_address_mask(NMSettingWireless *setting); - -const char *const *nm_setting_wireless_get_mac_address_blacklist(NMSettingWireless *setting); -guint32 nm_setting_wireless_get_num_mac_blacklist_items(NMSettingWireless *setting); -const char *nm_setting_wireless_get_mac_blacklist_item(NMSettingWireless *setting, guint32 idx); -gboolean nm_setting_wireless_add_mac_blacklist_item(NMSettingWireless *setting, const char *mac); -void nm_setting_wireless_remove_mac_blacklist_item(NMSettingWireless *setting, guint32 idx); -gboolean nm_setting_wireless_remove_mac_blacklist_item_by_value(NMSettingWireless *setting, - const char * mac); -void nm_setting_wireless_clear_mac_blacklist_items(NMSettingWireless *setting); - -guint32 nm_setting_wireless_get_mtu(NMSettingWireless *setting); -gboolean nm_setting_wireless_get_hidden(NMSettingWireless *setting); -NM_AVAILABLE_IN_1_2 -guint32 nm_setting_wireless_get_powersave(NMSettingWireless *setting); - -NM_AVAILABLE_IN_1_2 -NMSettingMacRandomization -nm_setting_wireless_get_mac_address_randomization(NMSettingWireless *setting); - -gboolean nm_setting_wireless_add_seen_bssid(NMSettingWireless *setting, const char *bssid); - -guint32 nm_setting_wireless_get_num_seen_bssids(NMSettingWireless *setting); -const char *nm_setting_wireless_get_seen_bssid(NMSettingWireless *setting, guint32 i); - -gboolean nm_setting_wireless_ap_security_compatible(NMSettingWireless * s_wireless, - NMSettingWirelessSecurity *s_wireless_sec, - NM80211ApFlags ap_flags, - NM80211ApSecurityFlags ap_wpa, - NM80211ApSecurityFlags ap_rsn, - NM80211Mode ap_mode); - -NM_AVAILABLE_IN_1_12 -NMSettingWirelessWakeOnWLan nm_setting_wireless_get_wake_on_wlan(NMSettingWireless *setting); - -NM_AVAILABLE_IN_1_28 -NMTernary nm_setting_wireless_get_ap_isolation(NMSettingWireless *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_WIRELESS_H__ */ diff --git a/libnm-core/nm-setting-wpan.c b/libnm-core/nm-setting-wpan.c deleted file mode 100644 index 13bd368469..0000000000 --- a/libnm-core/nm-setting-wpan.c +++ /dev/null @@ -1,393 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Lubomir Rintel - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-wpan.h" - -#include "nm-connection-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-private.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-wpan - * @short_description: Describes connection properties for IEEE 802.15.4 (WPAN) MAC - * - * The #NMSettingWpan object is a #NMSetting subclass that describes properties - * necessary for configuring IEEE 802.15.4 (WPAN) MAC layer devices. - **/ - -/* Ideally we'll be able to get these from a public header. */ -#ifndef IEEE802154_ADDR_LEN - #define IEEE802154_ADDR_LEN 8 -#endif - -#ifndef IEEE802154_MAX_PAGE - #define IEEE802154_MAX_PAGE 31 -#endif - -#ifndef IEEE802154_MAX_CHANNEL - #define IEEE802154_MAX_CHANNEL 26 -#endif - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_MAC_ADDRESS, - PROP_PAN_ID, - PROP_SHORT_ADDRESS, - PROP_PAGE, - PROP_CHANNEL, ); - -typedef struct { - char * mac_address; - guint16 pan_id; - guint16 short_address; - gint16 page; - gint16 channel; -} NMSettingWpanPrivate; - -/** - * NMSettingWpan: - * - * IEEE 802.15.4 (WPAN) MAC Settings - */ -struct _NMSettingWpan { - NMSetting parent; -}; - -struct _NMSettingWpanClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE(NMSettingWpan, nm_setting_wpan, NM_TYPE_SETTING) - -#define NM_SETTING_WPAN_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_WPAN, NMSettingWpanPrivate)) - -/*****************************************************************************/ - -/** - * nm_setting_wpan_get_mac_address: - * @setting: the #NMSettingWpan - * - * Returns: the #NMSettingWpan:mac-address property of the setting - * - * Since: 1.14 - **/ -const char * -nm_setting_wpan_get_mac_address(NMSettingWpan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), NULL); - - return NM_SETTING_WPAN_GET_PRIVATE(setting)->mac_address; -} - -/** - * nm_setting_wpan_get_pan_id: - * @setting: the #NMSettingWpan - * - * Returns: the #NMSettingWpan:pan-id property of the setting - * - * Since: 1.14 - **/ -guint16 -nm_setting_wpan_get_pan_id(NMSettingWpan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), G_MAXUINT16); - - return NM_SETTING_WPAN_GET_PRIVATE(setting)->pan_id; -} - -/** - * nm_setting_wpan_get_short_address: - * @setting: the #NMSettingWpan - * - * Returns: the #NMSettingWpan:short-address property of the setting - * - * Since: 1.14 - **/ -guint16 -nm_setting_wpan_get_short_address(NMSettingWpan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), G_MAXUINT16); - - return NM_SETTING_WPAN_GET_PRIVATE(setting)->short_address; -} - -/** - * nm_setting_wpan_get_page: - * @setting: the #NMSettingWpan - * - * Returns: the #NMSettingWpan:page property of the setting - * - * Since: 1.16 - **/ -gint16 -nm_setting_wpan_get_page(NMSettingWpan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), NM_SETTING_WPAN_PAGE_DEFAULT); - - return NM_SETTING_WPAN_GET_PRIVATE(setting)->page; -} - -/** - * nm_setting_wpan_get_channel: - * @setting: the #NMSettingWpan - * - * Returns: the #NMSettingWpan:channel property of the setting - * - * Since: 1.16 - **/ -gint16 -nm_setting_wpan_get_channel(NMSettingWpan *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), NM_SETTING_WPAN_CHANNEL_DEFAULT); - - return NM_SETTING_WPAN_GET_PRIVATE(setting)->channel; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE(setting); - - if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, IEEE802154_ADDR_LEN)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_MAC_ADDRESS); - return FALSE; - } - - if ((priv->page == NM_SETTING_WPAN_PAGE_DEFAULT) - != (priv->channel == NM_SETTING_WPAN_CHANNEL_DEFAULT)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("page must be defined along with a channel")); - g_prefix_error(error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_PAGE); - return FALSE; - } - - if (priv->page < NM_SETTING_WPAN_PAGE_DEFAULT || priv->page > IEEE802154_MAX_PAGE) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("page must be between %d and %d"), - NM_SETTING_WPAN_PAGE_DEFAULT, - IEEE802154_MAX_PAGE); - g_prefix_error(error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_PAGE); - return FALSE; - } - - if (priv->channel < NM_SETTING_WPAN_CHANNEL_DEFAULT || priv->channel > IEEE802154_MAX_CHANNEL) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("channel must not be between %d and %d"), - NM_SETTING_WPAN_CHANNEL_DEFAULT, - IEEE802154_MAX_CHANNEL); - g_prefix_error(error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_CHANNEL); - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingWpan *setting = NM_SETTING_WPAN(object); - - switch (prop_id) { - case PROP_MAC_ADDRESS: - g_value_set_string(value, nm_setting_wpan_get_mac_address(setting)); - break; - case PROP_PAN_ID: - g_value_set_uint(value, nm_setting_wpan_get_pan_id(setting)); - break; - case PROP_SHORT_ADDRESS: - g_value_set_uint(value, nm_setting_wpan_get_short_address(setting)); - break; - case PROP_PAGE: - g_value_set_int(value, nm_setting_wpan_get_page(setting)); - break; - case PROP_CHANNEL: - g_value_set_int(value, nm_setting_wpan_get_channel(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_MAC_ADDRESS: - g_free(priv->mac_address); - priv->mac_address = - _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), IEEE802154_ADDR_LEN); - break; - case PROP_PAN_ID: - priv->pan_id = g_value_get_uint(value); - break; - case PROP_SHORT_ADDRESS: - priv->short_address = g_value_get_uint(value); - break; - case PROP_PAGE: - priv->page = g_value_get_int(value); - break; - case PROP_CHANNEL: - priv->channel = g_value_get_int(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_wpan_init(NMSettingWpan *setting) -{ - NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE(setting); - - priv->pan_id = G_MAXUINT16; - priv->short_address = G_MAXUINT16; - priv->page = NM_SETTING_WPAN_PAGE_DEFAULT; - priv->channel = NM_SETTING_WPAN_CHANNEL_DEFAULT; -} - -/** - * nm_setting_wpan_new: - * - * Creates a new #NMSettingWpan object with default values. - * - * Returns: (transfer full): the new empty #NMSettingWpan object - * - * Since: 1.14 - **/ -NMSetting * -nm_setting_wpan_new(void) -{ - return g_object_new(NM_TYPE_SETTING_WPAN, NULL); -} - -static void -finalize(GObject *object) -{ - NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE(object); - - g_free(priv->mac_address); - - G_OBJECT_CLASS(nm_setting_wpan_parent_class)->finalize(object); -} - -static void -nm_setting_wpan_class_init(NMSettingWpanClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(setting_class, sizeof(NMSettingWpanPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - - /** - * NMSettingWpan:mac-address: - * - * If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) - * MAC layer device whose permanent MAC address matches. - **/ - /* ---keyfile--- - * property: mac-address - * format: usual hex-digits-and-colons notation - * description: MAC address in hex-digits-and-colons notation - * (e.g. 76:d8:9b:87:66:60:84:ee). - * ---end--- - */ - obj_properties[PROP_MAC_ADDRESS] = - g_param_spec_string(NM_SETTING_WPAN_MAC_ADDRESS, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWpan:pan-id: - * - * IEEE 802.15.4 Personal Area Network (PAN) identifier. - **/ - obj_properties[PROP_PAN_ID] = g_param_spec_uint(NM_SETTING_WPAN_PAN_ID, - "", - "", - 0, - G_MAXUINT16, - G_MAXUINT16, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWpan:short-address: - * - * Short IEEE 802.15.4 address to be used within a restricted environment. - **/ - obj_properties[PROP_SHORT_ADDRESS] = - g_param_spec_uint(NM_SETTING_WPAN_SHORT_ADDRESS, - "", - "", - 0, - G_MAXUINT16, - G_MAXUINT16, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWpan:page: - * - * IEEE 802.15.4 channel page. A positive integer or -1, meaning "do not - * set, use whatever the device is already set to". - * - * Since: 1.16 - **/ - obj_properties[PROP_PAGE] = g_param_spec_int(NM_SETTING_WPAN_PAGE, - "", - "", - G_MININT16, - G_MAXINT16, - NM_SETTING_WPAN_PAGE_DEFAULT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingWpan:channel: - * - * IEEE 802.15.4 channel. A positive integer or -1, meaning "do not - * set, use whatever the device is already set to". - * - * Since: 1.16 - **/ - obj_properties[PROP_CHANNEL] = g_param_spec_int(NM_SETTING_WPAN_CHANNEL, - "", - "", - G_MININT16, - G_MAXINT16, - NM_SETTING_WPAN_CHANNEL_DEFAULT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_WPAN); -} diff --git a/libnm-core/nm-setting-wpan.h b/libnm-core/nm-setting-wpan.h deleted file mode 100644 index 2a09d49bbd..0000000000 --- a/libnm-core/nm-setting-wpan.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Lubomir Rintel - */ - -#ifndef __NM_SETTING_WPAN_H__ -#define __NM_SETTING_WPAN_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-setting.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING_WPAN (nm_setting_wpan_get_type()) -#define NM_SETTING_WPAN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WPAN, NMSettingWpan)) -#define NM_SETTING_WPAN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WPANCONFIG, NMSettingWpanClass)) -#define NM_IS_SETTING_WPAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WPAN)) -#define NM_IS_SETTING_WPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WPAN)) -#define NM_SETTING_WPAN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WPAN, NMSettingWpanClass)) - -#define NM_SETTING_WPAN_SETTING_NAME "wpan" -#define NM_SETTING_WPAN_MAC_ADDRESS "mac-address" -#define NM_SETTING_WPAN_PAN_ID "pan-id" -#define NM_SETTING_WPAN_SHORT_ADDRESS "short-address" -#define NM_SETTING_WPAN_PAGE "page" -#define NM_SETTING_WPAN_CHANNEL "channel" - -#define NM_SETTING_WPAN_PAGE_DEFAULT -1 -#define NM_SETTING_WPAN_CHANNEL_DEFAULT -1 - -typedef struct _NMSettingWpanClass NMSettingWpanClass; - -NM_AVAILABLE_IN_1_14 -GType nm_setting_wpan_get_type(void); -NM_AVAILABLE_IN_1_14 -NMSetting *nm_setting_wpan_new(void); - -NM_AVAILABLE_IN_1_14 -const char *nm_setting_wpan_get_mac_address(NMSettingWpan *setting); -NM_AVAILABLE_IN_1_14 -guint16 nm_setting_wpan_get_pan_id(NMSettingWpan *setting); -NM_AVAILABLE_IN_1_14 -guint16 nm_setting_wpan_get_short_address(NMSettingWpan *setting); -NM_AVAILABLE_IN_1_16 -gint16 nm_setting_wpan_get_page(NMSettingWpan *setting); -NM_AVAILABLE_IN_1_16 -gint16 nm_setting_wpan_get_channel(NMSettingWpan *setting); - -G_END_DECLS - -#endif /* __NM_SETTING_WPAN_H__ */ diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c deleted file mode 100644 index 45644ac341..0000000000 --- a/libnm-core/nm-setting.c +++ /dev/null @@ -1,2834 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2011 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting.h" - -#include "nm-setting-private.h" -#include "nm-utils.h" -#include "nm-core-internal.h" -#include "nm-utils-private.h" -#include "nm-property-compare.h" - -/** - * SECTION:nm-setting - * @short_description: Describes related configuration information - * - * Each #NMSetting contains properties that describe configuration that applies - * to a specific network layer (like IPv4 or IPv6 configuration) or device type - * (like Ethernet, or Wi-Fi). A collection of individual settings together - * make up an #NMConnection. Each property is strongly typed and usually has - * a number of allowed values. See each #NMSetting subclass for a description - * of properties and allowed values. - */ - -/*****************************************************************************/ - -typedef struct { - GHashTable * hash; - const char **names; - GVariant ** values; -} GenData; - -typedef struct { - const char * name; - GType type; - NMSettingPriority priority; -} SettingInfo; - -NM_GOBJECT_PROPERTIES_DEFINE(NMSetting, PROP_NAME, ); - -typedef struct { - GenData *gendata; -} NMSettingPrivate; - -G_DEFINE_ABSTRACT_TYPE(NMSetting, nm_setting, G_TYPE_OBJECT) - -#define NM_SETTING_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING, NMSettingPrivate)) - -/*****************************************************************************/ - -static GenData *_gendata_hash(NMSetting *setting, gboolean create_if_necessary); - -/*****************************************************************************/ - -NMSettingPriority -_nm_setting_get_setting_priority(NMSetting *setting) -{ - const NMMetaSettingInfo *setting_info; - - g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_PRIORITY_INVALID); - - setting_info = NM_SETTING_GET_CLASS(setting)->setting_info; - return setting_info ? setting_info->setting_priority : NM_SETTING_PRIORITY_INVALID; -} - -NMSettingPriority -_nm_setting_get_base_type_priority(NMSetting *setting) -{ - g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_PRIORITY_INVALID); - - return nm_meta_setting_info_get_base_type_priority(NM_SETTING_GET_CLASS(setting)->setting_info, - G_OBJECT_TYPE(setting)); -} - -/** - * nm_setting_lookup_type: - * @name: a setting name - * - * Returns the #GType of the setting's class for a given setting name. - * - * Returns: the #GType of the setting's class, or %G_TYPE_INVALID if - * @name is not recognized. - **/ -GType -nm_setting_lookup_type(const char *name) -{ - const NMMetaSettingInfo *setting_info; - - g_return_val_if_fail(name, G_TYPE_INVALID); - - setting_info = nm_meta_setting_infos_by_name(name); - return setting_info ? setting_info->get_setting_gtype() : G_TYPE_INVALID; -} - -int -_nm_setting_compare_priority(gconstpointer a, gconstpointer b) -{ - NMSettingPriority prio_a, prio_b; - - prio_a = _nm_setting_get_setting_priority((NMSetting *) a); - prio_b = _nm_setting_get_setting_priority((NMSetting *) b); - - if (prio_a < prio_b) - return -1; - else if (prio_a == prio_b) - return 0; - return 1; -} - -/*****************************************************************************/ - -gboolean -_nm_setting_slave_type_is_valid(const char *slave_type, const char **out_port_type) -{ - const char *port_type = NULL; - gboolean found = TRUE; - - if (!slave_type) - found = FALSE; - else if (NM_IN_STRSET(slave_type, NM_SETTING_BOND_SETTING_NAME, NM_SETTING_VRF_SETTING_NAME)) { - /* pass */ - } else if (nm_streq(slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) - port_type = NM_SETTING_BRIDGE_PORT_SETTING_NAME; - else if (nm_streq(slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) - port_type = NM_SETTING_OVS_PORT_SETTING_NAME; - else if (nm_streq(slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) - port_type = NM_SETTING_OVS_INTERFACE_SETTING_NAME; - else if (nm_streq(slave_type, NM_SETTING_TEAM_SETTING_NAME)) - port_type = NM_SETTING_TEAM_PORT_SETTING_NAME; - else - found = FALSE; - - if (out_port_type) - *out_port_type = port_type; - return found; -} - -/*****************************************************************************/ - -static const NMSettInfoProperty * -_nm_sett_info_property_find_in_array(const NMSettInfoProperty *properties, - guint len, - const char * name) -{ - guint i; - - for (i = 0; i < len; i++) { - if (nm_streq(name, properties[i].name)) - return &properties[i]; - } - return NULL; -} - -static GVariant * -_gprop_to_dbus_fcn_bytes(const GValue *val) -{ - nm_assert(G_VALUE_HOLDS(val, G_TYPE_BYTES)); - return nm_utils_gbytes_to_variant_ay(g_value_get_boxed(val)); -} - -static GVariant * -_gprop_to_dbus_fcn_enum(const GValue *val) -{ - return g_variant_new_int32(g_value_get_enum(val)); -} - -static GVariant * -_gprop_to_dbus_fcn_flags(const GValue *val) -{ - return g_variant_new_uint32(g_value_get_flags(val)); -} - -gboolean -_nm_properties_override_assert(const NMSettInfoProperty *prop_info) -{ - nm_assert(prop_info); - nm_assert((!!prop_info->name) != (!!prop_info->param_spec)); - nm_assert(!prop_info->param_spec || !prop_info->name - || nm_streq0(prop_info->name, prop_info->param_spec->name)); - -#define _PROPERT_EXTRA(prop_info, member) \ - ({ \ - const NMSettInfoProperty *_prop_info = (prop_info); \ - \ - (_prop_info->property_type ? _prop_info->property_type->member : 0); \ - }) - - nm_assert(!_PROPERT_EXTRA(prop_info, gprop_from_dbus_fcn) - || _PROPERT_EXTRA(prop_info, dbus_type)); - nm_assert(!_PROPERT_EXTRA(prop_info, from_dbus_fcn) || _PROPERT_EXTRA(prop_info, dbus_type)); - nm_assert(!_PROPERT_EXTRA(prop_info, to_dbus_fcn) || _PROPERT_EXTRA(prop_info, dbus_type)); - - nm_assert(!_PROPERT_EXTRA(prop_info, to_dbus_fcn) - || !_PROPERT_EXTRA(prop_info, gprop_to_dbus_fcn)); - nm_assert(!_PROPERT_EXTRA(prop_info, from_dbus_fcn) - || !_PROPERT_EXTRA(prop_info, gprop_from_dbus_fcn)); - - nm_assert(!_PROPERT_EXTRA(prop_info, gprop_to_dbus_fcn) || prop_info->param_spec); - nm_assert(!_PROPERT_EXTRA(prop_info, gprop_from_dbus_fcn) || prop_info->param_spec); - -#undef _PROPERT_EXTRA - - return TRUE; -} - -static NMSettInfoSetting _sett_info_settings[_NM_META_SETTING_TYPE_NUM]; - -const NMSettInfoSetting * -nmtst_sett_info_settings(void) -{ - return _sett_info_settings; -} - -static int -_property_infos_sort_cmp_setting_connection(gconstpointer p_a, - gconstpointer p_b, - gpointer user_data) -{ - const NMSettInfoProperty *a = *((const NMSettInfoProperty *const *) p_a); - const NMSettInfoProperty *b = *((const NMSettInfoProperty *const *) p_b); - int c_name; - - c_name = strcmp(a->name, b->name); - nm_assert(c_name != 0); - -#define CMP_AND_RETURN(n_a, n_b, name) \ - G_STMT_START \ - { \ - gboolean _is = nm_streq(n_a, "" name); \ - \ - if (_is || nm_streq(n_b, "" name)) \ - return _is ? -1 : 1; \ - } \ - G_STMT_END - - /* for [connection], report first id, uuid, type in that order. */ - if (c_name != 0) { - CMP_AND_RETURN(a->name, b->name, NM_SETTING_CONNECTION_ID); - CMP_AND_RETURN(a->name, b->name, NM_SETTING_CONNECTION_UUID); - CMP_AND_RETURN(a->name, b->name, NM_SETTING_CONNECTION_TYPE); - } - -#undef CMP_AND_RETURN - - return c_name; -} - -static const NMSettInfoProperty *const * -_property_infos_sort(const NMSettInfoProperty *property_infos, - guint property_infos_len, - NMSettingClass * setting_class) -{ - const NMSettInfoProperty **arr; - guint i; - -#if NM_MORE_ASSERTS > 5 - /* assert that the property names are all unique and sorted. */ - for (i = 0; i < property_infos_len; i++) { - if (property_infos[i].param_spec) - nm_assert(nm_streq(property_infos[i].name, property_infos[i].param_spec->name)); - if (i > 0) - nm_assert(strcmp(property_infos[i - 1].name, property_infos[i].name) < 0); - } -#endif - - if (property_infos_len <= 1) - return NULL; - if (G_TYPE_FROM_CLASS(setting_class) != NM_TYPE_SETTING_CONNECTION) { - /* we only do something special for certain setting types. This one, - * has just alphabetical sorting. */ - return NULL; - } - - arr = g_new(const NMSettInfoProperty *, property_infos_len); - for (i = 0; i < property_infos_len; i++) - arr[i] = &property_infos[i]; - - g_qsort_with_data(arr, - property_infos_len, - sizeof(const NMSettInfoProperty *), - _property_infos_sort_cmp_setting_connection, - NULL); - return arr; -} - -void -_nm_setting_class_commit_full(NMSettingClass * setting_class, - NMMetaSettingType meta_type, - const NMSettInfoSettDetail *detail, - GArray * properties_override) -{ - NMSettInfoSetting *sett_info; - gs_free GParamSpec **property_specs = NULL; - guint i, n_property_specs, override_len; - - nm_assert(NM_IS_SETTING_CLASS(setting_class)); - nm_assert(!setting_class->setting_info); - - nm_assert(meta_type < G_N_ELEMENTS(_sett_info_settings)); - - sett_info = &_sett_info_settings[meta_type]; - - nm_assert(!sett_info->setting_class); - nm_assert(!sett_info->property_infos_len); - nm_assert(!sett_info->property_infos); - - if (!properties_override) { - override_len = 0; - properties_override = _nm_sett_info_property_override_create_array(); - } else - override_len = properties_override->len; - - property_specs = - g_object_class_list_properties(G_OBJECT_CLASS(setting_class), &n_property_specs); - - for (i = 0; i < properties_override->len; i++) { - NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); - - nm_assert((!!p->name) != (!!p->param_spec)); - - if (!p->name) { - nm_assert(p->param_spec); - p->name = p->param_spec->name; - } else - nm_assert(!p->param_spec); - } - -#if NM_MORE_ASSERTS > 10 - /* assert that properties_override is constructed consistently. */ - for (i = 0; i < override_len; i++) { - const NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); - gboolean found = FALSE; - guint j; - - nm_assert( - !_nm_sett_info_property_find_in_array((NMSettInfoProperty *) properties_override->data, - i, - p->name)); - for (j = 0; j < n_property_specs; j++) { - if (!nm_streq(property_specs[j]->name, p->name)) - continue; - nm_assert(!found); - found = TRUE; - nm_assert(p->param_spec == property_specs[j]); - } - nm_assert(found == (p->param_spec != NULL)); - } -#endif - - for (i = 0; i < n_property_specs; i++) { - const char * name = property_specs[i]->name; - NMSettInfoProperty *p; - - if (_nm_sett_info_property_find_in_array((NMSettInfoProperty *) properties_override->data, - override_len, - name)) - continue; - - g_array_set_size(properties_override, properties_override->len + 1); - p = &g_array_index(properties_override, NMSettInfoProperty, properties_override->len - 1); - memset(p, 0, sizeof(*p)); - p->name = name; - p->param_spec = property_specs[i]; - } - - for (i = 0; i < properties_override->len; i++) { - NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); - GType vtype; - - if (p->property_type) - goto has_property_type; - - nm_assert(p->param_spec); - - vtype = p->param_spec->value_type; - if (vtype == G_TYPE_BOOLEAN) - p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BOOLEAN); - else if (vtype == G_TYPE_UCHAR) - p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BYTE); - else if (vtype == G_TYPE_INT) - p->property_type = &nm_sett_info_propert_type_plain_i; - else if (vtype == G_TYPE_UINT) - p->property_type = &nm_sett_info_propert_type_plain_u; - else if (vtype == G_TYPE_INT64) - p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_INT64); - else if (vtype == G_TYPE_UINT64) - p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT64); - else if (vtype == G_TYPE_STRING) - p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING); - else if (vtype == G_TYPE_DOUBLE) - p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_DOUBLE); - else if (vtype == G_TYPE_STRV) - p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING_ARRAY); - else if (vtype == G_TYPE_BYTES) { - p->property_type = - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BYTESTRING, - .gprop_to_dbus_fcn = _gprop_to_dbus_fcn_bytes); - } else if (g_type_is_a(vtype, G_TYPE_ENUM)) { - p->property_type = - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_INT32, - .gprop_to_dbus_fcn = _gprop_to_dbus_fcn_enum); - } else if (g_type_is_a(vtype, G_TYPE_FLAGS)) { - p->property_type = - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT32, - .gprop_to_dbus_fcn = _gprop_to_dbus_fcn_flags); - } else - nm_assert_not_reached(); - -has_property_type: - nm_assert(p->property_type); - nm_assert(p->property_type->dbus_type); - nm_assert(g_variant_type_string_is_valid((const char *) p->property_type->dbus_type)); - } - - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMSettInfoProperty, name) == 0); - g_array_sort(properties_override, nm_strcmp_p); - - setting_class->setting_info = &nm_meta_setting_infos[meta_type]; - sett_info->setting_class = setting_class; - if (detail) - sett_info->detail = *detail; - nm_assert(properties_override->len > 0); - sett_info->property_infos_len = properties_override->len; - sett_info->property_infos = - nm_memdup(properties_override->data, sizeof(NMSettInfoProperty) * properties_override->len); - - sett_info->property_infos_sorted = _property_infos_sort(sett_info->property_infos, - sett_info->property_infos_len, - setting_class); - - g_array_free(properties_override, TRUE); -} - -const NMSettInfoProperty * -_nm_sett_info_setting_get_property_info(const NMSettInfoSetting *sett_info, - const char * property_name) -{ - const NMSettInfoProperty *property; - gssize idx; - - nm_assert(property_name); - - if (!sett_info) - return NULL; - - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMSettInfoProperty, name) == 0); - idx = nm_utils_array_find_binary_search(sett_info->property_infos, - sizeof(NMSettInfoProperty), - sett_info->property_infos_len, - &property_name, - nm_strcmp_p_with_data, - NULL); - - if (idx < 0) - return NULL; - - property = &sett_info->property_infos[idx]; - - nm_assert(idx == 0 || strcmp(property[-1].name, property[0].name) < 0); - nm_assert(idx == sett_info->property_infos_len - 1 - || strcmp(property[0].name, property[1].name) < 0); - - return property; -} - -const NMSettInfoSetting * -_nm_setting_class_get_sett_info(NMSettingClass *setting_class) -{ - const NMSettInfoSetting *sett_info; - - if (!NM_IS_SETTING_CLASS(setting_class) || !setting_class->setting_info) - return NULL; - - nm_assert(setting_class->setting_info->meta_type < G_N_ELEMENTS(_sett_info_settings)); - sett_info = &_sett_info_settings[setting_class->setting_info->meta_type]; - nm_assert(sett_info->setting_class == setting_class); - return sett_info; -} - -/*****************************************************************************/ - -void -_nm_setting_emit_property_changed(NMSetting *setting) -{ - /* Some settings have "properties" that are not implemented as GObject properties. - * - * For example: - * - * - gendata-base settings like NMSettingEthtool. Here properties are just - * GVariant values in the gendata hash. - * - * - NMSettingWireGuard's peers are not backed by a GObject property. Instead - * there is C-API to access/modify peers. - * - * We still want to emit property-changed notifications for such properties, - * in particular because NMConnection registers to such signals to re-emit - * it as NM_CONNECTION_CHANGED signal. In fact, there are unlikely any other - * uses of such a property-changed signal, because generally it doesn't make - * too much sense. - * - * So, instead of adding yet another (artificial) signal "setting-changed", - * hijack the "notify" signal and just notify about changes of the "name". - * Of course, the "name" doesn't really ever change, because it's tied to - * the GObject's type. - */ - _notify(setting, PROP_NAME); -} - -/*****************************************************************************/ - -gboolean -_nm_setting_use_legacy_property(NMSetting * setting, - GVariant * connection_dict, - const char *legacy_property, - const char *new_property) -{ - GVariant *setting_dict, *value; - - setting_dict = g_variant_lookup_value(connection_dict, - nm_setting_get_name(NM_SETTING(setting)), - NM_VARIANT_TYPE_SETTING); - g_return_val_if_fail(setting_dict != NULL, FALSE); - - /* If the new property isn't set, we have to use the legacy property. */ - value = g_variant_lookup_value(setting_dict, new_property, NULL); - if (!value) { - g_variant_unref(setting_dict); - return TRUE; - } - g_variant_unref(value); - - /* Otherwise, clients always prefer new properties sent from the daemon. */ - if (!_nm_utils_is_manager_process) { - g_variant_unref(setting_dict); - return FALSE; - } - - /* The daemon prefers the legacy property if it exists. */ - value = g_variant_lookup_value(setting_dict, legacy_property, NULL); - g_variant_unref(setting_dict); - - if (value) { - g_variant_unref(value); - return TRUE; - } else - return FALSE; -} - -/*****************************************************************************/ - -static GVariant * -property_to_dbus(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options, - gboolean ignore_flags, - gboolean ignore_default) -{ - const NMSettInfoProperty *property = &sett_info->property_infos[property_idx]; - GVariant * variant; - - nm_assert(property->property_type->dbus_type); - - if (!property->param_spec) { - if (!property->property_type->to_dbus_fcn) - return NULL; - } else if (!ignore_flags - && !NM_FLAGS_HAS(property->param_spec->flags, - NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS)) { - if (!NM_FLAGS_HAS(property->param_spec->flags, G_PARAM_WRITABLE)) - return NULL; - - if (NM_FLAGS_HAS(property->param_spec->flags, NM_SETTING_PARAM_LEGACY) - && !_nm_utils_is_manager_process) - return NULL; - - if (NM_FLAGS_HAS(property->param_spec->flags, NM_SETTING_PARAM_SECRET)) { - if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_NO_SECRETS)) - return NULL; - - if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED)) { - NMSettingSecretFlags f; - - /* see also _nm_connection_serialize_secrets() */ - if (!nm_setting_get_secret_flags(setting, property->param_spec->name, &f, NULL)) - return NULL; - if (!NM_FLAGS_HAS(f, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) - return NULL; - } - } else { - if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS)) - return NULL; - } - } - - if (property->property_type->to_dbus_fcn) { - variant = property->property_type - ->to_dbus_fcn(sett_info, property_idx, connection, setting, flags, options); - nm_g_variant_take_ref(variant); - } else { - nm_auto_unset_gvalue GValue prop_value = { - 0, - }; - - nm_assert(property->param_spec); - - g_value_init(&prop_value, property->param_spec->value_type); - - g_object_get_property(G_OBJECT(setting), property->param_spec->name, &prop_value); - - if (ignore_default && g_param_value_defaults(property->param_spec, &prop_value)) - return NULL; - - if (property->property_type->gprop_to_dbus_fcn) { - variant = property->property_type->gprop_to_dbus_fcn(&prop_value); - nm_g_variant_take_ref(variant); - } else - variant = g_dbus_gvalue_to_gvariant(&prop_value, property->property_type->dbus_type); - } - - nm_assert(!variant || !g_variant_is_floating(variant)); - nm_assert(!variant || g_variant_is_of_type(variant, property->property_type->dbus_type)); - - return variant; -} - -static gboolean -set_property_from_dbus(const NMSettInfoProperty *property, GVariant *src_value, GValue *dst_value) -{ - nm_assert(property->param_spec); - nm_assert(property->property_type->dbus_type); - - if (property->property_type->gprop_from_dbus_fcn) { - if (!g_variant_type_equal(g_variant_get_type(src_value), - property->property_type->dbus_type)) - return FALSE; - property->property_type->gprop_from_dbus_fcn(src_value, dst_value); - } else if (dst_value->g_type == G_TYPE_BYTES) { - if (!g_variant_is_of_type(src_value, G_VARIANT_TYPE_BYTESTRING)) - return FALSE; - - _nm_utils_bytes_from_dbus(src_value, dst_value); - } else { - GValue tmp = G_VALUE_INIT; - - g_dbus_gvariant_to_gvalue(src_value, &tmp); - if (G_VALUE_TYPE(&tmp) == G_VALUE_TYPE(dst_value)) - *dst_value = tmp; - else { - gboolean success; - - success = g_value_transform(&tmp, dst_value); - g_value_unset(&tmp); - if (!success) - return FALSE; - } - } - - return TRUE; -} - -/** - * _nm_setting_to_dbus: - * @setting: the #NMSetting - * @connection: the #NMConnection containing @setting - * @flags: hash flags, e.g. %NM_CONNECTION_SERIALIZE_ALL - * @options: the #NMConnectionSerializationOptions options to control - * what/how gets serialized. - * - * Converts the #NMSetting into a #GVariant of type #NM_VARIANT_TYPE_SETTING - * mapping each setting property name to a value describing that property, - * suitable for marshalling over D-Bus or serializing. - * - * Returns: (transfer none): a new floating #GVariant describing the setting's - * properties - **/ -GVariant * -_nm_setting_to_dbus(NMSetting * setting, - NMConnection * connection, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMSettingPrivate * priv; - GVariantBuilder builder; - const NMSettInfoSetting *sett_info; - guint n_properties, i; - const char *const * gendata_keys; - - g_return_val_if_fail(NM_IS_SETTING(setting), NULL); - - priv = NM_SETTING_GET_PRIVATE(setting); - - g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); - - n_properties = _nm_setting_option_get_all(setting, &gendata_keys, NULL); - for (i = 0; i < n_properties; i++) { - g_variant_builder_add(&builder, - "{sv}", - gendata_keys[i], - g_hash_table_lookup(priv->gendata->hash, gendata_keys[i])); - } - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); - for (i = 0; i < sett_info->property_infos_len; i++) { - gs_unref_variant GVariant *dbus_value = NULL; - - dbus_value = - property_to_dbus(sett_info, i, connection, setting, flags, options, FALSE, TRUE); - if (dbus_value) { - g_variant_builder_add(&builder, "{sv}", sett_info->property_infos[i].name, dbus_value); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * _nm_setting_new_from_dbus: - * @setting_type: the #NMSetting type which the hash contains properties for - * @setting_dict: the #GVariant containing an %NM_VARIANT_TYPE_SETTING dictionary - * mapping property names to values - * @connection_dict: the #GVariant containing an %NM_VARIANT_TYPE_CONNECTION - * dictionary mapping setting names to dictionaries. - * @parse_flags: flags to determine behavior during parsing. - * @error: location to store error, or %NULL - * - * Creates a new #NMSetting object and populates that object with the properties - * contained in @setting_dict, using each key as the property to set, and each - * value as the value to set that property to. Setting properties are strongly - * typed, thus the #GVariantType of the dict value must be correct. See the - * documentation on each #NMSetting object subclass for the correct property - * names and value types. - * - * Returns: a new #NMSetting object populated with the properties from the - * hash table, or %NULL if @setting_hash could not be deserialized. - **/ -NMSetting * -_nm_setting_new_from_dbus(GType setting_type, - GVariant * setting_dict, - GVariant * connection_dict, - NMSettingParseFlags parse_flags, - GError ** error) -{ - gs_unref_ptrarray GPtrArray *keys_keep_variant = NULL; - gs_unref_object NMSetting *setting = NULL; - gs_unref_hashtable GHashTable *keys = NULL; - - g_return_val_if_fail(G_TYPE_IS_INSTANTIATABLE(setting_type), NULL); - g_return_val_if_fail(g_variant_is_of_type(setting_dict, NM_VARIANT_TYPE_SETTING), NULL); - - nm_assert(!NM_FLAGS_ANY(parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL)); - nm_assert(!NM_FLAGS_ALL(parse_flags, - NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT)); - - /* connection_dict is not technically optional, but some tests in test-general - * don't bother with it in cases where they know it's not needed. - */ - if (connection_dict) - g_return_val_if_fail(g_variant_is_of_type(connection_dict, NM_VARIANT_TYPE_CONNECTION), - NULL); - - /* Build the setting object from the properties we know about; we assume - * that any propreties in @setting_dict that we don't know about can - * either be ignored or else has a backward-compatibility equivalent - * that we do know about. - */ - setting = g_object_new(setting_type, NULL); - - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - GVariantIter iter; - GVariant * entry, *entry_key; - const char * key; - - keys_keep_variant = g_ptr_array_new_with_free_func((GDestroyNotify) g_variant_unref); - keys = g_hash_table_new(nm_str_hash, g_str_equal); - - g_variant_iter_init(&iter, setting_dict); - while ((entry = g_variant_iter_next_value(&iter))) { - entry_key = g_variant_get_child_value(entry, 0); - g_ptr_array_add(keys_keep_variant, entry_key); - g_variant_unref(entry); - - key = g_variant_get_string(entry_key, NULL); - if (!g_hash_table_add(keys, (char *) key)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("duplicate property")); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), key); - return NULL; - } - } - } - - if (!NM_SETTING_GET_CLASS(setting) - ->init_from_dbus(setting, keys, setting_dict, connection_dict, parse_flags, error)) - return NULL; - - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT) && g_hash_table_size(keys) > 0) { - GHashTableIter iter; - const char * key; - - g_hash_table_iter_init(&iter, keys); - if (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("unknown property")); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), key); - return NULL; - } - } - - return g_steal_pointer(&setting); -} - -static gboolean -init_from_dbus(NMSetting * setting, - GHashTable * keys, - GVariant * setting_dict, - GVariant * connection_dict, - guint /* NMSettingParseFlags */ parse_flags, - GError ** error) -{ - const NMSettInfoSetting *sett_info; - - guint i; - - nm_assert(NM_IS_SETTING(setting)); - nm_assert(!NM_FLAGS_ANY(parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL)); - nm_assert(!NM_FLAGS_ALL(parse_flags, - NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT)); - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); - - if (sett_info->detail.gendata_info) { - GHashTable * hash; - GVariantIter iter; - char * key; - GVariant * val; - - hash = _gendata_hash(setting, TRUE)->hash; - - g_variant_iter_init(&iter, setting_dict); - while (g_variant_iter_next(&iter, "{sv}", &key, &val)) { - g_hash_table_insert(hash, key, val); - if (keys) - g_hash_table_remove(keys, key); - } - - _nm_setting_option_notify(setting, TRUE); - - /* Currently, only NMSettingEthtool supports gendata based options, and - * that one has no other properties (except "name"). That means, we - * consumed all options above. - * - * In the future it may be interesting to have settings that are both - * based on gendata and regular properties. In that case, we would need - * to handle this case differently. */ - nm_assert(nm_streq(G_OBJECT_TYPE_NAME(setting), "NMSettingEthtool")); - nm_assert(sett_info->property_infos_len == 1); - - return TRUE; - } - - for (i = 0; i < sett_info->property_infos_len; i++) { - const NMSettInfoProperty *property_info = &sett_info->property_infos[i]; - gs_unref_variant GVariant *value = NULL; - gs_free_error GError *local = NULL; - - if (property_info->param_spec && !(property_info->param_spec->flags & G_PARAM_WRITABLE)) - continue; - - value = g_variant_lookup_value(setting_dict, property_info->name, NULL); - - if (value && keys) - g_hash_table_remove(keys, property_info->name); - - if (value && property_info->property_type->from_dbus_fcn) { - if (!g_variant_type_equal(g_variant_get_type(value), - property_info->property_type->dbus_type)) { - /* for backward behavior, fail unless best-effort is chosen. */ - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) - continue; - g_set_error( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("can't set property of type '%s' from value of type '%s'"), - property_info->property_type->dbus_type - ? g_variant_type_peek_string(property_info->property_type->dbus_type) - : property_info->param_spec ? g_type_name(property_info->param_spec->value_type) - : "(unknown)", - g_variant_get_type_string(value)); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); - return FALSE; - } - - if (!property_info->property_type->from_dbus_fcn(setting, - connection_dict, - property_info->name, - value, - parse_flags, - &local)) { - if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) - continue; - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("failed to set property: %s"), - local->message); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); - return FALSE; - } - } else if (!value && property_info->property_type->missing_from_dbus_fcn) { - if (!property_info->property_type->missing_from_dbus_fcn(setting, - connection_dict, - property_info->name, - parse_flags, - &local)) { - if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) - continue; - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("failed to set property: %s"), - local->message); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); - return FALSE; - } - } else if (value && property_info->param_spec) { - nm_auto_unset_gvalue GValue object_value = G_VALUE_INIT; - - g_value_init(&object_value, property_info->param_spec->value_type); - if (!set_property_from_dbus(property_info, value, &object_value)) { - /* for backward behavior, fail unless best-effort is chosen. */ - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) - continue; - g_set_error( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("can't set property of type '%s' from value of type '%s'"), - property_info->property_type->dbus_type - ? g_variant_type_peek_string(property_info->property_type->dbus_type) - : (property_info->param_spec - ? g_type_name(property_info->param_spec->value_type) - : "(unknown)"), - g_variant_get_type_string(value)); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); - return FALSE; - } - - if (!nm_g_object_set_property(G_OBJECT(setting), - property_info->param_spec->name, - &object_value, - &local)) { - if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) - continue; - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("can not set property: %s"), - local->message); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); - return FALSE; - } - } - } - - return TRUE; -} - -/** - * nm_setting_get_dbus_property_type: - * @setting: an #NMSetting - * @property_name: the property of @setting to get the type of - * - * Gets the D-Bus marshalling type of a property. @property_name is a D-Bus - * property name, which may not necessarily be a #GObject property. - * - * Returns: the D-Bus marshalling type of @property on @setting. - */ -const GVariantType * -nm_setting_get_dbus_property_type(NMSetting *setting, const char *property_name) -{ - const NMSettInfoProperty *property; - - g_return_val_if_fail(NM_IS_SETTING(setting), NULL); - g_return_val_if_fail(property_name != NULL, NULL); - - property = _nm_setting_class_get_property_info(NM_SETTING_GET_CLASS(setting), property_name); - - g_return_val_if_fail(property != NULL, NULL); - - nm_assert(property->property_type); - nm_assert(g_variant_type_string_is_valid((const char *) property->property_type->dbus_type)); - - return property->property_type->dbus_type; -} - -gboolean -_nm_setting_get_property(NMSetting *setting, const char *property_name, GValue *value) -{ - const NMSettInfoSetting * sett_info; - const NMSettInfoProperty *property_info; - - g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); - g_return_val_if_fail(property_name, FALSE); - g_return_val_if_fail(value, FALSE); - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); - - if (sett_info->detail.gendata_info) { - GVariant *variant; - GenData * gendata = _gendata_hash(setting, FALSE); - - variant = gendata ? g_hash_table_lookup(gendata->hash, property_name) : NULL; - - if (!variant) { - g_value_unset(value); - return FALSE; - } - - g_value_init(value, G_TYPE_VARIANT); - g_value_set_variant(value, variant); - return TRUE; - } - - property_info = _nm_sett_info_setting_get_property_info(sett_info, property_name); - if (!property_info || !property_info->param_spec) { - g_value_unset(value); - return FALSE; - } - - g_value_init(value, property_info->param_spec->value_type); - g_object_get_property(G_OBJECT(setting), property_name, value); - return TRUE; -} - -static void -_gobject_copy_property(GObject *src, GObject *dst, const char *property_name, GType gtype) -{ - nm_auto_unset_gvalue GValue value = G_VALUE_INIT; - - nm_assert(G_IS_OBJECT(src)); - nm_assert(G_IS_OBJECT(dst)); - - g_value_init(&value, gtype); - g_object_get_property(src, property_name, &value); - g_object_set_property(dst, property_name, &value); -} - -static void -duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) -{ - if (sett_info->detail.gendata_info) { - GenData *gendata = _gendata_hash(src, FALSE); - - nm_assert(!_gendata_hash(dst, FALSE)); - - if (gendata && g_hash_table_size(gendata->hash) > 0) { - GHashTableIter iter; - GHashTable * h = _gendata_hash(dst, TRUE)->hash; - const char * key; - GVariant * val; - - g_hash_table_iter_init(&iter, gendata->hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - g_hash_table_insert(h, g_strdup(key), g_variant_ref(val)); - } - } - } - - if (sett_info->property_infos_len > 0) { - gboolean frozen = FALSE; - guint i; - - for (i = 0; i < sett_info->property_infos_len; i++) { - const NMSettInfoProperty *property_info = &sett_info->property_infos[i]; - - if (property_info->param_spec) { - if ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) - != G_PARAM_WRITABLE) - continue; - - if (!frozen) { - g_object_freeze_notify(G_OBJECT(dst)); - frozen = TRUE; - } - _gobject_copy_property(G_OBJECT(src), - G_OBJECT(dst), - property_info->param_spec->name, - G_PARAM_SPEC_VALUE_TYPE(property_info->param_spec)); - continue; - } - } - - if (frozen) - g_object_thaw_notify(G_OBJECT(dst)); - } -} - -/** - * nm_setting_duplicate: - * @setting: the #NMSetting to duplicate - * - * Duplicates a #NMSetting. - * - * Returns: (transfer full): a new #NMSetting containing the same properties and values as the - * source #NMSetting - **/ -NMSetting * -nm_setting_duplicate(NMSetting *setting) -{ - const NMSettInfoSetting *sett_info; - NMSettingClass * klass; - NMSetting * dst; - - g_return_val_if_fail(NM_IS_SETTING(setting), NULL); - - klass = NM_SETTING_GET_CLASS(setting); - nm_assert(NM_IS_SETTING_CLASS(klass)); - nm_assert(klass->duplicate_copy_properties); - - dst = g_object_new(G_TYPE_FROM_CLASS(klass), NULL); - - sett_info = _nm_setting_class_get_sett_info(klass); - nm_assert(sett_info); - - klass->duplicate_copy_properties(sett_info, setting, dst); - return dst; -} - -/** - * nm_setting_get_name: - * @setting: the #NMSetting - * - * Returns the type name of the #NMSetting object - * - * Returns: a string containing the type name of the #NMSetting object, - * like 'ppp' or 'wireless' or 'wired'. - **/ -const char * -nm_setting_get_name(NMSetting *setting) -{ - const NMMetaSettingInfo *setting_info; - - g_return_val_if_fail(NM_IS_SETTING(setting), NULL); - - setting_info = NM_SETTING_GET_CLASS(setting)->setting_info; - return setting_info ? setting_info->setting_name : NULL; -} - -/** - * nm_setting_verify: - * @setting: the #NMSetting to verify - * @connection: (allow-none): the #NMConnection that @setting came from, or - * %NULL if @setting is being verified in isolation. - * @error: location to store error, or %NULL - * - * Validates the setting. Each setting's properties have allowed values, and - * some are dependent on other values (hence the need for @connection). The - * returned #GError contains information about which property of the setting - * failed validation, and in what way that property failed validation. - * - * Returns: %TRUE if the setting is valid, %FALSE if it is not - **/ -gboolean -nm_setting_verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingVerifyResult result = _nm_setting_verify(setting, connection, error); - - if (result == NM_SETTING_VERIFY_NORMALIZABLE) - g_clear_error(error); - - return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE; -} - -NMSettingVerifyResult -_nm_setting_verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_VERIFY_ERROR); - g_return_val_if_fail(!connection || NM_IS_CONNECTION(connection), NM_SETTING_VERIFY_ERROR); - g_return_val_if_fail(!error || *error == NULL, NM_SETTING_VERIFY_ERROR); - - if (NM_SETTING_GET_CLASS(setting)->verify) - return NM_SETTING_GET_CLASS(setting)->verify(setting, connection, error); - - return NM_SETTING_VERIFY_SUCCESS; -} - -/** - * nm_setting_verify_secrets: - * @setting: the #NMSetting to verify secrets in - * @connection: (allow-none): the #NMConnection that @setting came from, or - * %NULL if @setting is being verified in isolation. - * @error: location to store error, or %NULL - * - * Verifies the secrets in the setting. - * The returned #GError contains information about which secret of the setting - * failed validation, and in what way that secret failed validation. - * The secret validation is done separately from main setting validation, because - * in some cases connection failure is not desired just for the secrets. - * - * Returns: %TRUE if the setting secrets are valid, %FALSE if they are not - * - * Since: 1.2 - **/ -gboolean -nm_setting_verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) -{ - g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_VERIFY_ERROR); - g_return_val_if_fail(!connection || NM_IS_CONNECTION(connection), NM_SETTING_VERIFY_ERROR); - g_return_val_if_fail(!error || *error == NULL, NM_SETTING_VERIFY_ERROR); - - if (NM_SETTING_GET_CLASS(setting)->verify_secrets) - return NM_SETTING_GET_CLASS(setting)->verify_secrets(setting, connection, error); - - return NM_SETTING_VERIFY_SUCCESS; -} - -gboolean -_nm_setting_verify_secret_string(const char *str, - const char *setting_name, - const char *property, - GError ** error) -{ - if (str && !*str) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, "%s.%s: ", setting_name, property); - return FALSE; - } - return TRUE; -} - -gboolean -_nm_setting_should_compare_secret_property(NMSetting * setting, - NMSetting * other, - const char * secret_name, - NMSettingCompareFlags flags) -{ - NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE; - NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - nm_assert(NM_IS_SETTING(setting)); - nm_assert(!other || G_OBJECT_TYPE(setting) == G_OBJECT_TYPE(other)); - - /* secret_name must be a valid secret for @setting. */ - nm_assert(nm_setting_get_secret_flags(setting, secret_name, NULL, NULL)); - - if (!NM_FLAGS_ANY(flags, - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS - | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) - return TRUE; - - nm_setting_get_secret_flags(setting, secret_name, &a_secret_flags, NULL); - if (other) { - if (!nm_setting_get_secret_flags(other, secret_name, &b_secret_flags, NULL)) { - /* secret-name may not be a valid secret for @other. That is fine, we ignore that - * and treat @b_secret_flags as NM_SETTING_SECRET_FLAG_NONE. - * - * This can happen with VPN secrets, where the caller knows that @secret_name - * is a secret for setting, but it may not be a secret for @other. Accept that. - * - * Mark @other as missing. */ - other = NULL; - } - } - - /* when @setting has the secret-flags that should be ignored, - * we skip the comparison if: - * - * - @other is not present, - * - @other does not have a secret named @secret_name - * - @other also has the secret flat to be ignored. - * - * This makes the check symmetric (aside the fact that @setting must - * have the secret while @other may not -- which is asymmetric). */ - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) - && NM_FLAGS_HAS(a_secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED) - && (!other || NM_FLAGS_HAS(b_secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED))) - return FALSE; - - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) - && NM_FLAGS_HAS(a_secret_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED) - && (!other || NM_FLAGS_HAS(b_secret_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED))) - return FALSE; - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - const NMSettInfoProperty *property_info = &sett_info->property_infos[property_idx]; - const GParamSpec * param_spec = property_info->param_spec; - - if (!param_spec) - return NM_TERNARY_DEFAULT; - - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_FUZZY) - && NM_FLAGS_ANY(param_spec->flags, NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)) - return NM_TERNARY_DEFAULT; - - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE) - && !NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_INFERRABLE)) - return NM_TERNARY_DEFAULT; - - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY) - && NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_REAPPLY_IMMEDIATELY)) - return NM_TERNARY_DEFAULT; - - if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) - && NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_SECRET)) - return NM_TERNARY_DEFAULT; - - if (nm_streq(param_spec->name, NM_SETTING_NAME)) - return NM_TERNARY_DEFAULT; - - if (NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_SECRET) - && !_nm_setting_should_compare_secret_property(set_a, set_b, param_spec->name, flags)) - return NM_TERNARY_DEFAULT; - - if (set_b) { - gs_unref_variant GVariant *value1 = NULL; - gs_unref_variant GVariant *value2 = NULL; - - value1 = property_to_dbus(sett_info, - property_idx, - con_a, - set_a, - NM_CONNECTION_SERIALIZE_ALL, - NULL, - TRUE, - TRUE); - value2 = property_to_dbus(sett_info, - property_idx, - con_b, - set_b, - NM_CONNECTION_SERIALIZE_ALL, - NULL, - TRUE, - TRUE); - if (nm_property_compare(value1, value2) != 0) - return NM_TERNARY_FALSE; - } - - return NM_TERNARY_TRUE; -} - -static NMTernary -_compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMTernary compare_result; - - nm_assert(sett_info); - nm_assert(NM_IS_SETTING_CLASS(sett_info->setting_class)); - nm_assert(property_idx < sett_info->property_infos_len); - nm_assert(NM_SETTING_GET_CLASS(set_a) == sett_info->setting_class); - nm_assert(!set_b || NM_SETTING_GET_CLASS(set_b) == sett_info->setting_class); - - compare_result = - NM_SETTING_GET_CLASS(set_a) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); - - nm_assert(NM_IN_SET(compare_result, NM_TERNARY_DEFAULT, NM_TERNARY_FALSE, NM_TERNARY_TRUE)); - - /* check that the inferable flag and the GObject property flag corresponds. */ - nm_assert(!NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE) - || !sett_info->property_infos[property_idx].param_spec - || NM_FLAGS_HAS(sett_info->property_infos[property_idx].param_spec->flags, - NM_SETTING_PARAM_INFERRABLE) - || compare_result == NM_TERNARY_DEFAULT); - -#if NM_MORE_ASSERTS > 10 - /* assert that compare_property() is symeric. */ - nm_assert(!set_b - || compare_result - == NM_SETTING_GET_CLASS(set_a)->compare_property(sett_info, - property_idx, - con_b, - set_b, - con_a, - set_a, - flags)); -#endif - - return compare_result; -} - -/** - * nm_setting_compare: - * @a: a #NMSetting - * @b: a second #NMSetting to compare with the first - * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT - * - * Compares two #NMSetting objects for similarity, with comparison behavior - * modified by a set of flags. See the documentation for #NMSettingCompareFlags - * for a description of each flag's behavior. - * - * Returns: %TRUE if the comparison succeeds, %FALSE if it does not - **/ -gboolean -nm_setting_compare(NMSetting *a, NMSetting *b, NMSettingCompareFlags flags) -{ - return _nm_setting_compare(NULL, a, NULL, b, flags); -} - -gboolean -_nm_setting_compare(NMConnection * con_a, - NMSetting * a, - NMConnection * con_b, - NMSetting * b, - NMSettingCompareFlags flags) -{ - const NMSettInfoSetting *sett_info; - guint i; - - g_return_val_if_fail(NM_IS_SETTING(a), FALSE); - g_return_val_if_fail(NM_IS_SETTING(b), FALSE); - - nm_assert(!con_a || NM_IS_CONNECTION(con_a)); - nm_assert(!con_b || NM_IS_CONNECTION(con_b)); - - /* First check that both have the same type */ - if (G_OBJECT_TYPE(a) != G_OBJECT_TYPE(b)) - return FALSE; - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(a)); - - if (sett_info->detail.gendata_info) { - GenData *a_gendata = _gendata_hash(a, FALSE); - GenData *b_gendata = _gendata_hash(b, FALSE); - - return nm_utils_hashtable_equal(a_gendata ? a_gendata->hash : NULL, - b_gendata ? b_gendata->hash : NULL, - TRUE, - g_variant_equal); - } - - for (i = 0; i < sett_info->property_infos_len; i++) { - if (_compare_property(sett_info, i, con_a, a, con_b, b, flags) == NM_TERNARY_FALSE) - return FALSE; - } - - return TRUE; -} - -static void -_setting_diff_add_result(GHashTable *results, const char *prop_name, NMSettingDiffResult r) -{ - void *p; - - if (r == NM_SETTING_DIFF_RESULT_UNKNOWN) - return; - - if (g_hash_table_lookup_extended(results, prop_name, NULL, &p)) { - if (!NM_FLAGS_ALL((guint) r, GPOINTER_TO_UINT(p))) - g_hash_table_insert(results, - g_strdup(prop_name), - GUINT_TO_POINTER(((guint) r) | GPOINTER_TO_UINT(p))); - } else - g_hash_table_insert(results, g_strdup(prop_name), GUINT_TO_POINTER(r)); -} - -/** - * nm_setting_diff: - * @a: a #NMSetting - * @b: a second #NMSetting to compare with the first - * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT - * @invert_results: this parameter is used internally by libnm and should - * be set to %FALSE. If %TRUE inverts the meaning of the #NMSettingDiffResult. - * @results: (inout) (transfer full) (element-type utf8 guint32): if the - * settings differ, on return a hash table mapping the differing keys to one or - * more %NMSettingDiffResult values OR-ed together. If the settings do not - * differ, any hash table passed in is unmodified. If no hash table is passed - * in and the settings differ, a new one is created and returned. - * - * Compares two #NMSetting objects for similarity, with comparison behavior - * modified by a set of flags. See the documentation for #NMSettingCompareFlags - * for a description of each flag's behavior. If the settings differ, the keys - * of each setting that differ from the other are added to @results, mapped to - * one or more #NMSettingDiffResult values. - * - * Returns: %TRUE if the settings contain the same values, %FALSE if they do not - **/ -gboolean -nm_setting_diff(NMSetting * a, - NMSetting * b, - NMSettingCompareFlags flags, - gboolean invert_results, - GHashTable ** results) -{ - return _nm_setting_diff(NULL, a, NULL, b, flags, invert_results, results); -} - -gboolean -_nm_setting_diff(NMConnection * con_a, - NMSetting * a, - NMConnection * con_b, - NMSetting * b, - NMSettingCompareFlags flags, - gboolean invert_results, - GHashTable ** results) -{ - const NMSettInfoSetting *sett_info; - guint i; - NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A; - NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B; - NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; - NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; - gboolean results_created = FALSE; - gboolean compared_any = FALSE; - gboolean diff_found = FALSE; - - g_return_val_if_fail(results != NULL, FALSE); - g_return_val_if_fail(NM_IS_SETTING(a), FALSE); - if (b) { - g_return_val_if_fail(NM_IS_SETTING(b), FALSE); - g_return_val_if_fail(G_OBJECT_TYPE(a) == G_OBJECT_TYPE(b), FALSE); - } - - nm_assert(!con_a || NM_IS_CONNECTION(con_a)); - nm_assert(!con_b || NM_IS_CONNECTION(con_b)); - - if ((flags - & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT - | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) - == (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT - | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) { - /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */ - flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT; - } - - /* If the caller is calling this function in a pattern like this to get - * complete diffs: - * - * nm_setting_diff (A, B, FALSE, &results); - * nm_setting_diff (B, A, TRUE, &results); - * - * and wants us to invert the results so that the second invocation comes - * out correctly, do that here. - */ - if (invert_results) { - a_result = NM_SETTING_DIFF_RESULT_IN_B; - b_result = NM_SETTING_DIFF_RESULT_IN_A; - a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; - b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; - } - - if (*results == NULL) { - *results = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, NULL); - results_created = TRUE; - } - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(a)); - - if (sett_info->detail.gendata_info) { - const char * key; - GVariant * val, *val2; - GHashTableIter iter; - GenData * a_gendata = _gendata_hash(a, FALSE); - GenData * b_gendata = b ? _gendata_hash(b, FALSE) : NULL; - - if (!a_gendata || !b_gendata) { - if (a_gendata || b_gendata) { - NMSettingDiffResult one_sided_result; - - one_sided_result = a_gendata ? a_result : b_result; - g_hash_table_iter_init(&iter, a_gendata ? a_gendata->hash : b_gendata->hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) { - diff_found = TRUE; - _setting_diff_add_result(*results, key, one_sided_result); - } - } - } else { - g_hash_table_iter_init(&iter, a_gendata->hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - val2 = g_hash_table_lookup(b_gendata->hash, key); - compared_any = TRUE; - if (!val2 || !g_variant_equal(val, val2)) { - diff_found = TRUE; - _setting_diff_add_result(*results, key, a_result); - } - } - g_hash_table_iter_init(&iter, b_gendata->hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - val2 = g_hash_table_lookup(a_gendata->hash, key); - compared_any = TRUE; - if (!val2 || !g_variant_equal(val, val2)) { - diff_found = TRUE; - _setting_diff_add_result(*results, key, b_result); - } - } - } - } else { - for (i = 0; i < sett_info->property_infos_len; i++) { - NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; - const NMSettInfoProperty *property_info; - NMTernary compare_result; - GParamSpec * prop_spec; - - compare_result = _compare_property(sett_info, i, con_a, a, con_b, b, flags); - if (compare_result == NM_TERNARY_DEFAULT) - continue; - - if (NM_FLAGS_ANY(flags, - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS - | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) - && b && compare_result == NM_TERNARY_FALSE) { - /* we have setting @b and the property is not the same. But we also are instructed - * to ignore secrets based on the flags. - * - * Note that compare_property() called with two settings will ignore secrets - * based on the flags, but it will do so if *both* settings have the flag we - * look for. So that is symmetric behavior and good. - * - * But for the purpose of diff(), we do a asymmetric comparison because and - * we want to skip testing the property if setting @a alone indicates to do - * so. - * - * We need to double-check whether the property should be ignored by - * looking at @a alone. */ - if (_compare_property(sett_info, i, con_a, a, NULL, NULL, flags) - == NM_TERNARY_DEFAULT) - continue; - } - - compared_any = TRUE; - - property_info = &sett_info->property_infos[i]; - prop_spec = property_info->param_spec; - - if (b) { - if (compare_result == NM_TERNARY_FALSE) { - if (prop_spec) { - gboolean a_is_default, b_is_default; - GValue value = G_VALUE_INIT; - - g_value_init(&value, prop_spec->value_type); - g_object_get_property(G_OBJECT(a), prop_spec->name, &value); - a_is_default = g_param_value_defaults(prop_spec, &value); - - g_value_reset(&value); - g_object_get_property(G_OBJECT(b), prop_spec->name, &value); - b_is_default = g_param_value_defaults(prop_spec, &value); - - g_value_unset(&value); - if (!NM_FLAGS_HAS(flags, - NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)) { - if (!a_is_default) - r |= a_result; - if (!b_is_default) - r |= b_result; - } else { - r |= a_result | b_result; - if (a_is_default) - r |= a_result_default; - if (b_is_default) - r |= b_result_default; - } - } else - r |= a_result | b_result; - } - } else if ((flags - & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT - | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) - == 0) - r = a_result; /* only in A */ - else { - if (prop_spec) { - GValue value = G_VALUE_INIT; - - g_value_init(&value, prop_spec->value_type); - g_object_get_property(G_OBJECT(a), prop_spec->name, &value); - if (!g_param_value_defaults(prop_spec, &value)) - r |= a_result; - else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) - r |= a_result | a_result_default; - - g_value_unset(&value); - } else - r |= a_result; - } - - if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { - diff_found = TRUE; - _setting_diff_add_result(*results, property_info->name, r); - } - } - } - - if (!compared_any && !b) { - /* special case: the setting has no properties, and the opposite - * setting @b is not given. The settings differ, and we signal that - * by returning an empty results hash. */ - diff_found = TRUE; - } - - if (diff_found) { - /* if there is a difference, we always return FALSE. It also means, we might - * have allocated a new @results hash, and return it to the caller. */ - return FALSE; - } else { - if (results_created) { - /* the allocated hash is unused. Clear it again. */ - g_hash_table_destroy(*results); - *results = NULL; - } else { - /* we found no diff, and return false. However, the input - * @result is returned unmodified. */ - } - return TRUE; - } -} - -static void -enumerate_values(const NMSettInfoProperty *property_info, - NMSetting * setting, - NMSettingValueIterFn func, - gpointer user_data) -{ - GValue value = G_VALUE_INIT; - - if (!property_info->param_spec) - return; - - g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(property_info->param_spec)); - g_object_get_property(G_OBJECT(setting), property_info->param_spec->name, &value); - func(setting, - property_info->param_spec->name, - &value, - property_info->param_spec->flags, - user_data); - g_value_unset(&value); -} - -/** - * nm_setting_enumerate_values: - * @setting: the #NMSetting - * @func: (scope call): user-supplied function called for each property of the setting - * @user_data: user data passed to @func at each invocation - * - * Iterates over each property of the #NMSetting object, calling the supplied - * user function for each property. - **/ -void -nm_setting_enumerate_values(NMSetting *setting, NMSettingValueIterFn func, gpointer user_data) -{ - const NMSettInfoSetting *sett_info; - guint i; - - g_return_if_fail(NM_IS_SETTING(setting)); - g_return_if_fail(func != NULL); - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); - - if (sett_info->detail.gendata_info) { - const char *const *names; - guint n_properties; - - /* the properties of this setting are not real GObject properties. - * Hence, this API makes little sense (or does it?). Still, call - * @func with each value. */ - n_properties = _nm_setting_option_get_all(setting, &names, NULL); - if (n_properties > 0) { - gs_strfreev char **keys = g_strdupv((char **) names); - GHashTable * h = _gendata_hash(setting, FALSE)->hash; - - for (i = 0; i < n_properties; i++) { - GValue value = G_VALUE_INIT; - GVariant *val = g_hash_table_lookup(h, keys[i]); - - if (!val) { - /* was deleted in the meantime? Skip */ - continue; - } - - g_value_init(&value, G_TYPE_VARIANT); - g_value_set_variant(&value, val); - /* call it will GParamFlags 0. It shall indicate that this - * is not a "real" GObject property. */ - func(setting, keys[i], &value, 0, user_data); - g_value_unset(&value); - } - } - return; - } - - for (i = 0; i < sett_info->property_infos_len; i++) { - NM_SETTING_GET_CLASS(setting)->enumerate_values( - _nm_sett_info_property_info_get_sorted(sett_info, i), - setting, - func, - user_data); - } -} - -static gboolean -aggregate(NMSetting *setting, int type_i, gpointer arg) -{ - NMConnectionAggregateType type = type_i; - const NMSettInfoSetting * sett_info; - guint i; - - nm_assert(NM_IN_SET(type, - NM_CONNECTION_AGGREGATE_ANY_SECRETS, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS)); - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); - for (i = 0; i < sett_info->property_infos_len; i++) { - const NMSettInfoProperty * property_info = &sett_info->property_infos[i]; - GParamSpec * prop_spec = property_info->param_spec; - nm_auto_unset_gvalue GValue value = G_VALUE_INIT; - NMSettingSecretFlags secret_flags; - - if (!prop_spec || !NM_FLAGS_HAS(prop_spec->flags, NM_SETTING_PARAM_SECRET)) { - nm_assert(!nm_setting_get_secret_flags(setting, property_info->name, NULL, NULL)); - continue; - } - - /* for the moment, all aggregate types only care about secrets. */ - nm_assert(nm_setting_get_secret_flags(setting, property_info->name, NULL, NULL)); - - switch (type) { - case NM_CONNECTION_AGGREGATE_ANY_SECRETS: - g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(prop_spec)); - g_object_get_property(G_OBJECT(setting), prop_spec->name, &value); - if (!g_param_value_defaults(prop_spec, &value)) { - *((gboolean *) arg) = TRUE; - return TRUE; - } - break; - - case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: - if (!nm_setting_get_secret_flags(setting, prop_spec->name, &secret_flags, NULL)) - nm_assert_not_reached(); - if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { - *((gboolean *) arg) = TRUE; - return TRUE; - } - break; - } - } - - return FALSE; -} - -/** - * _nm_setting_aggregate: - * @setting: the #NMSetting to aggregate. - * @type: the #NMConnectionAggregateType aggregate type. - * @arg: the in/out arguments for aggregation. They depend on @type. - * - * This is the implementation detail of _nm_connection_aggregate(). It - * makes no sense to call this function directly outside of _nm_connection_aggregate(). - * - * Returns: %TRUE if afterwards the aggregation is complete. That means, - * the only caller _nm_connection_aggregate() will not visit other settings - * after a setting returns %TRUE (indicating that there is nothing further - * to aggregate). Note that is very different from the boolean return - * argument of _nm_connection_aggregate(), which serves a different purpose. - */ -gboolean -_nm_setting_aggregate(NMSetting *setting, NMConnectionAggregateType type, gpointer arg) -{ - g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); - g_return_val_if_fail(arg, FALSE); - g_return_val_if_fail(NM_IN_SET(type, - NM_CONNECTION_AGGREGATE_ANY_SECRETS, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS), - FALSE); - - return NM_SETTING_GET_CLASS(setting)->aggregate(setting, type, arg); -} - -static gboolean -clear_secrets(const NMSettInfoSetting * sett_info, - guint property_idx, - NMSetting * setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data) -{ - NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; - GParamSpec * param_spec = sett_info->property_infos[property_idx].param_spec; - - if (!param_spec) - return FALSE; - - if (!NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_SECRET)) - return FALSE; - - if (func) { - if (!nm_setting_get_secret_flags(setting, param_spec->name, &flags, NULL)) - nm_assert_not_reached(); - if (!func(setting, param_spec->name, flags, user_data)) - return FALSE; - } else - nm_assert(nm_setting_get_secret_flags(setting, param_spec->name, NULL, NULL)); - - { - nm_auto_unset_gvalue GValue value = G_VALUE_INIT; - - g_value_init(&value, param_spec->value_type); - g_object_get_property(G_OBJECT(setting), param_spec->name, &value); - if (g_param_value_defaults(param_spec, &value)) - return FALSE; - - g_param_value_set_default(param_spec, &value); - g_object_set_property(G_OBJECT(setting), param_spec->name, &value); - } - - return TRUE; -} - -/** - * _nm_setting_clear_secrets: - * @setting: the #NMSetting - * @func: (scope call): function to be called to determine whether a - * specific secret should be cleared or not - * @user_data: caller-supplied data passed to @func - * - * Clears and frees secrets determined by @func. - * - * Returns: %TRUE if the setting changed at all - **/ -gboolean -_nm_setting_clear_secrets(NMSetting * setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data) -{ - const NMSettInfoSetting *sett_info; - gboolean changed = FALSE; - guint i; - gboolean (*my_clear_secrets)(const struct _NMSettInfoSetting *sett_info, - guint property_idx, - NMSetting * setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data); - - g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); - - my_clear_secrets = NM_SETTING_GET_CLASS(setting)->clear_secrets; - - sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); - for (i = 0; i < sett_info->property_infos_len; i++) { - changed |= my_clear_secrets(sett_info, i, setting, func, user_data); - } - return changed; -} - -/** - * _nm_setting_need_secrets: - * @setting: the #NMSetting - * - * Returns an array of property names for each secret which may be required - * to make a successful connection. The returned hints are only intended as a - * guide to what secrets may be required, because in some circumstances, there - * is no way to conclusively determine exactly which secrets are needed. - * - * Returns: (transfer container) (element-type utf8): a #GPtrArray containing - * the property names of secrets of the #NMSetting which may be required; the - * caller owns the array and must free it with g_ptr_array_free(), but must not - * free the elements. - **/ -GPtrArray * -_nm_setting_need_secrets(NMSetting *setting) -{ - GPtrArray *secrets = NULL; - - g_return_val_if_fail(NM_IS_SETTING(setting), NULL); - - if (NM_SETTING_GET_CLASS(setting)->need_secrets) - secrets = NM_SETTING_GET_CLASS(setting)->need_secrets(setting); - - return secrets; -} - -static int -update_one_secret(NMSetting *setting, const char *key, GVariant *value, GError **error) -{ - const NMSettInfoProperty *property; - GParamSpec * prop_spec; - GValue prop_value = { - 0, - }; - - property = _nm_setting_class_get_property_info(NM_SETTING_GET_CLASS(setting), key); - if (!property) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND, - _("secret not found")); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), key); - return NM_SETTING_UPDATE_SECRET_ERROR; - } - - /* Silently ignore non-secrets */ - prop_spec = property->param_spec; - if (!prop_spec || !(prop_spec->flags & NM_SETTING_PARAM_SECRET)) - return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - - if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING) && G_IS_PARAM_SPEC_STRING(prop_spec)) { - /* String is expected to be a common case. Handle it specially and check - * whether the value is already set. Otherwise, we just reset the - * property and assume the value got modified. - */ - char *v; - - g_object_get(G_OBJECT(setting), prop_spec->name, &v, NULL); - if (g_strcmp0(v, g_variant_get_string(value, NULL)) == 0) { - g_free(v); - return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - } - g_free(v); - } - - g_value_init(&prop_value, prop_spec->value_type); - set_property_from_dbus(property, value, &prop_value); - g_object_set_property(G_OBJECT(setting), prop_spec->name, &prop_value); - g_value_unset(&prop_value); - - return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; -} - -/** - * _nm_setting_update_secrets: - * @setting: the #NMSetting - * @secrets: a #GVariant of type #NM_VARIANT_TYPE_SETTING, mapping property - * names to secrets. - * @error: location to store error, or %NULL - * - * Update the setting's secrets, given a dictionary of secrets intended for that - * setting (deserialized from D-Bus for example). - * - * Returns: an #NMSettingUpdateSecretResult - **/ -NMSettingUpdateSecretResult -_nm_setting_update_secrets(NMSetting *setting, GVariant *secrets, GError **error) -{ - GVariantIter iter; - const char * secret_key; - GVariant * secret_value; - GError * tmp_error = NULL; - NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - - g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_UPDATE_SECRET_ERROR); - g_return_val_if_fail(g_variant_is_of_type(secrets, NM_VARIANT_TYPE_SETTING), - NM_SETTING_UPDATE_SECRET_ERROR); - if (error) - g_return_val_if_fail(*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR); - - g_variant_iter_init(&iter, secrets); - while (g_variant_iter_next(&iter, "{&sv}", &secret_key, &secret_value)) { - int success; - - success = NM_SETTING_GET_CLASS(setting)->update_one_secret(setting, - secret_key, - secret_value, - &tmp_error); - nm_assert(!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error))); - - g_variant_unref(secret_value); - - if (success == NM_SETTING_UPDATE_SECRET_ERROR) { - g_propagate_error(error, tmp_error); - return NM_SETTING_UPDATE_SECRET_ERROR; - } - - if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) - result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; - } - - return result; -} - -static void -for_each_secret(NMSetting * setting, - const char * secret_name, - GVariant * val, - gboolean remove_non_secrets, - _NMConnectionForEachSecretFunc callback, - gpointer callback_data, - GVariantBuilder * setting_builder) -{ - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - if (!nm_setting_get_secret_flags(setting, secret_name, &secret_flags, NULL)) { - if (!remove_non_secrets) - g_variant_builder_add(setting_builder, "{sv}", secret_name, val); - return; - } - if (callback(secret_flags, callback_data)) - g_variant_builder_add(setting_builder, "{sv}", secret_name, val); -} - -static void -_set_error_secret_property_not_found(GError **error, NMSetting *setting, const char *secret_name) -{ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND, - _("not a secret property")); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), secret_name); -} - -gboolean -_nm_setting_property_is_regular_secret(NMSetting *setting, const char *secret_name) -{ - const NMSettInfoProperty *property; - - nm_assert(NM_IS_SETTING(setting)); - nm_assert(secret_name); - - property = _nm_setting_class_get_property_info(NM_SETTING_GET_CLASS(setting), secret_name); - return property && property->param_spec - && NM_FLAGS_HAS(property->param_spec->flags, NM_SETTING_PARAM_SECRET); -} - -gboolean -_nm_setting_property_is_regular_secret_flags(NMSetting *setting, const char *secret_flags_name) -{ - const NMSettInfoProperty *property; - - nm_assert(NM_IS_SETTING(setting)); - nm_assert(secret_flags_name); - - property = - _nm_setting_class_get_property_info(NM_SETTING_GET_CLASS(setting), secret_flags_name); - return property && property->param_spec - && !NM_FLAGS_HAS(property->param_spec->flags, NM_SETTING_PARAM_SECRET) - && G_PARAM_SPEC_VALUE_TYPE(property->param_spec) == NM_TYPE_SETTING_SECRET_FLAGS; -} - -static gboolean -get_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags *out_flags, - GError ** error) -{ - gs_free char * secret_flags_name_free = NULL; - const char * secret_flags_name; - NMSettingSecretFlags flags; - - if (!_nm_setting_property_is_regular_secret(setting, secret_name)) { - _set_error_secret_property_not_found(error, setting, secret_name); - NM_SET_OUT(out_flags, NM_SETTING_SECRET_FLAG_NONE); - return FALSE; - } - - secret_flags_name = nm_construct_name_a("%s-flags", secret_name, &secret_flags_name_free); - - nm_assert(_nm_setting_property_is_regular_secret_flags(setting, secret_flags_name)); - - g_object_get(G_OBJECT(setting), secret_flags_name, &flags, NULL); - NM_SET_OUT(out_flags, flags); - return TRUE; -} - -/** - * nm_setting_get_secret_flags: - * @setting: the #NMSetting - * @secret_name: the secret key name to get flags for - * @out_flags: on success, the #NMSettingSecretFlags for the secret - * @error: location to store error, or %NULL - * - * For a given secret, retrieves the #NMSettingSecretFlags describing how to - * handle that secret. - * - * Returns: %TRUE on success (if the given secret name was a valid property of - * this setting, and if that property is secret), %FALSE if not - **/ -gboolean -nm_setting_get_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags *out_flags, - GError ** error) -{ - g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); - g_return_val_if_fail(secret_name != NULL, FALSE); - - return NM_SETTING_GET_CLASS(setting)->get_secret_flags(setting, secret_name, out_flags, error); -} - -static gboolean -set_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags flags, - GError ** error) -{ - gs_free char *secret_flags_name_free = NULL; - const char * secret_flags_name; - - if (!_nm_setting_property_is_regular_secret(setting, secret_name)) { - _set_error_secret_property_not_found(error, setting, secret_name); - return FALSE; - } - - secret_flags_name = nm_construct_name_a("%s-flags", secret_name, &secret_flags_name_free); - - nm_assert(_nm_setting_property_is_regular_secret_flags(setting, secret_flags_name)); - - if (!nm_g_object_set_property_flags(G_OBJECT(setting), - secret_flags_name, - NM_TYPE_SETTING_SECRET_FLAGS, - flags, - error)) - g_return_val_if_reached(FALSE); - return TRUE; -} - -/** - * nm_setting_set_secret_flags: - * @setting: the #NMSetting - * @secret_name: the secret key name to set flags for - * @flags: the #NMSettingSecretFlags for the secret - * @error: location to store error, or %NULL - * - * For a given secret, stores the #NMSettingSecretFlags describing how to - * handle that secret. - * - * Returns: %TRUE on success (if the given secret name was a valid property of - * this setting, and if that property is secret), %FALSE if not - **/ -gboolean -nm_setting_set_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags flags, - GError ** error) -{ - g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); - g_return_val_if_fail(secret_name != NULL, FALSE); - g_return_val_if_fail(_nm_setting_secret_flags_valid(flags), FALSE); - - return NM_SETTING_GET_CLASS(setting)->set_secret_flags(setting, secret_name, flags, error); -} - -/** - * nm_setting_to_string: - * @setting: the #NMSetting - * - * Convert the setting (including secrets!) into a string. For debugging - * purposes ONLY, should NOT be used for serialization of the setting, - * or machine-parsed in any way. The output format is not guaranteed to - * be stable and may change at any time. - * - * Returns: an allocated string containing a textual representation of the - * setting's properties and values, which the caller should - * free with g_free() - **/ -char * -nm_setting_to_string(NMSetting *setting) -{ - GString * string; - gs_unref_variant GVariant *variant = NULL; - GVariant * child; - GVariantIter iter; - - string = g_string_new(nm_setting_get_name(setting)); - g_string_append_c(string, '\n'); - - variant = _nm_setting_to_dbus(setting, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); - - g_variant_iter_init(&iter, variant); - while ((child = g_variant_iter_next_value(&iter))) { - gs_free char * name = NULL; - gs_free char * value_str = NULL; - gs_unref_variant GVariant *value = NULL; - - g_variant_get(child, "{sv}", &name, &value); - value_str = g_variant_print(value, FALSE); - - g_string_append_printf(string, "\t%s : %s\n", name, value_str); - } - - return g_string_free(string, FALSE); -} - -static GVariant * -_nm_setting_get_deprecated_virtual_interface_name(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMSettingConnection *s_con; - - if (!connection) - return NULL; - - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) - return NULL; - - if (nm_setting_connection_get_interface_name(s_con)) - return g_variant_new_string(nm_setting_connection_get_interface_name(s_con)); - else - return NULL; -} - -const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_interface_name = { - .dbus_type = G_VARIANT_TYPE_STRING, - .to_dbus_fcn = _nm_setting_get_deprecated_virtual_interface_name, -}; - -const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_i = { - .dbus_type = G_VARIANT_TYPE_INT32, - /* No functions set. This property type is to silently ignore the value on D-Bus. */ -}; - -const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_u = { - .dbus_type = G_VARIANT_TYPE_UINT32, - /* No functions set. This property type is to silently ignore the value on D-Bus. */ -}; - -const NMSettInfoPropertType nm_sett_info_propert_type_plain_i = { - .dbus_type = G_VARIANT_TYPE_INT32, -}; - -const NMSettInfoPropertType nm_sett_info_propert_type_plain_u = { - .dbus_type = G_VARIANT_TYPE_UINT32, -}; - -/*****************************************************************************/ - -static GenData * -_gendata_hash(NMSetting *setting, gboolean create_if_necessary) -{ - NMSettingPrivate *priv; - - nm_assert(NM_IS_SETTING(setting)); - - priv = NM_SETTING_GET_PRIVATE(setting); - - if (G_UNLIKELY(!priv->gendata)) { - if (!create_if_necessary) - return NULL; - priv->gendata = g_slice_new(GenData); - priv->gendata->hash = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref); - priv->gendata->names = NULL; - priv->gendata->values = NULL; - } - - return priv->gendata; -} - -GHashTable * -_nm_setting_option_hash(NMSetting *setting, gboolean create_if_necessary) -{ - GenData *gendata; - - gendata = _gendata_hash(setting, create_if_necessary); - return gendata ? gendata->hash : NULL; -} - -void -_nm_setting_option_notify(NMSetting *setting, gboolean names_changed) -{ - GenData *gendata; - - gendata = _gendata_hash(setting, FALSE); - if (!gendata) - goto out; - - nm_clear_g_free(&gendata->values); - - if (names_changed) { - /* if only the values changed, it's sufficient to invalidate the - * values cache. Otherwise, the names cache must be invalidated too. */ - nm_clear_g_free(&gendata->names); - } - - /* Note, currently there is no way to notify the subclass when gendata changed. - * gendata is only changed in two situations: - * 1) from within NMSetting itself, for example when creating a NMSetting instance - * from keyfile or a D-Bus GVariant. - * 2) actively from the subclass itself - * For 2), we don't need the notification, because the subclass knows that something - * changed. - * For 1), we currently don't need the notification either, because all that the subclass - * currently would do, is emit a g_object_notify() signal. However, 1) only happens when - * the setting instance is newly created, at that point, nobody listens to the signal. - * - * If we ever need it, then we would need to call a virtual function to notify the subclass - * that gendata changed. */ - -out: - _nm_setting_emit_property_changed(setting); -} - -guint -_nm_setting_option_get_all(NMSetting * setting, - const char *const **out_names, - GVariant *const ** out_values) -{ - GenData * gendata; - GHashTable *hash; - guint i, len; - - nm_assert(NM_IS_SETTING(setting)); - - gendata = _gendata_hash(setting, FALSE); - if (!gendata) - goto out_zero; - - hash = gendata->hash; - len = g_hash_table_size(hash); - if (len == 0) - goto out_zero; - - if (!out_names && !out_values) - return len; - - if (G_UNLIKELY(!gendata->names)) { - gendata->names = nm_utils_strdict_get_keys(hash, TRUE, NULL); - } - - if (out_values) { - if (G_UNLIKELY(!gendata->values)) { - gendata->values = g_new(GVariant *, len + 1); - for (i = 0; i < len; i++) - gendata->values[i] = g_hash_table_lookup(hash, gendata->names[i]); - gendata->values[i] = NULL; - } - *out_values = gendata->values; - } - - NM_SET_OUT(out_names, (const char *const *) gendata->names); - return len; - -out_zero: - NM_SET_OUT(out_names, NULL); - NM_SET_OUT(out_values, NULL); - return 0; -} - -/** - * nm_setting_option_get_all_names: - * @setting: the #NMSetting - * @out_len: (allow-none) (out): - * - * Gives the name of all set options. - * - * Returns: (array length=out_len zero-terminated=1) (transfer none): - * A %NULL terminated array of key names. If no names are present, this returns - * %NULL. The returned array and the names are owned by %NMSetting and might be invalidated - * by the next operation. - * - * Since: 1.26 - **/ -const char *const * -nm_setting_option_get_all_names(NMSetting *setting, guint *out_len) -{ - const char *const *names; - guint len; - - g_return_val_if_fail(NM_IS_SETTING(setting), NULL); - - len = _nm_setting_option_get_all(setting, &names, NULL); - NM_SET_OUT(out_len, len); - return names; -} - -gboolean -_nm_setting_option_clear(NMSetting *setting, const char *optname) -{ - GHashTable *ht; - - nm_assert(NM_IS_SETTING(setting)); - nm_assert(nm_str_not_empty(optname)); - - ht = _nm_setting_option_hash(setting, FALSE); - if (!ht) - return FALSE; - - return g_hash_table_remove(ht, optname); -} - -/** - * nm_setting_option_clear_by_name: - * @setting: the #NMSetting - * @predicate: (allow-none) (scope call): the predicate for which names - * should be clear. - * If the predicate returns %TRUE for an option name, the option - * gets removed. If %NULL, all options will be removed. - * - * Since: 1.26 - */ -void -nm_setting_option_clear_by_name(NMSetting *setting, NMUtilsPredicateStr predicate) -{ - GHashTable * hash; - GHashTableIter iter; - const char * name; - gboolean changed = FALSE; - - g_return_if_fail(NM_IS_SETTING(setting)); - - hash = _nm_setting_option_hash(NM_SETTING(setting), FALSE); - if (!hash) - return; - - if (!predicate) { - changed = (g_hash_table_size(hash) > 0); - if (changed) - g_hash_table_remove_all(hash); - } else { - g_hash_table_iter_init(&iter, hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &name, NULL)) { - if (predicate(name)) { - g_hash_table_iter_remove(&iter); - changed = TRUE; - } - } - } - - if (changed) - _nm_setting_option_notify(setting, TRUE); -} - -/*****************************************************************************/ - -/** - * nm_setting_option_get: - * @setting: the #NMSetting - * @opt_name: the option name to request. - * - * Returns: (transfer none): the #GVariant or %NULL if the option - * is not set. - * - * Since: 1.26. - */ -GVariant * -nm_setting_option_get(NMSetting *setting, const char *opt_name) -{ - GenData *gendata; - - g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); - g_return_val_if_fail(opt_name, FALSE); - - gendata = _gendata_hash(setting, FALSE); - return gendata ? g_hash_table_lookup(gendata->hash, opt_name) : NULL; -} - -/** - * nm_setting_option_get_boolean: - * @setting: the #NMSetting - * @opt_name: the option to get - * @out_value: (allow-none) (out): the optional output value. - * If the option is unset, %FALSE will be returned. - * - * Returns: %TRUE if @opt_name is set to a boolean variant. - * - * Since: 1.26 - */ -gboolean -nm_setting_option_get_boolean(NMSetting *setting, const char *opt_name, gboolean *out_value) -{ - GVariant *v; - - v = nm_setting_option_get(NM_SETTING(setting), opt_name); - if (v && g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) { - NM_SET_OUT(out_value, g_variant_get_boolean(v)); - return TRUE; - } - NM_SET_OUT(out_value, FALSE); - return FALSE; -} - -/** - * nm_setting_option_get_uint32: - * @setting: the #NMSetting - * @opt_name: the option to get - * @out_value: (allow-none) (out): the optional output value. - * If the option is unset, 0 will be returned. - * - * Returns: %TRUE if @opt_name is set to a uint32 variant. - * - * Since: 1.26 - */ -gboolean -nm_setting_option_get_uint32(NMSetting *setting, const char *opt_name, guint32 *out_value) -{ - GVariant *v; - - v = nm_setting_option_get(NM_SETTING(setting), opt_name); - if (v && g_variant_is_of_type(v, G_VARIANT_TYPE_UINT32)) { - NM_SET_OUT(out_value, g_variant_get_uint32(v)); - return TRUE; - } - NM_SET_OUT(out_value, 0); - return FALSE; -} - -/** - * nm_setting_option_set: - * @setting: the #NMSetting - * @opt_name: the option name to set - * @variant: (allow-none): the variant to set. - * - * If @variant is %NULL, this clears the option if it is set. - * Otherwise, @variant is set as the option. If @variant is - * a floating reference, it will be consumed. - * - * Note that not all setting types support options. It is a bug - * setting a variant to a setting that doesn't support it. - * Currently, only #NMSettingEthtool supports it. - * - * Since: 1.26 - */ -void -nm_setting_option_set(NMSetting *setting, const char *opt_name, GVariant *variant) -{ - GVariant * old_variant; - gboolean changed_name; - gboolean changed_value; - GHashTable *hash; - - g_return_if_fail(NM_IS_SETTING(setting)); - g_return_if_fail(opt_name); - - hash = _nm_setting_option_hash(setting, variant != NULL); - - if (!variant) { - if (hash) { - if (g_hash_table_remove(hash, opt_name)) - _nm_setting_option_notify(setting, TRUE); - } - return; - } - - /* Currently, it is a bug setting any option, unless the setting type supports it. - * And currently, only NMSettingEthtool supports it. - * - * In the future, more setting types may support it. Or we may relax this so - * that options can be attached to all setting types (to indicate "unsupported" - * settings for forward compatibility). - * - * As it is today, internal code will only add gendata options to NMSettingEthtool, - * and there exists not public API to add such options. Still, it is permissible - * to call get(), clear() and set(variant=NULL) also on settings that don't support - * it, as these operations don't add options. - */ - g_return_if_fail( - _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting))->detail.gendata_info); - - old_variant = g_hash_table_lookup(hash, opt_name); - - changed_name = (old_variant == NULL); - changed_value = changed_name || !g_variant_equal(old_variant, variant); - - /* We always want to replace the variant, even if it has - * the same value according to g_variant_equal(). The reason - * is that we want to take a reference on @variant, because - * that is what the user might expect. */ - g_hash_table_insert(hash, g_strdup(opt_name), g_variant_ref_sink(variant)); - - if (changed_value) - _nm_setting_option_notify(setting, !changed_name); -} - -/** - * nm_setting_option_set_boolean: - * @setting: the #NMSetting - * @value: the value to set. - * - * Like nm_setting_option_set() to set a boolean GVariant. - * - * Since: 1.26 - */ -void -nm_setting_option_set_boolean(NMSetting *setting, const char *opt_name, gboolean value) -{ - GVariant * old_variant; - gboolean changed_name; - gboolean changed_value; - GHashTable *hash; - - g_return_if_fail(NM_IS_SETTING(setting)); - g_return_if_fail(opt_name); - - value = (!!value); - - hash = _nm_setting_option_hash(setting, TRUE); - - old_variant = g_hash_table_lookup(hash, opt_name); - - changed_name = (old_variant == NULL); - changed_value = changed_name - || (!g_variant_is_of_type(old_variant, G_VARIANT_TYPE_BOOLEAN) - || g_variant_get_boolean(old_variant) != value); - - g_hash_table_insert(hash, g_strdup(opt_name), g_variant_ref_sink(g_variant_new_boolean(value))); - - if (changed_value) - _nm_setting_option_notify(setting, !changed_name); -} - -/** - * nm_setting_option_set_uint32: - * @setting: the #NMSetting - * @value: the value to set. - * - * Like nm_setting_option_set() to set a uint32 GVariant. - * - * Since: 1.26 - */ -void -nm_setting_option_set_uint32(NMSetting *setting, const char *opt_name, guint32 value) -{ - GVariant * old_variant; - gboolean changed_name; - gboolean changed_value; - GHashTable *hash; - - g_return_if_fail(NM_IS_SETTING(setting)); - g_return_if_fail(opt_name); - - hash = _nm_setting_option_hash(setting, TRUE); - - old_variant = g_hash_table_lookup(hash, opt_name); - - changed_name = (old_variant == NULL); - changed_value = changed_name - || (!g_variant_is_of_type(old_variant, G_VARIANT_TYPE_UINT32) - || g_variant_get_uint32(old_variant) != value); - - g_hash_table_insert(hash, g_strdup(opt_name), g_variant_ref_sink(g_variant_new_uint32(value))); - - if (changed_value) - _nm_setting_option_notify(setting, !changed_name); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSetting *setting = NM_SETTING(object); - - switch (prop_id) { - case PROP_NAME: - g_value_set_string(value, nm_setting_get_name(setting)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_init(NMSetting *setting) -{} - -static void -finalize(GObject *object) -{ - NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE(object); - - if (priv->gendata) { - g_free(priv->gendata->names); - g_free(priv->gendata->values); - g_hash_table_unref(priv->gendata->hash); - g_slice_free(GenData, priv->gendata); - } - - G_OBJECT_CLASS(nm_setting_parent_class)->finalize(object); -} - -static void -nm_setting_class_init(NMSettingClass *setting_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(setting_class); - - g_type_class_add_private(setting_class, sizeof(NMSettingPrivate)); - - object_class->get_property = get_property; - object_class->finalize = finalize; - - setting_class->update_one_secret = update_one_secret; - setting_class->get_secret_flags = get_secret_flags; - setting_class->set_secret_flags = set_secret_flags; - setting_class->compare_property = compare_property; - setting_class->clear_secrets = clear_secrets; - setting_class->for_each_secret = for_each_secret; - setting_class->duplicate_copy_properties = duplicate_copy_properties; - setting_class->enumerate_values = enumerate_values; - setting_class->aggregate = aggregate; - setting_class->init_from_dbus = init_from_dbus; - - /** - * NMSetting:name: - * - * The setting's name, which uniquely identifies the setting within the - * connection. Each setting type has a name unique to that type, for - * example "ppp" or "802-11-wireless" or "802-3-ethernet". - **/ - obj_properties[PROP_NAME] = g_param_spec_string(NM_SETTING_NAME, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); -} diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h deleted file mode 100644 index e5cf753dc6..0000000000 --- a/libnm-core/nm-setting.h +++ /dev/null @@ -1,353 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2011 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef __NM_SETTING_H__ -#define __NM_SETTING_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-core-types.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SETTING (nm_setting_get_type()) -#define NM_SETTING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING, NMSetting)) -#define NM_SETTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING, NMSettingClass)) -#define NM_IS_SETTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING)) -#define NM_IS_SETTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING)) -#define NM_SETTING_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING, NMSettingClass)) - -/* The property of the #NMSetting is required for the setting to be valid */ -#define NM_SETTING_PARAM_REQUIRED (1 << (1 + G_PARAM_USER_SHIFT)) - -/* The property of the #NMSetting is a secret */ -#define NM_SETTING_PARAM_SECRET (1 << (2 + G_PARAM_USER_SHIFT)) - -/* The property of the #NMSetting should be ignored during comparisons that - * use the %NM_SETTING_COMPARE_FLAG_FUZZY flag. - */ -#define NM_SETTING_PARAM_FUZZY_IGNORE (1 << (3 + G_PARAM_USER_SHIFT)) - -/* Note: all non-glib GParamFlags bits are reserved by NetworkManager */ - -#define NM_SETTING_NAME "name" - -/** - * NMSettingSecretFlags: - * @NM_SETTING_SECRET_FLAG_NONE: the system is responsible for providing and - * storing this secret (default) - * @NM_SETTING_SECRET_FLAG_AGENT_OWNED: a user secret agent is responsible - * for providing and storing this secret; when it is required agents will be - * asked to retrieve it - * @NM_SETTING_SECRET_FLAG_NOT_SAVED: this secret should not be saved, but - * should be requested from the user each time it is needed - * @NM_SETTING_SECRET_FLAG_NOT_REQUIRED: in situations where it cannot be - * automatically determined that the secret is required (some VPNs and PPP - * providers don't require all secrets) this flag indicates that the specific - * secret is not required - * - * These flags indicate specific behavior related to handling of a secret. Each - * secret has a corresponding set of these flags which indicate how the secret - * is to be stored and/or requested when it is needed. - * - **/ -typedef enum { /*< flags >*/ - NM_SETTING_SECRET_FLAG_NONE = 0x00000000, - NM_SETTING_SECRET_FLAG_AGENT_OWNED = 0x00000001, - NM_SETTING_SECRET_FLAG_NOT_SAVED = 0x00000002, - NM_SETTING_SECRET_FLAG_NOT_REQUIRED = 0x00000004 - - /* NOTE: if adding flags, update nm-core-internal.h as well */ -} NMSettingSecretFlags; - -/** - * NMSettingCompareFlags: - * @NM_SETTING_COMPARE_FLAG_EXACT: match all properties exactly - * @NM_SETTING_COMPARE_FLAG_FUZZY: match only important attributes, like SSID, - * type, security settings, etc. Does not match, for example, connection ID - * or UUID. - * @NM_SETTING_COMPARE_FLAG_IGNORE_ID: ignore the connection's ID - * @NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS: ignore all secrets - * @NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS: ignore secrets for which - * the secret's flags indicate the secret is owned by a user secret agent - * (ie, the secret's flag includes @NM_SETTING_SECRET_FLAG_AGENT_OWNED) - * @NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS: ignore secrets for which - * the secret's flags indicate the secret should not be saved to persistent - * storage (ie, the secret's flag includes @NM_SETTING_SECRET_FLAG_NOT_SAVED) - * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT: if this flag is set, - * nm_setting_diff() and nm_connection_diff() will also include properties that - * are set to their default value. See also @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT. - * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT: if this flag is set, - * nm_setting_diff() and nm_connection_diff() will not include properties that - * are set to their default value. This is the opposite of - * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. If both flags are set together, - * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT wins. If both flags are unset, - * this means to exclude default properties if there is a setting to compare, - * but include all properties, if the setting 'b' is missing. This is the legacy - * behaviour of libnm-util, where nm_setting_diff() behaved differently depending - * on whether the setting 'b' was available. If @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT - * is set, nm_setting_diff() will also set the flags @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT - * and @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT, if the values are default values. - * @NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP: ignore the connection's timestamp - * - * These flags modify the comparison behavior when comparing two settings or - * two connections. - * - **/ -typedef enum { - NM_SETTING_COMPARE_FLAG_EXACT = 0x00000000, - NM_SETTING_COMPARE_FLAG_FUZZY = 0x00000001, - NM_SETTING_COMPARE_FLAG_IGNORE_ID = 0x00000002, - NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS = 0x00000004, - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS = 0x00000008, - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS = 0x00000010, - NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT = 0x00000020, - NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT = 0x00000040, - NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP = 0x00000080, - - /* Higher flags like 0x80000000 and 0x40000000 are used internally as private flags */ -} NMSettingCompareFlags; - -/** - * NMSettingMacRandomization: - * @NM_SETTING_MAC_RANDOMIZATION_DEFAULT: the default value, which unless - * overridden by user-controlled defaults configuration, is "never". - * @NM_SETTING_MAC_RANDOMIZATION_NEVER: the device's MAC address is always used. - * @NM_SETTING_MAC_RANDOMIZATION_ALWAYS: a random MAC address is used. - * - * Controls if and how the MAC address of a device is randomzied. - **/ -typedef enum { - NM_SETTING_MAC_RANDOMIZATION_DEFAULT = 0, - NM_SETTING_MAC_RANDOMIZATION_NEVER, - NM_SETTING_MAC_RANDOMIZATION_ALWAYS, -} NMSettingMacRandomization; - -/** - * NMSetting: - * - * The NMSetting struct contains only private data. - * It should only be accessed through the functions described below. - */ -struct _NMSetting { - GObject parent; -}; - -/** - * NMSettingClearSecretsWithFlagsFn: - * @setting: The setting for which secrets are being iterated - * @secret: The secret's name - * @flags: The secret's flags, eg %NM_SETTING_SECRET_FLAG_AGENT_OWNED - * @user_data: User data passed to nm_connection_clear_secrets_with_flags() - * - * Returns: %TRUE to clear the secret, %FALSE to not clear the secret - */ -typedef gboolean (*NMSettingClearSecretsWithFlagsFn)(NMSetting * setting, - const char * secret, - NMSettingSecretFlags flags, - gpointer user_data); - -struct _NMMetaSettingInfo; -struct _NMSettInfoSetting; -struct _NMSettInfoProperty; - -/** - * NMSettingValueIterFn: - * @setting: The setting for which properties are being iterated, given to - * nm_setting_enumerate_values() - * @key: The value/property name - * @value: The property's value - * @flags: The property's flags, like %NM_SETTING_PARAM_SECRET - * @user_data: User data passed to nm_setting_enumerate_values() - */ -typedef void (*NMSettingValueIterFn)(NMSetting * setting, - const char * key, - const GValue *value, - GParamFlags flags, - gpointer user_data); - -/*< private >*/ -typedef gboolean (*_NMConnectionForEachSecretFunc)(NMSettingSecretFlags flags, gpointer user_data); - -typedef struct { - GObjectClass parent; - - /* Virtual functions */ - int (*verify)(NMSetting *setting, NMConnection *connection, GError **error); - - gboolean (*verify_secrets)(NMSetting *setting, NMConnection *connection, GError **error); - - GPtrArray *(*need_secrets)(NMSetting *setting); - - int (*update_one_secret)(NMSetting *setting, const char *key, GVariant *value, GError **error); - - gboolean (*get_secret_flags)(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags *out_flags, - GError ** error); - - gboolean (*set_secret_flags)(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags flags, - GError ** error); - - /*< private >*/ - gboolean (*clear_secrets)(const struct _NMSettInfoSetting *sett_info, - guint property_idx, - NMSetting * setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data); - - /* compare_property() returns a ternary, where DEFAULT means that the property should not - * be compared due to the compare @flags. A TRUE/FALSE result means that the property is - * equal/not-equal. - * - * @other may be %NULL, in which case the function only determines whether - * the setting should be compared (TRUE) or not (DEFAULT). */ - /*< private >*/ - NMTernary (*compare_property)(const struct _NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags); - - /*< private >*/ - void (*duplicate_copy_properties)(const struct _NMSettInfoSetting *sett_info, - NMSetting * src, - NMSetting * dst); - - /*< private >*/ - void (*enumerate_values)(const struct _NMSettInfoProperty *property_info, - NMSetting * setting, - NMSettingValueIterFn func, - gpointer user_data); - - /*< private >*/ - gboolean (*aggregate)(NMSetting *setting, int type_i, gpointer arg); - - /*< private >*/ - void (*for_each_secret)(NMSetting * setting, - const char * secret_name, - GVariant * val, - gboolean remove_non_secrets, - _NMConnectionForEachSecretFunc callback, - gpointer callback_data, - GVariantBuilder * setting_builder); - - /*< private >*/ - gboolean (*init_from_dbus)(NMSetting * setting, - GHashTable * keys, - GVariant * setting_dict, - GVariant * connection_dict, - guint /* NMSettingParseFlags */ parse_flags, - GError ** error); - - /*< private >*/ - gpointer padding[1]; - - /*< private >*/ - const struct _NMMetaSettingInfo *setting_info; -} NMSettingClass; - -GType nm_setting_get_type(void); - -GType nm_setting_lookup_type(const char *name); - -NMSetting *nm_setting_duplicate(NMSetting *setting); - -const char *nm_setting_get_name(NMSetting *setting); - -gboolean nm_setting_verify(NMSetting *setting, NMConnection *connection, GError **error); - -NM_AVAILABLE_IN_1_2 -gboolean nm_setting_verify_secrets(NMSetting *setting, NMConnection *connection, GError **error); - -gboolean nm_setting_compare(NMSetting *a, NMSetting *b, NMSettingCompareFlags flags); - -/** - * NMSettingDiffResult: - * @NM_SETTING_DIFF_RESULT_UNKNOWN: unknown result - * @NM_SETTING_DIFF_RESULT_IN_A: the property is present in setting A - * @NM_SETTING_DIFF_RESULT_IN_B: the property is present in setting B - * @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT: the property is present in - * setting A but is set to the default value. This flag is only set, - * if you specify @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. - * @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT: analog to @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT. - * - * These values indicate the result of a setting difference operation. - **/ -typedef enum { - NM_SETTING_DIFF_RESULT_UNKNOWN = 0x00000000, - NM_SETTING_DIFF_RESULT_IN_A = 0x00000001, - NM_SETTING_DIFF_RESULT_IN_B = 0x00000002, - NM_SETTING_DIFF_RESULT_IN_A_DEFAULT = 0x00000004, - NM_SETTING_DIFF_RESULT_IN_B_DEFAULT = 0x00000008, -} NMSettingDiffResult; - -gboolean nm_setting_diff(NMSetting * a, - NMSetting * b, - NMSettingCompareFlags flags, - gboolean invert_results, - GHashTable ** results); - -void nm_setting_enumerate_values(NMSetting *setting, NMSettingValueIterFn func, gpointer user_data); - -char *nm_setting_to_string(NMSetting *setting); - -/*****************************************************************************/ - -gboolean nm_setting_get_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags *out_flags, - GError ** error); - -gboolean nm_setting_set_secret_flags(NMSetting * setting, - const char * secret_name, - NMSettingSecretFlags flags, - GError ** error); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_26 -GVariant *nm_setting_option_get(NMSetting *setting, const char *opt_name); - -NM_AVAILABLE_IN_1_26 -gboolean -nm_setting_option_get_boolean(NMSetting *setting, const char *opt_name, gboolean *out_value); - -NM_AVAILABLE_IN_1_26 -gboolean nm_setting_option_get_uint32(NMSetting *setting, const char *opt_name, guint32 *out_value); - -NM_AVAILABLE_IN_1_26 -void nm_setting_option_set(NMSetting *setting, const char *opt_name, GVariant *variant); - -NM_AVAILABLE_IN_1_26 -void nm_setting_option_set_uint32(NMSetting *setting, const char *opt_name, guint32 value); - -NM_AVAILABLE_IN_1_26 -void nm_setting_option_set_boolean(NMSetting *setting, const char *opt_name, gboolean value); - -NM_AVAILABLE_IN_1_26 -const char *const *nm_setting_option_get_all_names(NMSetting *setting, guint *out_len); - -NM_AVAILABLE_IN_1_26 -void nm_setting_option_clear_by_name(NMSetting *setting, NMUtilsPredicateStr predicate); - -/*****************************************************************************/ - -const GVariantType *nm_setting_get_dbus_property_type(NMSetting * setting, - const char *property_name); - -/*****************************************************************************/ - -G_END_DECLS - -#endif /* __NM_SETTING_H__ */ diff --git a/libnm-core/nm-simple-connection.c b/libnm-core/nm-simple-connection.c deleted file mode 100644 index 6f1e3a9b3f..0000000000 --- a/libnm-core/nm-simple-connection.c +++ /dev/null @@ -1,152 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2014 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-simple-connection.h" - -#include "nm-setting-private.h" - -/** - * SECTION:nm-simple-connection - * @short_description: An unmanaged connection - * - * An #NMSimpleConnection does not directly represent a D-Bus-exported connection, - * but might be used in the process of creating a new one. - **/ - -/*****************************************************************************/ - -static void nm_simple_connection_interface_init(NMConnectionInterface *iface); - -G_DEFINE_TYPE_WITH_CODE(NMSimpleConnection, - nm_simple_connection, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(NM_TYPE_CONNECTION, - nm_simple_connection_interface_init);) - -/*****************************************************************************/ - -static void -nm_simple_connection_init(NMSimpleConnection *self) -{} - -/** - * nm_simple_connection_new: - * - * Creates a new #NMSimpleConnection object with no #NMSetting objects. - * - * Returns: (transfer full): the new empty #NMConnection object - **/ -NMConnection * -nm_simple_connection_new(void) -{ - return g_object_new(NM_TYPE_SIMPLE_CONNECTION, NULL); -} - -/** - * _nm_simple_connection_new_from_dbus: - * @dict: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION describing the connection - * @error: on unsuccessful return, an error - * - * Creates a new #NMSimpleConnection from a hash table describing the - * connection. See nm_connection_to_dbus() for a description of the expected - * hash table. - * - * Returns: (transfer full): the new #NMSimpleConnection object, populated with - * settings created from the values in the hash table, or %NULL if there was - * an error. - **/ -NMConnection * -_nm_simple_connection_new_from_dbus(GVariant *dict, NMSettingParseFlags parse_flags, GError **error) -{ - NMConnection *connection; - - g_return_val_if_fail(dict != NULL, NULL); - g_return_val_if_fail(g_variant_is_of_type(dict, NM_VARIANT_TYPE_CONNECTION), NULL); - g_return_val_if_fail(!NM_FLAGS_ANY(parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL), NULL); - g_return_val_if_fail( - !NM_FLAGS_ALL(parse_flags, - NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT), - NULL); - - connection = nm_simple_connection_new(); - if (!_nm_connection_replace_settings(connection, dict, parse_flags, error)) - g_clear_object(&connection); - return connection; -} - -/** - * nm_simple_connection_new_from_dbus: - * @dict: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION describing the connection - * @error: on unsuccessful return, an error - * - * Creates a new #NMSimpleConnection from a hash table describing the - * connection and normalize the connection. See nm_connection_to_dbus() for a - * description of the expected hash table. - * - * Returns: (transfer full): the new #NMSimpleConnection object, populated with - * settings created from the values in the hash table, or %NULL if the - * connection failed to normalize. - **/ -NMConnection * -nm_simple_connection_new_from_dbus(GVariant *dict, GError **error) -{ - return _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, error); -} - -/** - * nm_simple_connection_new_clone: - * @connection: the #NMConnection to clone - * - * Clones an #NMConnection as an #NMSimpleConnection. - * - * Returns: (transfer full): a new #NMConnection containing the same settings - * and properties as the source #NMConnection - **/ -NMConnection * -nm_simple_connection_new_clone(NMConnection *connection) -{ - NMConnection *clone; - const char * path; - - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - - clone = nm_simple_connection_new(); - - path = nm_connection_get_path(connection); - if (path) - nm_connection_set_path(clone, path); - - nm_connection_replace_settings_from_connection(clone, connection); - - return clone; -} - -static void -dispose(GObject *object) -{ -#if NM_MORE_ASSERTS - g_signal_handlers_disconnect_by_data(object, - (gpointer) &_nmtst_connection_unchanging_user_data); -#endif - - nm_connection_clear_secrets(NM_CONNECTION(object)); - - G_OBJECT_CLASS(nm_simple_connection_parent_class)->dispose(object); -} - -static void -nm_simple_connection_class_init(NMSimpleConnectionClass *simple_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(simple_class); - - object_class->dispose = dispose; -} - -static void -nm_simple_connection_interface_init(NMConnectionInterface *iface) -{} diff --git a/libnm-core/nm-simple-connection.h b/libnm-core/nm-simple-connection.h deleted file mode 100644 index 38473b6287..0000000000 --- a/libnm-core/nm-simple-connection.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 Red Hat, Inc. - */ - -#ifndef __NM_SIMPLE_CONNECTION_H__ -#define __NM_SIMPLE_CONNECTION_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include "nm-connection.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SIMPLE_CONNECTION (nm_simple_connection_get_type()) -#define NM_SIMPLE_CONNECTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnection)) -#define NM_SIMPLE_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnectionClass)) -#define NM_IS_SIMPLE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SIMPLE_CONNECTION)) -#define NM_IS_SIMPLE_CONNECTION_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SIMPLE_CONNECTION)) -#define NM_SIMPLE_CONNECTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnectionClass)) - -/** - * NMSimpleConnection: - */ -struct _NMSimpleConnection { - GObject parent; -}; - -typedef struct { - GObjectClass parent_class; - - /*< private >*/ - gpointer padding[4]; -} NMSimpleConnectionClass; - -GType nm_simple_connection_get_type(void); - -NMConnection *nm_simple_connection_new(void); - -NMConnection *nm_simple_connection_new_from_dbus(GVariant *dict, GError **error); - -NMConnection *nm_simple_connection_new_clone(NMConnection *connection); - -G_END_DECLS - -#endif /* __NM_SIMPLE_CONNECTION__ */ diff --git a/libnm-core/nm-team-utils.c b/libnm-core/nm-team-utils.c deleted file mode 100644 index b7da35aae2..0000000000 --- a/libnm-core/nm-team-utils.c +++ /dev/null @@ -1,2866 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#define NM_VALUE_TYPE_DEFINE_FUNCTIONS - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-team-utils.h" - -#include "nm-errors.h" -#include "nm-utils-private.h" -#include "nm-glib-aux/nm-json-aux.h" -#include "nm-core-internal.h" -#include "nm-setting-team.h" -#include "nm-setting-team-port.h" - -/*****************************************************************************/ - -typedef enum { - SET_FIELD_MODE_UNSET = 0, - SET_FIELD_MODE_SET = 1, - - /* Sets the field as set, unless the field is at the default. - * This is the case for API that is called from NMSettingTeam/NMSettingTeamPort. - * This means, using libnm API to reset the value of a NMSetting to the default, - * will mark the field as unset. - * This is different from initializing the field when parsing JSON/GVariant. In - * that case an explicitly set field (even set to the default value) will be remembered - * to be set. */ - SET_FIELD_MODE_SET_UNLESS_DEFAULT = 2, -} SetFieldModeEnum; - -typedef enum { - RESET_JSON_NO = FALSE, - RESET_JSON_YES = TRUE, -} ResetJsonEnum; - -/* we rely on "config" being the first. At various places we iterate over attribute types, - * starting after "config".*/ -G_STATIC_ASSERT(_NM_TEAM_ATTRIBUTE_0 == 0); -G_STATIC_ASSERT(NM_TEAM_ATTRIBUTE_CONFIG == 1); - -static const char *const _valid_names_runner[] = { - NM_SETTING_TEAM_RUNNER_BROADCAST, - NM_SETTING_TEAM_RUNNER_ROUNDROBIN, - NM_SETTING_TEAM_RUNNER_RANDOM, - NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP, - NM_SETTING_TEAM_RUNNER_LOADBALANCE, - NM_SETTING_TEAM_RUNNER_LACP, - NULL, -}; - -static const char *const _valid_names_runner_hwaddr_policy[] = { - NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL, - NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE, - NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE, - NULL, -}; - -static const char *const _valid_names_runner_tx_balancer[] = { - "basic", - NULL, -}; - -static const char *const _valid_names_runner_tx_hash[] = { - "eth", - "vlan", - "ipv4", - "ipv6", - "ip", - "l3", - "l4", - "tcp", - "udp", - "sctp", - NULL, -}; - -static const char *const _valid_names_runner_agg_select_policy[] = { - "lacp_prio", - "lacp_prio_stable", - "bandwidth", - "count", - "port_config", - NULL, -}; - -typedef struct { - NMTeamAttribute team_attr; - const char *const *valid_runners; -} RunnerCompatElem; - -static const RunnerCompatElem _runner_compat_lst[] = { - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP), - }, - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LOADBALANCE, NM_SETTING_TEAM_RUNNER_LACP), - }, - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LOADBALANCE, NM_SETTING_TEAM_RUNNER_LACP), - }, - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LOADBALANCE, NM_SETTING_TEAM_RUNNER_LACP), - }, - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), - }, - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), - }, - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), - }, - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), - }, - { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, - NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), - }, -}; - -typedef struct { - const char *const *js_keys; - const char * property_name; - NMValueTypUnion default_val; - union { - struct { - gint32 min; - gint32 max; - } r_int32; - struct { - const char *const *valid_names; - } r_string; - } range; - NMTeamAttribute team_attr; - NMValueType value_type; - guint8 field_offset; - guint8 js_keys_len; - bool for_master : 1; - bool for_port : 1; - bool has_range : 1; -} TeamAttrData; - -#define TEAM_ATTR_IDX(_is_port, _team_attr) \ - (((!(_is_port) || (_team_attr) < _NM_TEAM_ATTRIBUTE_START) \ - ? (int) (_team_attr) \ - : (((int) (_NM_TEAM_ATTRIBUTE_MASTER_NUM - _NM_TEAM_ATTRIBUTE_START)) \ - + ((int) (_team_attr)))) \ - - 1) - -#define TEAM_ATTR_IDX_CONFIG (TEAM_ATTR_IDX(FALSE, NM_TEAM_ATTRIBUTE_CONFIG)) - -static const TeamAttrData team_attr_datas[] = { - -#define _JS_KEYS(...) .js_keys = NM_MAKE_STRV(__VA_ARGS__), .js_keys_len = NM_NARG(__VA_ARGS__) - -#define _VAL_BOOL(_default) .default_val.v_bool = (_default) - -#define _VAL_INT32(_default) .default_val.v_int32 = (_default) - -#define _VAL_INT32_RANGE(_default, _min, _max) \ - _VAL_INT32(_default), .has_range = TRUE, \ - .range.r_int32 = { \ - .min = _min, \ - .max = _max, \ - } - -#define _VAL_STRING() .default_val.v_string = NULL - -#define _VAL_STRING_RANGE(_valid_names) \ - _VAL_STRING(), .has_range = TRUE, \ - .range.r_string = { \ - .valid_names = (_valid_names), \ - } - -#define _VAL_UNSPEC() .default_val.v_string = (NULL) - -#define _INIT(_is_port, _team_attr, field, _value_type, _property_name, ...) \ - [TEAM_ATTR_IDX(_is_port, _team_attr)] = { \ - .for_master = (_team_attr) < _NM_TEAM_ATTRIBUTE_START || !(_is_port), \ - .for_port = (_team_attr) < _NM_TEAM_ATTRIBUTE_START || (_is_port), \ - .team_attr = (_team_attr), \ - .field_offset = G_STRUCT_OFFSET(NMTeamSetting, _data_priv.field), \ - .value_type = (_value_type), \ - .property_name = ""_property_name \ - "", \ - __VA_ARGS__} - - _INIT(0, NM_TEAM_ATTRIBUTE_CONFIG, _js_str, NM_VALUE_TYPE_UNSPEC, NM_SETTING_TEAM_CONFIG, ), - - _INIT(0, - NM_TEAM_ATTRIBUTE_LINK_WATCHERS, - link_watchers, - NM_VALUE_TYPE_UNSPEC, - NM_SETTING_TEAM_LINK_WATCHERS, - _JS_KEYS("link_watch"), - _VAL_UNSPEC(), ), - - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT, - master.notify_peers_count, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, - _JS_KEYS("notify_peers", "count"), - _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, - master.notify_peers_interval, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, - _JS_KEYS("notify_peers", "interval"), - _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, - master.mcast_rejoin_count, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_MCAST_REJOIN_COUNT, - _JS_KEYS("mcast_rejoin", "count"), - _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, - master.mcast_rejoin_interval, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, - _JS_KEYS("mcast_rejoin", "interval"), - _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER, - master.runner, - NM_VALUE_TYPE_STRING, - NM_SETTING_TEAM_RUNNER, - _JS_KEYS("runner", "name"), - _VAL_STRING_RANGE(_valid_names_runner), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, - master.runner_hwaddr_policy, - NM_VALUE_TYPE_STRING, - NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, - _JS_KEYS("runner", "hwaddr_policy"), - _VAL_STRING_RANGE(_valid_names_runner_hwaddr_policy), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - master.runner_tx_hash, - NM_VALUE_TYPE_UNSPEC, - NM_SETTING_TEAM_RUNNER_TX_HASH, - _JS_KEYS("runner", "tx_hash"), - _VAL_UNSPEC(), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, - master.runner_tx_balancer, - NM_VALUE_TYPE_STRING, - NM_SETTING_TEAM_RUNNER_TX_BALANCER, - _JS_KEYS("runner", "tx_balancer", "name"), - _VAL_STRING_RANGE(_valid_names_runner_tx_balancer), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, - master.runner_tx_balancer_interval, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, - _JS_KEYS("runner", "tx_balancer", "balancing_interval"), - _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, - master.runner_active, - NM_VALUE_TYPE_BOOL, - NM_SETTING_TEAM_RUNNER_ACTIVE, - _JS_KEYS("runner", "active"), - _VAL_BOOL(TRUE), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, - master.runner_fast_rate, - NM_VALUE_TYPE_BOOL, - NM_SETTING_TEAM_RUNNER_FAST_RATE, - _JS_KEYS("runner", "fast_rate"), - _VAL_BOOL(FALSE), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, - master.runner_sys_prio, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_RUNNER_SYS_PRIO, - _JS_KEYS("runner", "sys_prio"), - _VAL_INT32_RANGE(-1, 0, USHRT_MAX + 1), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, - master.runner_min_ports, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_RUNNER_MIN_PORTS, - _JS_KEYS("runner", "min_ports"), - _VAL_INT32_RANGE(-1, 1, UCHAR_MAX + 1), ), - _INIT(0, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, - master.runner_agg_select_policy, - NM_VALUE_TYPE_STRING, - NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, - _JS_KEYS("runner", "agg_select_policy"), - _VAL_STRING_RANGE(_valid_names_runner_agg_select_policy), ), - - _INIT(1, - NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID, - port.queue_id, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_PORT_QUEUE_ID, - _JS_KEYS("queue_id"), - _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), - _INIT(1, - NM_TEAM_ATTRIBUTE_PORT_PRIO, - port.prio, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_PORT_PRIO, - _JS_KEYS("prio"), - _VAL_INT32(0), ), - _INIT(1, - NM_TEAM_ATTRIBUTE_PORT_STICKY, - port.sticky, - NM_VALUE_TYPE_BOOL, - NM_SETTING_TEAM_PORT_STICKY, - _JS_KEYS("sticky"), - _VAL_BOOL(FALSE), ), - _INIT(1, - NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, - port.lacp_prio, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_PORT_LACP_PRIO, - _JS_KEYS("lacp_prio"), - _VAL_INT32_RANGE(-1, 0, USHRT_MAX + 1), ), - _INIT(1, - NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, - port.lacp_key, - NM_VALUE_TYPE_INT32, - NM_SETTING_TEAM_PORT_LACP_KEY, - _JS_KEYS("lacp_key"), - _VAL_INT32_RANGE(-1, 0, USHRT_MAX + 1), ), - -#undef _INIT -}; - -/*****************************************************************************/ - -typedef enum { - LINK_WATCHER_ATTRIBUTE_NAME, - LINK_WATCHER_ATTRIBUTE_DELAY_UP, - LINK_WATCHER_ATTRIBUTE_DELAY_DOWN, - LINK_WATCHER_ATTRIBUTE_INTERVAL, - LINK_WATCHER_ATTRIBUTE_INIT_WAIT, - LINK_WATCHER_ATTRIBUTE_MISSED_MAX, - LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, - LINK_WATCHER_ATTRIBUTE_TARGET_HOST, - LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, - LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, - LINK_WATCHER_ATTRIBUTE_VLANID, - LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS, -} LinkWatcherAttribute; - -#define _EXPECTED_LINK_WATCHER_ATTRIBUTES_ETHTOOL \ - LINK_WATCHER_ATTRIBUTE_NAME, LINK_WATCHER_ATTRIBUTE_DELAY_UP, LINK_WATCHER_ATTRIBUTE_DELAY_DOWN -#define _EXPECTED_LINK_WATCHER_ATTRIBUTES_NSNA_PING \ - LINK_WATCHER_ATTRIBUTE_NAME, LINK_WATCHER_ATTRIBUTE_INTERVAL, \ - LINK_WATCHER_ATTRIBUTE_INIT_WAIT, LINK_WATCHER_ATTRIBUTE_MISSED_MAX, \ - LINK_WATCHER_ATTRIBUTE_TARGET_HOST -#define _EXPECTED_LINK_WATCHER_ATTRIBUTES_ARP_PING \ - LINK_WATCHER_ATTRIBUTE_NAME, LINK_WATCHER_ATTRIBUTE_INTERVAL, \ - LINK_WATCHER_ATTRIBUTE_INIT_WAIT, LINK_WATCHER_ATTRIBUTE_MISSED_MAX, \ - LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, LINK_WATCHER_ATTRIBUTE_TARGET_HOST, \ - LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, \ - LINK_WATCHER_ATTRIBUTE_VLANID, LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS - -typedef struct { - const char * js_key; - const char * dbus_name; - NMValueTypUnion default_val; - LinkWatcherAttribute link_watcher_attr; - NMValueType value_type; -} LinkWatcherAttrData; - -static const LinkWatcherAttrData link_watcher_attr_datas[] = { -#define _INIT(_link_watcher_attr, _js_key, _dbus_name, _value_type, ...) \ - [_link_watcher_attr] = {.link_watcher_attr = (_link_watcher_attr), \ - .value_type = (_value_type), \ - .js_key = (""_js_key \ - ""), \ - .dbus_name = (""_dbus_name \ - ""), \ - __VA_ARGS__} - _INIT(LINK_WATCHER_ATTRIBUTE_NAME, "name", "name", NM_VALUE_TYPE_STRING, ), - _INIT(LINK_WATCHER_ATTRIBUTE_DELAY_UP, "delay_up", "delay-up", NM_VALUE_TYPE_INT, ), - _INIT(LINK_WATCHER_ATTRIBUTE_DELAY_DOWN, "delay_down", "delay-down", NM_VALUE_TYPE_INT, ), - _INIT(LINK_WATCHER_ATTRIBUTE_INTERVAL, "interval", "interval", NM_VALUE_TYPE_INT, ), - _INIT(LINK_WATCHER_ATTRIBUTE_INIT_WAIT, "init_wait", "init-wait", NM_VALUE_TYPE_INT, ), - _INIT(LINK_WATCHER_ATTRIBUTE_MISSED_MAX, - "missed_max", - "missed-max", - NM_VALUE_TYPE_INT, - .default_val.v_int = 3, ), - _INIT(LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, "source_host", "source-host", NM_VALUE_TYPE_STRING, ), - _INIT(LINK_WATCHER_ATTRIBUTE_TARGET_HOST, "target_host", "target-host", NM_VALUE_TYPE_STRING, ), - _INIT(LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, - "validate_active", - "validate-active", - NM_VALUE_TYPE_BOOL, ), - _INIT(LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, - "validate_inactive", - "validate-inactive", - NM_VALUE_TYPE_BOOL, ), - _INIT(LINK_WATCHER_ATTRIBUTE_VLANID, - "vlanid", - "vlanid", - NM_VALUE_TYPE_INT, - .default_val.v_int = -1, ), - _INIT(LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS, "send_always", "send-always", NM_VALUE_TYPE_BOOL, ), -#undef _INIT -}; - -/*****************************************************************************/ - -static const TeamAttrData *_team_attr_data_get(gboolean is_port, NMTeamAttribute team_attr); -static gpointer _team_setting_get_field(const NMTeamSetting *self, const TeamAttrData *attr_data); -static void _link_watcher_to_json(const NMTeamLinkWatcher *link_watcher, GString *gstr); - -/*****************************************************************************/ - -static void -_team_attr_data_ASSERT(const TeamAttrData *attr_data) -{ -#if NM_MORE_ASSERTS > 5 - nm_assert(attr_data); - if (attr_data->for_port) - nm_assert(attr_data == _team_attr_data_get(TRUE, attr_data->team_attr)); - if (attr_data->for_master) - nm_assert(attr_data == _team_attr_data_get(FALSE, attr_data->team_attr)); - nm_assert((attr_data - team_attr_datas) - == TEAM_ATTR_IDX(attr_data->for_port, attr_data->team_attr)); - nm_assert(attr_data->value_type > 0); - nm_assert(attr_data->field_offset < sizeof(NMTeamSetting)); - nm_assert(attr_data->js_keys_len == NM_PTRARRAY_LEN(attr_data->js_keys)); - nm_assert(attr_data->property_name); - { - static int checked = 0; - - if (checked == 0) { - checked = 1; - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; - attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) - _team_attr_data_ASSERT(attr_data); - } - } -#endif -} - -static gboolean -_team_attr_data_is_relevant(const TeamAttrData *attr_data, gboolean is_port) -{ - return is_port ? attr_data->for_port : attr_data->for_master; -} - -static const TeamAttrData * -_team_attr_data_get(gboolean is_port, NMTeamAttribute team_attr) -{ - const int idx = TEAM_ATTR_IDX(is_port, team_attr); - - nm_assert(idx >= 0 && idx < G_N_ELEMENTS(team_attr_datas)); - nm_assert(team_attr_datas[idx].team_attr == team_attr); - nm_assert(_team_attr_data_is_relevant(&team_attr_datas[idx], is_port)); - - return &team_attr_datas[idx]; -} - -static const TeamAttrData * -_team_attr_data_find_for_property_name(gboolean is_port, const char *property_name) -{ - const TeamAttrData *attr_data; - - for (attr_data = team_attr_datas; attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) { - if (_team_attr_data_is_relevant(attr_data, is_port) - && nm_streq(property_name, attr_data->property_name)) - return attr_data; - } - return NULL; -} - -static int -_team_attr_data_cmp(const TeamAttrData *attr_data, - gboolean is_port, - gconstpointer val_a, - gconstpointer val_b) -{ - const GPtrArray *v_ptrarray_a; - const GPtrArray *v_ptrarray_b; - guint len; - - _team_attr_data_ASSERT(attr_data); - nm_assert(val_a); - nm_assert(val_b); - - if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) - NM_CMP_RETURN(nm_value_type_cmp(attr_data->value_type, val_a, val_b)); - else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { - v_ptrarray_a = *((const GPtrArray *const *) val_a); - v_ptrarray_b = *((const GPtrArray *const *) val_b); - len = v_ptrarray_a ? v_ptrarray_a->len : 0u; - NM_CMP_DIRECT(len, (v_ptrarray_b ? v_ptrarray_b->len : 0u)); - if (len > 0) { - NM_CMP_RETURN( - nm_team_link_watchers_cmp((const NMTeamLinkWatcher *const *) v_ptrarray_a->pdata, - (const NMTeamLinkWatcher *const *) v_ptrarray_b->pdata, - len, - FALSE)); - } - } else if (!is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { - v_ptrarray_a = *((const GPtrArray *const *) val_a); - v_ptrarray_b = *((const GPtrArray *const *) val_b); - NM_CMP_RETURN( - nm_utils_strv_cmp_n(v_ptrarray_a ? (const char *const *) v_ptrarray_a->pdata : NULL, - v_ptrarray_a ? v_ptrarray_a->len : 0u, - v_ptrarray_b ? (const char *const *) v_ptrarray_b->pdata : NULL, - v_ptrarray_b ? v_ptrarray_b->len : 0u)); - } else - nm_assert_not_reached(); - return 0; -} - -static gboolean -_team_attr_data_equal(const TeamAttrData *attr_data, - gboolean is_port, - gconstpointer val_a, - gconstpointer val_b) -{ - return _team_attr_data_cmp(attr_data, is_port, val_a, val_b) == 0; -} - -static void -_team_attr_data_copy(const TeamAttrData *attr_data, - gboolean is_port, - gpointer dst, - gconstpointer src) -{ - GPtrArray * v_ptrarray_dst; - const GPtrArray *v_ptrarray_src; - GPtrArray * dst_array; - guint i, len; - - if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) - nm_value_type_copy(attr_data->value_type, dst, src); - else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { - v_ptrarray_src = *((const GPtrArray *const *) src); - v_ptrarray_dst = *((GPtrArray **) dst); - len = (v_ptrarray_src ? v_ptrarray_src->len : 0u); - - if (len == 0) { - if (v_ptrarray_dst) - g_ptr_array_set_size(v_ptrarray_dst, 0); - } else { - dst_array = g_ptr_array_new_full(len, (GDestroyNotify) nm_team_link_watcher_unref); - for (i = 0; i < len; i++) { - if (v_ptrarray_src->pdata[i]) { - nm_team_link_watcher_ref(v_ptrarray_src->pdata[i]); - g_ptr_array_add(dst_array, v_ptrarray_src->pdata[i]); - } - } - if (v_ptrarray_dst) - g_ptr_array_unref(v_ptrarray_dst); - *((GPtrArray **) dst) = dst_array; - } - } else if (!is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { - v_ptrarray_src = *((const GPtrArray *const *) src); - v_ptrarray_dst = *((GPtrArray **) dst); - len = (v_ptrarray_src ? v_ptrarray_src->len : 0u); - - if (v_ptrarray_src && v_ptrarray_src->len > 0) { - dst_array = g_ptr_array_new_full(v_ptrarray_src->len, g_free); - for (i = 0; i < v_ptrarray_src->len; i++) - g_ptr_array_add(dst_array, g_strdup(v_ptrarray_src->pdata[i])); - } else - dst_array = NULL; - if (v_ptrarray_dst) - g_ptr_array_unref(v_ptrarray_dst); - *((GPtrArray **) dst) = dst_array; - } else - nm_assert_not_reached(); -} - -static void -_team_attr_data_to_json(const TeamAttrData *attr_data, - gboolean is_port, - GString * gstr, - gconstpointer p_field) -{ - guint i; - - _team_attr_data_ASSERT(attr_data); - nm_assert(p_field); - - nm_json_gstr_append_obj_name(gstr, attr_data->js_keys[attr_data->js_keys_len - 1], '\0'); - - if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) { - nm_value_type_to_json(attr_data->value_type, gstr, p_field); - return; - } - - if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { - const GPtrArray *v_ptrarray = *((const GPtrArray *const *) p_field); - - if (!v_ptrarray) - g_string_append(gstr, "null"); - else if (v_ptrarray->len == 0) - g_string_append(gstr, "[ ]"); - else if (v_ptrarray->len == 1) - _link_watcher_to_json(v_ptrarray->pdata[0], gstr); - else { - g_string_append(gstr, "[ "); - for (i = 0; i < v_ptrarray->len; i++) { - if (i > 0) - nm_json_gstr_append_delimiter(gstr); - _link_watcher_to_json(v_ptrarray->pdata[i], gstr); - } - g_string_append(gstr, " ]"); - } - return; - } - - if (!is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { - const GPtrArray *v_ptrarray = *((const GPtrArray *const *) p_field); - - if (!v_ptrarray) - g_string_append(gstr, "null"); - else { - g_string_append(gstr, "[ "); - for (i = 0; i < v_ptrarray->len; i++) { - if (i > 0) - nm_json_gstr_append_delimiter(gstr); - nm_json_gstr_append_string(gstr, v_ptrarray->pdata[i]); - } - g_string_append(gstr, i > 0 ? " ]" : "]"); - } - return; - } - - nm_assert_not_reached(); -} - -/*****************************************************************************/ - -static void -_team_setting_ASSERT(const NMTeamSetting *self) -{ - nm_assert(self); - nm_assert(!self->d._js_str_need_synthetize || !self->d._js_str); -#if NM_MORE_ASSERTS > 2 - if (!self->d.strict_validated) { - nm_assert(!self->d._js_str_need_synthetize); - nm_assert(self->d._js_str); - } - nm_assert(self->d.link_watchers); - nm_assert(self->d.is_port || !self->d.master.runner_tx_hash - || self->d.master.runner_tx_hash->len > 0); -#endif -} - -static gboolean -_team_setting_has_field(const NMTeamSetting *self, const TeamAttrData *attr_data) -{ - _team_setting_ASSERT(self); - return NM_FLAGS_ALL(self->d.has_fields_mask, nm_team_attribute_to_flags(attr_data->team_attr)); -} - -static gboolean -_team_setting_has_fields_any_v(const NMTeamSetting * self, - const NMTeamAttribute *team_attrs, - gsize n_team_attrs) -{ - gsize i; - - for (i = 0; i < n_team_attrs; i++) { - const TeamAttrData *attr_data = _team_attr_data_get(self->d.is_port, team_attrs[i]); - - if (_team_setting_has_field(self, attr_data)) - return TRUE; - } - return FALSE; -} - -#define _team_setting_has_fields_any(self, ...) \ - _team_setting_has_fields_any_v((self), \ - ((const NMTeamAttribute[]){__VA_ARGS__}), \ - NM_NARG(__VA_ARGS__)) - -static void -_team_setting_has_field_set(NMTeamSetting * self, - const TeamAttrData *attr_data, - SetFieldModeEnum set_field_mode) -{ - guint32 mask = nm_team_attribute_to_flags(attr_data->team_attr); - - _team_setting_ASSERT(self); - - switch (set_field_mode) { - case SET_FIELD_MODE_UNSET: - goto do_unset; - case SET_FIELD_MODE_SET: - goto do_set; - case SET_FIELD_MODE_SET_UNLESS_DEFAULT: - if (_team_attr_data_equal(attr_data, - self->d.is_port, - _team_setting_get_field(self, attr_data), - &attr_data->default_val)) - goto do_unset; - goto do_set; - } - nm_assert_not_reached(); - -do_unset: - self->_data_priv.has_fields_mask &= ~mask; - return; -do_set: - self->_data_priv.has_fields_mask |= mask; -} - -static gpointer -_team_setting_get_field(const NMTeamSetting *self, const TeamAttrData *attr_data) -{ - _team_setting_ASSERT(self); - _team_attr_data_ASSERT(attr_data); - nm_assert(_team_attr_data_is_relevant(attr_data, self->d.is_port)); - -#if NM_MORE_ASSERTS > 5 - if (attr_data->for_master && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO) - nm_assert((gpointer)(((char *) self) + attr_data->field_offset) - == &self->d.master.runner_sys_prio); -#endif - - return (((char *) self) + attr_data->field_offset); -} - -static guint32 -_team_setting_attribute_changed(NMTeamSetting * self, - const TeamAttrData *attr_data, - gboolean changed, - SetFieldModeEnum set_field_mode, - ResetJsonEnum reset_json) -{ - guint32 changed_flags; - - _team_setting_has_field_set(self, attr_data, set_field_mode); - - if (!reset_json) { - return changed ? nm_team_attribute_to_flags(attr_data->team_attr) : 0u; - } - - if (!changed) { - /* a regular attribute was set, but the value did not change. - * - * If we previously were in non-strict mode, then - * - * - switch to strict-mode. Clearly the user set a regular attribute - * and hence now we want to validate the setting. - * - * - clear the JSON string. We need to regenerate it. - */ - if (self->_data_priv.strict_validated) - return 0; - changed_flags = nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); - } else { - changed_flags = nm_team_attribute_to_flags(attr_data->team_attr) - | nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); - } - - nm_clear_g_free((char **) &self->_data_priv._js_str); - self->_data_priv.strict_validated = TRUE; - self->_data_priv._js_str_need_synthetize = TRUE; - - return changed_flags; -} - -static guint32 -_team_setting_attribute_changed_attr(NMTeamSetting * self, - NMTeamAttribute team_attr, - gboolean changed, - SetFieldModeEnum set_field_mode, - ResetJsonEnum reset_json) -{ - return _team_setting_attribute_changed(self, - _team_attr_data_get(self->d.is_port, team_attr), - changed, - set_field_mode, - reset_json); -} - -static gboolean -_team_setting_field_to_json(const NMTeamSetting *self, - GString * gstr, - gboolean prepend_delimiter, - const TeamAttrData * attr_data) -{ - if (!_team_setting_has_field(self, attr_data)) - return FALSE; - - if (prepend_delimiter) - nm_json_gstr_append_delimiter(gstr); - _team_attr_data_to_json(attr_data, - self->d.is_port, - gstr, - _team_setting_get_field(self, attr_data)); - return TRUE; -} - -static gboolean -_team_setting_fields_to_json_maybe(const NMTeamSetting * self, - GString * gstr, - gboolean prepend_delimiter, - const NMTeamAttribute *team_attrs_lst, - gsize team_attrs_lst_len) -{ - gsize i; - gboolean any_added = FALSE; - - for (i = 0; i < team_attrs_lst_len; i++) { - if (_team_setting_field_to_json(self, - gstr, - prepend_delimiter, - _team_attr_data_get(self->d.is_port, team_attrs_lst[i]))) { - any_added = TRUE; - prepend_delimiter = TRUE; - } - } - return any_added; -} - -static guint32 -_team_setting_set(NMTeamSetting * self, - gboolean modify, - const bool * has_lst, - const NMValueTypUnion *val_lst) -{ - guint32 changed_flags = 0; - const TeamAttrData *attr_data; - - nm_assert((!has_lst) == (!val_lst)); - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; - attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) { - const NMValueTypUnion *p_val; - gconstpointer p_field; - gboolean has_field; - - if (!_team_attr_data_is_relevant(attr_data, self->d.is_port)) - continue; - - has_field = (has_lst && has_lst[attr_data->team_attr]); - - p_val = has_field ? &val_lst[attr_data->team_attr] : &attr_data->default_val; - - p_field = _team_setting_get_field(self, attr_data); - - if (!_team_attr_data_equal(attr_data, self->d.is_port, p_val, p_field)) { - if (modify) { - _team_attr_data_copy(attr_data, self->d.is_port, (gpointer) p_field, p_val); - } - changed_flags |= nm_team_attribute_to_flags(attr_data->team_attr); - } - - if (modify) { - _team_setting_has_field_set(self, - attr_data, - has_field ? SET_FIELD_MODE_SET : SET_FIELD_MODE_UNSET); - } - } - - return changed_flags; -} - -static guint32 -_team_setting_check_default(const NMTeamSetting *self) -{ - return _team_setting_set((NMTeamSetting *) self, FALSE, NULL, NULL); -} - -static guint32 -_team_setting_set_default(NMTeamSetting *self) -{ - return _team_setting_set(self, TRUE, NULL, NULL); -} - -/*****************************************************************************/ - -gconstpointer -_nm_team_setting_value_get(const NMTeamSetting *self, - NMTeamAttribute team_attr, - NMValueType value_type) -{ - const TeamAttrData *attr_data = _team_attr_data_get(self->d.is_port, team_attr); - - nm_assert(value_type == attr_data->value_type); - - nm_assert(_team_setting_has_field(self, attr_data) - || _team_attr_data_equal(attr_data, - self->d.is_port, - _team_setting_get_field(self, attr_data), - &attr_data->default_val)); - return _team_setting_get_field(self, attr_data); -} - -static guint32 -_team_setting_value_set(NMTeamSetting * self, - const TeamAttrData *attr_data, - gconstpointer val, - SetFieldModeEnum set_field_mode, - ResetJsonEnum reset_json) -{ - gpointer p_field; - gboolean changed; - - nm_assert(self); - _team_attr_data_ASSERT(attr_data); - nm_assert(val); - - p_field = _team_setting_get_field(self, attr_data); - - changed = !_team_attr_data_equal(attr_data, self->d.is_port, p_field, val); - if (changed) - nm_value_type_copy(attr_data->value_type, p_field, val); - return _team_setting_attribute_changed(self, attr_data, changed, set_field_mode, reset_json); -} - -guint32 -nm_team_setting_value_reset(NMTeamSetting * self, - NMTeamAttribute team_attr, - gboolean to_default /* or else unset */) -{ - const TeamAttrData *attr_data; - - nm_assert(self); - - attr_data = _team_attr_data_get(self->d.is_port, team_attr); - - return _team_setting_value_set(self, - attr_data, - &attr_data->default_val, - to_default ? SET_FIELD_MODE_SET : SET_FIELD_MODE_UNSET, - RESET_JSON_YES); -} - -guint32 -_nm_team_setting_value_set(NMTeamSetting * self, - NMTeamAttribute team_attr, - NMValueType value_type, - gconstpointer val) -{ - const TeamAttrData *attr_data; - - nm_assert(self); - - attr_data = _team_attr_data_get(self->d.is_port, team_attr); - - nm_assert(value_type == attr_data->value_type); - - return _team_setting_value_set(self, - attr_data, - val, - SET_FIELD_MODE_SET_UNLESS_DEFAULT, - RESET_JSON_YES); -} - -guint32 -nm_team_setting_value_link_watchers_add(NMTeamSetting *self, const NMTeamLinkWatcher *link_watcher) -{ - guint i; - gboolean changed; - - for (i = 0; i < self->d.link_watchers->len; i++) { - if (nm_team_link_watcher_equal(self->d.link_watchers->pdata[i], link_watcher)) { - changed = FALSE; - goto out; - } - } - changed = TRUE; - g_ptr_array_add((GPtrArray *) self->d.link_watchers, - _nm_team_link_watcher_ref((NMTeamLinkWatcher *) link_watcher)); -out: - return _team_setting_attribute_changed_attr(self, - NM_TEAM_ATTRIBUTE_LINK_WATCHERS, - changed, - SET_FIELD_MODE_SET_UNLESS_DEFAULT, - RESET_JSON_YES); -} - -guint32 -nm_team_setting_value_link_watchers_remove_by_value(NMTeamSetting * self, - const NMTeamLinkWatcher *link_watcher) -{ - guint i; - - for (i = 0; i < self->d.link_watchers->len; i++) { - if (nm_team_link_watcher_equal(self->d.link_watchers->pdata[i], link_watcher)) - return nm_team_setting_value_link_watchers_remove(self, i); - } - return _team_setting_attribute_changed_attr(self, - NM_TEAM_ATTRIBUTE_LINK_WATCHERS, - FALSE, - SET_FIELD_MODE_SET_UNLESS_DEFAULT, - RESET_JSON_YES); -} - -guint32 -nm_team_setting_value_link_watchers_remove(NMTeamSetting *self, guint idx) -{ - g_ptr_array_remove_index((GPtrArray *) self->d.link_watchers, idx); - return _team_setting_attribute_changed_attr(self, - NM_TEAM_ATTRIBUTE_LINK_WATCHERS, - TRUE, - SET_FIELD_MODE_SET_UNLESS_DEFAULT, - RESET_JSON_YES); -} - -static guint32 -_team_setting_value_link_watchers_set_list(NMTeamSetting * self, - const NMTeamLinkWatcher *const *arr, - guint len, - SetFieldModeEnum set_field_mode, - ResetJsonEnum reset_json) -{ - gboolean changed; - - if (self->d.link_watchers->len == len - && nm_team_link_watchers_cmp( - (const NMTeamLinkWatcher *const *) self->d.link_watchers->pdata, - arr, - len, - FALSE) - == 0) { - changed = FALSE; - goto out; - } - - changed = TRUE; - if (len == 0) - g_ptr_array_set_size((GPtrArray *) self->d.link_watchers, 0); - else { - _nm_unused gs_unref_ptrarray GPtrArray *old_val_destroy = NULL; - guint i; - - old_val_destroy = (GPtrArray *) g_steal_pointer(&self->_data_priv.link_watchers); - - self->_data_priv.link_watchers = - g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); - - for (i = 0; i < len; i++) { - if (arr[i]) { - g_ptr_array_add((GPtrArray *) self->d.link_watchers, - _nm_team_link_watcher_ref((NMTeamLinkWatcher *) arr[i])); - } - } - } - -out: - return _team_setting_attribute_changed_attr(self, - NM_TEAM_ATTRIBUTE_LINK_WATCHERS, - changed, - set_field_mode, - reset_json); -} - -guint32 -nm_team_setting_value_link_watchers_set_list(NMTeamSetting * self, - const NMTeamLinkWatcher *const *arr, - guint len) -{ - return _team_setting_value_link_watchers_set_list(self, - arr, - len, - SET_FIELD_MODE_SET_UNLESS_DEFAULT, - RESET_JSON_YES); -} - -/*****************************************************************************/ - -guint32 -nm_team_setting_value_master_runner_tx_hash_add(NMTeamSetting *self, const char *txhash) -{ - gboolean changed; - guint i; - - if (!self->d.master.runner_tx_hash) - self->_data_priv.master.runner_tx_hash = g_ptr_array_new_with_free_func(g_free); - else { - for (i = 0; i < self->d.master.runner_tx_hash->len; i++) { - if (nm_streq(txhash, self->d.master.runner_tx_hash->pdata[i])) { - changed = FALSE; - goto out; - } - } - } - changed = TRUE; - g_ptr_array_add((GPtrArray *) self->d.master.runner_tx_hash, g_strdup(txhash)); -out: - return _team_setting_attribute_changed_attr(self, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - changed, - SET_FIELD_MODE_SET_UNLESS_DEFAULT, - RESET_JSON_YES); -} - -guint32 -nm_team_setting_value_master_runner_tx_hash_remove(NMTeamSetting *self, guint idx) -{ - g_ptr_array_remove_index((GPtrArray *) self->d.master.runner_tx_hash, idx); - return _team_setting_attribute_changed_attr(self, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - TRUE, - SET_FIELD_MODE_SET_UNLESS_DEFAULT, - RESET_JSON_YES); -} - -static guint32 -_team_setting_value_master_runner_tx_hash_set_list(NMTeamSetting * self, - const char *const *arr, - guint len, - SetFieldModeEnum set_field_mode, - ResetJsonEnum reset_json) -{ - _nm_unused gs_unref_ptrarray GPtrArray *old_val_destroy = NULL; - gboolean changed; - guint i; - - if (nm_utils_strv_cmp_n(self->d.master.runner_tx_hash - ? (const char *const *) self->d.master.runner_tx_hash->pdata - : NULL, - self->d.master.runner_tx_hash ? self->d.master.runner_tx_hash->len : 0u, - arr, - len) - == 0) { - changed = FALSE; - goto out; - } - - changed = TRUE; - - old_val_destroy = (GPtrArray *) g_steal_pointer(&self->_data_priv.master.runner_tx_hash); - - for (i = 0; i < len; i++) { - if (!arr[i]) - continue; - if (!self->d.master.runner_tx_hash) - self->_data_priv.master.runner_tx_hash = g_ptr_array_new_with_free_func(g_free); - g_ptr_array_add((GPtrArray *) self->d.master.runner_tx_hash, g_strdup(arr[i])); - } - -out: - return _team_setting_attribute_changed_attr(self, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - changed, - set_field_mode, - reset_json); -} - -guint32 -nm_team_setting_value_master_runner_tx_hash_set_list(NMTeamSetting * self, - const char *const *arr, - guint len) -{ - return _team_setting_value_master_runner_tx_hash_set_list(self, - arr, - len, - SET_FIELD_MODE_SET_UNLESS_DEFAULT, - RESET_JSON_YES); -} - -/*****************************************************************************/ - -#define _LINK_WATCHER_ATTR_GET(args, link_watcher_attribute, _value_type) \ - ({ \ - const NMValueTypUnioMaybe *const _args = (args); \ - \ - nm_assert(link_watcher_attr_datas[(link_watcher_attribute)].value_type == (_value_type)); \ - \ - _args[(link_watcher_attribute)].has \ - ? &_args[(link_watcher_attribute)].val \ - : &link_watcher_attr_datas[(link_watcher_attribute)].default_val; \ - }) -#define _LINK_WATCHER_ATTR_GET_BOOL(args, link_watcher_attribute) \ - (_LINK_WATCHER_ATTR_GET(args, link_watcher_attribute, NM_VALUE_TYPE_BOOL)->v_bool) -#define _LINK_WATCHER_ATTR_GET_INT(args, link_watcher_attribute) \ - (_LINK_WATCHER_ATTR_GET(args, link_watcher_attribute, NM_VALUE_TYPE_INT)->v_int) -#define _LINK_WATCHER_ATTR_GET_STRING(args, link_watcher_attribute) \ - (_LINK_WATCHER_ATTR_GET(args, link_watcher_attribute, NM_VALUE_TYPE_STRING)->v_string) - -#define _LINK_WATCHER_ATTR_SET(args, link_watcher_attribute, _value_type, c_type, val) \ - ({ \ - nm_assert(link_watcher_attr_datas[(link_watcher_attribute)].value_type == (_value_type)); \ - \ - NM_VALUE_TYP_UNIO_MAYBE_SET(&(args)[(link_watcher_attribute)], c_type, (val)); \ - }) -#define _LINK_WATCHER_ATTR_SET_BOOL(args, link_watcher_attribute, val) \ - _LINK_WATCHER_ATTR_SET((args), (link_watcher_attribute), NM_VALUE_TYPE_BOOL, v_bool, (val)) -#define _LINK_WATCHER_ATTR_SET_INT(args, link_watcher_attribute, val) \ - _LINK_WATCHER_ATTR_SET((args), (link_watcher_attribute), NM_VALUE_TYPE_INT, v_int, (val)) -#define _LINK_WATCHER_ATTR_SET_STRING(args, link_watcher_attribute, val) \ - _LINK_WATCHER_ATTR_SET((args), (link_watcher_attribute), NM_VALUE_TYPE_STRING, v_string, (val)) - -static void -_link_watcher_unpack(const NMTeamLinkWatcher *link_watcher, - NMValueTypUnioMaybe args[static G_N_ELEMENTS(link_watcher_attr_datas)]) -{ - const char * v_name = nm_team_link_watcher_get_name(link_watcher); - NMTeamLinkWatcherArpPingFlags v_arp_ping_flags; - - memset(args, 0, sizeof(args[0]) * G_N_ELEMENTS(link_watcher_attr_datas)); - - _LINK_WATCHER_ATTR_SET_STRING(args, LINK_WATCHER_ATTRIBUTE_NAME, v_name); - - if (nm_streq(v_name, NM_TEAM_LINK_WATCHER_ETHTOOL)) { - _LINK_WATCHER_ATTR_SET_INT(args, - LINK_WATCHER_ATTRIBUTE_DELAY_UP, - nm_team_link_watcher_get_delay_up(link_watcher)); - _LINK_WATCHER_ATTR_SET_INT(args, - LINK_WATCHER_ATTRIBUTE_DELAY_DOWN, - nm_team_link_watcher_get_delay_down(link_watcher)); - } else if (NM_IN_STRSET(v_name, - NM_TEAM_LINK_WATCHER_NSNA_PING, - NM_TEAM_LINK_WATCHER_ARP_PING)) { - _LINK_WATCHER_ATTR_SET_INT(args, - LINK_WATCHER_ATTRIBUTE_INIT_WAIT, - nm_team_link_watcher_get_init_wait(link_watcher)); - _LINK_WATCHER_ATTR_SET_INT(args, - LINK_WATCHER_ATTRIBUTE_INTERVAL, - nm_team_link_watcher_get_interval(link_watcher)); - _LINK_WATCHER_ATTR_SET_INT(args, - LINK_WATCHER_ATTRIBUTE_MISSED_MAX, - nm_team_link_watcher_get_missed_max(link_watcher)); - _LINK_WATCHER_ATTR_SET_STRING(args, - LINK_WATCHER_ATTRIBUTE_TARGET_HOST, - nm_team_link_watcher_get_target_host(link_watcher)); - if (nm_streq(v_name, NM_TEAM_LINK_WATCHER_ARP_PING)) { - v_arp_ping_flags = nm_team_link_watcher_get_flags(link_watcher); - _LINK_WATCHER_ATTR_SET_INT(args, - LINK_WATCHER_ATTRIBUTE_VLANID, - nm_team_link_watcher_get_vlanid(link_watcher)); - _LINK_WATCHER_ATTR_SET_STRING(args, - LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, - nm_team_link_watcher_get_source_host(link_watcher)); - _LINK_WATCHER_ATTR_SET_BOOL( - args, - LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, - NM_FLAGS_HAS(v_arp_ping_flags, NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE)); - _LINK_WATCHER_ATTR_SET_BOOL( - args, - LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, - NM_FLAGS_HAS(v_arp_ping_flags, - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE)); - _LINK_WATCHER_ATTR_SET_BOOL( - args, - LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS, - NM_FLAGS_HAS(v_arp_ping_flags, NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS)); - } - } -} - -static void -_link_watcher_to_json(const NMTeamLinkWatcher *link_watcher, GString *gstr) -{ - NMValueTypUnioMaybe args[G_N_ELEMENTS(link_watcher_attr_datas)]; - int i; - gboolean is_first = TRUE; - - if (!link_watcher) { - g_string_append(gstr, "null"); - return; - } - - _link_watcher_unpack(link_watcher, args); - - g_string_append(gstr, "{ "); - - for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) { - const NMValueTypUnioMaybe *p_val = &args[i]; - const LinkWatcherAttrData *attr_data = &link_watcher_attr_datas[i]; - - if (!p_val->has) - continue; - if (nm_value_type_equal(attr_data->value_type, &attr_data->default_val, &p_val->val)) - continue; - - if (is_first) - is_first = FALSE; - else - nm_json_gstr_append_delimiter(gstr); - nm_json_gstr_append_obj_name(gstr, attr_data->js_key, '\0'); - nm_value_type_to_json(attr_data->value_type, gstr, &p_val->val); - } - - g_string_append(gstr, " }"); -} - -static NMTeamLinkWatcher * -_link_watcher_from_json(const NMJsonVt * vt, - const nm_json_t *root_js_obj, - gboolean * out_unrecognized_content) -{ - NMValueTypUnioMaybe args[G_N_ELEMENTS(link_watcher_attr_datas)] = {}; - const char * j_key; - nm_json_t * j_val; - const char * v_name; - NMTeamLinkWatcher * result = NULL; - - if (!nm_json_is_object(root_js_obj)) - goto fail; - - nm_json_object_foreach (vt, (nm_json_t *) root_js_obj, j_key, j_val) { - const LinkWatcherAttrData *attr_data = NULL; - NMValueTypUnioMaybe * parse_result; - - if (j_key) { - int i; - - for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) { - if (nm_streq(link_watcher_attr_datas[i].js_key, j_key)) { - attr_data = &link_watcher_attr_datas[i]; - break; - } - } - } - if (!attr_data) { - *out_unrecognized_content = TRUE; - continue; - } - - parse_result = &args[attr_data->link_watcher_attr]; - - if (parse_result->has) - *out_unrecognized_content = TRUE; - - if (!nm_value_type_from_json(vt, attr_data->value_type, j_val, &parse_result->val)) - *out_unrecognized_content = TRUE; - else - parse_result->has = TRUE; - } - -#define _PARSE_RESULT_HAS_UNEXPECTED_ATTRIBUTES(_parse_results, ...) \ - ({ \ - int _i; \ - \ - for (_i = 0; _i < (int) G_N_ELEMENTS((_parse_results)); _i++) { \ - if ((_parse_results)[_i].has && !NM_IN_SET((LinkWatcherAttribute) _i, __VA_ARGS__)) \ - break; \ - } \ - \ - (_i == (int) G_N_ELEMENTS((_parse_results))); \ - }) - - v_name = _LINK_WATCHER_ATTR_GET_STRING(args, LINK_WATCHER_ATTRIBUTE_NAME); - - if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_ETHTOOL)) { - if (_PARSE_RESULT_HAS_UNEXPECTED_ATTRIBUTES(args, - _EXPECTED_LINK_WATCHER_ATTRIBUTES_ETHTOOL)) - *out_unrecognized_content = TRUE; - result = nm_team_link_watcher_new_ethtool( - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_DELAY_UP), - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_DELAY_DOWN), - NULL); - } else if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_NSNA_PING)) { - if (_PARSE_RESULT_HAS_UNEXPECTED_ATTRIBUTES(args, - _EXPECTED_LINK_WATCHER_ATTRIBUTES_NSNA_PING)) - *out_unrecognized_content = TRUE; - result = nm_team_link_watcher_new_nsna_ping( - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_INIT_WAIT), - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_INTERVAL), - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_MISSED_MAX), - _LINK_WATCHER_ATTR_GET_STRING(args, LINK_WATCHER_ATTRIBUTE_TARGET_HOST), - NULL); - } else if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_ARP_PING)) { - NMTeamLinkWatcherArpPingFlags v_flags = NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE; - - if (_PARSE_RESULT_HAS_UNEXPECTED_ATTRIBUTES(args, - _EXPECTED_LINK_WATCHER_ATTRIBUTES_ARP_PING)) - *out_unrecognized_content = TRUE; - - if (_LINK_WATCHER_ATTR_GET_BOOL(args, LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE)) - v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE; - if (_LINK_WATCHER_ATTR_GET_BOOL(args, LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE)) - v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE; - if (_LINK_WATCHER_ATTR_GET_BOOL(args, LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS)) - v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS; - - result = nm_team_link_watcher_new_arp_ping2( - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_INIT_WAIT), - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_INTERVAL), - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_MISSED_MAX), - _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_VLANID), - _LINK_WATCHER_ATTR_GET_STRING(args, LINK_WATCHER_ATTRIBUTE_TARGET_HOST), - _LINK_WATCHER_ATTR_GET_STRING(args, LINK_WATCHER_ATTRIBUTE_SOURCE_HOST), - v_flags, - NULL); - } - - if (result) - return result; -fail: - *out_unrecognized_content = TRUE; - return NULL; -} - -/*****************************************************************************/ - -static GVariant * -_link_watcher_to_variant(const NMTeamLinkWatcher *link_watcher) -{ - NMValueTypUnioMaybe args[G_N_ELEMENTS(link_watcher_attr_datas)]; - GVariantBuilder builder; - int i; - - if (!link_watcher) - return NULL; - - _link_watcher_unpack(link_watcher, args); - - if (!args[LINK_WATCHER_ATTRIBUTE_NAME].has) - return NULL; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - - for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) { - const NMValueTypUnioMaybe *p_val = &args[i]; - const LinkWatcherAttrData *attr_data = &link_watcher_attr_datas[i]; - GVariant * v; - - if (!p_val->has) - continue; - if (nm_value_type_equal(attr_data->value_type, &attr_data->default_val, &p_val->val)) - continue; - - if (attr_data->value_type == NM_VALUE_TYPE_INT) - v = g_variant_new_int32(p_val->val.v_int); - else { - v = nm_value_type_to_variant(attr_data->value_type, &p_val->val); - } - if (!v) - continue; - - nm_assert(g_variant_is_floating(v)); - g_variant_builder_add(&builder, "{sv}", attr_data->dbus_name, v); - } - - return g_variant_builder_end(&builder); -} - -#define _LINK_WATCHER_ATTR_VARGET(variants, link_watcher_attribute, _value_type, c_type, _cmd) \ - ({ \ - GVariant *const *_variants = (variants); \ - GVariant * _cc; \ - \ - nm_assert(link_watcher_attr_datas[(link_watcher_attribute)].value_type == (_value_type)); \ - \ - (_cc = _variants[(link_watcher_attribute)]) \ - ? (_cmd) \ - : link_watcher_attr_datas[(link_watcher_attribute)].default_val.c_type; \ - }) -#define _LINK_WATCHER_ATTR_VARGET_BOOL(variants, link_watcher_attribute) \ - (_LINK_WATCHER_ATTR_VARGET(variants, \ - link_watcher_attribute, \ - NM_VALUE_TYPE_BOOL, \ - v_bool, \ - g_variant_get_boolean(_cc))) -#define _LINK_WATCHER_ATTR_VARGET_INT(variants, link_watcher_attribute) \ - (_LINK_WATCHER_ATTR_VARGET(variants, \ - link_watcher_attribute, \ - NM_VALUE_TYPE_INT, \ - v_int, \ - g_variant_get_int32(_cc))) -#define _LINK_WATCHER_ATTR_VARGET_STRING(variants, link_watcher_attribute) \ - (_LINK_WATCHER_ATTR_VARGET(variants, \ - link_watcher_attribute, \ - NM_VALUE_TYPE_STRING, \ - v_string, \ - g_variant_get_string(_cc, NULL))) - -static void -_variants_list_link_watcher_unref_auto(GVariant *(*p_variants)[]) -{ - int i; - - for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) - nm_g_variant_unref((*p_variants)[i]); -} - -static NMTeamLinkWatcher * -_link_watcher_from_variant(GVariant *watcher_var, gboolean strict_parsing, GError **error) -{ - nm_auto(_variants_list_link_watcher_unref_auto) - GVariant *variants[G_N_ELEMENTS(link_watcher_attr_datas)] = { - NULL, - }; - const char * v_key; - GVariant * v_val; - const char * v_name; - GVariantIter iter; - - g_return_val_if_fail(g_variant_is_of_type(watcher_var, G_VARIANT_TYPE("a{sv}")), NULL); - - g_variant_iter_init(&iter, watcher_var); - while (g_variant_iter_next(&iter, "{&sv}", &v_key, &v_val)) { - _nm_unused gs_unref_variant GVariant *v_val_free = v_val; - const LinkWatcherAttrData * attr_data = NULL; - const GVariantType * variant_type; - int i; - - for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) { - if (nm_streq(link_watcher_attr_datas[i].dbus_name, v_key)) { - attr_data = &link_watcher_attr_datas[i]; - break; - } - } - if (!attr_data) { - if (strict_parsing) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid D-Bus property \"%s\""), - v_key); - return NULL; - } - continue; - } - - if (attr_data->value_type == NM_VALUE_TYPE_INT) - variant_type = G_VARIANT_TYPE_INT32; - else - variant_type = nm_value_type_get_variant_type(attr_data->value_type); - - if (!g_variant_is_of_type(v_val, variant_type)) { - if (strict_parsing) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid D-Bus property \"%s\""), - v_key); - return NULL; - } - continue; - } - - if (variants[attr_data->link_watcher_attr]) { - if (strict_parsing) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("duplicate D-Bus property \"%s\""), - v_key); - return NULL; - } - g_variant_unref(variants[attr_data->link_watcher_attr]); - } - variants[attr_data->link_watcher_attr] = g_steal_pointer(&v_val_free); - } - -#define _VARIANTS_HAVE_UNEXPECTED_ATTRIBUTES(_type, _variants, _error, ...) \ - ({ \ - int _i; \ - gboolean _has_error = FALSE; \ - \ - for (_i = 0; _i < (int) G_N_ELEMENTS((_variants)); _i++) { \ - if ((_variants)[_i] && !NM_IN_SET((LinkWatcherAttribute) _i, __VA_ARGS__)) { \ - _has_error = TRUE; \ - g_set_error(_error, \ - NM_CONNECTION_ERROR, \ - NM_CONNECTION_ERROR_INVALID_PROPERTY, \ - _("invalid D-Bus property \"%s\" for \"%s\""), \ - link_watcher_attr_datas[_i].dbus_name, \ - _type); \ - break; \ - } \ - } \ - \ - _has_error; \ - }) - - v_name = _LINK_WATCHER_ATTR_VARGET_STRING(variants, LINK_WATCHER_ATTRIBUTE_NAME); - - if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_ETHTOOL)) { - if (strict_parsing - && _VARIANTS_HAVE_UNEXPECTED_ATTRIBUTES(v_name, - variants, - error, - _EXPECTED_LINK_WATCHER_ATTRIBUTES_ETHTOOL)) - return NULL; - return nm_team_link_watcher_new_ethtool( - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_DELAY_UP), - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_DELAY_DOWN), - strict_parsing ? error : NULL); - } - - if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_NSNA_PING)) { - if (strict_parsing - && _VARIANTS_HAVE_UNEXPECTED_ATTRIBUTES(v_name, - variants, - error, - _EXPECTED_LINK_WATCHER_ATTRIBUTES_NSNA_PING)) - return NULL; - return nm_team_link_watcher_new_nsna_ping( - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_INIT_WAIT), - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_INTERVAL), - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_MISSED_MAX), - _LINK_WATCHER_ATTR_VARGET_STRING(variants, LINK_WATCHER_ATTRIBUTE_TARGET_HOST), - strict_parsing ? error : NULL); - } - - if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_ARP_PING)) { - NMTeamLinkWatcherArpPingFlags v_flags = NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE; - - if (strict_parsing - && _VARIANTS_HAVE_UNEXPECTED_ATTRIBUTES(v_name, - variants, - error, - _EXPECTED_LINK_WATCHER_ATTRIBUTES_ARP_PING)) - return NULL; - - if (_LINK_WATCHER_ATTR_VARGET_BOOL(variants, LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE)) - v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE; - if (_LINK_WATCHER_ATTR_VARGET_BOOL(variants, LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE)) - v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE; - if (_LINK_WATCHER_ATTR_VARGET_BOOL(variants, LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS)) - v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS; - - return nm_team_link_watcher_new_arp_ping2( - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_INIT_WAIT), - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_INTERVAL), - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_MISSED_MAX), - _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_VLANID), - _LINK_WATCHER_ATTR_VARGET_STRING(variants, LINK_WATCHER_ATTRIBUTE_TARGET_HOST), - _LINK_WATCHER_ATTR_VARGET_STRING(variants, LINK_WATCHER_ATTRIBUTE_SOURCE_HOST), - v_flags, - strict_parsing ? error : NULL); - } - - if (strict_parsing) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("unknown link-watcher name \"%s\""), - v_name); - } - return NULL; -} - -/*****************************************************************************/ - -/** - * _nm_utils_team_link_watchers_to_variant: - * @link_watchers: (element-type NMTeamLinkWatcher): array of #NMTeamLinkWatcher - * - * Utility function to convert a #GPtrArray of #NMTeamLinkWatcher objects - * representing link watcher configuration for team devices into a #GVariant - * of type 'aa{sv}' representing an array of link watchers. - * - * Returns: (transfer full): a new floating #GVariant representing link watchers. - **/ -GVariant * -_nm_utils_team_link_watchers_to_variant(const GPtrArray *link_watchers) -{ - GVariantBuilder builder; - guint i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - if (link_watchers) { - for (i = 0; i < link_watchers->len; i++) { - g_variant_builder_add(&builder, - "@a{sv}", - _link_watcher_to_variant(link_watchers->pdata[i])); - } - } - return g_variant_builder_end(&builder); -} - -/** - * _nm_utils_team_link_watchers_from_variant: - * @value: a #GVariant of type 'aa{sv}' - * @strict_parsing: whether to parse strictly or ignore everything invalid. - * @error: error reason. - * - * Utility function to convert a #GVariant representing a list of team link - * watchers int a #GPtrArray of #NMTeamLinkWatcher objects. - * - * Returns: (transfer full) (element-type NMTeamLinkWatcher): a newly allocated - * #GPtrArray of #NMTeamLinkWatcher objects. - * - * Note that if you provide an @error, then the function can only fail (and return %NULL) - * or succeed (and not return %NULL). If you don't provide an @error, then the function - * never returns %NULL. - **/ -GPtrArray * -_nm_utils_team_link_watchers_from_variant(GVariant *value, gboolean strict_parsing, GError **error) -{ - gs_unref_ptrarray GPtrArray *link_watchers = NULL; - GVariantIter iter; - GVariant * watcher_var; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); - - link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); - - g_variant_iter_init(&iter, value); - while (g_variant_iter_next(&iter, "@a{sv}", &watcher_var)) { - _nm_unused gs_unref_variant GVariant *watcher_var_free = watcher_var; - NMTeamLinkWatcher * watcher; - - watcher = _link_watcher_from_variant(watcher_var, strict_parsing, error); - if (error && *error) - return NULL; - if (watcher) - g_ptr_array_add(link_watchers, watcher); - } - - return g_steal_pointer(&link_watchers); -} - -/*****************************************************************************/ - -const char * -nm_team_setting_config_get(const NMTeamSetting *self) -{ - char *js_str; - - nm_assert(self); - - if (G_LIKELY(!self->d._js_str_need_synthetize)) - return self->d._js_str; - - nm_assert(!self->d._js_str); - nm_assert(self->d.strict_validated); - - if (_team_setting_check_default(self) == 0) { - /* the default is set. We signal this as a NULL JSON string. - * Nothing to do. */ - js_str = NULL; - } else { - gboolean list_is_empty = TRUE; - GString *gstr; - - gstr = g_string_new(NULL); - - g_string_append(gstr, "{ "); - - if (self->d.is_port) { - static const NMTeamAttribute attr_lst_port[] = { - NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID, - NM_TEAM_ATTRIBUTE_PORT_PRIO, - NM_TEAM_ATTRIBUTE_PORT_STICKY, - NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, - NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, - }; - - if (_team_setting_fields_to_json_maybe(self, - gstr, - !list_is_empty, - attr_lst_port, - G_N_ELEMENTS(attr_lst_port))) - list_is_empty = FALSE; - } else { - static const NMTeamAttribute attr_lst_runner_pt1[] = { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - }; - static const NMTeamAttribute attr_lst_runner_pt2[] = { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, - }; - static const NMTeamAttribute attr_lst_runner_pt3[] = { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, - }; - static const NMTeamAttribute attr_lst_notify_peers[] = { - NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT, - NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, - }; - static const NMTeamAttribute attr_lst_mcast_rejoin[] = { - NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, - NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, - }; - - if (_team_setting_has_fields_any_v(self, - attr_lst_runner_pt1, - G_N_ELEMENTS(attr_lst_runner_pt1)) - || _team_setting_has_fields_any_v(self, - attr_lst_runner_pt2, - G_N_ELEMENTS(attr_lst_runner_pt2)) - || _team_setting_has_fields_any_v(self, - attr_lst_runner_pt3, - G_N_ELEMENTS(attr_lst_runner_pt3))) { - gboolean list_is_empty2 = TRUE; - - nm_assert(list_is_empty); - - nm_json_gstr_append_obj_name(gstr, "runner", '{'); - - if (_team_setting_fields_to_json_maybe(self, - gstr, - !list_is_empty2, - attr_lst_runner_pt1, - G_N_ELEMENTS(attr_lst_runner_pt1))) - list_is_empty2 = FALSE; - - if (_team_setting_has_fields_any_v(self, - attr_lst_runner_pt2, - G_N_ELEMENTS(attr_lst_runner_pt2))) { - if (!list_is_empty2) - nm_json_gstr_append_delimiter(gstr); - nm_json_gstr_append_obj_name(gstr, "tx_balancer", '{'); - if (!_team_setting_fields_to_json_maybe(self, - gstr, - FALSE, - attr_lst_runner_pt2, - G_N_ELEMENTS(attr_lst_runner_pt2))) - nm_assert_not_reached(); - g_string_append(gstr, " }"); - list_is_empty2 = FALSE; - } - - if (_team_setting_fields_to_json_maybe(self, - gstr, - !list_is_empty2, - attr_lst_runner_pt3, - G_N_ELEMENTS(attr_lst_runner_pt3))) - list_is_empty2 = FALSE; - - nm_assert(!list_is_empty2); - g_string_append(gstr, " }"); - list_is_empty = FALSE; - } - - if (_team_setting_has_fields_any_v(self, - attr_lst_notify_peers, - G_N_ELEMENTS(attr_lst_notify_peers))) { - if (!list_is_empty) - nm_json_gstr_append_delimiter(gstr); - nm_json_gstr_append_obj_name(gstr, "notify_peers", '{'); - if (!_team_setting_fields_to_json_maybe(self, - gstr, - FALSE, - attr_lst_notify_peers, - G_N_ELEMENTS(attr_lst_notify_peers))) - nm_assert_not_reached(); - g_string_append(gstr, " }"); - list_is_empty = FALSE; - } - - if (_team_setting_has_fields_any_v(self, - attr_lst_mcast_rejoin, - G_N_ELEMENTS(attr_lst_mcast_rejoin))) { - if (!list_is_empty) - nm_json_gstr_append_delimiter(gstr); - nm_json_gstr_append_obj_name(gstr, "mcast_rejoin", '{'); - if (!_team_setting_fields_to_json_maybe(self, - gstr, - FALSE, - attr_lst_mcast_rejoin, - G_N_ELEMENTS(attr_lst_mcast_rejoin))) - nm_assert_not_reached(); - g_string_append(gstr, " }"); - list_is_empty = FALSE; - } - } - - if (_team_setting_field_to_json( - self, - gstr, - !list_is_empty, - _team_attr_data_get(self->d.is_port, NM_TEAM_ATTRIBUTE_LINK_WATCHERS))) - list_is_empty = FALSE; - - if (!list_is_empty) - g_string_append(gstr, " }"); - - js_str = g_string_free(gstr, list_is_empty); - } - - /* mutate the constant object. In C++ speak, these fields are "mutable". - * That is because we construct the JSON string lazily/on-demand. */ - *((char **) &self->_data_priv._js_str) = js_str; - *((bool *) &self->_data_priv._js_str_need_synthetize) = FALSE; - - return self->d._js_str; -} - -/*****************************************************************************/ - -static gboolean -_attr_data_match_keys(const TeamAttrData *attr_data, const char *const *keys, guint8 n_keys) -{ - guint8 i; - - _team_attr_data_ASSERT(attr_data); - nm_assert(keys); - nm_assert(n_keys > 0); - nm_assert(({ - gboolean all_non_null = TRUE; - - for (i = 0; i < n_keys; i++) - all_non_null = all_non_null && keys[i] && keys[i][0] != '\0'; - all_non_null; - })); - - if (attr_data->js_keys_len < n_keys) - return FALSE; - for (i = 0; i < n_keys; i++) { - if (!nm_streq(keys[i], attr_data->js_keys[i])) - return FALSE; - } - return TRUE; -} - -static const TeamAttrData * -_attr_data_find_by_json_key(gboolean is_port, const char *const *keys, guint8 n_keys) -{ - const TeamAttrData *attr_data; - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; - attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) { - if (_team_attr_data_is_relevant(attr_data, is_port) - && _attr_data_match_keys(attr_data, keys, n_keys)) - return attr_data; - } - - return NULL; -} - -static void -_js_parse_locate_keys(const NMJsonVt *vt, - NMTeamSetting * self, - nm_json_t * root_js_obj, - nm_json_t * found_keys[static _NM_TEAM_ATTRIBUTE_NUM], - gboolean * out_unrecognized_content) -{ - const char *keys[3]; - const char *cur_key1; - const char *cur_key2; - const char *cur_key3; - nm_json_t * cur_val1; - nm_json_t * cur_val2; - nm_json_t * cur_val3; - - nm_assert(vt); - -#define _handle(_self, _cur_key, _cur_val, _keys, _level, _found_keys, _out_unrecognized_content) \ - ({ \ - const TeamAttrData *_attr_data; \ - gboolean _handled = FALSE; \ - \ - (_keys)[(_level) -1] = (_cur_key); \ - _attr_data = _attr_data_find_by_json_key((_self)->d.is_port, (_keys), (_level)); \ - if (_attr_data && _attr_data->js_keys_len == (_level)) { \ - if ((_found_keys)[_attr_data->team_attr]) \ - *(_out_unrecognized_content) = TRUE; \ - (_found_keys)[_attr_data->team_attr] = (_cur_val); \ - _handled = TRUE; \ - } else if (!_attr_data || !nm_json_is_object((_cur_val))) { \ - *(_out_unrecognized_content) = TRUE; \ - _handled = TRUE; \ - } \ - _handled; \ - }) - - nm_json_object_foreach (vt, root_js_obj, cur_key1, cur_val1) { - if (!_handle(self, cur_key1, cur_val1, keys, 1, found_keys, out_unrecognized_content)) { - nm_json_object_foreach (vt, cur_val1, cur_key2, cur_val2) { - if (!_handle(self, - cur_key2, - cur_val2, - keys, - 2, - found_keys, - out_unrecognized_content)) { - nm_json_object_foreach (vt, cur_val2, cur_key3, cur_val3) { - if (!_handle(self, - cur_key3, - cur_val3, - keys, - 3, - found_keys, - out_unrecognized_content)) - *out_unrecognized_content = TRUE; - } - } - } - } - } - -#undef _handle -} - -static void -_js_parse_unpack(const NMJsonVt *vt, - gboolean is_port, - nm_json_t * found_keys[static _NM_TEAM_ATTRIBUTE_NUM], - bool out_has_lst[static _NM_TEAM_ATTRIBUTE_NUM], - NMValueTypUnion out_val_lst[static _NM_TEAM_ATTRIBUTE_NUM], - gboolean * out_unrecognized_content, - GPtrArray ** out_ptr_array_link_watchers_free, - GPtrArray ** out_ptr_array_master_runner_tx_hash_free) -{ - const TeamAttrData *attr_data; - - nm_assert(vt); - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; - attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) { - NMValueTypUnion *p_out_val; - gboolean valid = FALSE; - nm_json_t * arg_js_obj; - - if (!_team_attr_data_is_relevant(attr_data, is_port)) - continue; - - nm_assert(!out_has_lst[attr_data->team_attr]); - - arg_js_obj = found_keys[attr_data->team_attr]; - if (!arg_js_obj) - continue; - - p_out_val = &out_val_lst[attr_data->team_attr]; - - if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) - valid = nm_value_type_from_json(vt, attr_data->value_type, arg_js_obj, p_out_val); - else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { - GPtrArray * link_watchers = NULL; - NMTeamLinkWatcher *link_watcher; - - nm_assert(out_ptr_array_link_watchers_free && !*out_ptr_array_link_watchers_free); - if (nm_json_is_array(arg_js_obj)) { - gsize i, len; - - len = vt->nm_json_array_size(arg_js_obj); - link_watchers = - g_ptr_array_new_full(len, (GDestroyNotify) nm_team_link_watcher_unref); - for (i = 0; i < len; i++) { - link_watcher = _link_watcher_from_json(vt, - vt->nm_json_array_get(arg_js_obj, i), - out_unrecognized_content); - if (link_watcher) - g_ptr_array_add(link_watchers, link_watcher); - } - } else { - link_watcher = _link_watcher_from_json(vt, arg_js_obj, out_unrecognized_content); - if (link_watcher) { - link_watchers = - g_ptr_array_new_full(1, (GDestroyNotify) nm_team_link_watcher_unref); - g_ptr_array_add(link_watchers, link_watcher); - } - } - if (link_watchers) { - valid = TRUE; - p_out_val->v_ptrarray = link_watchers; - *out_ptr_array_link_watchers_free = link_watchers; - } - } else if (!is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { - GPtrArray *strv = NULL; - - nm_assert(out_ptr_array_master_runner_tx_hash_free - && !*out_ptr_array_master_runner_tx_hash_free); - if (nm_json_is_array(arg_js_obj)) { - gsize i, len; - - len = vt->nm_json_array_size(arg_js_obj); - if (len > 0) { - strv = g_ptr_array_sized_new(len); - for (i = 0; i < len; i++) { - const char *v_string; - - if (nm_jansson_json_as_string(vt, - vt->nm_json_array_get(arg_js_obj, i), - &v_string) - <= 0 - || !v_string || v_string[0] == '\0') { - /* we remember that there was some invalid content, but parts of the - * list could still be parsed. */ - *out_unrecognized_content = TRUE; - continue; - } - g_ptr_array_add(strv, (char *) v_string); - } - } - valid = TRUE; - *out_ptr_array_master_runner_tx_hash_free = strv; - } - p_out_val->v_ptrarray = strv; - } else - nm_assert_not_reached(); - - out_has_lst[attr_data->team_attr] = valid; - if (!valid) - *out_unrecognized_content = TRUE; - } -} - -guint32 -nm_team_setting_config_set(NMTeamSetting *self, const char *js_str) -{ - const NMJsonVt *vt; - guint32 changed_flags = 0; - gboolean do_set_default = TRUE; - gboolean new_js_str_invalid = FALSE; - - _team_setting_ASSERT(self); - - if (!js_str || js_str[0] == '\0') { - changed_flags = _team_setting_set_default(self); - if (changed_flags != 0 || !nm_streq0(js_str, self->d._js_str)) - changed_flags |= nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); - nm_clear_g_free((char **) &self->_data_priv._js_str); - self->_data_priv._js_str = g_strdup(js_str); - self->_data_priv._js_str_need_synthetize = FALSE; - self->_data_priv.strict_validated = TRUE; - self->_data_priv.js_str_invalid = FALSE; - return changed_flags; - } - - if (self->d._js_str && nm_streq(js_str, self->d._js_str)) { - if (!self->d.strict_validated) { - /* setting the same JSON string twice in a row has no effect. */ - return 0; - } - } else - changed_flags |= nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); - - if ((vt = nm_json_vt())) { - nm_auto_decref_json nm_json_t *root_js_obj = NULL; - - root_js_obj = vt->nm_json_loads(js_str, 0, NULL); - if (!root_js_obj || !nm_json_is_object(root_js_obj)) - new_js_str_invalid = TRUE; - else { - gboolean unrecognized_content = FALSE; - bool has_lst[_NM_TEAM_ATTRIBUTE_NUM] = { - FALSE, - }; - NMValueTypUnion val_lst[_NM_TEAM_ATTRIBUTE_NUM]; - nm_json_t * found_keys[_NM_TEAM_ATTRIBUTE_NUM] = { - NULL, - }; - gs_unref_ptrarray GPtrArray *ptr_array_master_runner_tx_hash_free = NULL; - gs_unref_ptrarray GPtrArray *ptr_array_link_watchers_free = NULL; - - _js_parse_locate_keys(vt, self, root_js_obj, found_keys, &unrecognized_content); - - _js_parse_unpack(vt, - self->d.is_port, - found_keys, - has_lst, - val_lst, - &unrecognized_content, - &ptr_array_link_watchers_free, - &ptr_array_master_runner_tx_hash_free); - - do_set_default = FALSE; - - changed_flags |= _team_setting_set(self, TRUE, has_lst, val_lst); - } - } - - if (do_set_default) - changed_flags |= _team_setting_set_default(self); - - self->_data_priv.strict_validated = FALSE; - self->_data_priv._js_str_need_synthetize = FALSE; - self->_data_priv.js_str_invalid = new_js_str_invalid; - g_free((char *) self->_data_priv._js_str); - self->_data_priv._js_str = g_strdup(js_str); - - return changed_flags; -} - -/*****************************************************************************/ - -static void -_team_setting_prefix_error_plain(gboolean is_port, const char *property_name, GError **error) -{ - g_prefix_error(error, - "%s.%s: ", - is_port ? NM_SETTING_TEAM_PORT_SETTING_NAME : NM_SETTING_TEAM_SETTING_NAME, - property_name); -} - -static void -_team_setting_prefix_error(const NMTeamSetting *self, - const char * prop_name_master, - const char * prop_name_port, - GError ** error) -{ - _team_setting_ASSERT(self); - nm_assert(self->d.is_port ? (!!prop_name_port) : (!!prop_name_master)); - _team_setting_prefix_error_plain(self->d.is_port, - self->d.is_port ? prop_name_port : prop_name_master, - error); -} - -static gboolean -_team_setting_verify_properties(const NMTeamSetting *self, GError **error) -{ - const TeamAttrData *attr_data; - guint i; - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; - attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) { - if (!_team_attr_data_is_relevant(attr_data, self->d.is_port)) - continue; - if (!_team_setting_has_field(self, attr_data)) - continue; - - if (attr_data->has_range) { - gconstpointer p_field; - - p_field = _team_setting_get_field(self, attr_data); - if (attr_data->value_type == NM_VALUE_TYPE_INT32) { - gint32 v = *((const gint32 *) p_field); - - if (v < attr_data->range.r_int32.min || v > attr_data->range.r_int32.max) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("value out or range")); - _team_setting_prefix_error_plain(self->d.is_port, - attr_data->property_name, - error); - return FALSE; - } - } else if (attr_data->value_type == NM_VALUE_TYPE_STRING) { - const char *v = *((const char *const *) p_field); - - if (nm_utils_strv_find_first((char **) attr_data->range.r_string.valid_names, -1, v) - < 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("invalid value")); - _team_setting_prefix_error_plain(self->d.is_port, - attr_data->property_name, - error); - return FALSE; - } - } else - nm_assert_not_reached(); - } - - if (!self->d.is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { - if (self->d.master.runner_tx_hash) { - for (i = 0; i < self->d.master.runner_tx_hash->len; i++) { - const char *val = self->d.master.runner_tx_hash->pdata[i]; - - if (!val - || (nm_utils_strv_find_first((char **) _valid_names_runner_tx_hash, -1, val) - < 0)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("invalid runner-tx-hash")); - _team_setting_prefix_error_plain(self->d.is_port, - NM_SETTING_TEAM_RUNNER_TX_HASH, - error); - return FALSE; - } - } - } - } - } - - if (!self->d.is_port) { - for (i = 0; i < G_N_ELEMENTS(_runner_compat_lst); i++) { - const RunnerCompatElem *e = &_runner_compat_lst[i]; - - nm_assert(NM_PTRARRAY_LEN(e->valid_runners) > 0); - - attr_data = _team_attr_data_get(FALSE, e->team_attr); - - if (!_team_setting_has_field(self, attr_data)) - continue; - if (self->d.master.runner - && (nm_utils_strv_find_first((char **) e->valid_runners, -1, self->d.master.runner) - >= 0)) - continue; - if (e->valid_runners[1] == NULL) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("%s is only allowed for runner %s"), - attr_data->property_name, - e->valid_runners[0]); - } else { - gs_free char *s = NULL; - - s = g_strjoinv(",", (char **) e->valid_runners); - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("%s is only allowed for runners %s"), - attr_data->property_name, - s); - } - _team_setting_prefix_error_plain(self->d.is_port, NM_SETTING_TEAM_RUNNER, error); - return FALSE; - } - } else { - gboolean has_lacp_attrs; - gboolean has_activebackup_attrs; - - has_lacp_attrs = _team_setting_has_fields_any(self, - NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, - NM_TEAM_ATTRIBUTE_PORT_LACP_KEY); - has_activebackup_attrs = _team_setting_has_fields_any(self, - NM_TEAM_ATTRIBUTE_PORT_PRIO, - NM_TEAM_ATTRIBUTE_PORT_STICKY); - if (has_lacp_attrs && has_activebackup_attrs) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("cannot set parameters for lacp and activebackup runners together")); - _team_setting_prefix_error(self, - NM_SETTING_TEAM_LINK_WATCHERS, - NM_SETTING_TEAM_PORT_LINK_WATCHERS, - error); - return FALSE; - } - } - - for (i = 0; i < self->d.link_watchers->len; i++) { - if (!self->d.link_watchers->pdata[i]) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("missing link watcher")); - _team_setting_prefix_error(self, - NM_SETTING_TEAM_LINK_WATCHERS, - NM_SETTING_TEAM_PORT_LINK_WATCHERS, - error); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -_team_setting_verify_config(const NMTeamSetting *self, GError **error) -{ - const char *js_str; - - /* we always materialize the JSON string. That is because we want to validate the - * string length of the resulting JSON. */ - js_str = nm_team_setting_config_get(self); - - if (js_str) { - if (strlen(js_str) > 1 * 1024 * 1024) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("team config exceeds size limit")); - _team_setting_prefix_error(self, - NM_SETTING_TEAM_CONFIG, - NM_SETTING_TEAM_PORT_CONFIG, - error); - return FALSE; - } - if (!g_utf8_validate(js_str, -1, NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("team config is not valid UTF-8")); - _team_setting_prefix_error(self, - NM_SETTING_TEAM_CONFIG, - NM_SETTING_TEAM_PORT_CONFIG, - error); - return FALSE; - } - if (self->d.js_str_invalid) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid json")); - _team_setting_prefix_error(self, - NM_SETTING_TEAM_CONFIG, - NM_SETTING_TEAM_PORT_CONFIG, - error); - return FALSE; - } - } - - return TRUE; -} - -gboolean -nm_team_setting_verify(const NMTeamSetting *self, GError **error) -{ - if (self->d.strict_validated) { - if (!_team_setting_verify_properties(self, error)) - return FALSE; - } - return _team_setting_verify_config(self, error); -} - -/*****************************************************************************/ - -int -nm_team_setting_cmp(const NMTeamSetting *self_a, - const NMTeamSetting *self_b, - gboolean ignore_js_str) -{ - const TeamAttrData *attr_data; - - NM_CMP_SELF(self_a, self_b); - - NM_CMP_FIELD_UNSAFE(self_a, self_b, d.is_port); - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; - attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) { - if (!_team_attr_data_is_relevant(attr_data, self_a->d.is_port)) - continue; - - NM_CMP_RETURN(_team_attr_data_cmp(attr_data, - self_a->d.is_port, - _team_setting_get_field(self_a, attr_data), - _team_setting_get_field(self_b, attr_data))); - } - - if (!ignore_js_str) { - NM_CMP_DIRECT_STRCMP0(nm_team_setting_config_get(self_a), - nm_team_setting_config_get(self_b)); - } - - return 0; -} - -guint32 -nm_team_setting_reset(NMTeamSetting *self, const NMTeamSetting *src) -{ - const TeamAttrData *attr_data; - guint32 changed_flags; - - _team_setting_ASSERT(self); - _team_setting_ASSERT(src); - nm_assert(self->d.is_port == src->d.is_port); - - if (self == src) - return 0; - - changed_flags = 0; - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; - attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) { - if (!_team_attr_data_is_relevant(attr_data, self->d.is_port)) - continue; - if (_team_attr_data_equal(attr_data, - self->d.is_port, - _team_setting_get_field(self, attr_data), - _team_setting_get_field(src, attr_data))) - continue; - _team_attr_data_copy(attr_data, - self->d.is_port, - _team_setting_get_field(self, attr_data), - _team_setting_get_field(src, attr_data)); - changed_flags |= nm_team_attribute_to_flags(attr_data->team_attr); - } - - self->_data_priv.has_fields_mask = src->d.has_fields_mask; - - if (!nm_streq0(self->d._js_str, src->d._js_str)) { - g_free((char *) self->_data_priv._js_str); - self->_data_priv._js_str = g_strdup(src->d._js_str); - changed_flags |= nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); - } else if (changed_flags != 0) - changed_flags |= nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); - - self->_data_priv._js_str_need_synthetize = src->d._js_str_need_synthetize; - self->_data_priv.strict_validated = src->d.strict_validated; - self->_data_priv.js_str_invalid = src->d.js_str_invalid; - - return changed_flags; -} - -static void -_variants_list_team_unref_auto(GVariant *(*p_variants)[]) -{ - int i; - - for (i = 0; i < _NM_TEAM_ATTRIBUTE_NUM; i++) - nm_g_variant_unref((*p_variants)[i]); -} - -gboolean -nm_team_setting_reset_from_dbus(NMTeamSetting * self, - GVariant * setting_dict, - GHashTable * keys, - guint32 * out_changed, - guint /* NMSettingParseFlags */ parse_flags, - GError ** error) -{ - nm_auto(_variants_list_team_unref_auto) GVariant *variants[_NM_TEAM_ATTRIBUTE_NUM] = { - NULL, - }; - gs_unref_ptrarray GPtrArray *v_link_watchers = NULL; - const TeamAttrData * attr_data; - GVariantIter iter; - const char * v_key; - GVariant * v_val; - const NMJsonVt * vt; - - *out_changed = 0; - - g_variant_iter_init(&iter, setting_dict); - while (g_variant_iter_next(&iter, "{&sv}", &v_key, &v_val)) { - _nm_unused gs_unref_variant GVariant *v_val_free = v_val; - const GVariantType * variant_type = NULL; - - attr_data = _team_attr_data_find_for_property_name(self->d.is_port, v_key); - if (!attr_data) { - /* _nm_setting_new_from_dbus() already checks for unknown keys. Don't - * do that here. */ - continue; - } - - if (keys) - g_hash_table_remove(keys, v_key); - - if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) - variant_type = nm_value_type_get_variant_type(attr_data->value_type); - else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_CONFIG) - variant_type = G_VARIANT_TYPE_STRING; - else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) - variant_type = G_VARIANT_TYPE("aa{sv}"); - else if (!self->d.is_port - && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) - variant_type = G_VARIANT_TYPE_STRING_ARRAY; - else - nm_assert_not_reached(); - - if (!g_variant_is_of_type(v_val, variant_type)) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid D-Bus type \"%s\""), - g_variant_get_type_string(v_val)); - _team_setting_prefix_error_plain(self->d.is_port, attr_data->property_name, error); - return FALSE; - } - continue; - } - - /* _nm_setting_new_from_dbus() already checks for duplicate keys. Don't - * do that here. */ - nm_g_variant_unref(variants[attr_data->team_attr]); - variants[attr_data->team_attr] = g_steal_pointer(&v_val_free); - } - - vt = nm_json_vt(); - - if (variants[NM_TEAM_ATTRIBUTE_LINK_WATCHERS]) { - if (variants[NM_TEAM_ATTRIBUTE_CONFIG] && vt - && !NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - /* we don't require the content of the "link-watchers" and we also - * don't perform strict validation. No need to parse it. */ - } else { - gs_free_error GError *local = NULL; - - /* We might need the parsed v_link_watchers array below (because there is no JSON - * "config" present or because we don't have json support). - * - * Or we might run with NM_SETTING_PARSE_FLAGS_STRICT. In that mode, we may not necessarily - * require that the entire setting as a whole validates (if a JSON config is present and - * we are not "strict_validated") , but we require that we can at least parse the link watchers - * on their own. */ - v_link_watchers = _nm_utils_team_link_watchers_from_variant( - variants[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], - NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT), - &local); - if (local && NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid link-watchers: %s"), - local->message); - _team_setting_prefix_error(self, - NM_SETTING_TEAM_LINK_WATCHERS, - NM_SETTING_TEAM_PORT_LINK_WATCHERS, - error); - return FALSE; - } - } - } - - *out_changed |= nm_team_setting_config_set( - self, - variants[NM_TEAM_ATTRIBUTE_CONFIG] - ? g_variant_get_string(variants[NM_TEAM_ATTRIBUTE_CONFIG], NULL) - : NULL); - - if (vt && variants[NM_TEAM_ATTRIBUTE_CONFIG]) { - /* for team settings, the JSON must be able to express all possible options. That means, - * if the GVariant contains both the JSON "config" and other options, then the other options - * are silently ignored. */ - } else { - guint32 extra_changed = 0u; - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; - attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; - attr_data++) { - NMValueTypUnion val; - guint32 changed_flags = 0u; - - if (!_team_attr_data_is_relevant(attr_data, self->d.is_port)) - continue; - if (!variants[attr_data->team_attr]) - continue; - - if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) { - nm_value_type_get_from_variant(attr_data->value_type, - &val, - variants[attr_data->team_attr], - FALSE); - changed_flags = _team_setting_value_set(self, - attr_data, - &val, - SET_FIELD_MODE_SET, - RESET_JSON_NO); - } else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { - changed_flags = _team_setting_value_link_watchers_set_list( - self, - v_link_watchers ? (const NMTeamLinkWatcher *const *) v_link_watchers->pdata - : NULL, - v_link_watchers ? v_link_watchers->len : 0u, - SET_FIELD_MODE_SET, - RESET_JSON_NO); - } else if (!self->d.is_port - && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { - gs_free const char **strv = NULL; - gsize len; - - strv = g_variant_get_strv(variants[attr_data->team_attr], &len); - changed_flags = _team_setting_value_master_runner_tx_hash_set_list( - self, - strv, - NM_MIN(len, (gsize) G_MAXUINT), - SET_FIELD_MODE_SET, - RESET_JSON_NO); - } else - nm_assert_not_reached(); - - extra_changed |= changed_flags; - } - - if (!variants[NM_TEAM_ATTRIBUTE_CONFIG]) { - /* clear the JSON string so it can be regenerated. But only if we didn't set - * it above. */ - self->_data_priv.strict_validated = TRUE; - self->_data_priv._js_str_need_synthetize = TRUE; - } - - *out_changed |= extra_changed; - } - - return TRUE; -} - -/*****************************************************************************/ - -gboolean -nm_team_setting_maybe_changed(NMSetting * source, - const GParamSpec *const *obj_properties, - guint32 changed_flags) -{ - NMTeamAttribute team_attr; - int count_flags; - guint32 ch; - - if (changed_flags == 0u) - return FALSE; - - count_flags = 0; - for (ch = changed_flags; ch != 0u; ch >>= 1) { - if (NM_FLAGS_HAS(ch, 0x1u)) - count_flags++; - } - - if (count_flags > 1) - g_object_freeze_notify(G_OBJECT(source)); - - ch = changed_flags; - for (team_attr = 0; team_attr < _NM_TEAM_ATTRIBUTE_NUM; team_attr++) { - if (!NM_FLAGS_ANY(ch, nm_team_attribute_to_flags(team_attr))) - continue; - g_object_notify_by_pspec(G_OBJECT(source), (GParamSpec *) obj_properties[team_attr]); - ch &= ~nm_team_attribute_to_flags(team_attr); - if (ch == 0) - break; - } - - if (count_flags > 1) - g_object_thaw_notify(G_OBJECT(source)); - - return TRUE; -} - -/*****************************************************************************/ - -NMTeamSetting * -_nm_setting_get_team_setting(struct _NMSetting *setting) -{ - if (NM_IS_SETTING_TEAM(setting)) - return _nm_setting_team_get_team_setting(NM_SETTING_TEAM(setting)); - return _nm_setting_team_port_get_team_setting(NM_SETTING_TEAM_PORT(setting)); -} - -static GVariant * -_nm_team_settings_property_to_dbus(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMTeamSetting * self = _nm_setting_get_team_setting(setting); - const TeamAttrData *attr_data = - _team_attr_data_get(self->d.is_port, - sett_info->property_infos[property_idx].param_spec->param_id); - - if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_CONFIG) { - const char *config; - - if (self->d.strict_validated && !_nm_utils_is_manager_process) { - /* if we are in strict validating mode on the client side, the JSON is generated - * artificially. In this case, don't send the config via D-Bus to the server. - * - * This also will cause NetworkManager to strictly validate the settings. - * If a JSON "config" is present, strict validation won't be performed. */ - return NULL; - } - - config = nm_team_setting_config_get(self); - return config ? g_variant_new_string(config) : NULL; - } - - if (!_team_setting_has_field(self, attr_data)) - return NULL; - - if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) { - return nm_value_type_to_variant(attr_data->value_type, - _team_setting_get_field(self, attr_data)); - } - if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) - return _nm_utils_team_link_watchers_to_variant(self->d.link_watchers); - if (!self->d.is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { - return g_variant_new_strv(self->d.master.runner_tx_hash - ? (const char *const *) self->d.master.runner_tx_hash->pdata - : NULL, - self->d.master.runner_tx_hash ? self->d.master.runner_tx_hash->len - : 0u); - } - - nm_assert_not_reached(); - return NULL; -} - -static void -_nm_team_settings_property_from_dbus_link_watchers(GVariant *dbus_value, GValue *prop_value) -{ - g_value_take_boxed(prop_value, - _nm_utils_team_link_watchers_from_variant(dbus_value, FALSE, NULL)); -} - -const NMSettInfoPropertType nm_sett_info_propert_type_team_b = { - .dbus_type = G_VARIANT_TYPE_BOOLEAN, - .to_dbus_fcn = _nm_team_settings_property_to_dbus, -}; - -const NMSettInfoPropertType nm_sett_info_propert_type_team_i = { - .dbus_type = G_VARIANT_TYPE_INT32, - .to_dbus_fcn = _nm_team_settings_property_to_dbus, -}; - -const NMSettInfoPropertType nm_sett_info_propert_type_team_s = { - .dbus_type = G_VARIANT_TYPE_STRING, - .to_dbus_fcn = _nm_team_settings_property_to_dbus, -}; - -const NMSettInfoPropertType nm_sett_info_propert_type_team_as = { - .dbus_type = NM_G_VARIANT_TYPE("as"), - .to_dbus_fcn = _nm_team_settings_property_to_dbus, -}; - -const NMSettInfoPropertType nm_sett_info_propert_type_team_link_watchers = { - .dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _nm_team_settings_property_to_dbus, - .gprop_from_dbus_fcn = _nm_team_settings_property_from_dbus_link_watchers, -}; - -/*****************************************************************************/ - -NMTeamSetting * -nm_team_setting_new(gboolean is_port, const char *js_str) -{ - NMTeamSetting *self; - gsize l; - - G_STATIC_ASSERT_EXPR(sizeof(*self) == sizeof(self->_data_priv)); - G_STATIC_ASSERT_EXPR(sizeof(*self) - == NM_CONST_MAX(nm_offsetofend(NMTeamSetting, d.master), - nm_offsetofend(NMTeamSetting, d.port))); - - l = is_port ? nm_offsetofend(NMTeamSetting, d.port) : nm_offsetofend(NMTeamSetting, d.master); - - self = g_malloc0(l); - - self->_data_priv.is_port = is_port; - self->_data_priv.strict_validated = TRUE; - self->_data_priv._js_str_need_synthetize = FALSE; - self->_data_priv.link_watchers = - g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); - - _team_setting_ASSERT(self); - - nm_team_setting_config_set(self, js_str); - - _team_setting_ASSERT(self); - - return self; -} - -void -nm_team_setting_free(NMTeamSetting *self) -{ - if (!self) - return; - - _team_setting_ASSERT(self); - - if (!self->d.is_port) { - nm_clear_pointer(((GPtrArray **) &self->_data_priv.master.runner_tx_hash), - g_ptr_array_unref); - g_free((char *) self->_data_priv.master.runner); - g_free((char *) self->_data_priv.master.runner_hwaddr_policy); - g_free((char *) self->_data_priv.master.runner_tx_balancer); - g_free((char *) self->_data_priv.master.runner_agg_select_policy); - } - g_ptr_array_unref((GPtrArray *) self->_data_priv.link_watchers); - g_free((char *) self->_data_priv._js_str); - g_free(self); -} diff --git a/libnm-core/nm-team-utils.h b/libnm-core/nm-team-utils.h deleted file mode 100644 index 77a34e5fdb..0000000000 --- a/libnm-core/nm-team-utils.h +++ /dev/null @@ -1,271 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#ifndef __NM_TEAM_UITLS_H__ -#define __NM_TEAM_UITLS_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) - #error Cannot use this header. -#endif - -#include "nm-glib-aux/nm-value-type.h" -#include "nm-core-internal.h" - -struct _NMSetting; - -struct NMTeamLinkWatcher; - -typedef enum { - - _NM_TEAM_ATTRIBUTE_0 = 0, - NM_TEAM_ATTRIBUTE_CONFIG = 1, - NM_TEAM_ATTRIBUTE_LINK_WATCHERS = 2, - - _NM_TEAM_ATTRIBUTE_START = 3, - - NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT = _NM_TEAM_ATTRIBUTE_START, - NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, - NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, - NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, - _NM_TEAM_ATTRIBUTE_MASTER_NUM, - - NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID = _NM_TEAM_ATTRIBUTE_START, - NM_TEAM_ATTRIBUTE_PORT_PRIO, - NM_TEAM_ATTRIBUTE_PORT_STICKY, - NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, - NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, - _NM_TEAM_ATTRIBUTE_PORT_NUM, - - _NM_TEAM_ATTRIBUTE_NUM = MAX(_NM_TEAM_ATTRIBUTE_MASTER_NUM, _NM_TEAM_ATTRIBUTE_PORT_NUM), - -} NMTeamAttribute; - -static inline guint32 -nm_team_attribute_to_flags(NMTeamAttribute team_attr) -{ - nm_assert(_NM_INT_NOT_NEGATIVE(team_attr)); - nm_assert(team_attr < _NM_TEAM_ATTRIBUTE_NUM); - G_STATIC_ASSERT_EXPR(_NM_TEAM_ATTRIBUTE_NUM < 32); - - return ((guint32) 1) << team_attr; -} - -struct _NMTeamSettingData { - const char *_js_str; - - const GPtrArray *link_watchers; - - /* this means that @_js_str is unset and needs to be created by - * converting the properties to JSON. This flag indicates that - * we need to re-generate the JSON string on-demand (lazily). */ - bool _js_str_need_synthetize; - - bool strict_validated : 1; - - /* indicates tha the JSON is invalid. Usually, we do a very relaxed validation of - * the JSON config, in case !@strict_validated and accept all unknown fields. This - * flag indicates that the JSON value is not even parsable as JSON. nm_connection_verify() - * would reject such a setting. */ - bool js_str_invalid : 1; - - bool is_port : 1; - - guint32 has_fields_mask; - - union { - struct { - const GPtrArray *runner_tx_hash; - const char * runner; - const char * runner_hwaddr_policy; - const char * runner_tx_balancer; - const char * runner_agg_select_policy; - gint32 notify_peers_count; - gint32 notify_peers_interval; - gint32 mcast_rejoin_count; - gint32 mcast_rejoin_interval; - gint32 runner_sys_prio; - gint32 runner_min_ports; - gint32 runner_tx_balancer_interval; - bool runner_active; - bool runner_fast_rate; - } master; - struct { - gint32 queue_id; - gint32 prio; - gint32 lacp_prio; - gint32 lacp_key; - bool sticky; - } port; - }; -}; - -/*****************************************************************************/ - -typedef struct { - union { - const struct _NMTeamSettingData d; - - struct _NMTeamSettingData _data_priv; - }; -} NMTeamSetting; - -NMTeamSetting *nm_team_setting_new(gboolean is_port, const char *js_str); - -void nm_team_setting_free(NMTeamSetting *self); - -NM_AUTO_DEFINE_FCN0(NMTeamSetting *, _nm_auto_free_team_setting, nm_team_setting_free); -#define nm_auto_free_team_setting nm_auto(_nm_auto_free_team_setting) - -/*****************************************************************************/ - -const char *nm_team_setting_config_get(const NMTeamSetting *self); - -guint32 nm_team_setting_config_set(NMTeamSetting *self, const char *js_str); - -/*****************************************************************************/ - -gconstpointer _nm_team_setting_value_get(const NMTeamSetting *self, - NMTeamAttribute team_attr, - NMValueType value_type); - -static inline gboolean -nm_team_setting_value_get_bool(const NMTeamSetting *self, NMTeamAttribute team_attr) -{ - const bool *p; - - p = _nm_team_setting_value_get(self, team_attr, NM_VALUE_TYPE_BOOL); - return p ? *p : 0; -} - -static inline gint32 -nm_team_setting_value_get_int32(const NMTeamSetting *self, NMTeamAttribute team_attr) -{ - const gint32 *p; - - p = _nm_team_setting_value_get(self, team_attr, NM_VALUE_TYPE_INT32); - return p ? *p : 0; -} - -static inline const char * -nm_team_setting_value_get_string(const NMTeamSetting *self, NMTeamAttribute team_attr) -{ - const char *const *p; - - p = _nm_team_setting_value_get(self, team_attr, NM_VALUE_TYPE_STRING); - return p ? *p : NULL; -} - -/*****************************************************************************/ - -guint32 nm_team_setting_value_reset(NMTeamSetting * self, - NMTeamAttribute team_attr, - gboolean to_default /* or else unset */); - -guint32 _nm_team_setting_value_set(NMTeamSetting * self, - NMTeamAttribute team_attr, - NMValueType value_type, - gconstpointer val); - -static inline guint32 -nm_team_setting_value_set_bool(NMTeamSetting *self, NMTeamAttribute team_attr, gboolean val) -{ - const bool bool_val = val; - - return _nm_team_setting_value_set(self, team_attr, NM_VALUE_TYPE_BOOL, &bool_val); -} - -static inline guint32 -nm_team_setting_value_set_int32(NMTeamSetting *self, NMTeamAttribute team_attr, gint32 val) -{ - return _nm_team_setting_value_set(self, team_attr, NM_VALUE_TYPE_INT32, &val); -} - -static inline guint32 -nm_team_setting_value_set_string(NMTeamSetting *self, NMTeamAttribute team_attr, const char *arg) -{ - return _nm_team_setting_value_set(self, team_attr, NM_VALUE_TYPE_STRING, &arg); -} - -/*****************************************************************************/ - -guint32 nm_team_setting_value_link_watchers_add(NMTeamSetting * self, - const struct NMTeamLinkWatcher *link_watcher); - -guint32 nm_team_setting_value_link_watchers_remove(NMTeamSetting *self, guint idx); - -guint32 -nm_team_setting_value_link_watchers_remove_by_value(NMTeamSetting * self, - const struct NMTeamLinkWatcher *link_watcher); - -guint32 nm_team_setting_value_link_watchers_set_list(NMTeamSetting * self, - const struct NMTeamLinkWatcher *const *arr, - guint len); - -/*****************************************************************************/ - -guint32 nm_team_setting_value_master_runner_tx_hash_add(NMTeamSetting *self, const char *txhash); - -guint32 nm_team_setting_value_master_runner_tx_hash_remove(NMTeamSetting *self, guint idx); - -guint32 nm_team_setting_value_master_runner_tx_hash_set_list(NMTeamSetting * self, - const char *const *arr, - guint len); - -/*****************************************************************************/ - -gboolean nm_team_setting_verify(const NMTeamSetting *self, GError **error); - -/*****************************************************************************/ - -int nm_team_setting_cmp(const NMTeamSetting *self_a, - const NMTeamSetting *self_b, - gboolean ignore_js_str); - -guint32 nm_team_setting_reset(NMTeamSetting *self, const NMTeamSetting *src); - -gboolean nm_team_setting_reset_from_dbus(NMTeamSetting * self, - GVariant * setting_dict, - GHashTable * keys, - guint32 * out_changed, - guint /* NMSettingParseFlags */ parse_flags, - GError ** error); - -/*****************************************************************************/ - -GPtrArray * -_nm_utils_team_link_watchers_from_variant(GVariant *value, gboolean strict_parsing, GError **error); -GVariant *_nm_utils_team_link_watchers_to_variant(const GPtrArray *link_watchers); - -/*****************************************************************************/ - -gboolean nm_team_setting_maybe_changed(struct _NMSetting * source, - const GParamSpec *const *obj_properties, - guint32 changed); - -struct _NMSettingTeam; -struct _NMSettingTeamPort; -NMTeamSetting *_nm_setting_team_get_team_setting(struct _NMSettingTeam *setting); -NMTeamSetting *_nm_setting_team_port_get_team_setting(struct _NMSettingTeamPort *setting); -NMTeamSetting *_nm_setting_get_team_setting(struct _NMSetting *setting); - -/*****************************************************************************/ - -extern const NMSettInfoPropertType nm_sett_info_propert_type_team_b; -extern const NMSettInfoPropertType nm_sett_info_propert_type_team_i; -extern const NMSettInfoPropertType nm_sett_info_propert_type_team_s; -extern const NMSettInfoPropertType nm_sett_info_propert_type_team_as; -extern const NMSettInfoPropertType nm_sett_info_propert_type_team_link_watchers; - -#endif /* __NM_TEAM_UITLS_H__ */ diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h deleted file mode 100644 index eb545d0fa8..0000000000 --- a/libnm-core/nm-utils-private.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2005 - 2017 Red Hat, Inc. - */ - -#ifndef __NM_UTILS_PRIVATE_H__ -#define __NM_UTILS_PRIVATE_H__ - -#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) - #error Cannot use this header. -#endif - -#include "nm-setting-private.h" -#include "nm-setting-ip-config.h" - -#define NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(_name, _type, ...) \ - (&((const NMVariantAttributeSpec){.name = _name, .type = _type, __VA_ARGS__})) - -gboolean _nm_utils_string_slist_validate(GSList *list, const char **valid_values); - -gboolean _nm_utils_secret_flags_validate(NMSettingSecretFlags secret_flags, - const char * setting_name, - const char * property_name, - NMSettingSecretFlags disallowed_flags, - GError ** error); - -gboolean _nm_utils_wps_method_validate(NMSettingWirelessSecurityWpsMethod wps_method, - const char * setting_name, - const char * property_name, - gboolean wps_required, - GError ** error); - -/* D-Bus transform funcs */ - -extern const NMSettInfoPropertType nm_sett_info_propert_type_strdict; - -extern const NMSettInfoPropertType nm_sett_info_propert_type_mac_address; - -extern const NMSettInfoPropertType nm_sett_info_propert_type_cloned_mac_address; - -extern const NMSettInfoPropertType nm_sett_info_propert_type_assigned_mac_address; - -extern const NMSettInfoPropertType nm_sett_info_propert_type_bridge_vlans; - -void _nm_utils_strdict_from_dbus(GVariant *dbus_value, GValue *prop_value); - -void _nm_utils_bytes_from_dbus(GVariant *dbus_value, GValue *prop_value); - -char *_nm_utils_hwaddr_canonical_or_invalid(const char *mac, gssize length); - -gboolean _nm_utils_hwaddr_link_local_valid(const char *mac); - -gboolean _nm_sriov_vf_parse_vlans(NMSriovVF *vf, const char *str, GError **error); - -gboolean _nm_utils_bridge_vlan_verify_list(GPtrArray * vlans, - gboolean check_normalizable, - GError ** error, - const char *setting, - const char *property); - -#endif diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c deleted file mode 100644 index 6ceef1e402..0000000000 --- a/libnm-core/nm-utils.c +++ /dev/null @@ -1,6056 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2005 - 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-utils.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-glib-aux/nm-json-aux.h" -#include "nm-glib-aux/nm-str-buf.h" -#include "nm-glib-aux/nm-enum-utils.h" -#include "nm-glib-aux/nm-time-utils.h" -#include "nm-glib-aux/nm-secret-utils.h" -#include "systemd/nm-sd-utils-shared.h" -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-utils-private.h" -#include "nm-setting-private.h" -#include "nm-crypto.h" -#include "nm-setting-bond.h" -#include "nm-setting-bridge.h" -#include "nm-setting-bridge-port.h" -#include "nm-setting-infiniband.h" -#include "nm-setting-ip6-config.h" -#include "nm-setting-team.h" -#include "nm-setting-vlan.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireless.h" - -/** - * SECTION:nm-utils - * @short_description: Utility functions - * - * A collection of utility functions for working with SSIDs, IP addresses, Wi-Fi - * access points and devices, among other things. - */ - -/*****************************************************************************/ - -/** - * NMUtilsPredicateStr: - * @str: the name to check. - * - * This function takes a string argument and returns either %TRUE or %FALSE. - * It is a general purpose predicate, for example used by nm_setting_option_clear_by_name(). - * - * Returns: %TRUE if the predicate function matches. - * - * Since: 1.26 - */ - -/*****************************************************************************/ - -struct _NMSockAddrEndpoint { - const char *host; - guint16 port; - guint refcount; - char endpoint[]; -}; - -static gboolean -NM_IS_SOCK_ADDR_ENDPOINT(const NMSockAddrEndpoint *self) -{ - return self && self->refcount > 0; -} - -static const char * -_parse_endpoint(char *str, guint16 *out_port) -{ - char * s; - const char *s_port; - gint16 port; - - /* Like - * - https://git.zx2c4.com/WireGuard/tree/src/tools/config.c?id=5e99a6d43fe2351adf36c786f5ea2086a8fe7ab8#n192 - * - https://github.com/systemd/systemd/blob/911649fdd43f3a9158b847947724a772a5a45c34/src/network/netdev/wireguard.c#L614 - */ - - g_strstrip(str); - - if (!str[0]) - return NULL; - - if (str[0] == '[') { - str++; - s = strchr(str, ']'); - if (!s) - return NULL; - if (s == str) - return NULL; - if (s[1] != ':') - return NULL; - if (!s[2]) - return NULL; - *s = '\0'; - s_port = &s[2]; - } else { - s = strrchr(str, ':'); - if (!s) - return NULL; - if (s == str) - return NULL; - if (!s[1]) - return NULL; - *s = '\0'; - s_port = &s[1]; - } - - if (!NM_STRCHAR_ALL(s_port, ch, (ch >= '0' && ch <= '9'))) - return NULL; - - port = _nm_utils_ascii_str_to_int64(s_port, 10, 1, G_MAXUINT16, 0); - if (port == 0) - return NULL; - - *out_port = port; - return str; -} - -/** - * nm_sock_addr_endpoint_new: - * @endpoint: the endpoint string. - * - * This function cannot fail, even if the @endpoint is invalid. - * The reason is to allow NMSockAddrEndpoint also to be used - * for tracking invalid endpoints. Use nm_sock_addr_endpoint_get_host() - * to determine whether the endpoint is valid. - * - * Returns: (transfer full): the new #NMSockAddrEndpoint endpoint. - */ -NMSockAddrEndpoint * -nm_sock_addr_endpoint_new(const char *endpoint) -{ - NMSockAddrEndpoint *ep; - gsize l_endpoint; - gsize l_host = 0; - gsize i; - gs_free char * host_clone = NULL; - const char * host; - guint16 port; - - g_return_val_if_fail(endpoint, NULL); - - l_endpoint = strlen(endpoint) + 1; - - host = _parse_endpoint(nm_strndup_a(200, endpoint, l_endpoint - 1, &host_clone), &port); - - if (host) - l_host = strlen(host) + 1; - - ep = g_malloc(sizeof(NMSockAddrEndpoint) + l_endpoint + l_host); - ep->refcount = 1; - memcpy(ep->endpoint, endpoint, l_endpoint); - if (host) { - i = l_endpoint; - memcpy(&ep->endpoint[i], host, l_host); - ep->host = &ep->endpoint[i]; - ep->port = port; - } else { - ep->host = NULL; - ep->port = 0; - } - return ep; -} - -/** - * nm_sock_addr_endpoint_ref: - * @self: (allow-none): the #NMSockAddrEndpoint - */ -NMSockAddrEndpoint * -nm_sock_addr_endpoint_ref(NMSockAddrEndpoint *self) -{ - if (!self) - return NULL; - - g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), NULL); - - nm_assert(self->refcount < G_MAXUINT); - - self->refcount++; - return self; -} - -/** - * nm_sock_addr_endpoint_unref: - * @self: (allow-none): the #NMSockAddrEndpoint - */ -void -nm_sock_addr_endpoint_unref(NMSockAddrEndpoint *self) -{ - if (!self) - return; - - g_return_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self)); - - if (--self->refcount == 0) - g_free(self); -} - -/** - * nm_sock_addr_endpoint_get_endpoint: - * @self: the #NMSockAddrEndpoint - * - * Gives the endpoint string. Since #NMSockAddrEndpoint's only - * information is the endpoint string, this can be used for comparing - * to instances for equality and order them lexically. - * - * Returns: (transfer none): the endpoint. - */ -const char * -nm_sock_addr_endpoint_get_endpoint(NMSockAddrEndpoint *self) -{ - g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), NULL); - - return self->endpoint; -} - -/** - * nm_sock_addr_endpoint_get_host: - * @self: the #NMSockAddrEndpoint - * - * Returns: (transfer none): the parsed host part of the endpoint. - * If the endpoint is invalid, %NULL will be returned. - */ -const char * -nm_sock_addr_endpoint_get_host(NMSockAddrEndpoint *self) -{ - g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), NULL); - - return self->host; -} - -/** - * nm_sock_addr_endpoint_get_port: - * @self: the #NMSockAddrEndpoint - * - * Returns: the parsed port part of the endpoint (the service). - * If the endpoint is invalid, -1 will be returned. - */ -gint32 -nm_sock_addr_endpoint_get_port(NMSockAddrEndpoint *self) -{ - g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), -1); - - return self->host ? (int) self->port : -1; -} - -gboolean -nm_sock_addr_endpoint_get_fixed_sockaddr(NMSockAddrEndpoint *self, gpointer sockaddr) -{ - int addr_family; - NMIPAddr addrbin; - const char *s; - guint scope_id = 0; - - g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), FALSE); - g_return_val_if_fail(sockaddr, FALSE); - - if (!self->host) - return FALSE; - - if (nm_utils_parse_inaddr_bin(AF_UNSPEC, self->host, &addr_family, &addrbin)) - goto good; - - /* See if there is an IPv6 scope-id... - * - * Note that it does not make sense to persist connection profiles to disk, - * that refenrence a scope-id (because the interface's ifindex changes on - * reboot). However, we also support runtime only changes like `nmcli device modify` - * where nothing is persisted to disk. At least in that case, passing a scope-id - * might be reasonable. So, parse that too. */ - s = strchr(self->host, '%'); - if (!s) - return FALSE; - - if (s[1] == '\0' || !NM_STRCHAR_ALL(&s[1], ch, (ch >= '0' && ch <= '9'))) - return FALSE; - - scope_id = _nm_utils_ascii_str_to_int64(&s[1], 10, 0, G_MAXINT32, G_MAXUINT); - if (scope_id == G_MAXUINT && errno) - return FALSE; - - { - gs_free char *tmp_str = NULL; - const char * host_part; - - host_part = nm_strndup_a(200, self->host, s - self->host, &tmp_str); - if (nm_utils_parse_inaddr_bin(AF_INET6, host_part, &addr_family, &addrbin)) - goto good; - } - - return FALSE; - -good: - switch (addr_family) { - case AF_INET: - *((struct sockaddr_in *) sockaddr) = (struct sockaddr_in){ - .sin_family = AF_INET, - .sin_addr = addrbin.addr4_struct, - .sin_port = htons(self->port), - }; - return TRUE; - case AF_INET6: - *((struct sockaddr_in6 *) sockaddr) = (struct sockaddr_in6){ - .sin6_family = AF_INET6, - .sin6_addr = addrbin.addr6, - .sin6_port = htons(self->port), - .sin6_scope_id = scope_id, - .sin6_flowinfo = 0, - }; - return TRUE; - } - - return FALSE; -} - -/*****************************************************************************/ - -struct IsoLangToEncodings { - const char * lang; - const char *const *encodings; -}; - -#define LANG_ENCODINGS(l, ...) \ - { \ - .lang = l, .encodings = NM_MAKE_STRV(__VA_ARGS__), \ - } - -/* 5-letter language codes */ -static const struct IsoLangToEncodings isoLangEntries5[] = { - /* Simplified Chinese */ - LANG_ENCODINGS("zh_cn", "euc-cn", "gb2312", "gb18030"), /* PRC */ - LANG_ENCODINGS("zh_sg", "euc-cn", "gb2312", "gb18030"), /* Singapore */ - - /* Traditional Chinese */ - LANG_ENCODINGS("zh_tw", "big5", "euc-tw"), /* Taiwan */ - LANG_ENCODINGS("zh_hk", "big5", "euc-tw", "big5-hkcs"), /* Hong Kong */ - LANG_ENCODINGS("zh_mo", "big5", "euc-tw"), /* Macau */ - - LANG_ENCODINGS(NULL, NULL)}; - -/* 2-letter language codes; we don't care about the other 3 in this table */ -static const struct IsoLangToEncodings isoLangEntries2[] = { - /* Japanese */ - LANG_ENCODINGS("ja", "euc-jp", "shift_jis", "iso-2022-jp"), - - /* Korean */ - LANG_ENCODINGS("ko", "euc-kr", "iso-2022-kr", "johab"), - - /* Thai */ - LANG_ENCODINGS("th", "iso-8859-11", "windows-874"), - - /* Central European */ - LANG_ENCODINGS("hu", "iso-8859-2", "windows-1250"), /* Hungarian */ - LANG_ENCODINGS("cs", "iso-8859-2", "windows-1250"), /* Czech */ - LANG_ENCODINGS("hr", "iso-8859-2", "windows-1250"), /* Croatian */ - LANG_ENCODINGS("pl", "iso-8859-2", "windows-1250"), /* Polish */ - LANG_ENCODINGS("ro", "iso-8859-2", "windows-1250"), /* Romanian */ - LANG_ENCODINGS("sk", "iso-8859-2", "windows-1250"), /* Slovakian */ - LANG_ENCODINGS("sl", "iso-8859-2", "windows-1250"), /* Slovenian */ - LANG_ENCODINGS("sh", "iso-8859-2", "windows-1250"), /* Serbo-Croatian */ - - /* Cyrillic */ - LANG_ENCODINGS("ru", "koi8-r", "windows-1251", "iso-8859-5"), /* Russian */ - LANG_ENCODINGS("be", "koi8-r", "windows-1251", "iso-8859-5"), /* Belorussian */ - LANG_ENCODINGS("bg", "windows-1251", "koi8-r", "iso-8859-5"), /* Bulgarian */ - LANG_ENCODINGS("mk", "koi8-r", "windows-1251", "iso-8859-5"), /* Macedonian */ - LANG_ENCODINGS("sr", "koi8-r", "windows-1251", "iso-8859-5"), /* Serbian */ - LANG_ENCODINGS("uk", "koi8-u", "koi8-r", "windows-1251"), /* Ukrainian */ - - /* Arabic */ - LANG_ENCODINGS("ar", "iso-8859-6", "windows-1256"), - - /* Baltic */ - LANG_ENCODINGS("et", "iso-8859-4", "windows-1257"), /* Estonian */ - LANG_ENCODINGS("lt", "iso-8859-4", "windows-1257"), /* Lithuanian */ - LANG_ENCODINGS("lv", "iso-8859-4", "windows-1257"), /* Latvian */ - - /* Greek */ - LANG_ENCODINGS("el", "iso-8859-7", "windows-1253"), - - /* Hebrew */ - LANG_ENCODINGS("he", "iso-8859-8", "windows-1255"), - LANG_ENCODINGS("iw", "iso-8859-8", "windows-1255"), - - /* Turkish */ - LANG_ENCODINGS("tr", "iso-8859-9", "windows-1254"), - - /* Table end */ - LANG_ENCODINGS(NULL, NULL)}; - -static GHashTable *langToEncodings5 = NULL; -static GHashTable *langToEncodings2 = NULL; - -static void -init_lang_to_encodings_hash(void) -{ - struct IsoLangToEncodings *enc; - - if (G_UNLIKELY(langToEncodings5 == NULL)) { - /* Five-letter codes */ - enc = (struct IsoLangToEncodings *) &isoLangEntries5[0]; - langToEncodings5 = g_hash_table_new(nm_str_hash, g_str_equal); - while (enc->lang) { - g_hash_table_insert(langToEncodings5, (gpointer) enc->lang, (gpointer) enc->encodings); - enc++; - } - } - - if (G_UNLIKELY(langToEncodings2 == NULL)) { - /* Two-letter codes */ - enc = (struct IsoLangToEncodings *) &isoLangEntries2[0]; - langToEncodings2 = g_hash_table_new(nm_str_hash, g_str_equal); - while (enc->lang) { - g_hash_table_insert(langToEncodings2, (gpointer) enc->lang, (gpointer) enc->encodings); - enc++; - } - } -} - -static gboolean -get_encodings_for_lang(const char *lang, const char *const **encodings) -{ - gs_free char *tmp_lang = NULL; - - g_return_val_if_fail(lang, FALSE); - g_return_val_if_fail(encodings, FALSE); - - init_lang_to_encodings_hash(); - - if ((*encodings = g_hash_table_lookup(langToEncodings5, lang))) - return TRUE; - - /* Truncate tmp_lang to length of 2 */ - if (strlen(lang) > 2) { - tmp_lang = g_strdup(lang); - tmp_lang[2] = '\0'; - if ((*encodings = g_hash_table_lookup(langToEncodings2, tmp_lang))) - return TRUE; - } - - return FALSE; -} - -static const char *const * -get_system_encodings(void) -{ - static const char *const *cached_encodings; - static char * default_encodings[4]; - const char *const * encodings = NULL; - char * lang; - - if (cached_encodings) - return cached_encodings; - - /* Use environment variables as encoding hint */ - lang = getenv("LC_ALL"); - if (!lang) - lang = getenv("LC_CTYPE"); - if (!lang) - lang = getenv("LANG"); - if (lang) { - char *dot; - - lang = g_ascii_strdown(lang, -1); - if ((dot = strchr(lang, '.'))) - *dot = '\0'; - - get_encodings_for_lang(lang, &encodings); - g_free(lang); - } - if (!encodings) { - g_get_charset((const char **) &default_encodings[0]); - default_encodings[1] = "iso-8859-1"; - default_encodings[2] = "windows-1251"; - default_encodings[3] = NULL; - encodings = (const char *const *) default_encodings; - } - - cached_encodings = encodings; - return cached_encodings; -} - -/*****************************************************************************/ - -static void __attribute__((constructor)) _nm_utils_init(void) -{ - static int initialized = 0; - - if (g_atomic_int_get(&initialized) != 0) - return; - - /* we don't expect this code to run multiple times, nor on multiple threads. - * - * In practice, it would not be a problem if two threads concurrently try to - * run the initialization code below, all code below itself is thread-safe, - * Hence, a poor-man guard "initialized" above is more than sufficient, - * although it does not guarantee that the code is not run concurrently. */ - - bindtextdomain(GETTEXT_PACKAGE, NMLOCALEDIR); - bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); - - _nm_dbus_errors_init(); - - g_atomic_int_set(&initialized, 1); -} - -/*****************************************************************************/ - -gboolean _nm_utils_is_manager_process; - -/* ssid helpers */ - -/** - * nm_utils_ssid_to_utf8: - * @ssid: (array length=len): pointer to a buffer containing the SSID data - * @len: length of the SSID data in @ssid - * - * Wi-Fi SSIDs are byte arrays, they are _not_ strings. Thus, an SSID may - * contain embedded NULLs and other unprintable characters. Often it is - * useful to print the SSID out for debugging purposes, but that should be the - * _only_ use of this function. Do not use this function for any persistent - * storage of the SSID, since the printable SSID returned from this function - * cannot be converted back into the real SSID of the access point. - * - * This function does almost everything humanly possible to convert the input - * into a printable UTF-8 string, using roughly the following procedure: - * - * 1) if the input data is already UTF-8 safe, no conversion is performed - * 2) attempts to get the current system language from the LANG environment - * variable, and depending on the language, uses a table of alternative - * encodings to try. For example, if LANG=hu_HU, the table may first try - * the ISO-8859-2 encoding, and if that fails, try the Windows-1250 encoding. - * If all fallback encodings fail, replaces non-UTF-8 characters with '?'. - * 3) If the system language was unable to be determined, falls back to the - * ISO-8859-1 encoding, then to the Windows-1251 encoding. - * 4) If step 3 fails, replaces non-UTF-8 characters with '?'. - * - * Again, this function should be used for debugging and display purposes - * _only_. - * - * Returns: (transfer full): an allocated string containing a UTF-8 - * representation of the SSID, which must be freed by the caller using g_free(). - * Returns %NULL on errors. - **/ -char * -nm_utils_ssid_to_utf8(const guint8 *ssid, gsize len) -{ - const char *const *encodings; - const char *const *e; - char * converted = NULL; - - g_return_val_if_fail(ssid != NULL, NULL); - - if (g_utf8_validate((const char *) ssid, len, NULL)) - return g_strndup((const char *) ssid, len); - - encodings = get_system_encodings(); - - for (e = encodings; *e; e++) { - converted = g_convert((const char *) ssid, len, "UTF-8", *e, NULL, NULL, NULL); - if (converted) - break; - } - - if (!converted) { - converted = g_convert_with_fallback((const char *) ssid, - len, - "UTF-8", - encodings[0], - "?", - NULL, - NULL, - NULL); - } - - if (!converted) { - /* If there is still no converted string, the SSID probably - * contains characters not valid in the current locale. Convert - * the string to ASCII instead. - */ - - /* Use the printable range of 0x20-0x7E */ - char *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" - "abcdefghijklmnopqrstuvwxyz{|}~"; - - converted = g_strndup((const char *) ssid, len); - g_strcanon(converted, valid_chars, '?'); - } - - return converted; -} - -char * -_nm_utils_ssid_to_utf8(GBytes *ssid) -{ - const guint8 *p; - gsize l; - - g_return_val_if_fail(ssid, NULL); - - p = g_bytes_get_data(ssid, &l); - return nm_utils_ssid_to_utf8(p, l); -} - -/* Shamelessly ripped from the Linux kernel ieee80211 stack */ -/** - * nm_utils_is_empty_ssid: - * @ssid: (array length=len): pointer to a buffer containing the SSID data - * @len: length of the SSID data in @ssid - * - * Different manufacturers use different mechanisms for not broadcasting the - * AP's SSID. This function attempts to detect blank/empty SSIDs using a - * number of known SSID-cloaking methods. - * - * Returns: %TRUE if the SSID is "empty", %FALSE if it is not - **/ -gboolean -nm_utils_is_empty_ssid(const guint8 *ssid, gsize len) -{ - /* Single white space is for Linksys APs */ - if (len == 1 && ssid[0] == ' ') - return TRUE; - - /* Otherwise, if the entire ssid is 0, we assume it is hidden */ - while (len--) { - if (ssid[len] != '\0') - return FALSE; - } - return TRUE; -} - -gboolean -_nm_utils_is_empty_ssid(GBytes *ssid) -{ - const guint8 *p; - gsize l; - - g_return_val_if_fail(ssid, FALSE); - - p = g_bytes_get_data(ssid, &l); - return nm_utils_is_empty_ssid(p, l); -} - -#define ESSID_MAX_SIZE 32 - -/** - * nm_utils_escape_ssid: - * @ssid: (array length=len): pointer to a buffer containing the SSID data - * @len: length of the SSID data in @ssid - * - * This function does a quick printable character conversion of the SSID, simply - * replacing embedded NULLs and non-printable characters with the hexadecimal - * representation of that character. Intended for debugging only, should not - * be used for display of SSIDs. - * - * Returns: pointer to the escaped SSID, which uses an internal static buffer - * and will be overwritten by subsequent calls to this function - **/ -const char * -nm_utils_escape_ssid(const guint8 *ssid, gsize len) -{ - static char escaped[ESSID_MAX_SIZE * 2 + 1]; - const guint8 *s = ssid; - char * d = escaped; - - if (nm_utils_is_empty_ssid(ssid, len)) { - memcpy(escaped, "", sizeof("")); - return escaped; - } - - len = MIN(len, (guint32) ESSID_MAX_SIZE); - while (len--) { - if (*s == '\0') { - *d++ = '\\'; - *d++ = '0'; - s++; - } else { - *d++ = *s++; - } - } - *d = '\0'; - return escaped; -} - -char * -_nm_utils_ssid_to_string_arr(const guint8 *ssid, gsize len) -{ - gs_free char *s_copy = NULL; - const char * s_cnst; - - if (len == 0) - return g_strdup("(empty)"); - - s_cnst = - nm_utils_buf_utf8safe_escape(ssid, len, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, &s_copy); - nm_assert(s_cnst); - - if (nm_utils_is_empty_ssid(ssid, len)) - return g_strdup_printf("\"%s\" (hidden)", s_cnst); - - return g_strdup_printf("\"%s\"", s_cnst); -} - -char * -_nm_utils_ssid_to_string(GBytes *ssid) -{ - gconstpointer p; - gsize l; - - if (!ssid) - return g_strdup("(none)"); - - p = g_bytes_get_data(ssid, &l); - return _nm_utils_ssid_to_string_arr(p, l); -} - -/** - * nm_utils_same_ssid: - * @ssid1: (array length=len1): the first SSID to compare - * @len1: length of the SSID data in @ssid1 - * @ssid2: (array length=len2): the second SSID to compare - * @len2: length of the SSID data in @ssid2 - * @ignore_trailing_null: %TRUE to ignore one trailing NULL byte - * - * Earlier versions of the Linux kernel added a NULL byte to the end of the - * SSID to enable easy printing of the SSID on the console or in a terminal, - * but this behavior was problematic (SSIDs are simply byte arrays, not strings) - * and thus was changed. This function compensates for that behavior at the - * cost of some compatibility with odd SSIDs that may legitimately have trailing - * NULLs, even though that is functionally pointless. - * - * Returns: %TRUE if the SSIDs are the same, %FALSE if they are not - **/ -gboolean -nm_utils_same_ssid(const guint8 *ssid1, - gsize len1, - const guint8 *ssid2, - gsize len2, - gboolean ignore_trailing_null) -{ - g_return_val_if_fail(ssid1 != NULL || len1 == 0, FALSE); - g_return_val_if_fail(ssid2 != NULL || len2 == 0, FALSE); - - if (ssid1 == ssid2 && len1 == len2) - return TRUE; - if (!ssid1 || !ssid2) - return FALSE; - - if (ignore_trailing_null) { - if (len1 && ssid1[len1 - 1] == '\0') - len1--; - if (len2 && ssid2[len2 - 1] == '\0') - len2--; - } - - if (len1 != len2) - return FALSE; - - return memcmp(ssid1, ssid2, len1) == 0 ? TRUE : FALSE; -} - -gboolean -_nm_utils_string_slist_validate(GSList *list, const char **valid_values) -{ - GSList *iter; - - for (iter = list; iter; iter = iter->next) { - if (!g_strv_contains(valid_values, (char *) iter->data)) - return FALSE; - } - - return TRUE; -} - -/** - * _nm_utils_hash_values_to_slist: - * @hash: a #GHashTable - * - * Utility function to iterate over a hash table and return - * its values as a #GSList. - * - * Returns: (element-type gpointer) (transfer container): a newly allocated #GSList - * containing the values of the hash table. The caller must free the - * returned list with g_slist_free(). The hash values are not owned - * by the returned list. - **/ -GSList * -_nm_utils_hash_values_to_slist(GHashTable *hash) -{ - GSList * list = NULL; - GHashTableIter iter; - void * value; - - g_return_val_if_fail(hash, NULL); - - g_hash_table_iter_init(&iter, hash); - while (g_hash_table_iter_next(&iter, NULL, &value)) - list = g_slist_prepend(list, value); - - return list; -} - -static GVariant * -_nm_utils_strdict_to_dbus(const GValue *prop_value) -{ - return nm_utils_strdict_to_variant_ass(g_value_get_boxed(prop_value)); -} - -void -_nm_utils_strdict_from_dbus(GVariant *dbus_value, GValue *prop_value) -{ - GVariantIter iter; - const char * key, *value; - GHashTable * hash; - - hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); - g_variant_iter_init(&iter, dbus_value); - while (g_variant_iter_next(&iter, "{&s&s}", &key, &value)) - g_hash_table_insert(hash, g_strdup(key), g_strdup(value)); - - g_value_take_boxed(prop_value, hash); -} - -const NMSettInfoPropertType nm_sett_info_propert_type_strdict = { - .dbus_type = NM_G_VARIANT_TYPE("a{ss}"), - .gprop_to_dbus_fcn = _nm_utils_strdict_to_dbus, - .gprop_from_dbus_fcn = _nm_utils_strdict_from_dbus, -}; - -GHashTable * -_nm_utils_copy_strdict(GHashTable *strdict) -{ - GHashTable * copy; - GHashTableIter iter; - gpointer key, value; - - copy = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); - if (strdict) { - g_hash_table_iter_init(&iter, strdict); - while (g_hash_table_iter_next(&iter, &key, &value)) - g_hash_table_insert(copy, g_strdup(key), g_strdup(value)); - } - return copy; -} - -GPtrArray * -_nm_utils_copy_array(const GPtrArray *array, NMUtilsCopyFunc copy_func, GDestroyNotify free_func) -{ - GPtrArray *copy; - guint i; - - if (!array) - return g_ptr_array_new_with_free_func(free_func); - - copy = g_ptr_array_new_full(array->len, free_func); - for (i = 0; i < array->len; i++) - g_ptr_array_add(copy, copy_func(array->pdata[i])); - return copy; -} - -GPtrArray * -_nm_utils_copy_object_array(const GPtrArray *array) -{ - return _nm_utils_copy_array(array, g_object_ref, g_object_unref); -} - -gssize -_nm_utils_ptrarray_find_first(gconstpointer *list, gssize len, gconstpointer needle) -{ - gssize i; - - if (len == 0) - return -1; - - if (len > 0) { - g_return_val_if_fail(list, -1); - for (i = 0; i < len; i++) { - if (list[i] == needle) - return i; - } - } else { - g_return_val_if_fail(needle, -1); - for (i = 0; list && list[i]; i++) { - if (list[i] == needle) - return i; - } - } - return -1; -} - -void -_nm_utils_bytes_from_dbus(GVariant *dbus_value, GValue *prop_value) -{ - GBytes *bytes; - - if (g_variant_n_children(dbus_value)) { - gconstpointer data; - gsize length; - - data = g_variant_get_fixed_array(dbus_value, &length, 1); - bytes = g_bytes_new(data, length); - } else - bytes = NULL; - g_value_take_boxed(prop_value, bytes); -} - -/*****************************************************************************/ - -GSList * -_nm_utils_strv_to_slist(char **strv, gboolean deep_copy) -{ - GSList *list = NULL; - gsize i; - - if (!strv) - return NULL; - - if (deep_copy) { - for (i = 0; strv[i]; i++) - list = g_slist_prepend(list, g_strdup(strv[i])); - } else { - for (i = 0; strv[i]; i++) - list = g_slist_prepend(list, strv[i]); - } - return g_slist_reverse(list); -} - -char ** -_nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy) -{ - const GSList *iter; - char ** strv; - guint len, i; - - if (!slist) - return NULL; - - len = g_slist_length((GSList *) slist); - - strv = g_new(char *, len + 1); - - if (deep_copy) { - for (i = 0, iter = slist; iter; iter = iter->next, i++) { - nm_assert(iter->data); - strv[i] = g_strdup(iter->data); - } - } else { - for (i = 0, iter = slist; iter; iter = iter->next, i++) { - nm_assert(iter->data); - strv[i] = iter->data; - } - } - strv[i] = NULL; - - return strv; -} - -GPtrArray * -_nm_utils_strv_to_ptrarray(char **strv) -{ - GPtrArray *ptrarray; - gsize i, l; - - l = NM_PTRARRAY_LEN(strv); - - ptrarray = g_ptr_array_new_full(l, g_free); - - if (strv) { - for (i = 0; strv[i]; i++) - g_ptr_array_add(ptrarray, g_strdup(strv[i])); - } - - return ptrarray; -} - -char ** -_nm_utils_ptrarray_to_strv(const GPtrArray *ptrarray) -{ - char **strv; - guint i; - - if (!ptrarray) - return g_new0(char *, 1); - - strv = g_new(char *, ptrarray->len + 1); - - for (i = 0; i < ptrarray->len; i++) - strv[i] = g_strdup(ptrarray->pdata[i]); - strv[i] = NULL; - - return strv; -} - -/*****************************************************************************/ - -static gboolean -device_supports_ap_ciphers(guint32 dev_caps, guint32 ap_flags, gboolean static_wep) -{ - gboolean have_pair = FALSE; - gboolean have_group = FALSE; - /* Device needs to support at least one pairwise and one group cipher */ - - /* Pairwise */ - if (static_wep) { - /* Static WEP only uses group ciphers */ - have_pair = TRUE; - } else { - if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40) - if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP40) - have_pair = TRUE; - if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104) - if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP104) - have_pair = TRUE; - if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) - if (ap_flags & NM_802_11_AP_SEC_PAIR_TKIP) - have_pair = TRUE; - if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) - if (ap_flags & NM_802_11_AP_SEC_PAIR_CCMP) - have_pair = TRUE; - } - - /* Group */ - if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40) - if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP40) - have_group = TRUE; - if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104) - if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP104) - have_group = TRUE; - if (!static_wep) { - if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) - if (ap_flags & NM_802_11_AP_SEC_GROUP_TKIP) - have_group = TRUE; - if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) - if (ap_flags & NM_802_11_AP_SEC_GROUP_CCMP) - have_group = TRUE; - } - - return (have_pair && have_group); -} - -/** - * nm_utils_ap_mode_security_valid: - * @type: the security type to check device capabilities against, - * e.g. #NMU_SEC_STATIC_WEP - * @wifi_caps: bitfield of the capabilities of the specific Wi-Fi device, e.g. - * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40 - * - * Given a set of device capabilities, and a desired security type to check - * against, determines whether the combination of device capabilities and - * desired security type are valid for AP/Hotspot connections. - * - * Returns: %TRUE if the device capabilities are compatible with the desired - * @type, %FALSE if they are not. - **/ -gboolean -nm_utils_ap_mode_security_valid(NMUtilsSecurityType type, NMDeviceWifiCapabilities wifi_caps) -{ - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_AP)) - return FALSE; - - /* Return TRUE for any security that wpa_supplicant's lightweight AP - * mode can handle: which is open, WEP, and WPA/WPA2 PSK. - */ - switch (type) { - case NMU_SEC_NONE: - case NMU_SEC_STATIC_WEP: - case NMU_SEC_WPA_PSK: - case NMU_SEC_WPA2_PSK: - case NMU_SEC_SAE: - case NMU_SEC_OWE: - return TRUE; - case NMU_SEC_LEAP: - case NMU_SEC_DYNAMIC_WEP: - case NMU_SEC_WPA_ENTERPRISE: - case NMU_SEC_WPA2_ENTERPRISE: - case NMU_SEC_WPA3_SUITE_B_192: - return FALSE; - case NMU_SEC_INVALID: - break; - } - return FALSE; -} - -/** - * nm_utils_security_valid: - * @type: the security type to check AP flags and device capabilities against, - * e.g. #NMU_SEC_STATIC_WEP - * @wifi_caps: bitfield of the capabilities of the specific Wi-Fi device, e.g. - * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40 - * @have_ap: whether the @ap_flags, @ap_wpa, and @ap_rsn arguments are valid - * @adhoc: whether the capabilities being tested are from an Ad-Hoc AP (IBSS) - * @ap_flags: bitfield of AP capabilities, e.g. #NM_802_11_AP_FLAGS_PRIVACY - * @ap_wpa: bitfield of AP capabilities derived from the AP's WPA beacon, - * e.g. (#NM_802_11_AP_SEC_PAIR_TKIP | #NM_802_11_AP_SEC_KEY_MGMT_PSK) - * @ap_rsn: bitfield of AP capabilities derived from the AP's RSN/WPA2 beacon, - * e.g. (#NM_802_11_AP_SEC_PAIR_CCMP | #NM_802_11_AP_SEC_PAIR_TKIP) - * - * Given a set of device capabilities, and a desired security type to check - * against, determines whether the combination of device, desired security - * type, and AP capabilities intersect. - * - * NOTE: this function cannot handle checking security for AP/Hotspot mode; - * use nm_utils_ap_mode_security_valid() instead. - * - * Returns: %TRUE if the device capabilities and AP capabilities intersect and are - * compatible with the desired @type, %FALSE if they are not - **/ -gboolean -nm_utils_security_valid(NMUtilsSecurityType type, - NMDeviceWifiCapabilities wifi_caps, - gboolean have_ap, - gboolean adhoc, - NM80211ApFlags ap_flags, - NM80211ApSecurityFlags ap_wpa, - NM80211ApSecurityFlags ap_rsn) -{ - switch (type) { - case NMU_SEC_NONE: - if (!have_ap) - return TRUE; - if (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) - return FALSE; - if (ap_wpa || ap_rsn) - return FALSE; - return TRUE; - case NMU_SEC_LEAP: /* require PRIVACY bit for LEAP? */ - if (adhoc) - return FALSE; - /* fall-through */ - case NMU_SEC_STATIC_WEP: - if (!have_ap) { - if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) - return TRUE; - return FALSE; - } - if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) - return FALSE; - if (ap_wpa || ap_rsn) { - if (!device_supports_ap_ciphers(wifi_caps, ap_wpa, TRUE)) { - if (!device_supports_ap_ciphers(wifi_caps, ap_rsn, TRUE)) - return FALSE; - } - } - return TRUE; - case NMU_SEC_DYNAMIC_WEP: - if (adhoc) - return FALSE; - if (!have_ap) { - if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) - return TRUE; - return FALSE; - } - if (ap_rsn || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) - return FALSE; - /* Some APs broadcast minimal WPA-enabled beacons that must be handled */ - if (ap_wpa) { - if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return FALSE; - if (!device_supports_ap_ciphers(wifi_caps, ap_wpa, FALSE)) - return FALSE; - } - return TRUE; - case NMU_SEC_WPA_PSK: - if (adhoc) - return FALSE; - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) - return FALSE; - if (!have_ap) - return TRUE; - if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) { - if ((ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) - return TRUE; - if ((ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - } - return FALSE; - case NMU_SEC_WPA2_PSK: - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) - return FALSE; - if (!have_ap) - return TRUE; - if (adhoc) { - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_IBSS_RSN)) - return FALSE; - if ((ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - return FALSE; - } - if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) { - if ((ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) - return TRUE; - if ((ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - } - return FALSE; - case NMU_SEC_WPA_ENTERPRISE: - if (adhoc) - return FALSE; - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) - return FALSE; - if (!have_ap) - return TRUE; - if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return FALSE; - /* Ensure at least one WPA cipher is supported */ - if (!device_supports_ap_ciphers(wifi_caps, ap_wpa, FALSE)) - return FALSE; - return TRUE; - case NMU_SEC_WPA2_ENTERPRISE: - if (adhoc) - return FALSE; - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) - return FALSE; - if (!have_ap) - return TRUE; - if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return FALSE; - /* Ensure at least one WPA cipher is supported */ - if (!device_supports_ap_ciphers(wifi_caps, ap_rsn, FALSE)) - return FALSE; - return TRUE; - case NMU_SEC_SAE: - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) - return FALSE; - if (adhoc) - return FALSE; - if (!have_ap) - return TRUE; - if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE) { - if ((ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) - && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - return TRUE; - } - return FALSE; - case NMU_SEC_OWE: - if (adhoc) - return FALSE; - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) - return FALSE; - if (!have_ap) - return TRUE; - if (!NM_FLAGS_ANY(ap_rsn, NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) - return FALSE; - return TRUE; - case NMU_SEC_WPA3_SUITE_B_192: - if (adhoc) - return FALSE; - if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) - return FALSE; - if (!have_ap) - return TRUE; - if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192) - return TRUE; - return FALSE; - case NMU_SEC_INVALID: - break; - } - - return FALSE; -} - -/** - * nm_utils_wep_key_valid: - * @key: a string that might be a WEP key - * @wep_type: the #NMWepKeyType type of the WEP key - * - * Checks if @key is a valid WEP key - * - * Returns: %TRUE if @key is a WEP key, %FALSE if not - */ -gboolean -nm_utils_wep_key_valid(const char *key, NMWepKeyType wep_type) -{ - gsize keylen; - gsize i; - - if (!key) - return FALSE; - - if (wep_type == NM_WEP_KEY_TYPE_UNKNOWN) { - return nm_utils_wep_key_valid(key, NM_WEP_KEY_TYPE_KEY) - || nm_utils_wep_key_valid(key, NM_WEP_KEY_TYPE_PASSPHRASE); - } - - keylen = strlen(key); - if (wep_type == NM_WEP_KEY_TYPE_KEY) { - if (keylen == 10 || keylen == 26) { - /* Hex key */ - for (i = 0; i < keylen; i++) { - if (!g_ascii_isxdigit(key[i])) - return FALSE; - } - } else if (keylen == 5 || keylen == 13) { - /* ASCII key */ - for (i = 0; i < keylen; i++) { - if (!g_ascii_isprint(key[i])) - return FALSE; - } - } else - return FALSE; - } else if (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE) { - if (!keylen || keylen > 64) - return FALSE; - } - - return TRUE; -} - -/** - * nm_utils_wpa_psk_valid: - * @psk: a string that might be a WPA PSK - * - * Checks if @psk is a valid WPA PSK - * - * Returns: %TRUE if @psk is a WPA PSK, %FALSE if not - */ -gboolean -nm_utils_wpa_psk_valid(const char *psk) -{ - gsize psklen; - gsize i; - - if (!psk) - return FALSE; - - psklen = strlen(psk); - if (psklen < 8 || psklen > 64) - return FALSE; - - if (psklen == 64) { - /* Hex PSK */ - for (i = 0; i < psklen; i++) { - if (!g_ascii_isxdigit(psk[i])) - return FALSE; - } - } - - return TRUE; -} - -/** - * nm_utils_ip4_dns_to_variant: - * @dns: (type utf8): an array of IP address strings - * - * Utility function to convert an array of IP address strings int a #GVariant of - * type 'au' representing an array of IPv4 addresses. - * - * Returns: (transfer none): a new floating #GVariant representing @dns. - **/ -GVariant * -nm_utils_ip4_dns_to_variant(char **dns) -{ - GVariantBuilder builder; - gsize i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); - - if (dns) { - for (i = 0; dns[i]; i++) { - guint32 ip = 0; - - inet_pton(AF_INET, dns[i], &ip); - g_variant_builder_add(&builder, "u", ip); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * nm_utils_ip4_dns_from_variant: - * @value: a #GVariant of type 'au' - * - * Utility function to convert a #GVariant of type 'au' representing a list of - * IPv4 addresses into an array of IP address strings. - * - * Returns: (transfer full) (type utf8): a %NULL-terminated array of IP address strings. - **/ -char ** -nm_utils_ip4_dns_from_variant(GVariant *value) -{ - const guint32 *array; - gsize length; - char ** dns; - gsize i; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("au")), NULL); - - array = g_variant_get_fixed_array(value, &length, sizeof(guint32)); - dns = g_new(char *, length + 1u); - for (i = 0; i < length; i++) - dns[i] = nm_utils_inet4_ntop_dup(array[i]); - dns[i] = NULL; - - return dns; -} - -/** - * nm_utils_ip4_addresses_to_variant: - * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects - * @gateway: (allow-none): the gateway IP address - * - * Utility function to convert a #GPtrArray of #NMIPAddress objects representing - * IPv4 addresses into a #GVariant of type 'aau' representing an array of - * NetworkManager IPv4 addresses (which are tuples of address, prefix, and - * gateway). The "gateway" field of the first address will get the value of - * @gateway (if non-%NULL). In all of the other addresses, that field will be 0. - * - * Returns: (transfer none): a new floating #GVariant representing @addresses. - **/ -GVariant * -nm_utils_ip4_addresses_to_variant(GPtrArray *addresses, const char *gateway) -{ - GVariantBuilder builder; - guint i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aau")); - - if (addresses) { - for (i = 0; i < addresses->len; i++) { - NMIPAddress *addr = addresses->pdata[i]; - guint32 array[3]; - in_addr_t gw; - - if (nm_ip_address_get_family(addr) != AF_INET) - continue; - - gw = 0u; - if (gateway) { - in_addr_t a; - - if (inet_pton(AF_INET, gateway, &a) == 1) - gw = a; - gateway = NULL; - } - - nm_ip_address_get_address_binary(addr, &array[0]); - array[1] = nm_ip_address_get_prefix(addr); - array[2] = gw; - - g_variant_builder_add( - &builder, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 3, sizeof(guint32))); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * nm_utils_ip4_addresses_from_variant: - * @value: a #GVariant of type 'aau' - * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway - * - * Utility function to convert a #GVariant of type 'aau' representing a list of - * NetworkManager IPv4 addresses (which are tuples of address, prefix, and - * gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field of - * the first address (if set) will be returned in @out_gateway; the "gateway" fields - * of the other addresses are ignored. - * - * Returns: (transfer full) (element-type NMIPAddress): a newly allocated - * #GPtrArray of #NMIPAddress objects - **/ -GPtrArray * -nm_utils_ip4_addresses_from_variant(GVariant *value, char **out_gateway) -{ - GPtrArray * addresses; - GVariantIter iter; - GVariant * addr_var; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aau")), NULL); - - if (out_gateway) - *out_gateway = NULL; - - g_variant_iter_init(&iter, value); - addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); - - while (g_variant_iter_next(&iter, "@au", &addr_var)) { - const guint32 *addr_array; - gsize length; - NMIPAddress * addr; - GError * error = NULL; - - addr_array = g_variant_get_fixed_array(addr_var, &length, sizeof(guint32)); - if (length < 3) { - g_warning("Ignoring invalid IP4 address"); - g_variant_unref(addr_var); - continue; - } - - addr = nm_ip_address_new_binary(AF_INET, &addr_array[0], addr_array[1], &error); - if (addr) { - g_ptr_array_add(addresses, addr); - - if (addr_array[2] && out_gateway && !*out_gateway) - *out_gateway = nm_utils_inet4_ntop_dup(addr_array[2]); - } else { - g_warning("Ignoring invalid IP4 address: %s", error->message); - g_clear_error(&error); - } - - g_variant_unref(addr_var); - } - - return addresses; -} - -/** - * nm_utils_ip4_routes_to_variant: - * @routes: (element-type NMIPRoute): an array of #NMIP4Route objects - * - * Utility function to convert a #GPtrArray of #NMIPRoute objects representing - * IPv4 routes into a #GVariant of type 'aau' representing an array of - * NetworkManager IPv4 routes (which are tuples of route, prefix, next hop, and - * metric). - * - * Returns: (transfer none): a new floating #GVariant representing @routes. - **/ -GVariant * -nm_utils_ip4_routes_to_variant(GPtrArray *routes) -{ - GVariantBuilder builder; - guint i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aau")); - - if (routes) { - for (i = 0; i < routes->len; i++) { - NMIPRoute *route = routes->pdata[i]; - guint32 array[4]; - - if (nm_ip_route_get_family(route) != AF_INET) - continue; - - nm_ip_route_get_dest_binary(route, &array[0]); - array[1] = nm_ip_route_get_prefix(route); - nm_ip_route_get_next_hop_binary(route, &array[2]); - /* The old routes format uses "0" for default, not "-1" */ - array[3] = MAX(0, nm_ip_route_get_metric(route)); - - g_variant_builder_add( - &builder, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 4, sizeof(guint32))); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * nm_utils_ip4_routes_from_variant: - * @value: #GVariant of type 'aau' - * - * Utility function to convert a #GVariant of type 'aau' representing an array - * of NetworkManager IPv4 routes (which are tuples of route, prefix, next hop, - * and metric) into a #GPtrArray of #NMIPRoute objects. - * - * Returns: (transfer full) (element-type NMIPRoute): a newly allocated - * #GPtrArray of #NMIPRoute objects - **/ -GPtrArray * -nm_utils_ip4_routes_from_variant(GVariant *value) -{ - GVariantIter iter; - GVariant * route_var; - GPtrArray * routes; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aau")), NULL); - - g_variant_iter_init(&iter, value); - routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); - - while (g_variant_iter_next(&iter, "@au", &route_var)) { - const guint32 *route_array; - gsize length; - NMIPRoute * route; - GError * error = NULL; - - route_array = g_variant_get_fixed_array(route_var, &length, sizeof(guint32)); - if (length < 4) { - g_warning("Ignoring invalid IP4 route"); - g_variant_unref(route_var); - continue; - } - - route = nm_ip_route_new_binary(AF_INET, - &route_array[0], - route_array[1], - &route_array[2], - /* The old routes format uses "0" for default, not "-1" */ - route_array[3] ? (gint64) route_array[3] : -1, - &error); - if (route) - g_ptr_array_add(routes, route); - else { - g_warning("Ignoring invalid IP4 route: %s", error->message); - g_clear_error(&error); - } - g_variant_unref(route_var); - } - - return routes; -} - -/** - * nm_utils_ip4_netmask_to_prefix: - * @netmask: an IPv4 netmask in network byte order - * - * Returns: the CIDR prefix represented by the netmask - **/ -guint32 -nm_utils_ip4_netmask_to_prefix(guint32 netmask) -{ - G_STATIC_ASSERT_EXPR(__SIZEOF_INT__ == 4); - G_STATIC_ASSERT_EXPR(sizeof(int) == 4); - G_STATIC_ASSERT_EXPR(sizeof(netmask) == 4); - - return ((netmask != 0u) ? (guint32)(32 - __builtin_ctz(ntohl(netmask))) : 0u); -} - -/** - * nm_utils_ip4_prefix_to_netmask: - * @prefix: a CIDR prefix - * - * Returns: the netmask represented by the prefix, in network byte order - **/ -guint32 -nm_utils_ip4_prefix_to_netmask(guint32 prefix) -{ - return _nm_utils_ip4_prefix_to_netmask(prefix); -} - -/** - * nm_utils_ip4_get_default_prefix: - * @ip: an IPv4 address (in network byte order) - * - * When the Internet was originally set up, various ranges of IP addresses were - * segmented into three network classes: A, B, and C. This function will return - * a prefix that is associated with the IP address specified defining where it - * falls in the predefined classes. - * - * Returns: the default class prefix for the given IP - **/ -/* The function is originally from ipcalc.c of Red Hat's initscripts. */ -guint32 -nm_utils_ip4_get_default_prefix(guint32 ip) -{ - return _nm_utils_ip4_get_default_prefix(ip); -} - -/** - * nm_utils_ip6_dns_to_variant: - * @dns: (type utf8): an array of IP address strings - * - * Utility function to convert an array of IP address strings int a #GVariant of - * type 'aay' representing an array of IPv6 addresses. - * - * If a string cannot be parsed, it will be silently ignored. - * - * Returns: (transfer none): a new floating #GVariant representing @dns. - **/ -GVariant * -nm_utils_ip6_dns_to_variant(char **dns) -{ - GVariantBuilder builder; - gsize i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aay")); - if (dns) { - for (i = 0; dns[i]; i++) { - struct in6_addr ip; - - if (inet_pton(AF_INET6, dns[i], &ip) != 1) - continue; - g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip)); - } - } - return g_variant_builder_end(&builder); -} - -/** - * nm_utils_ip6_dns_from_variant: - * @value: a #GVariant of type 'aay' - * - * Utility function to convert a #GVariant of type 'aay' representing a list of - * IPv6 addresses into an array of IP address strings. Each "ay" entry must be - * a IPv6 address in binary form (16 bytes long). Invalid entries are silently - * ignored. - * - * Returns: (transfer full) (type utf8): a %NULL-terminated array of IP address strings. - **/ -char ** -nm_utils_ip6_dns_from_variant(GVariant *value) -{ - GVariantIter iter; - GVariant * ip_var; - char ** dns; - gsize i; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aay")), NULL); - - dns = g_new(char *, g_variant_n_children(value) + 1); - - g_variant_iter_init(&iter, value); - i = 0; - while (g_variant_iter_next(&iter, "@ay", &ip_var)) { - gsize length; - const struct in6_addr *ip = g_variant_get_fixed_array(ip_var, &length, 1); - - if (length == sizeof(struct in6_addr)) - dns[i++] = nm_utils_inet6_ntop_dup(ip); - - g_variant_unref(ip_var); - } - dns[i] = NULL; - - return dns; -} - -/** - * nm_utils_ip6_addresses_to_variant: - * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects - * @gateway: (allow-none): the gateway IP address - * - * Utility function to convert a #GPtrArray of #NMIPAddress objects representing - * IPv6 addresses into a #GVariant of type 'a(ayuay)' representing an array of - * NetworkManager IPv6 addresses (which are tuples of address, prefix, and - * gateway). The "gateway" field of the first address will get the value of - * @gateway (if non-%NULL). In all of the other addresses, that field will be - * all 0s. - * - * Returns: (transfer none): a new floating #GVariant representing @addresses. - **/ -GVariant * -nm_utils_ip6_addresses_to_variant(GPtrArray *addresses, const char *gateway) -{ - GVariantBuilder builder; - guint i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ayuay)")); - - if (addresses) { - for (i = 0; i < addresses->len; i++) { - NMIPAddress * addr = addresses->pdata[i]; - struct in6_addr address_bin; - struct in6_addr gateway_bin_data; - const struct in6_addr *gateway_bin; - - if (nm_ip_address_get_family(addr) != AF_INET6) - continue; - - nm_ip_address_get_address_binary(addr, &address_bin); - - gateway_bin = &in6addr_any; - if (gateway) { - if (inet_pton(AF_INET6, gateway, &gateway_bin_data) == 1) - gateway_bin = &gateway_bin_data; - gateway = NULL; - } - - g_variant_builder_add(&builder, - "(@ayu@ay)", - nm_g_variant_new_ay_in6addr(&address_bin), - (guint32) nm_ip_address_get_prefix(addr), - nm_g_variant_new_ay_in6addr(gateway_bin)); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * nm_utils_ip6_addresses_from_variant: - * @value: a #GVariant of type 'a(ayuay)' - * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway - * - * Utility function to convert a #GVariant of type 'a(ayuay)' representing a - * list of NetworkManager IPv6 addresses (which are tuples of address, prefix, - * and gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field - * of the first address (if set) will be returned in @out_gateway; the "gateway" - * fields of the other addresses are ignored. - * - * Returns: (transfer full) (element-type NMIPAddress): a newly allocated - * #GPtrArray of #NMIPAddress objects - **/ -GPtrArray * -nm_utils_ip6_addresses_from_variant(GVariant *value, char **out_gateway) -{ - GVariantIter iter; - GVariant * addr_var, *gateway_var; - guint32 prefix; - GPtrArray * addresses; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("a(ayuay)")), NULL); - - if (out_gateway) - *out_gateway = NULL; - - g_variant_iter_init(&iter, value); - addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); - - while (g_variant_iter_next(&iter, "(@ayu@ay)", &addr_var, &prefix, &gateway_var)) { - NMIPAddress * addr; - const struct in6_addr *addr_bytes, *gateway_bytes; - gsize addr_len, gateway_len; - GError * error = NULL; - - if (!g_variant_is_of_type(addr_var, G_VARIANT_TYPE_BYTESTRING) - || !g_variant_is_of_type(gateway_var, G_VARIANT_TYPE_BYTESTRING)) { - g_warning("%s: ignoring invalid IP6 address structure", __func__); - goto next; - } - - addr_bytes = g_variant_get_fixed_array(addr_var, &addr_len, 1); - if (addr_len != 16) { - g_warning("%s: ignoring invalid IP6 address of length %d", __func__, (int) addr_len); - goto next; - } - - addr = nm_ip_address_new_binary(AF_INET6, addr_bytes, prefix, &error); - if (addr) { - g_ptr_array_add(addresses, addr); - - if (out_gateway && !*out_gateway) { - gateway_bytes = g_variant_get_fixed_array(gateway_var, &gateway_len, 1); - if (gateway_len != 16) { - g_warning("%s: ignoring invalid IP6 address of length %d", - __func__, - (int) gateway_len); - goto next; - } - if (!IN6_IS_ADDR_UNSPECIFIED(gateway_bytes)) - *out_gateway = nm_utils_inet6_ntop_dup(gateway_bytes); - } - } else { - g_warning("Ignoring invalid IP6 address: %s", error->message); - g_clear_error(&error); - } - -next: - g_variant_unref(addr_var); - g_variant_unref(gateway_var); - } - - return addresses; -} - -/** - * nm_utils_ip6_routes_to_variant: - * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects - * - * Utility function to convert a #GPtrArray of #NMIPRoute objects representing - * IPv6 routes into a #GVariant of type 'a(ayuayu)' representing an array of - * NetworkManager IPv6 routes (which are tuples of route, prefix, next hop, and - * metric). - * - * Returns: (transfer none): a new floating #GVariant representing @routes. - **/ -GVariant * -nm_utils_ip6_routes_to_variant(GPtrArray *routes) -{ - GVariantBuilder builder; - guint i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ayuayu)")); - - if (routes) { - for (i = 0; i < routes->len; i++) { - NMIPRoute * route = routes->pdata[i]; - struct in6_addr dest_bytes; - struct in6_addr next_hop_bytes; - guint32 metric; - - if (nm_ip_route_get_family(route) != AF_INET6) - continue; - - nm_ip_route_get_dest_binary(route, &dest_bytes); - nm_ip_route_get_next_hop_binary(route, &next_hop_bytes); - - /* The old routes format uses "0" for default, not "-1" */ - metric = NM_MAX(0, nm_ip_route_get_metric(route)); - - g_variant_builder_add(&builder, - "(@ayu@ayu)", - nm_g_variant_new_ay_in6addr(&dest_bytes), - (guint32) nm_ip_route_get_prefix(route), - nm_g_variant_new_ay_in6addr(&next_hop_bytes), - metric); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * nm_utils_ip6_routes_from_variant: - * @value: #GVariant of type 'a(ayuayu)' - * - * Utility function to convert a #GVariant of type 'a(ayuayu)' representing an - * array of NetworkManager IPv6 routes (which are tuples of route, prefix, next - * hop, and metric) into a #GPtrArray of #NMIPRoute objects. - * - * Returns: (transfer full) (element-type NMIPRoute): a newly allocated - * #GPtrArray of #NMIPRoute objects - **/ -GPtrArray * -nm_utils_ip6_routes_from_variant(GVariant *value) -{ - GPtrArray * routes; - GVariantIter iter; - GVariant * dest_var, *next_hop_var; - const struct in6_addr *dest, *next_hop; - gsize dest_len, next_hop_len; - guint32 prefix, metric; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("a(ayuayu)")), NULL); - - routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); - - g_variant_iter_init(&iter, value); - while (g_variant_iter_next(&iter, "(@ayu@ayu)", &dest_var, &prefix, &next_hop_var, &metric)) { - NMIPRoute *route; - GError * error = NULL; - - if (!g_variant_is_of_type(dest_var, G_VARIANT_TYPE_BYTESTRING) - || !g_variant_is_of_type(next_hop_var, G_VARIANT_TYPE_BYTESTRING)) { - g_warning("%s: ignoring invalid IP6 address structure", __func__); - goto next; - } - - dest = g_variant_get_fixed_array(dest_var, &dest_len, 1); - if (dest_len != 16) { - g_warning("%s: ignoring invalid IP6 address of length %d", __func__, (int) dest_len); - goto next; - } - - next_hop = g_variant_get_fixed_array(next_hop_var, &next_hop_len, 1); - if (next_hop_len != 16) { - g_warning("%s: ignoring invalid IP6 address of length %d", - __func__, - (int) next_hop_len); - goto next; - } - - route = nm_ip_route_new_binary(AF_INET6, - dest, - prefix, - next_hop, - metric ? (gint64) metric : -1, - &error); - if (route) - g_ptr_array_add(routes, route); - else { - g_warning("Ignoring invalid IP6 route: %s", error->message); - g_clear_error(&error); - } - -next: - g_variant_unref(dest_var); - g_variant_unref(next_hop_var); - } - - return routes; -} - -/** - * nm_utils_ip_addresses_to_variant: - * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects - * - * Utility function to convert a #GPtrArray of #NMIPAddress objects representing - * IPv4 or IPv6 addresses into a #GVariant of type 'aa{sv}' representing an - * array of new-style NetworkManager IP addresses. All addresses will include - * "address" (an IP address string), and "prefix" (a uint). Some addresses may - * include additional attributes. - * - * Returns: (transfer none): a new floating #GVariant representing @addresses. - **/ -GVariant * -nm_utils_ip_addresses_to_variant(GPtrArray *addresses) -{ - GVariantBuilder builder; - guint i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - - if (addresses) { - for (i = 0; i < addresses->len; i++) { - NMIPAddress * addr = addresses->pdata[i]; - GVariantBuilder addr_builder; - gs_free const char **names = NULL; - guint j, len; - - g_variant_builder_init(&addr_builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&addr_builder, - "{sv}", - "address", - g_variant_new_string(nm_ip_address_get_address(addr))); - g_variant_builder_add(&addr_builder, - "{sv}", - "prefix", - g_variant_new_uint32(nm_ip_address_get_prefix(addr))); - - names = _nm_ip_address_get_attribute_names(addr, TRUE, &len); - for (j = 0; j < len; j++) { - g_variant_builder_add(&addr_builder, - "{sv}", - names[j], - nm_ip_address_get_attribute(addr, names[j])); - } - - g_variant_builder_add(&builder, "a{sv}", &addr_builder); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * nm_utils_ip_addresses_from_variant: - * @value: a #GVariant of type 'aa{sv}' - * @family: an IP address family - * - * Utility function to convert a #GVariant representing a list of new-style - * NetworkManager IPv4 or IPv6 addresses (as described in the documentation for - * nm_utils_ip_addresses_to_variant()) into a #GPtrArray of #NMIPAddress - * objects. - * - * Returns: (transfer full) (element-type NMIPAddress): a newly allocated - * #GPtrArray of #NMIPAddress objects - **/ -GPtrArray * -nm_utils_ip_addresses_from_variant(GVariant *value, int family) -{ - GPtrArray * addresses; - GVariantIter iter, attrs_iter; - GVariant * addr_var; - const char * ip; - guint32 prefix; - const char * attr_name; - GVariant * attr_val; - NMIPAddress *addr; - GError * error = NULL; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); - - g_variant_iter_init(&iter, value); - addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); - - while (g_variant_iter_next(&iter, "@a{sv}", &addr_var)) { - if (!g_variant_lookup(addr_var, "address", "&s", &ip) - || !g_variant_lookup(addr_var, "prefix", "u", &prefix)) { - g_warning("Ignoring invalid address"); - g_variant_unref(addr_var); - continue; - } - - addr = nm_ip_address_new(family, ip, prefix, &error); - if (!addr) { - g_warning("Ignoring invalid address: %s", error->message); - g_clear_error(&error); - g_variant_unref(addr_var); - continue; - } - - g_variant_iter_init(&attrs_iter, addr_var); - while (g_variant_iter_next(&attrs_iter, "{&sv}", &attr_name, &attr_val)) { - if (!NM_IN_STRSET(attr_name, "address", "prefix")) - nm_ip_address_set_attribute(addr, attr_name, attr_val); - g_variant_unref(attr_val); - } - - g_variant_unref(addr_var); - g_ptr_array_add(addresses, addr); - } - - return addresses; -} - -/** - * nm_utils_ip_routes_to_variant: - * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects - * - * Utility function to convert a #GPtrArray of #NMIPRoute objects representing - * IPv4 or IPv6 routes into a #GVariant of type 'aa{sv}' representing an array - * of new-style NetworkManager IP routes (which are tuples of destination, - * prefix, next hop, metric, and additional attributes). - * - * Returns: (transfer none): a new floating #GVariant representing @routes. - **/ -GVariant * -nm_utils_ip_routes_to_variant(GPtrArray *routes) -{ - GVariantBuilder builder; - guint i; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - - if (routes) { - for (i = 0; i < routes->len; i++) { - NMIPRoute * route = routes->pdata[i]; - GVariantBuilder route_builder; - gs_free const char **names = NULL; - guint j, len; - - g_variant_builder_init(&route_builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&route_builder, - "{sv}", - "dest", - g_variant_new_string(nm_ip_route_get_dest(route))); - g_variant_builder_add(&route_builder, - "{sv}", - "prefix", - g_variant_new_uint32(nm_ip_route_get_prefix(route))); - if (nm_ip_route_get_next_hop(route)) { - g_variant_builder_add(&route_builder, - "{sv}", - "next-hop", - g_variant_new_string(nm_ip_route_get_next_hop(route))); - } - if (nm_ip_route_get_metric(route) != -1) { - g_variant_builder_add( - &route_builder, - "{sv}", - "metric", - g_variant_new_uint32((guint32) nm_ip_route_get_metric(route))); - } - - names = _nm_ip_route_get_attribute_names(route, TRUE, &len); - for (j = 0; j < len; j++) { - g_variant_builder_add(&route_builder, - "{sv}", - names[j], - nm_ip_route_get_attribute(route, names[j])); - } - - g_variant_builder_add(&builder, "a{sv}", &route_builder); - } - } - - return g_variant_builder_end(&builder); -} - -/** - * nm_utils_ip_routes_from_variant: - * @value: a #GVariant of type 'aa{sv}' - * @family: an IP address family - * - * Utility function to convert a #GVariant representing a list of new-style - * NetworkManager IPv4 or IPv6 addresses (which are tuples of destination, - * prefix, next hop, metric, and additional attributes) into a #GPtrArray of - * #NMIPRoute objects. - * - * Returns: (transfer full) (element-type NMIPRoute): a newly allocated - * #GPtrArray of #NMIPRoute objects - **/ -GPtrArray * -nm_utils_ip_routes_from_variant(GVariant *value, int family) -{ - GPtrArray * routes; - GVariantIter iter, attrs_iter; - GVariant * route_var; - const char * dest, *next_hop; - guint32 prefix, metric32; - gint64 metric; - const char * attr_name; - GVariant * attr_val; - NMIPRoute * route; - GError * error = NULL; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); - - g_variant_iter_init(&iter, value); - routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); - - while (g_variant_iter_next(&iter, "@a{sv}", &route_var)) { - if (!g_variant_lookup(route_var, "dest", "&s", &dest) - || !g_variant_lookup(route_var, "prefix", "u", &prefix)) { - g_warning("Ignoring invalid address"); - goto next; - } - if (!g_variant_lookup(route_var, "next-hop", "&s", &next_hop)) - next_hop = NULL; - if (g_variant_lookup(route_var, "metric", "u", &metric32)) - metric = metric32; - else - metric = -1; - - route = nm_ip_route_new(family, dest, prefix, next_hop, metric, &error); - if (!route) { - g_warning("Ignoring invalid route: %s", error->message); - g_clear_error(&error); - goto next; - } - - g_variant_iter_init(&attrs_iter, route_var); - while (g_variant_iter_next(&attrs_iter, "{&sv}", &attr_name, &attr_val)) { - if (!NM_IN_STRSET(attr_name, "dest", "prefix", "next-hop", "metric")) - nm_ip_route_set_attribute(route, attr_name, attr_val); - g_variant_unref(attr_val); - } - - g_ptr_array_add(routes, route); -next: - g_variant_unref(route_var); - } - - return routes; -} - -/*****************************************************************************/ - -static void -_string_append_tc_handle(GString *string, guint32 handle) -{ - g_string_append_printf(string, "%x:", TC_H_MAJ(handle) >> 16); - if (TC_H_MIN(handle) != TC_H_UNSPEC) - g_string_append_printf(string, "%x", TC_H_MIN(handle)); -} - -/** - * _nm_utils_string_append_tc_parent: - * @string: the string to write the parent handle to - * @prefix: optional prefix for the numeric handle - * @parent: the parent handle - * - * This is used to either write out the parent handle to the tc qdisc string - * or to pretty-format (use symbolic name for root) the key in keyfile. - * The presence of prefix determines which one is the case. - * - * Private API due to general ugliness and overall uselessness for anything - * sensible. - */ -void -_nm_utils_string_append_tc_parent(GString *string, const char *prefix, guint32 parent) -{ - if (parent == TC_H_ROOT) { - g_string_append(string, "root"); - } else { - if (prefix) { - if (parent == TC_H_INGRESS) - return; - g_string_append_printf(string, "%s ", prefix); - } - _string_append_tc_handle(string, parent); - } - - if (prefix) - g_string_append_c(string, ' '); -} - -/** - * _nm_utils_parse_tc_handle: - * @str: the string representation of a qdisc handle - * @error: location of the error - * - * Parses tc style handle number into a numeric representation. - * Don't use this, use nm_utils_tc_qdisc_from_str() instead. - */ -guint32 -_nm_utils_parse_tc_handle(const char *str, GError **error) -{ - gint64 maj; - gint64 min = 0; - const char *sep; - - nm_assert(str); - - maj = nm_g_ascii_strtoll(str, (char **) &sep, 0x10); - if (sep == str) - goto fail; - - sep = nm_str_skip_leading_spaces(sep); - - if (sep[0] == ':') { - const char *str2 = &sep[1]; - - min = nm_g_ascii_strtoll(str2, (char **) &sep, 0x10); - sep = nm_str_skip_leading_spaces(sep); - if (sep[0] != '\0') - goto fail; - } else if (sep[0] != '\0') - goto fail; - - if (maj <= 0 || maj > 0xffff || min < 0 || min > 0xffff - || !NM_STRCHAR_ALL(str, ch, (g_ascii_isxdigit(ch) || ch == ':' || g_ascii_isspace(ch)))) { - goto fail; - } - - return TC_H_MAKE(((guint32) maj) << 16, (guint32) min); -fail: - nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("'%s' is not a valid handle."), str); - return TC_H_UNSPEC; -} - -static const NMVariantAttributeSpec *const tc_object_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("root", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("parent", G_VARIANT_TYPE_STRING, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("handle", G_VARIANT_TYPE_STRING, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("", - G_VARIANT_TYPE_STRING, - .no_value = TRUE, - .consumes_rest = TRUE, ), - NULL, -}; - -static const NMVariantAttributeSpec *const tc_qdisc_sfq_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("quantum", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("perturb", G_VARIANT_TYPE_INT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("limit", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("divisor", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("flows", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("depth", G_VARIANT_TYPE_UINT32, ), - NULL, -}; - -static const NMVariantAttributeSpec *const tc_qdisc_tbf_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("rate", G_VARIANT_TYPE_UINT64, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("burst", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("limit", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("latency", G_VARIANT_TYPE_UINT32, ), - NULL, -}; - -static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("limit", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("flows", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("target", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("interval", G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("quantum", G_VARIANT_TYPE_UINT32, ), - - /* 0x83126E97u is not a valid value (it means "disabled"). We should reject that - * value. Or alternatively, reject all values >= MAX_INT(32). */ - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("ce_threshold", G_VARIANT_TYPE_UINT32, ), - - /* kernel clamps the value at 2^31. Possibly such values should be rejected from configuration - * as they cannot be configured. Leaving the attribute unspecified causes kernel to choose - * a default (currently 32MB). */ - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("memory_limit", G_VARIANT_TYPE_UINT32, ), - - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("ecn", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), - NULL, -}; - -typedef struct { - const char * kind; - const NMVariantAttributeSpec *const *attrs; -} NMQdiscAttributeSpec; - -static const NMQdiscAttributeSpec *const tc_qdisc_attribute_spec[] = { - &(const NMQdiscAttributeSpec){"fq_codel", tc_qdisc_fq_codel_spec}, - &(const NMQdiscAttributeSpec){"sfq", tc_qdisc_sfq_spec}, - &(const NMQdiscAttributeSpec){"tbf", tc_qdisc_tbf_spec}, - NULL, -}; - -/*****************************************************************************/ - -/** - * _nm_utils_string_append_tc_qdisc_rest: - * @string: the string to write the formatted qdisc to - * @qdisc: the %NMTCQdisc - * - * This formats the rest of the qdisc string but the parent. Useful to format - * the keyfile value and nowhere else. - * Use nm_utils_tc_qdisc_to_str() that also includes the parent instead. - */ -void -_nm_utils_string_append_tc_qdisc_rest(GString *string, NMTCQdisc *qdisc) -{ - guint32 handle = nm_tc_qdisc_get_handle(qdisc); - const char * kind = nm_tc_qdisc_get_kind(qdisc); - gs_free char *str = NULL; - - if (handle != TC_H_UNSPEC && !NM_IN_STRSET(kind, "ingress", "clsact")) { - g_string_append(string, "handle "); - _string_append_tc_handle(string, handle); - g_string_append_c(string, ' '); - } - - g_string_append(string, kind); - - str = nm_utils_format_variant_attributes(_nm_tc_qdisc_get_attributes(qdisc), ' ', ' '); - if (str) { - g_string_append_c(string, ' '); - g_string_append(string, str); - } -} - -/** - * nm_utils_tc_qdisc_to_str: - * @qdisc: the %NMTCQdisc - * @error: location of the error - * - * Turns the %NMTCQdisc into a tc style string representation of the queueing - * discipline. - * - * Returns: formatted string or %NULL - * - * Since: 1.12 - */ -char * -nm_utils_tc_qdisc_to_str(NMTCQdisc *qdisc, GError **error) -{ - GString *string; - - string = g_string_sized_new(60); - - _nm_utils_string_append_tc_parent(string, "parent", nm_tc_qdisc_get_parent(qdisc)); - _nm_utils_string_append_tc_qdisc_rest(string, qdisc); - - return g_string_free(string, FALSE); -} - -static gboolean -_tc_read_common_opts(const char *str, - guint32 * handle, - guint32 * parent, - char ** kind, - char ** rest, - GError ** error) -{ - gs_unref_hashtable GHashTable *ht = NULL; - GVariant * variant; - - ht = nm_utils_parse_variant_attributes(str, ' ', ' ', FALSE, tc_object_attribute_spec, error); - if (!ht) - return FALSE; - - if (g_hash_table_contains(ht, "root")) - *parent = TC_H_ROOT; - - variant = g_hash_table_lookup(ht, "parent"); - if (variant) { - if (*parent != TC_H_UNSPEC) { - g_set_error(error, - 1, - 0, - _("'%s' unexpected: parent already specified."), - g_variant_get_string(variant, NULL)); - return FALSE; - } - *parent = _nm_utils_parse_tc_handle(g_variant_get_string(variant, NULL), error); - if (*parent == TC_H_UNSPEC) - return FALSE; - } - - variant = g_hash_table_lookup(ht, "handle"); - if (variant) { - *handle = _nm_utils_parse_tc_handle(g_variant_get_string(variant, NULL), error); - if (*handle == TC_H_UNSPEC) - return FALSE; - if (TC_H_MIN(*handle)) { - g_set_error(error, - 1, - 0, - _("invalid handle: '%s'"), - g_variant_get_string(variant, NULL)); - return FALSE; - } - } - - variant = g_hash_table_lookup(ht, "kind"); - if (variant) { - *kind = g_variant_dup_string(variant, NULL); - if (NM_IN_STRSET(*kind, "ingress", "clsact")) { - if (*parent == TC_H_UNSPEC) - *parent = TC_H_INGRESS; - if (*handle == TC_H_UNSPEC) - *handle = TC_H_MAKE(TC_H_INGRESS, 0); - } - } - - if (*parent == TC_H_UNSPEC) { - if (*kind) { - g_free(*kind); - *kind = NULL; - } - g_set_error_literal(error, 1, 0, _("parent not specified.")); - return FALSE; - } - - variant = g_hash_table_lookup(ht, ""); - if (variant) - *rest = g_variant_dup_string(variant, NULL); - - return TRUE; -} - -/** - * nm_utils_tc_qdisc_from_str: - * @str: the string representation of a qdisc - * @error: location of the error - * - * Parses the tc style string qdisc representation of the queueing - * discipline to a %NMTCQdisc instance. Supports a subset of the tc language. - * - * Returns: the %NMTCQdisc or %NULL - * - * Since: 1.12 - */ -NMTCQdisc * -nm_utils_tc_qdisc_from_str(const char *str, GError **error) -{ - guint32 handle = TC_H_UNSPEC; - guint32 parent = TC_H_UNSPEC; - gs_free char * kind = NULL; - gs_free char * rest = NULL; - NMTCQdisc * qdisc = NULL; - gs_unref_hashtable GHashTable *options = NULL; - GHashTableIter iter; - gpointer key, value; - guint i; - - nm_assert(str); - nm_assert(!error || !*error); - - if (!_tc_read_common_opts(str, &handle, &parent, &kind, &rest, error)) - return NULL; - - for (i = 0; rest && tc_qdisc_attribute_spec[i]; i++) { - if (nm_streq(tc_qdisc_attribute_spec[i]->kind, kind)) { - options = nm_utils_parse_variant_attributes(rest, - ' ', - ' ', - FALSE, - tc_qdisc_attribute_spec[i]->attrs, - error); - if (!options) - return NULL; - break; - } - } - nm_clear_g_free(&rest); - - if (options) { - value = g_hash_table_lookup(options, ""); - if (value) - rest = g_variant_dup_string(value, NULL); - } - - if (rest) { - g_set_error(error, 1, 0, _("unsupported qdisc option: '%s'."), rest); - return NULL; - } - - qdisc = nm_tc_qdisc_new(kind, parent, error); - if (!qdisc) - return NULL; - - nm_tc_qdisc_set_handle(qdisc, handle); - - if (options) { - g_hash_table_iter_init(&iter, options); - while (g_hash_table_iter_next(&iter, &key, &value)) - nm_tc_qdisc_set_attribute(qdisc, key, g_variant_ref_sink(value)); - } - - return qdisc; -} - -/*****************************************************************************/ - -static const NMVariantAttributeSpec *const tc_action_simple_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("sdata", G_VARIANT_TYPE_BYTESTRING, ), - NULL, -}; - -static const NMVariantAttributeSpec *const tc_action_mirred_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("egress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("ingress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("mirror", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("redirect", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("dev", G_VARIANT_TYPE_STRING, ), - NULL, -}; - -static const NMVariantAttributeSpec *const tc_action_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("", - G_VARIANT_TYPE_STRING, - .no_value = TRUE, - .consumes_rest = TRUE, ), - NULL, -}; - -static gboolean -_string_append_tc_action(GString *string, NMTCAction *action, GError **error) -{ - const char * kind = nm_tc_action_get_kind(action); - gs_free char * str = NULL; - const NMVariantAttributeSpec *const *attrs; - - if (nm_streq(kind, "simple")) - attrs = tc_action_simple_attribute_spec; - else if (nm_streq(kind, "mirred")) - attrs = tc_action_mirred_attribute_spec; - else - attrs = NULL; - - g_string_append(string, kind); - - str = - _nm_utils_format_variant_attributes(_nm_tc_action_get_attributes(action), attrs, ' ', ' '); - if (str) { - g_string_append_c(string, ' '); - g_string_append(string, str); - } - - return TRUE; -} - -/** - * nm_utils_tc_action_to_str: - * @action: the %NMTCAction - * @error: location of the error - * - * Turns the %NMTCAction into a tc style string representation of the queueing - * discipline. - * - * Returns: formatted string or %NULL - * - * Since: 1.12 - */ -char * -nm_utils_tc_action_to_str(NMTCAction *action, GError **error) -{ - GString *string; - - string = g_string_sized_new(60); - if (!_string_append_tc_action(string, action, error)) { - g_string_free(string, TRUE); - return NULL; - } - - return g_string_free(string, FALSE); -} - -/** - * nm_utils_tc_action_from_str: - * @str: the string representation of a action - * @error: location of the error - * - * Parses the tc style string action representation of the queueing - * discipline to a %NMTCAction instance. Supports a subset of the tc language. - * - * Returns: the %NMTCAction or %NULL - * - * Since: 1.12 - */ -NMTCAction * -nm_utils_tc_action_from_str(const char *str, GError **error) -{ - const char * kind = NULL; - const char * rest = NULL; - NMTCAction * action = NULL; - gs_unref_hashtable GHashTable *ht = NULL; - gs_unref_hashtable GHashTable * options = NULL; - GVariant * variant; - const NMVariantAttributeSpec *const *attrs; - - nm_assert(str); - nm_assert(!error || !*error); - - ht = nm_utils_parse_variant_attributes(str, ' ', ' ', FALSE, tc_action_attribute_spec, error); - if (!ht) - return FALSE; - - variant = g_hash_table_lookup(ht, "kind"); - if (variant) { - kind = g_variant_get_string(variant, NULL); - } else { - g_set_error_literal(error, 1, 0, _("action name missing.")); - return NULL; - } - - kind = g_variant_get_string(variant, NULL); - if (nm_streq(kind, "simple")) - attrs = tc_action_simple_attribute_spec; - else if (nm_streq(kind, "mirred")) - attrs = tc_action_mirred_attribute_spec; - else - attrs = NULL; - - variant = g_hash_table_lookup(ht, ""); - if (variant) - rest = g_variant_get_string(variant, NULL); - - action = nm_tc_action_new(kind, error); - if (!action) - return NULL; - - if (rest) { - GHashTableIter iter; - gpointer key, value; - - if (!attrs) { - nm_tc_action_unref(action); - g_set_error(error, 1, 0, _("unsupported action option: '%s'."), rest); - return NULL; - } - - options = nm_utils_parse_variant_attributes(rest, ' ', ' ', FALSE, attrs, error); - if (!options) { - nm_tc_action_unref(action); - return NULL; - } - - g_hash_table_iter_init(&iter, options); - while (g_hash_table_iter_next(&iter, &key, &value)) - nm_tc_action_set_attribute(action, key, g_variant_ref_sink(value)); - } - - return action; -} - -/*****************************************************************************/ - -/** - * _nm_utils_string_append_tc_tfilter_rest: - * @string: the string to write the formatted tfilter to - * @tfilter: the %NMTCTfilter - * - * This formats the rest of the tfilter string but the parent. Useful to format - * the keyfile value and nowhere else. - * Use nm_utils_tc_tfilter_to_str() that also includes the parent instead. - */ -gboolean -_nm_utils_string_append_tc_tfilter_rest(GString *string, NMTCTfilter *tfilter, GError **error) -{ - guint32 handle = nm_tc_tfilter_get_handle(tfilter); - const char *kind = nm_tc_tfilter_get_kind(tfilter); - NMTCAction *action; - - if (handle != TC_H_UNSPEC) { - g_string_append(string, "handle "); - _string_append_tc_handle(string, handle); - g_string_append_c(string, ' '); - } - - g_string_append(string, kind); - - action = nm_tc_tfilter_get_action(tfilter); - if (action) { - g_string_append(string, " action "); - if (!_string_append_tc_action(string, action, error)) - return FALSE; - } - - return TRUE; -} - -/** - * nm_utils_tc_tfilter_to_str: - * @tfilter: the %NMTCTfilter - * @error: location of the error - * - * Turns the %NMTCTfilter into a tc style string representation of the queueing - * discipline. - * - * Returns: formatted string or %NULL - * - * Since: 1.12 - */ -char * -nm_utils_tc_tfilter_to_str(NMTCTfilter *tfilter, GError **error) -{ - GString *string; - - string = g_string_sized_new(60); - - _nm_utils_string_append_tc_parent(string, "parent", nm_tc_tfilter_get_parent(tfilter)); - if (!_nm_utils_string_append_tc_tfilter_rest(string, tfilter, error)) { - g_string_free(string, TRUE); - return NULL; - } - - return g_string_free(string, FALSE); -} - -static const NMVariantAttributeSpec *const tc_tfilter_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("action", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("", - G_VARIANT_TYPE_STRING, - .no_value = TRUE, - .consumes_rest = TRUE, ), - NULL, -}; - -/** - * nm_utils_tc_tfilter_from_str: - * @str: the string representation of a tfilter - * @error: location of the error - * - * Parses the tc style string tfilter representation of the queueing - * discipline to a %NMTCTfilter instance. Supports a subset of the tc language. - * - * Returns: the %NMTCTfilter or %NULL - * - * Since: 1.12 - */ -NMTCTfilter * -nm_utils_tc_tfilter_from_str(const char *str, GError **error) -{ - guint32 handle = TC_H_UNSPEC; - guint32 parent = TC_H_UNSPEC; - gs_free char * kind = NULL; - gs_free char * rest = NULL; - NMTCAction * action = NULL; - const char * extra_opts = NULL; - NMTCTfilter * tfilter = NULL; - gs_unref_hashtable GHashTable *ht = NULL; - GVariant * variant; - - nm_assert(str); - nm_assert(!error || !*error); - - if (!_tc_read_common_opts(str, &handle, &parent, &kind, &rest, error)) - return NULL; - - if (rest) { - ht = nm_utils_parse_variant_attributes(rest, - ' ', - ' ', - FALSE, - tc_tfilter_attribute_spec, - error); - if (!ht) - return NULL; - - variant = g_hash_table_lookup(ht, ""); - if (variant) - extra_opts = g_variant_get_string(variant, NULL); - - if (g_hash_table_contains(ht, "action")) { - action = nm_utils_tc_action_from_str(extra_opts, error); - if (!action) { - g_prefix_error(error, _("invalid action: ")); - return NULL; - } - } else { - g_set_error(error, 1, 0, _("unsupported tfilter option: '%s'."), rest); - return NULL; - } - } - - tfilter = nm_tc_tfilter_new(kind, parent, error); - if (!tfilter) - return NULL; - - nm_tc_tfilter_set_handle(tfilter, handle); - if (action) { - nm_tc_tfilter_set_action(tfilter, action); - nm_tc_action_unref(action); - } - - return tfilter; -} - -/*****************************************************************************/ - -extern const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[]; - -/** - * nm_utils_sriov_vf_to_str: - * @vf: the %NMSriovVF - * @omit_index: if %TRUE, the VF index will be omitted from output string - * @error: (out) (allow-none): location to store the error on failure - * - * Converts a SR-IOV virtual function object to its string representation. - * - * Returns: a newly allocated string or %NULL on error - * - * Since: 1.14 - */ -char * -nm_utils_sriov_vf_to_str(const NMSriovVF *vf, gboolean omit_index, GError **error) -{ - gs_free NMUtilsNamedValue *values = NULL; - gs_free const char ** names = NULL; - const guint * vlan_ids; - guint num_vlans, num_attrs; - guint i; - GString * str; - - str = g_string_new(""); - if (!omit_index) - g_string_append_printf(str, "%u", nm_sriov_vf_get_index(vf)); - - names = nm_sriov_vf_get_attribute_names(vf); - num_attrs = names ? g_strv_length((char **) names) : 0; - values = g_new0(NMUtilsNamedValue, num_attrs); - - for (i = 0; i < num_attrs; i++) { - values[i].name = names[i]; - values[i].value_ptr = nm_sriov_vf_get_attribute(vf, names[i]); - } - - if (num_attrs > 0) { - if (!omit_index) - g_string_append_c(str, ' '); - _nm_utils_format_variant_attributes_full(str, values, num_attrs, NULL, ' ', '='); - } - - vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num_vlans); - if (num_vlans != 0) { - g_string_append(str, " vlans"); - for (i = 0; i < num_vlans; i++) { - guint32 qos; - NMSriovVFVlanProtocol protocol; - - qos = nm_sriov_vf_get_vlan_qos(vf, vlan_ids[i]); - protocol = nm_sriov_vf_get_vlan_protocol(vf, vlan_ids[i]); - - g_string_append_c(str, i == 0 ? '=' : ';'); - - g_string_append_printf(str, "%u", vlan_ids[i]); - - if (qos != 0 || protocol != NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q) { - g_string_append_printf(str, - ".%u%s", - (unsigned) qos, - protocol == NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q ? "" : ".ad"); - } - } - } - - return g_string_free(str, FALSE); -} - -gboolean -_nm_sriov_vf_parse_vlans(NMSriovVF *vf, const char *str, GError **error) -{ - gs_free const char **vlans = NULL; - guint i; - - vlans = nm_utils_strsplit_set(str, ";"); - if (!vlans) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "empty VF VLAN"); - return FALSE; - } - - for (i = 0; vlans[i]; i++) { - gs_strfreev char **params = NULL; - guint id = G_MAXUINT; - gint64 qos = -1; - - /* we accept leading/trailing whitespace around vlans[1]. Hence - * the nm_str_skip_leading_spaces() and g_strchomp() below. - * - * However, we don't accept any whitespace inside the specifier. - * Hence the NM_STRCHAR_ALL() checks. */ - - params = g_strsplit(nm_str_skip_leading_spaces(vlans[i]), ".", 3); - if (!params || !params[0] || *params[0] == '\0') { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "empty VF VLAN"); - return FALSE; - } - - if (!params[1]) - g_strchomp(params[0]); - if (NM_STRCHAR_ALL(params[0], ch, ch == 'x' || g_ascii_isdigit(ch))) - id = _nm_utils_ascii_str_to_int64(params[0], 0, 0, 4095, G_MAXUINT); - if (id == G_MAXUINT) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "invalid VF VLAN id '%s'", - params[0]); - return FALSE; - } - if (!nm_sriov_vf_add_vlan(vf, id)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "duplicate VLAN id %u", - id); - return FALSE; - } - - if (!params[1]) - continue; - - if (!params[2]) - g_strchomp(params[1]); - if (NM_STRCHAR_ALL(params[1], ch, ch == 'x' || g_ascii_isdigit(ch))) - qos = _nm_utils_ascii_str_to_int64(params[1], 0, 0, G_MAXUINT32, -1); - if (qos == -1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "invalid VF VLAN QoS '%s'", - params[1]); - return FALSE; - } - nm_sriov_vf_set_vlan_qos(vf, id, qos); - - if (!params[2]) - continue; - - g_strchomp(params[2]); - - if (nm_streq(params[2], "ad")) - nm_sriov_vf_set_vlan_protocol(vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); - else if (nm_streq(params[2], "q")) - nm_sriov_vf_set_vlan_protocol(vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - else { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "invalid VF VLAN protocol '%s'", - params[2]); - return FALSE; - } - } - - return TRUE; -} - -/** - * nm_utils_sriov_vf_from_str: - * @str: the input string - * @error: (out) (allow-none): location to store the error on failure - * - * Converts a string to a SR-IOV virtual function object. - * - * Returns: (transfer full): the virtual function object - * - * Since: 1.14 - */ -NMSriovVF * -nm_utils_sriov_vf_from_str(const char *str, GError **error) -{ - gs_free char *index_free = NULL; - const char * detail; - - g_return_val_if_fail(str, NULL); - g_return_val_if_fail(!error || !*error, NULL); - - while (*str == ' ') - str++; - - detail = strchr(str, ' '); - if (detail) { - str = nm_strndup_a(200, str, detail - str, &index_free); - detail++; - } - - return _nm_utils_sriov_vf_from_strparts(str, detail, FALSE, error); -} - -NMSriovVF * -_nm_utils_sriov_vf_from_strparts(const char *index, - const char *detail, - gboolean ignore_unknown, - GError ** error) -{ - NMSriovVF * vf; - guint32 n_index; - GHashTableIter iter; - char * key; - GVariant * variant; - gs_unref_hashtable GHashTable *ht = NULL; - - n_index = _nm_utils_ascii_str_to_int64(index, 10, 0, G_MAXUINT32, 0); - if (errno) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "invalid index"); - return NULL; - } - - vf = nm_sriov_vf_new(n_index); - if (detail) { - ht = nm_utils_parse_variant_attributes(detail, - ' ', - '=', - ignore_unknown, - _nm_sriov_vf_attribute_spec, - error); - if (!ht) { - nm_sriov_vf_unref(vf); - return NULL; - } - - if ((variant = g_hash_table_lookup(ht, "vlans"))) { - if (!_nm_sriov_vf_parse_vlans(vf, g_variant_get_string(variant, NULL), error)) { - nm_sriov_vf_unref(vf); - return NULL; - } - g_hash_table_remove(ht, "vlans"); - } - - g_hash_table_iter_init(&iter, ht); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &variant)) - nm_sriov_vf_set_attribute(vf, key, g_variant_ref_sink(variant)); - } - - return vf; -} - -/*****************************************************************************/ - -NMUuid * -_nm_utils_uuid_parse(const char *str, NMUuid *out_uuid) -{ - nm_assert(str); - nm_assert(out_uuid); - - if (uuid_parse(str, out_uuid->uuid) != 0) - return NULL; - return out_uuid; -} - -char * -_nm_utils_uuid_unparse(const NMUuid *uuid, char *out_str /*[37]*/) -{ - nm_assert(uuid); - - if (!out_str) { - /* for convenience, allow %NULL to indicate that a new - * string should be allocated. */ - out_str = g_malloc(37); - } - uuid_unparse_lower(uuid->uuid, out_str); - return out_str; -} - -NMUuid * -_nm_utils_uuid_generate_random(NMUuid *out_uuid) -{ - nm_assert(out_uuid); - - uuid_generate_random(out_uuid->uuid); - return out_uuid; -} - -gboolean -nm_utils_uuid_is_null(const NMUuid *uuid) -{ - int i; - - if (!uuid) - return TRUE; - - for (i = 0; i < (int) G_N_ELEMENTS(uuid->uuid); i++) { - if (uuid->uuid[i]) - return FALSE; - } - return TRUE; -} - -/** - * nm_utils_uuid_generate_buf_: - * @buf: input buffer, must contain at least 37 bytes - * - * Returns: generates a new random UUID, writes it to @buf and returns @buf. - **/ -char * -nm_utils_uuid_generate_buf_(char *buf) -{ - NMUuid uuid; - - nm_assert(buf); - - _nm_utils_uuid_generate_random(&uuid); - return _nm_utils_uuid_unparse(&uuid, buf); -} - -/** - * nm_utils_uuid_generate: - * - * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection - * object's #NMSettingConnection:id: property. Should be freed with g_free() - **/ -char * -nm_utils_uuid_generate(void) -{ - return nm_utils_uuid_generate_buf_(g_malloc(37)); -} - -/** - * nm_utils_uuid_generate_from_string_bin: - * @uuid: the UUID to update inplace. This function cannot - * fail to succeed. - * @s: a string to use as the seed for the UUID - * @slen: if negative, treat @s as zero terminated C string. - * Otherwise, assume the length as given (and allow @s to be - * non-null terminated or contain '\0'). - * @uuid_type: a type identifier which UUID format to generate. - * @type_args: additional arguments, depending on the uuid_type - * - * For a given @s, this function will always return the same UUID. - * - * Returns: the input @uuid. This function cannot fail. - **/ -NMUuid * -nm_utils_uuid_generate_from_string_bin(NMUuid * uuid, - const char *s, - gssize slen, - int uuid_type, - gpointer type_args) -{ - g_return_val_if_fail(uuid, FALSE); - g_return_val_if_fail(slen == 0 || s, FALSE); - - if (slen < 0) - slen = s ? strlen(s) : 0; - - switch (uuid_type) { - case NM_UTILS_UUID_TYPE_LEGACY: - g_return_val_if_fail(!type_args, NULL); - nm_crypto_md5_hash(NULL, 0, (guint8 *) s, slen, (guint8 *) uuid, sizeof(*uuid)); - break; - case NM_UTILS_UUID_TYPE_VERSION3: - case NM_UTILS_UUID_TYPE_VERSION5: - { - NMUuid ns_uuid = {}; - - if (type_args) { - /* type_args can be a name space UUID. Interpret it as (char *) */ - if (!_nm_utils_uuid_parse(type_args, &ns_uuid)) - g_return_val_if_reached(NULL); - } - - if (uuid_type == NM_UTILS_UUID_TYPE_VERSION3) { - nm_crypto_md5_hash((guint8 *) s, - slen, - (guint8 *) &ns_uuid, - sizeof(ns_uuid), - (guint8 *) uuid, - sizeof(*uuid)); - } else { - nm_auto_free_checksum GChecksum *sum = NULL; - union { - guint8 sha1[NM_UTILS_CHECKSUM_LENGTH_SHA1]; - NMUuid uuid; - } digest; - - sum = g_checksum_new(G_CHECKSUM_SHA1); - g_checksum_update(sum, (guchar *) &ns_uuid, sizeof(ns_uuid)); - g_checksum_update(sum, (guchar *) s, slen); - nm_utils_checksum_get_digest(sum, digest.sha1); - - G_STATIC_ASSERT_EXPR(sizeof(digest.sha1) > sizeof(digest.uuid)); - *uuid = digest.uuid; - } - - uuid->uuid[6] = (uuid->uuid[6] & 0x0F) | (uuid_type << 4); - uuid->uuid[8] = (uuid->uuid[8] & 0x3F) | 0x80; - break; - } - default: - g_return_val_if_reached(NULL); - } - - return uuid; -} - -/** - * nm_utils_uuid_generate_from_string: - * @s: a string to use as the seed for the UUID - * @slen: if negative, treat @s as zero terminated C string. - * Otherwise, assume the length as given (and allow @s to be - * non-null terminated or contain '\0'). - * @uuid_type: a type identifier which UUID format to generate. - * @type_args: additional arguments, depending on the uuid_type - * - * For a given @s, this function will always return the same UUID. - * - * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection - * object's #NMSettingConnection:id: property - **/ -char * -nm_utils_uuid_generate_from_string(const char *s, gssize slen, int uuid_type, gpointer type_args) -{ - NMUuid uuid; - - nm_utils_uuid_generate_from_string_bin(&uuid, s, slen, uuid_type, type_args); - return _nm_utils_uuid_unparse(&uuid, NULL); -} - -/** - * _nm_utils_uuid_generate_from_strings: - * @string1: a variadic list of strings. Must be NULL terminated. - * - * Returns a variant3 UUID based on the concatenated C strings. - * It does not simply concatenate them, but also includes the - * terminating '\0' character. For example "a", "b", gives - * "a\0b\0". - * - * This has the advantage, that the following invocations - * all give different UUIDs: (NULL), (""), ("",""), ("","a"), ("a",""), - * ("aa"), ("aa", ""), ("", "aa"), ... - */ -char * -_nm_utils_uuid_generate_from_strings(const char *string1, ...) -{ - if (!string1) - return nm_utils_uuid_generate_from_string(NULL, - 0, - NM_UTILS_UUID_TYPE_VERSION3, - NM_UTILS_UUID_NS); - - { - nm_auto_str_buf NMStrBuf str = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); - va_list args; - const char * s; - - nm_str_buf_append_len(&str, string1, strlen(string1) + 1u); - - va_start(args, string1); - s = va_arg(args, const char *); - while (s) { - nm_str_buf_append_len(&str, s, strlen(s) + 1u); - s = va_arg(args, const char *); - } - va_end(args); - - return nm_utils_uuid_generate_from_string(nm_str_buf_get_str_unsafe(&str), - str.len, - NM_UTILS_UUID_TYPE_VERSION3, - NM_UTILS_UUID_NS); - } -} - -/*****************************************************************************/ - -static gboolean -file_has_extension(const char *filename, const char *extensions[]) -{ - const char *ext; - gsize i; - - ext = strrchr(filename, '.'); - if (!ext) - return FALSE; - - for (i = 0; extensions[i]; i++) { - if (!g_ascii_strcasecmp(ext, extensions[i])) - return TRUE; - } - - return FALSE; -} - -/** - * nm_utils_file_is_certificate: - * @filename: name of the file to test - * - * Tests if @filename has a valid extension for an X.509 certificate file - * (".cer", ".crt", ".der", or ".pem"), and contains a certificate in a format - * recognized by NetworkManager. - * - * Returns: %TRUE if the file is a certificate, %FALSE if it is not - **/ -gboolean -nm_utils_file_is_certificate(const char *filename) -{ - const char * extensions[] = {".der", ".pem", ".crt", ".cer", NULL}; - NMCryptoFileFormat file_format; - - g_return_val_if_fail(filename != NULL, FALSE); - - if (!file_has_extension(filename, extensions)) - return FALSE; - - if (!nm_crypto_load_and_verify_certificate(filename, &file_format, NULL, NULL)) - return FALSE; - return file_format = NM_CRYPTO_FILE_FORMAT_X509; -} - -/** - * nm_utils_file_is_private_key: - * @filename: name of the file to test - * @out_encrypted: (out): on return, whether the file is encrypted - * - * Tests if @filename has a valid extension for an X.509 private key file - * (".der", ".key", ".pem", or ".p12"), and contains a private key in a format - * recognized by NetworkManager. - * - * Returns: %TRUE if the file is a private key, %FALSE if it is not - **/ -gboolean -nm_utils_file_is_private_key(const char *filename, gboolean *out_encrypted) -{ - const char *extensions[] = {".der", ".pem", ".p12", ".key", NULL}; - - g_return_val_if_fail(filename != NULL, FALSE); - - NM_SET_OUT(out_encrypted, FALSE); - if (!file_has_extension(filename, extensions)) - return FALSE; - - return nm_crypto_verify_private_key(filename, NULL, out_encrypted, NULL) - != NM_CRYPTO_FILE_FORMAT_UNKNOWN; -} - -/** - * nm_utils_file_is_pkcs12: - * @filename: name of the file to test - * - * Tests if @filename is a PKCS#12 file. - * - * Returns: %TRUE if the file is PKCS#12, %FALSE if it is not - **/ -gboolean -nm_utils_file_is_pkcs12(const char *filename) -{ - g_return_val_if_fail(filename != NULL, FALSE); - - return nm_crypto_is_pkcs12_file(filename, NULL); -} - -/*****************************************************************************/ - -gboolean -_nm_utils_check_file(const char * filename, - gint64 check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - struct stat * out_st, - GError ** error) -{ - struct stat st_backup; - - if (!out_st) - out_st = &st_backup; - - if (stat(filename, out_st) != 0) { - int errsv = errno; - - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("failed stat file %s: %s"), - filename, - nm_strerror_native(errsv)); - return FALSE; - } - - /* ignore non-files. */ - if (!S_ISREG(out_st->st_mode)) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("not a file (%s)"), - filename); - return FALSE; - } - - /* with check_owner enabled, check that the file belongs to the - * owner or root. */ - if (check_owner >= 0 && (out_st->st_uid != 0 && (gint64) out_st->st_uid != check_owner)) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("invalid file owner %d for %s"), - out_st->st_uid, - filename); - return FALSE; - } - - /* with check_owner enabled, check that the file cannot be modified - * by other users (except root). */ - if (check_owner >= 0 && NM_FLAGS_ANY(out_st->st_mode, S_IWGRP | S_IWOTH | S_ISUID)) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("file permissions for %s"), - filename); - return FALSE; - } - - if (check_file && !check_file(filename, out_st, user_data, error)) { - if (error && !*error) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("reject %s"), - filename); - } - return FALSE; - } - - return TRUE; -} - -gboolean -_nm_utils_check_module_file(const char * name, - int check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - GError ** error) -{ - if (!g_path_is_absolute(name)) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("path is not absolute (%s)"), - name); - return FALSE; - } - - /* Set special error code if the file doesn't exist. - * The VPN package might be split into separate packages, - * so it could be correct that the plugin file is missing. - * - * Note that nm-applet checks for this error code to fail - * gracefully. */ - if (!g_file_test(name, G_FILE_TEST_EXISTS)) { - g_set_error(error, - G_FILE_ERROR, - G_FILE_ERROR_NOENT, - _("Plugin file does not exist (%s)"), - name); - return FALSE; - } - - if (!g_file_test(name, G_FILE_TEST_IS_REGULAR)) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("Plugin is not a valid file (%s)"), - name); - return FALSE; - } - - if (g_str_has_suffix(name, ".la")) { - /* g_module_open() treats files that end with .la special. - * We don't want to parse the libtool archive. Just error out. */ - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("libtool archives are not supported (%s)"), - name); - return FALSE; - } - - return _nm_utils_check_file(name, check_owner, check_file, user_data, NULL, error); -} - -/*****************************************************************************/ - -/** - * nm_utils_file_search_in_paths: - * @progname: the helper program name, like "iptables" - * Must be a non-empty string, without path separator (/). - * @try_first: (allow-none): a custom path to try first before searching. - * It is silently ignored if it is empty or not an absolute path. - * @paths: (allow-none): a %NULL terminated list of search paths. - * Can be empty or %NULL, in which case only @try_first is checked. - * @file_test_flags: the flags passed to g_file_test() when searching - * for @progname. Set it to 0 to skip the g_file_test(). - * @predicate: (scope call): if given, pass the file name to this function - * for additional checks. This check is performed after the check for - * @file_test_flags. You cannot omit both @file_test_flags and @predicate. - * @user_data: (closure) (allow-none): user data for @predicate function. - * @error: (allow-none): on failure, set a "not found" error %G_IO_ERROR %G_IO_ERROR_NOT_FOUND. - * - * Searches for a @progname file in a list of search @paths. - * - * Returns: (transfer none): the full path to the helper, if found, or %NULL if not found. - * The returned string is not owned by the caller, but later - * invocations of the function might overwrite it. - */ -const char * -nm_utils_file_search_in_paths(const char * progname, - const char * try_first, - const char *const * paths, - GFileTest file_test_flags, - NMUtilsFileSearchInPathsPredicate predicate, - gpointer user_data, - GError ** error) -{ - g_return_val_if_fail(!error || !*error, NULL); - g_return_val_if_fail(progname && progname[0] && !strchr(progname, '/'), NULL); - g_return_val_if_fail(file_test_flags || predicate, NULL); - - /* Only consider @try_first if it is a valid, absolute path. This makes - * it simpler to pass in a path from configure checks. */ - if (try_first && try_first[0] == '/' - && (file_test_flags == 0 || g_file_test(try_first, file_test_flags)) - && (!predicate || predicate(try_first, user_data))) - return g_intern_string(try_first); - - if (paths && paths[0]) { - nm_auto_str_buf NMStrBuf strbuf = - NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); - - for (; *paths; paths++) { - const char *path = *paths; - const char *s; - - if (!path[0]) - continue; - - nm_str_buf_reset(&strbuf); - nm_str_buf_append(&strbuf, path); - nm_str_buf_ensure_trailing_c(&strbuf, '/'); - s = nm_str_buf_append0(&strbuf, progname); - - if ((file_test_flags == 0 || g_file_test(s, file_test_flags)) - && (!predicate || predicate(s, user_data))) - return g_intern_string(s); - } - } - - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - _("Could not find \"%s\" binary"), - progname); - return NULL; -} - -/*****************************************************************************/ - -/* Band, channel/frequency stuff for wireless */ -struct cf_pair { - guint32 chan; - guint32 freq; -}; - -static const struct cf_pair a_table[] = { - /* A band */ - {7, 5035}, {8, 5040}, {9, 5045}, {11, 5055}, {12, 5060}, {16, 5080}, {34, 5170}, - {36, 5180}, {38, 5190}, {40, 5200}, {42, 5210}, {44, 5220}, {46, 5230}, {48, 5240}, - {50, 5250}, {52, 5260}, {56, 5280}, {58, 5290}, {60, 5300}, {64, 5320}, {100, 5500}, - {104, 5520}, {108, 5540}, {112, 5560}, {116, 5580}, {120, 5600}, {124, 5620}, {128, 5640}, - {132, 5660}, {136, 5680}, {140, 5700}, {149, 5745}, {152, 5760}, {153, 5765}, {157, 5785}, - {160, 5800}, {161, 5805}, {165, 5825}, {183, 4915}, {184, 4920}, {185, 4925}, {187, 4935}, - {188, 4945}, {192, 4960}, {196, 4980}, {0, 0}}; - -static const guint a_table_freqs[G_N_ELEMENTS(a_table)] = { - /* A band */ - 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240, 5250, 5260, - 5280, 5290, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, - 5760, 5765, 5785, 5800, 5805, 5825, 4915, 4920, 4925, 4935, 4945, 4960, 4980, 0, -}; - -static const struct cf_pair bg_table[] = { - /* B/G band */ - {1, 2412}, - {2, 2417}, - {3, 2422}, - {4, 2427}, - {5, 2432}, - {6, 2437}, - {7, 2442}, - {8, 2447}, - {9, 2452}, - {10, 2457}, - {11, 2462}, - {12, 2467}, - {13, 2472}, - {14, 2484}, - {0, 0}}; - -static const guint bg_table_freqs[G_N_ELEMENTS(bg_table)] = { - /* B/G band */ - 2412, - 2417, - 2422, - 2427, - 2432, - 2437, - 2442, - 2447, - 2452, - 2457, - 2462, - 2467, - 2472, - 2484, - 0, -}; - -/** - * nm_utils_wifi_freq_to_channel: - * @freq: frequency - * - * Utility function to translate a Wi-Fi frequency to its corresponding channel. - * - * Returns: the channel represented by the frequency or 0 - **/ -guint32 -nm_utils_wifi_freq_to_channel(guint32 freq) -{ - int i = 0; - - if (freq > 4900) { - while (a_table[i].freq && (a_table[i].freq != freq)) - i++; - return a_table[i].chan; - } - - while (bg_table[i].freq && (bg_table[i].freq != freq)) - i++; - return bg_table[i].chan; -} - -/** - * nm_utils_wifi_freq_to_band: - * @freq: frequency - * - * Utility function to translate a Wi-Fi frequency to its corresponding band. - * - * Returns: the band containing the frequency or NULL if freq is invalid - **/ -const char * -nm_utils_wifi_freq_to_band(guint32 freq) -{ - if (freq >= 4915 && freq <= 5825) - return "a"; - else if (freq >= 2412 && freq <= 2484) - return "bg"; - - return NULL; -} - -/** - * nm_utils_wifi_channel_to_freq: - * @channel: channel - * @band: frequency band for wireless ("a" or "bg") - * - * Utility function to translate a Wi-Fi channel to its corresponding frequency. - * - * Returns: the frequency represented by the channel of the band, - * or -1 when the freq is invalid, or 0 when the band - * is invalid - **/ -guint32 -nm_utils_wifi_channel_to_freq(guint32 channel, const char *band) -{ - int i; - - g_return_val_if_fail(band, 0); - - if (nm_streq(band, "a")) { - for (i = 0; a_table[i].chan; i++) { - if (a_table[i].chan == channel) - return a_table[i].freq; - } - return ((guint32) -1); - } - - if (nm_streq(band, "bg")) { - for (i = 0; bg_table[i].chan; i++) { - if (bg_table[i].chan == channel) - return bg_table[i].freq; - } - return ((guint32) -1); - } - - return 0; -} - -/** - * nm_utils_wifi_find_next_channel: - * @channel: current channel - * @direction: whether going downward (0 or less) or upward (1 or more) - * @band: frequency band for wireless ("a" or "bg") - * - * Utility function to find out next/previous Wi-Fi channel for a channel. - * - * Returns: the next channel in the specified direction or 0 - **/ -guint32 -nm_utils_wifi_find_next_channel(guint32 channel, int direction, char *band) -{ - size_t a_size = G_N_ELEMENTS(a_table); - size_t bg_size = G_N_ELEMENTS(bg_table); - const struct cf_pair *pair; - - if (nm_streq(band, "a")) { - if (channel < a_table[0].chan) - return a_table[0].chan; - if (channel > a_table[a_size - 2].chan) - return a_table[a_size - 2].chan; - pair = &a_table[0]; - } else if (nm_streq(band, "bg")) { - if (channel < bg_table[0].chan) - return bg_table[0].chan; - if (channel > bg_table[bg_size - 2].chan) - return bg_table[bg_size - 2].chan; - pair = &bg_table[0]; - } else - g_return_val_if_reached(0); - - while (pair->chan) { - if (channel == pair->chan) - return channel; - if ((channel < (pair + 1)->chan) && (channel > pair->chan)) { - if (direction > 0) - return (pair + 1)->chan; - else - return pair->chan; - } - pair++; - } - return 0; -} - -/** - * nm_utils_wifi_is_channel_valid: - * @channel: channel - * @band: frequency band for wireless ("a" or "bg") - * - * Utility function to verify Wi-Fi channel validity. - * - * Returns: %TRUE or %FALSE - **/ -gboolean -nm_utils_wifi_is_channel_valid(guint32 channel, const char *band) -{ - guint32 freq; - - freq = nm_utils_wifi_channel_to_freq(channel, band); - - return !NM_IN_SET(freq, 0u, (guint32) -1); -} - -#define _nm_assert_wifi_freqs(table, table_freqs) \ - G_STMT_START \ - { \ - if (NM_MORE_ASSERT_ONCE(5)) { \ - int i, j; \ - \ - G_STATIC_ASSERT(G_N_ELEMENTS(table) > 0); \ - G_STATIC_ASSERT(G_N_ELEMENTS(table) == G_N_ELEMENTS(table_freqs)); \ - \ - for (i = 0; i < (int) G_N_ELEMENTS(table); i++) { \ - nm_assert((i == G_N_ELEMENTS(table) - 1) == (table[i].chan == 0)); \ - nm_assert((i == G_N_ELEMENTS(table) - 1) == (table[i].freq == 0)); \ - nm_assert(table[i].freq == table_freqs[i]); \ - for (j = 0; j < i; j++) { \ - nm_assert(table[j].chan != table[i].chan); \ - nm_assert(table[j].freq != table[i].freq); \ - } \ - } \ - } \ - } \ - G_STMT_END - -/** - * nm_utils_wifi_2ghz_freqs: - * - * Utility function to return 2.4 GHz Wi-Fi frequencies (802.11bg band). - * - * Returns: zero-terminated array of frequencies numbers (in MHz) - * - * Since: 1.2 - **/ -const guint * -nm_utils_wifi_2ghz_freqs(void) -{ - _nm_assert_wifi_freqs(bg_table, bg_table_freqs); - return bg_table_freqs; -} - -/** - * nm_utils_wifi_5ghz_freqs: - * - * Utility function to return 5 GHz Wi-Fi frequencies (802.11a band). - * - * Returns: zero-terminated array of frequencies numbers (in MHz) - * - * Since: 1.2 - **/ -const guint * -nm_utils_wifi_5ghz_freqs(void) -{ - _nm_assert_wifi_freqs(a_table, a_table_freqs); - return a_table_freqs; -} - -/** - * nm_utils_wifi_strength_bars: - * @strength: the access point strength, from 0 to 100 - * - * Converts @strength into a 4-character-wide graphical representation of - * strength suitable for printing to stdout. - * - * Previous versions used to take a guess at the terminal type and possibly - * return a wide UTF-8 encoded string. Now it always returns a 7-bit - * clean strings of one to 0 to 4 asterisks. Users that actually need - * the functionality are encouraged to make their implementations instead. - * - * Returns: the graphical representation of the access point strength - */ -const char * -nm_utils_wifi_strength_bars(guint8 strength) -{ - if (strength > 80) - return "****"; - else if (strength > 55) - return "*** "; - else if (strength > 30) - return "** "; - else if (strength > 5) - return "* "; - else - return " "; -} - -/** - * nm_utils_hwaddr_len: - * @type: the type of address; either ARPHRD_ETHER or - * ARPHRD_INFINIBAND - * - * Returns the length in octets of a hardware address of type @type. - * - * Before 1.28, it was an error to call this function with any value other than - * ARPHRD_ETHER or ARPHRD_INFINIBAND. - * - * Return value: the length or zero if the type is unrecognized. - */ -gsize -nm_utils_hwaddr_len(int type) -{ - switch (type) { - case ARPHRD_ETHER: - return ETH_ALEN; - case ARPHRD_INFINIBAND: - return INFINIBAND_ALEN; - default: - return 0; - } -} - -/** - * nm_utils_hexstr2bin: - * @hex: a string of hexadecimal characters with optional ':' separators - * - * Converts a hexadecimal string @hex into an array of bytes. The optional - * separator ':' may be used between single or pairs of hexadecimal characters, - * eg "00:11" or "0:1". Any "0x" at the beginning of @hex is ignored. @hex - * may not start or end with ':'. - * - * Return value: (transfer full): the converted bytes, or %NULL on error - */ -GBytes * -nm_utils_hexstr2bin(const char *hex) -{ - guint8 *buffer; - gsize len; - - buffer = nm_utils_hexstr2bin_alloc(hex, TRUE, FALSE, ":", 0, &len); - if (!buffer) - return NULL; - buffer = g_realloc(buffer, len); - return g_bytes_new_take(buffer, len); -} - -/** - * nm_utils_hwaddr_atoba: - * @asc: the ASCII representation of a hardware address - * @length: the expected length in bytes of the result - * - * Parses @asc and converts it to binary form in a #GByteArray. See - * nm_utils_hwaddr_aton() if you don't want a #GByteArray. - * - * Return value: (transfer full): a new #GByteArray, or %NULL if @asc couldn't - * be parsed - */ -GByteArray * -nm_utils_hwaddr_atoba(const char *asc, gsize length) -{ - GByteArray *ba; - - g_return_val_if_fail(asc, NULL); - g_return_val_if_fail(length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL); - - ba = g_byte_array_sized_new(length); - g_byte_array_set_size(ba, length); - if (!_nm_utils_hwaddr_aton_exact(asc, ba->data, length)) - goto fail; - - return ba; -fail: - g_byte_array_unref(ba); - return NULL; -} - -/** - * nm_utils_hwaddr_aton: - * @asc: the ASCII representation of a hardware address - * @buffer: (type guint8) (array length=length): buffer to store the result into - * @length: the expected length in bytes of the result and - * the size of the buffer in bytes. - * - * Parses @asc and converts it to binary form in @buffer. - * Bytes in @asc can be separated by colons (:), or hyphens (-), but not mixed. - * - * Return value: @buffer, or %NULL if @asc couldn't be parsed - * or would be shorter or longer than @length. - */ -guint8 * -nm_utils_hwaddr_aton(const char *asc, gpointer buffer, gsize length) -{ - g_return_val_if_fail(asc, NULL); - g_return_val_if_fail(buffer, NULL); - g_return_val_if_fail(length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL); - - return _nm_utils_hwaddr_aton_exact(asc, buffer, length); -} - -/** - * nm_utils_bin2hexstr: - * @src: (type guint8) (array length=len): an array of bytes - * @len: the length of the @src array - * @final_len: an index where to cut off the returned string, or -1 - * - * Converts the byte array @src into a hexadecimal string. If @final_len is - * greater than -1, the returned string is terminated at that index - * (returned_string[final_len] == '\0'), - * - * Return value: (transfer full): the textual form of @bytes - */ -char * -nm_utils_bin2hexstr(gconstpointer src, gsize len, int final_len) -{ - char *result; - gsize buflen = (len * 2) + 1; - - g_return_val_if_fail(src != NULL, NULL); - g_return_val_if_fail(len > 0 && (buflen - 1) / 2 == len, NULL); - g_return_val_if_fail(final_len < 0 || (gsize) final_len < buflen, NULL); - - result = g_malloc(buflen); - - nm_utils_bin2hexstr_full(src, len, '\0', FALSE, result); - - /* Cut converted key off at the correct length for this cipher type */ - if (final_len >= 0 && (gsize) final_len < buflen) - result[final_len] = '\0'; - - return result; -} - -/** - * nm_utils_hwaddr_ntoa: - * @addr: (type guint8) (array length=length): a binary hardware address - * @length: the length of @addr - * - * Converts @addr to textual form. - * - * Return value: (transfer full): the textual form of @addr - */ -char * -nm_utils_hwaddr_ntoa(gconstpointer addr, gsize length) -{ - g_return_val_if_fail(addr, g_strdup("")); - g_return_val_if_fail(length > 0, g_strdup("")); - - return nm_utils_bin2hexstr_full(addr, length, ':', TRUE, NULL); -} - -/** - * nm_utils_hwaddr_valid: - * @asc: the ASCII representation of a hardware address - * @length: the length of address that @asc is expected to convert to - * (or -1 to accept any length up to %NM_UTILS_HWADDR_LEN_MAX) - * - * Parses @asc to see if it is a valid hardware address of the given - * length. - * - * Return value: %TRUE if @asc appears to be a valid hardware address - * of the indicated length, %FALSE if not. - */ -gboolean -nm_utils_hwaddr_valid(const char *asc, gssize length) -{ - guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; - gsize l; - - g_return_val_if_fail(asc != NULL, FALSE); - g_return_val_if_fail(length >= -1 && length <= NM_UTILS_HWADDR_LEN_MAX, FALSE); - - if (length == 0) - return FALSE; - - if (!_nm_utils_hwaddr_aton(asc, buf, sizeof(buf), &l)) - return FALSE; - - return length == -1 || length == (gssize) l; -} - -/** - * nm_utils_hwaddr_canonical: - * @asc: the ASCII representation of a hardware address - * @length: the length of address that @asc is expected to convert to - * (or -1 to accept any length up to %NM_UTILS_HWADDR_LEN_MAX) - * - * Parses @asc to see if it is a valid hardware address of the given - * length, and if so, returns it in canonical form (uppercase, with - * leading 0s as needed, and with colons rather than hyphens). - * - * Return value: (transfer full): the canonicalized address if @asc appears to - * be a valid hardware address of the indicated length, %NULL if not. - */ -char * -nm_utils_hwaddr_canonical(const char *asc, gssize length) -{ - guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; - gsize l; - - g_return_val_if_fail(asc, NULL); - g_return_val_if_fail(length == -1 || (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX), NULL); - - if (!_nm_utils_hwaddr_aton(asc, buf, sizeof(buf), &l)) - return NULL; - if (length != -1 && length != (gssize) l) - return NULL; - return nm_utils_hwaddr_ntoa(buf, l); -} - -/* This is used to possibly canonicalize values passed to MAC address property - * setters. Unlike nm_utils_hwaddr_canonical(), it accepts %NULL, and if you - * pass it an invalid MAC address, it just returns that string rather than - * returning %NULL (so that we can return a proper error from verify() later). - */ -char * -_nm_utils_hwaddr_canonical_or_invalid(const char *mac, gssize length) -{ - char *canonical; - - if (!mac) - return NULL; - - canonical = nm_utils_hwaddr_canonical(mac, length); - if (canonical) - return canonical; - else - return g_strdup(mac); -} - -/* - * Determine if given Ethernet address is link-local - * - * Return value: %TRUE if @mac is link local - * reserved addr (01:80:c2:00:00:0X) per IEEE 802.1Q 8.6.3 Frame filtering, %FALSE if not. - */ -gboolean -_nm_utils_hwaddr_link_local_valid(const char *mac) -{ - guint8 mac_net[ETH_ALEN]; - static const guint8 eth_reserved_addr_base[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; - - if (!mac) - return FALSE; - - if (!nm_utils_hwaddr_aton(mac, mac_net, ETH_ALEN)) - return FALSE; - - if (memcmp(mac_net, eth_reserved_addr_base, ETH_ALEN - 1) || (mac_net[5] & 0xF0)) - return FALSE; - - if (mac_net[5] == 1 /* 802.3x Pause address */ - || mac_net[5] == 2 /* 802.3ad Slow protocols */ - || mac_net[5] == 3) /* 802.1X PAE address */ - return FALSE; - - return TRUE; -} - -/** - * nm_utils_hwaddr_matches: - * @hwaddr1: (nullable): pointer to a binary or ASCII hardware address, or %NULL - * @hwaddr1_len: size of @hwaddr1, or -1 if @hwaddr1 is ASCII - * @hwaddr2: (nullable): pointer to a binary or ASCII hardware address, or %NULL - * @hwaddr2_len: size of @hwaddr2, or -1 if @hwaddr2 is ASCII - * - * Generalized hardware address comparison function. Tests if @hwaddr1 and - * @hwaddr2 "equal" (or more precisely, "equivalent"), with several advantages - * over a simple memcmp(): - * - * 1. If @hwaddr1_len or @hwaddr2_len is -1, then the corresponding address is - * assumed to be ASCII rather than binary, and will be converted to binary - * before being compared. - * - * 2. If @hwaddr1 or @hwaddr2 is %NULL, it is treated instead as though it was - * a zero-filled buffer @hwaddr1_len or @hwaddr2_len bytes long. - * - * 3. If @hwaddr1 and @hwaddr2 are InfiniBand hardware addresses (that is, if - * they are INFINIBAND_ALEN bytes long in binary form) - * then only the last 8 bytes are compared, since those are the only bytes - * that actually identify the hardware. (The other 12 bytes will change - * depending on the configuration of the InfiniBand fabric that the device - * is connected to.) - * - * If a passed-in ASCII hardware address cannot be parsed, or would parse to an - * address larger than %NM_UTILS_HWADDR_LEN_MAX, then it will silently fail to - * match. (This means that externally-provided address strings do not need to be - * sanity-checked before comparing them against known good addresses; they are - * guaranteed to not match if they are invalid.) - * - * Return value: %TRUE if @hwaddr1 and @hwaddr2 are equivalent, %FALSE if they are - * different (or either of them is invalid). - */ -gboolean -nm_utils_hwaddr_matches(gconstpointer hwaddr1, - gssize hwaddr1_len, - gconstpointer hwaddr2, - gssize hwaddr2_len) -{ - guint8 buf1[NM_UTILS_HWADDR_LEN_MAX], buf2[NM_UTILS_HWADDR_LEN_MAX]; - gsize l; - - if (hwaddr1_len == -1) { - if (hwaddr1 == NULL) { - hwaddr1_len = 0; - } else if (_nm_utils_hwaddr_aton(hwaddr1, buf1, sizeof(buf1), &l)) { - hwaddr1 = buf1; - hwaddr1_len = l; - } else { - g_return_val_if_fail(hwaddr2_len == -1 - || (hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX), - FALSE); - return FALSE; - } - } else { - g_return_val_if_fail(hwaddr1_len > 0 && hwaddr1_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE); - - if (!hwaddr1) { - memset(buf1, 0, hwaddr1_len); - hwaddr1 = buf1; - } - } - - if (hwaddr2_len == -1) { - if (hwaddr2 == NULL) - l = 0; - else if (!_nm_utils_hwaddr_aton(hwaddr2, buf2, sizeof(buf2), &l)) - return FALSE; - if (l != hwaddr1_len) - return FALSE; - hwaddr2 = buf2; - } else { - g_return_val_if_fail(hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE); - - if (hwaddr2_len != hwaddr1_len) - return FALSE; - - if (!hwaddr2) { - memset(buf2, 0, hwaddr2_len); - hwaddr2 = buf2; - } - } - - if (G_UNLIKELY(hwaddr1_len <= 0 || hwaddr1_len > NM_UTILS_HWADDR_LEN_MAX)) { - /* Only valid addresses can compare equal. In particular, - * addresses that are too long or of zero bytes, never - * compare equal. */ - return FALSE; - } - - if (hwaddr1_len == INFINIBAND_ALEN) { - hwaddr1 = &((guint8 *) hwaddr1)[INFINIBAND_ALEN - 8]; - hwaddr2 = &((guint8 *) hwaddr2)[INFINIBAND_ALEN - 8]; - hwaddr1_len = 8; - } - - return !memcmp(hwaddr1, hwaddr2, hwaddr1_len); -} - -/*****************************************************************************/ - -static GVariant * -_nm_utils_hwaddr_to_dbus_impl(const char *str) -{ - guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; - gsize len; - - if (!str) - return NULL; - if (!_nm_utils_hwaddr_aton(str, buf, sizeof(buf), &len)) - return NULL; - - return g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, buf, len, 1); -} - -static GVariant * -_nm_utils_hwaddr_cloned_get(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_free char *addr = NULL; - - nm_assert(nm_streq(sett_info->property_infos[property_idx].name, "cloned-mac-address")); - - g_object_get(setting, "cloned-mac-address", &addr, NULL); - return _nm_utils_hwaddr_to_dbus_impl(addr); -} - -static gboolean -_nm_utils_hwaddr_cloned_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - gsize length; - const guint8 *array; - char * str; - - nm_assert(nm_streq0(property, "cloned-mac-address")); - - if (!_nm_setting_use_legacy_property(setting, - connection_dict, - "cloned-mac-address", - "assigned-mac-address")) - return TRUE; - - length = 0; - array = g_variant_get_fixed_array(value, &length, 1); - - if (!length) - return TRUE; - - str = nm_utils_hwaddr_ntoa(array, length); - g_object_set(setting, "cloned-mac-address", str, NULL); - g_free(str); - return TRUE; -} - -static gboolean -_nm_utils_hwaddr_cloned_not_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - NMSettingParseFlags parse_flags, - GError ** error) -{ - nm_assert(nm_streq0(property, "cloned-mac-address")); - return TRUE; -} - -const NMSettInfoPropertType nm_sett_info_propert_type_cloned_mac_address = { - .dbus_type = G_VARIANT_TYPE_BYTESTRING, - .to_dbus_fcn = _nm_utils_hwaddr_cloned_get, - .from_dbus_fcn = _nm_utils_hwaddr_cloned_set, - .missing_from_dbus_fcn = _nm_utils_hwaddr_cloned_not_set, -}; - -static GVariant * -_nm_utils_hwaddr_cloned_data_synth(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_free char *addr = NULL; - - if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - return NULL; - - nm_assert(nm_streq0(sett_info->property_infos[property_idx].name, "assigned-mac-address")); - - g_object_get(setting, "cloned-mac-address", &addr, NULL); - - /* Before introducing the extended "cloned-mac-address" (and its D-Bus - * field "assigned-mac-address"), libnm's _nm_utils_hwaddr_to_dbus() - * would drop invalid values as it was unable to serialize them. - * - * Now, we would like to send invalid values as "assigned-mac-address" - * over D-Bus and let the server reject them. - * - * However, clients used to set the cloned-mac-address property - * to "" and it just worked as the value was not serialized in - * an ill form. - * - * To preserve that behavior, serialize "" as NULL. - */ - - return addr && addr[0] ? g_variant_new_take_string(g_steal_pointer(&addr)) : NULL; -} - -static gboolean -_nm_utils_hwaddr_cloned_data_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - nm_assert(nm_streq0(property, "assigned-mac-address")); - - if (_nm_setting_use_legacy_property(setting, - connection_dict, - "cloned-mac-address", - "assigned-mac-address")) - return TRUE; - - g_object_set(setting, - "cloned-mac-address", - nm_str_not_empty(g_variant_get_string(value, NULL)), - NULL); - return TRUE; -} - -const NMSettInfoPropertType nm_sett_info_propert_type_assigned_mac_address = { - .dbus_type = G_VARIANT_TYPE_STRING, - .to_dbus_fcn = _nm_utils_hwaddr_cloned_data_synth, - .from_dbus_fcn = _nm_utils_hwaddr_cloned_data_set, -}; - -static GVariant * -_nm_utils_hwaddr_to_dbus(const GValue *prop_value) -{ - return _nm_utils_hwaddr_to_dbus_impl(g_value_get_string(prop_value)); -} - -static void -_nm_utils_hwaddr_from_dbus(GVariant *dbus_value, GValue *prop_value) -{ - gsize length = 0; - const guint8 *array = g_variant_get_fixed_array(dbus_value, &length, 1); - char * str; - - str = length ? nm_utils_hwaddr_ntoa(array, length) : NULL; - g_value_take_string(prop_value, str); -} - -const NMSettInfoPropertType nm_sett_info_propert_type_mac_address = { - .dbus_type = G_VARIANT_TYPE_BYTESTRING, - .gprop_to_dbus_fcn = _nm_utils_hwaddr_to_dbus, - .gprop_from_dbus_fcn = _nm_utils_hwaddr_from_dbus, -}; - -/*****************************************************************************/ - -/* Validate secret-flags. Most settings don't validate them, which is a bug. - * But we possibly cannot enforce a strict validation now. - * - * For new settings, they shall validate the secret-flags strictly. */ -gboolean -_nm_utils_secret_flags_validate(NMSettingSecretFlags secret_flags, - const char * setting_name, - const char * property_name, - NMSettingSecretFlags disallowed_flags, - GError ** error) -{ - if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) - return TRUE; - - if (NM_FLAGS_ANY(secret_flags, ~NM_SETTING_SECRET_FLAG_ALL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("unknown secret flags")); - if (setting_name) - g_prefix_error(error, "%s.%s: ", setting_name, property_name); - return FALSE; - } - - if (!nm_utils_is_power_of_two(secret_flags)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("conflicting secret flags")); - if (setting_name) - g_prefix_error(error, "%s.%s: ", setting_name, property_name); - return FALSE; - } - - if (NM_FLAGS_ANY(secret_flags, disallowed_flags)) { - if (NM_FLAGS_HAS(secret_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("secret flags must not be \"not-required\"")); - if (setting_name) - g_prefix_error(error, "%s.%s: ", setting_name, property_name); - return FALSE; - } - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("unsupported secret flags")); - if (setting_name) - g_prefix_error(error, "%s.%s: ", setting_name, property_name); - return FALSE; - } - - return TRUE; -} - -gboolean -_nm_utils_wps_method_validate(NMSettingWirelessSecurityWpsMethod wps_method, - const char * setting_name, - const char * property_name, - gboolean wps_required, - GError ** error) -{ - if (wps_method > NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is invalid")); - g_prefix_error(error, "%s.%s: ", setting_name, property_name); - return FALSE; - } - - if (NM_FLAGS_HAS(wps_method, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED)) { - if (wps_method != NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("can't be simultaneously disabled and enabled")); - g_prefix_error(error, "%s.%s: ", setting_name, property_name); - return FALSE; - } - if (wps_required) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("WPS is required")); - g_prefix_error(error, "%s.%s: ", setting_name, property_name); - return FALSE; - } - } - - return TRUE; -} - -/*****************************************************************************/ - -static char * -_split_word(char *s) -{ - /* takes @s and truncates the string on the first white-space. - * then it returns the first word afterwards (again seeking - * over leading white-space). */ - for (; s[0]; s++) { - if (g_ascii_isspace(s[0])) { - s[0] = '\0'; - s++; - while (g_ascii_isspace(s[0])) - s++; - return s; - } - } - return s; -} - -gboolean -_nm_utils_generate_mac_address_mask_parse(const char * value, - struct ether_addr * out_mask, - struct ether_addr **out_ouis, - gsize * out_ouis_len, - GError ** error) -{ - gs_free char * s_free = NULL; - char * s, *s_next; - struct ether_addr mask; - gs_unref_array GArray *ouis = NULL; - - g_return_val_if_fail(!error || !*error, FALSE); - - if (!value || !*value) { - /* NULL and "" are valid values and both mean the default - * "q */ - if (out_mask) { - memset(out_mask, 0, sizeof(*out_mask)); - out_mask->ether_addr_octet[0] |= 0x02; - } - NM_SET_OUT(out_ouis, NULL); - NM_SET_OUT(out_ouis_len, 0); - return TRUE; - } - - s_free = g_strdup(value); - s = s_free; - - /* skip over leading whitespace */ - while (g_ascii_isspace(s[0])) - s++; - - /* parse the first mask */ - s_next = _split_word(s); - if (!nm_utils_hwaddr_aton(s, &mask, ETH_ALEN)) { - g_set_error(error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - _("not a valid ethernet MAC address for mask at position %lld"), - (long long) (s - s_free)); - return FALSE; - } - - if (s_next[0]) { - ouis = g_array_sized_new(FALSE, FALSE, sizeof(struct ether_addr), 4); - - do { - s = s_next; - s_next = _split_word(s); - - g_array_set_size(ouis, ouis->len + 1); - if (!nm_utils_hwaddr_aton(s, - &g_array_index(ouis, struct ether_addr, ouis->len - 1), - ETH_ALEN)) { - g_set_error(error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - _("not a valid ethernet MAC address #%u at position %lld"), - ouis->len, - (long long) (s - s_free)); - return FALSE; - } - } while (s_next[0]); - } - - NM_SET_OUT(out_mask, mask); - NM_SET_OUT(out_ouis_len, ouis ? ouis->len : 0); - NM_SET_OUT(out_ouis, - ouis ? ((struct ether_addr *) g_array_free(g_steal_pointer(&ouis), FALSE)) : NULL); - return TRUE; -} - -/*****************************************************************************/ - -gboolean -nm_utils_is_valid_iface_name_utf8safe(const char *utf8safe_name) -{ - gs_free gpointer bin_to_free = NULL; - gconstpointer bin; - gsize len; - - g_return_val_if_fail(utf8safe_name, FALSE); - - bin = nm_utils_buf_utf8safe_unescape(utf8safe_name, - NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, - &len, - &bin_to_free); - - if (bin_to_free) { - /* some unescaping happened... */ - - if (len != strlen(bin)) { - /* there are embedded NUL chars. Invalid. */ - return FALSE; - } - } - - return nm_utils_ifname_valid_kernel(bin, NULL); -} - -/** - * nm_utils_is_valid_iface_name: - * @name: (allow-none): Name of interface - * @error: location to store the error occurring, or %NULL to ignore - * - * Validate the network interface name. - * - * This function is a 1:1 copy of the kernel's interface validation - * function in net/core/dev.c. - * - * Returns: %TRUE if interface name is valid, otherwise %FALSE is returned. - * - * Before 1.20, this function did not accept %NULL as @name argument. If you - * want to run against older versions of libnm, don't pass %NULL. - */ -gboolean -nm_utils_is_valid_iface_name(const char *name, GError **error) -{ - g_return_val_if_fail(!error || !*error, FALSE); - - return nm_utils_ifname_valid_kernel(name, error); -} - -/** - * nm_utils_iface_valid_name: - * @name: (allow-none): Name of interface - * - * Validate the network interface name. - * - * Deprecated: 1.6: Use nm_utils_is_valid_iface_name() instead, with better error reporting. - * - * Returns: %TRUE if interface name is valid, otherwise %FALSE is returned. - * - * Before 1.20, this function did not accept %NULL as @name argument. If you - * want to run against older versions of libnm, don't pass %NULL. - */ -gboolean -nm_utils_iface_valid_name(const char *name) -{ - return nm_utils_is_valid_iface_name(name, NULL); -} - -/** - * nm_utils_is_uuid: - * @str: (allow-none): a string that might be a UUID - * - * Checks if @str is a UUID - * - * Returns: %TRUE if @str is a UUID, %FALSE if not - * - * In older versions, nm_utils_is_uuid() did not accept %NULL as @str - * argument. Don't pass %NULL if you run against older versions of libnm. - */ -gboolean -nm_utils_is_uuid(const char *str) -{ - const char *p = str; - int num_dashes = 0; - - if (!p) - return FALSE; - - while (*p) { - if (*p == '-') - num_dashes++; - else if (!g_ascii_isxdigit(*p)) - return FALSE; - p++; - } - - if ((num_dashes == 4) && (p - str == 36)) - return TRUE; - - /* Backwards compat for older configurations */ - if ((num_dashes == 0) && (p - str == 40)) - return TRUE; - - return FALSE; -} - -static _nm_thread_local char _nm_utils_inet_ntop_buffer[NM_UTILS_INET_ADDRSTRLEN]; - -/** - * nm_utils_inet4_ntop: (skip) - * @inaddr: the address that should be converted to string. - * @dst: the destination buffer, it must contain at least - * INET_ADDRSTRLEN or %NM_UTILS_INET_ADDRSTRLEN - * characters. If set to %NULL, it will return a pointer to an internal, static - * buffer (shared with nm_utils_inet6_ntop()). Beware, that the internal - * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or - * nm_utils_inet6_ntop() that does not provide its own @dst buffer. Since - * 1.28, the internal buffer is thread local and thus thread safe. Before - * it was not thread safe. When in doubt, pass your own - * @dst buffer to avoid these issues. - * - * Wrapper for inet_ntop. - * - * Returns: the input buffer @dst, or a pointer to an - * internal, static buffer. This function cannot fail. - **/ -const char * -nm_utils_inet4_ntop(in_addr_t inaddr, char *dst) -{ - /* relying on the static buffer (by leaving @dst as %NULL) is discouraged. - * Don't do that! - * - * However, still support it to be lenient against mistakes and because - * this is public API of libnm. */ - return _nm_utils_inet4_ntop(inaddr, dst ?: _nm_utils_inet_ntop_buffer); -} - -/** - * nm_utils_inet6_ntop: (skip) - * @in6addr: the address that should be converted to string. - * @dst: the destination buffer, it must contain at least - * INET6_ADDRSTRLEN or %NM_UTILS_INET_ADDRSTRLEN - * characters. If set to %NULL, it will return a pointer to an internal, static - * buffer (shared with nm_utils_inet4_ntop()). Beware, that the internal - * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or - * nm_utils_inet6_ntop() that does not provide its own @dst buffer. Since - * 1.28, the internal buffer is thread local and thus thread safe. Before - * it was not thread safe. When in doubt, pass your own - * @dst buffer to avoid these issues. - * - * Wrapper for inet_ntop. - * - * Returns: the input buffer @dst, or a pointer to an - * internal, static buffer. %NULL is not allowed as @in6addr, - * otherwise, this function cannot fail. - **/ -const char * -nm_utils_inet6_ntop(const struct in6_addr *in6addr, char *dst) -{ - /* relying on the static buffer (by leaving @dst as %NULL) is discouraged. - * Don't do that! - * - * However, still support it to be lenient against mistakes and because - * this is public API of libnm. */ - g_return_val_if_fail(in6addr, NULL); - return _nm_utils_inet6_ntop(in6addr, dst ?: _nm_utils_inet_ntop_buffer); -} - -/** - * nm_utils_ipaddr_valid: - * @family: AF_INET or AF_INET6, or - * AF_UNSPEC to accept either - * @ip: an IP address - * - * Checks if @ip contains a valid IP address of the given family. - * - * Return value: %TRUE or %FALSE - */ -gboolean -nm_utils_ipaddr_valid(int family, const char *ip) -{ - g_return_val_if_fail(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC, FALSE); - - return nm_utils_ipaddr_is_valid(family, ip); -} - -/** - * nm_utils_iinet6_is_token: - * @in6addr: the AF_INET6 address structure - * - * Checks if only the bottom 64bits of the address are set. - * - * Return value: %TRUE or %FALSE - */ -gboolean -_nm_utils_inet6_is_token(const struct in6_addr *in6addr) -{ - if (in6addr->s6_addr[0] || in6addr->s6_addr[1] || in6addr->s6_addr[2] || in6addr->s6_addr[3] - || in6addr->s6_addr[4] || in6addr->s6_addr[5] || in6addr->s6_addr[6] || in6addr->s6_addr[7]) - return FALSE; - - if (in6addr->s6_addr[8] || in6addr->s6_addr[9] || in6addr->s6_addr[10] || in6addr->s6_addr[11] - || in6addr->s6_addr[12] || in6addr->s6_addr[13] || in6addr->s6_addr[14] - || in6addr->s6_addr[15]) - return TRUE; - - return FALSE; -} - -/** - * _nm_utils_dhcp_duid_valid: - * @duid: the candidate DUID - * - * Checks if @duid string contains either a special duid value ("ll", - * "llt", "lease" or the "stable" variants) or a valid hex DUID. - * - * Return value: %TRUE or %FALSE - */ -gboolean -_nm_utils_dhcp_duid_valid(const char *duid, GBytes **out_duid_bin) -{ - guint8 duid_arr[128 + 2]; - gsize duid_len; - - NM_SET_OUT(out_duid_bin, NULL); - - if (!duid) - return FALSE; - - if (NM_IN_STRSET(duid, "lease", "llt", "ll", "stable-llt", "stable-ll", "stable-uuid")) { - return TRUE; - } - - if (nm_utils_hexstr2bin_full(duid, - FALSE, - FALSE, - FALSE, - ":", - 0, - duid_arr, - sizeof(duid_arr), - &duid_len)) { - /* MAX DUID length is 128 octects + the type code (2 octects). */ - if (duid_len > 2 && duid_len <= (128 + 2)) { - NM_SET_OUT(out_duid_bin, g_bytes_new(duid_arr, duid_len)); - return TRUE; - } - } - - return FALSE; -} - -/** - * nm_utils_check_virtual_device_compatibility: - * @virtual_type: a virtual connection type - * @other_type: a connection type to test against @virtual_type - * - * Determines if a connection of type @virtual_type can (in the - * general case) work with connections of type @other_type. - * - * If @virtual_type is %NM_TYPE_SETTING_VLAN, then this checks if - * @other_type is a valid type for the parent of a VLAN. - * - * If @virtual_type is a "master" type (eg, %NM_TYPE_SETTING_BRIDGE), - * then this checks if @other_type is a valid type for a slave of that - * master. - * - * Note that even if this returns %TRUE it is not guaranteed that - * every connection of type @other_type is - * compatible with @virtual_type; it may depend on the exact - * configuration of the two connections, or on the capabilities of an - * underlying device driver. - * - * Returns: %TRUE or %FALSE - */ -gboolean -nm_utils_check_virtual_device_compatibility(GType virtual_type, GType other_type) -{ - g_return_val_if_fail(_nm_setting_type_get_base_type_priority(virtual_type) - != NM_SETTING_PRIORITY_INVALID, - FALSE); - g_return_val_if_fail(_nm_setting_type_get_base_type_priority(other_type) - != NM_SETTING_PRIORITY_INVALID, - FALSE); - - if (virtual_type == NM_TYPE_SETTING_BOND) { - return (other_type == NM_TYPE_SETTING_INFINIBAND || other_type == NM_TYPE_SETTING_WIRED - || other_type == NM_TYPE_SETTING_BRIDGE || other_type == NM_TYPE_SETTING_BOND - || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN); - } else if (virtual_type == NM_TYPE_SETTING_BRIDGE) { - return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_BOND - || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN); - } else if (virtual_type == NM_TYPE_SETTING_TEAM) { - return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_BRIDGE - || other_type == NM_TYPE_SETTING_BOND || other_type == NM_TYPE_SETTING_TEAM - || other_type == NM_TYPE_SETTING_VLAN); - } else if (virtual_type == NM_TYPE_SETTING_VLAN) { - return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_WIRELESS - || other_type == NM_TYPE_SETTING_BRIDGE || other_type == NM_TYPE_SETTING_BOND - || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN); - } else { - g_warn_if_reached(); - return FALSE; - } -} - -/*****************************************************************************/ - -/** - * nm_utils_bond_mode_int_to_string: - * @mode: bonding mode as a numeric value - * - * Convert bonding mode from integer value to descriptive name. - * See https://www.kernel.org/doc/Documentation/networking/bonding.txt for - * available modes. - * - * Returns: bonding mode string, or NULL on error - * - * Since: 1.2 - */ -const char * -nm_utils_bond_mode_int_to_string(int mode) -{ - return _nm_setting_bond_mode_to_string(mode); -} - -/** - * nm_utils_bond_mode_string_to_int: - * @mode: bonding mode as string - * - * Convert bonding mode from string representation to numeric value. - * See https://www.kernel.org/doc/Documentation/networking/bonding.txt for - * available modes. - * The @mode string can be either a descriptive name or a number (as string). - * - * Returns: numeric bond mode, or -1 on error - * - * Since: 1.2 - */ -int -nm_utils_bond_mode_string_to_int(const char *mode) -{ - return _nm_setting_bond_mode_from_string(mode); -} - -/*****************************************************************************/ - -#define STRSTRDICTKEY_V1_SET 0x01 -#define STRSTRDICTKEY_V2_SET 0x02 -#define STRSTRDICTKEY_ALL_SET 0x03 - -struct _NMUtilsStrStrDictKey { - char type; - char data[1]; -}; - -guint -_nm_utils_strstrdictkey_hash(gconstpointer a) -{ - const NMUtilsStrStrDictKey *k = a; - const char * p; - NMHashState h; - - nm_hash_init(&h, 76642997u); - if (k) { - if (((int) k->type) & ~STRSTRDICTKEY_ALL_SET) - g_return_val_if_reached(0); - - nm_hash_update_val(&h, k->type); - if (k->type & STRSTRDICTKEY_ALL_SET) { - p = strchr(k->data, '\0'); - if (k->type == STRSTRDICTKEY_ALL_SET) { - /* the key contains two strings. Continue... */ - p = strchr(p + 1, '\0'); - } - if (p != k->data) - nm_hash_update(&h, k->data, p - k->data); - } - } - return nm_hash_complete(&h); -} - -gboolean -_nm_utils_strstrdictkey_equal(gconstpointer a, gconstpointer b) -{ - const NMUtilsStrStrDictKey *k1 = a; - const NMUtilsStrStrDictKey *k2 = b; - - if (k1 == k2) - return TRUE; - if (!k1 || !k2) - return FALSE; - - if (k1->type != k2->type) - return FALSE; - - if (k1->type & STRSTRDICTKEY_ALL_SET) { - if (!nm_streq(k1->data, k2->data)) - return FALSE; - - if (k1->type == STRSTRDICTKEY_ALL_SET) { - gsize l = strlen(k1->data) + 1; - - return nm_streq(&k1->data[l], &k2->data[l]); - } - } - - return TRUE; -} - -NMUtilsStrStrDictKey * -_nm_utils_strstrdictkey_create(const char *v1, const char *v2) -{ - char type = 0; - gsize l1 = 0, l2 = 0; - NMUtilsStrStrDictKey *k; - - if (!v1 && !v2) - return g_malloc0(1); - - /* we need to distinguish between ("",NULL) and (NULL,""). - * Thus, in @type we encode which strings we have present - * as not-NULL. */ - if (v1) { - type |= STRSTRDICTKEY_V1_SET; - l1 = strlen(v1) + 1; - } - if (v2) { - type |= STRSTRDICTKEY_V2_SET; - l2 = strlen(v2) + 1; - } - - k = g_malloc(G_STRUCT_OFFSET(NMUtilsStrStrDictKey, data) + l1 + l2); - k->type = type; - if (v1) - memcpy(&k->data[0], v1, l1); - if (v2) - memcpy(&k->data[l1], v2, l2); - - return k; -} - -static gboolean -validate_dns_option(const char * name, - gboolean numeric, - gboolean ipv6, - const NMUtilsDNSOptionDesc *option_descs) -{ - const NMUtilsDNSOptionDesc *desc; - - if (!option_descs) - return !!*name; - - for (desc = option_descs; desc->name; desc++) { - if (nm_streq(name, desc->name) && numeric == desc->numeric && (!desc->ipv6_only || ipv6)) - return TRUE; - } - - return FALSE; -} - -/** - * _nm_utils_dns_option_validate: - * @option: option string - * @out_name: (out) (allow-none): the option name - * @out_value: (out) (allow-none): the option value - * @ipv6: whether the option refers to a IPv6 configuration - * @option_descs: (allow-none): an array of NMUtilsDNSOptionDesc which describes the - * valid options - * - * Parses a DNS option in the form "name" or "name:number" and, if - * @option_descs is not NULL, checks that the option conforms to one - * of the provided descriptors. If @option_descs is NULL @ipv6 is - * not considered. - * - * Returns: %TRUE when the parsing was successful and the option is valid, - * %FALSE otherwise - */ -gboolean -_nm_utils_dns_option_validate(const char * option, - char ** out_name, - long * out_value, - gboolean ipv6, - const NMUtilsDNSOptionDesc *option_descs) -{ - gs_free char *option0_free = NULL; - const char * option0; - const char * option1; - const char * delim; - long option1_num; - - g_return_val_if_fail(option != NULL, FALSE); - - NM_SET_OUT(out_name, NULL); - NM_SET_OUT(out_value, -1); - - if (!option[0]) - return FALSE; - - delim = strchr(option, ':'); - if (!delim) { - if (!validate_dns_option(option, FALSE, ipv6, option_descs)) - return FALSE; - NM_SET_OUT(out_name, g_strdup(option)); - return TRUE; - } - - option1 = &delim[1]; - - if (!option1[0]) - return FALSE; - if (!NM_STRCHAR_ALL(option1, ch, g_ascii_isdigit(ch))) - return FALSE; - - option0 = nm_strndup_a(300, option, delim - option, &option0_free); - - if (!validate_dns_option(option0, TRUE, ipv6, option_descs)) - return FALSE; - - option1_num = _nm_utils_ascii_str_to_int64(option1, 10, 0, G_MAXINT32, -1); - if (option1_num == -1) - return FALSE; - - NM_SET_OUT(out_name, g_steal_pointer(&option0_free) ?: g_strdup(option0)); - NM_SET_OUT(out_value, option1_num); - return TRUE; -} - -/** - * _nm_utils_dns_option_find_idx: - * @array: an array of strings - * @option: a dns option string - * - * Searches for an option in an array of strings. The match is - * performed only the option name; the option value is ignored. - * - * Returns: the index of the option in the array or -1 if was not - * found. - */ -gssize -_nm_utils_dns_option_find_idx(GPtrArray *array, const char *option) -{ - gs_free char *option_name = NULL; - guint i; - - if (!_nm_utils_dns_option_validate(option, &option_name, NULL, FALSE, NULL)) - return -1; - - for (i = 0; i < array->len; i++) { - gs_free char *tmp_name = NULL; - - if (_nm_utils_dns_option_validate(array->pdata[i], &tmp_name, NULL, FALSE, NULL)) { - if (nm_streq(tmp_name, option_name)) - return i; - } - } - - return -1; -} - -/*****************************************************************************/ - -/** - * nm_utils_enum_to_str: - * @type: the %GType of the enum - * @value: the value to be translated - * - * Converts an enum value to its string representation. If the enum is a - * %G_TYPE_FLAGS the function returns a comma-separated list of matching values. - * If the value has no corresponding string representation, it is converted - * to a number. For enums it is converted to a decimal number, for flags - * to an (unsigned) hex number. - * - * Returns: a newly allocated string or %NULL - * - * Since: 1.2 - */ -char * -nm_utils_enum_to_str(GType type, int value) -{ - return _nm_utils_enum_to_str_full(type, value, ", ", NULL); -} - -/** - * nm_utils_enum_from_str: - * @type: the %GType of the enum - * @str: the input string - * @out_value: (out) (allow-none): the output value - * @err_token: (out) (allow-none) (transfer full): location to store the first unrecognized token - * - * Converts a string to the matching enum value. - * - * If the enum is a %G_TYPE_FLAGS the function returns the logical OR of values - * matching the comma-separated tokens in the string; if an unknown token is found - * the function returns %FALSE and stores a pointer to a newly allocated string - * containing the unrecognized token in @err_token. - * - * Returns: %TRUE if the conversion was successful, %FALSE otherwise - * - * Since: 1.2 - */ -gboolean -nm_utils_enum_from_str(GType type, const char *str, int *out_value, char **err_token) -{ - return _nm_utils_enum_from_str_full(type, str, out_value, err_token, NULL); -} - -/** - * nm_utils_enum_get_values: - * @type: the %GType of the enum - * @from: the first element to be returned - * @to: the last element to be returned - * - * Returns the list of possible values for a given enum. - * - * Returns: (transfer container): a NULL-terminated dynamically-allocated array of static strings - * or %NULL on error - * - * Since: 1.2 - */ -const char ** -nm_utils_enum_get_values(GType type, int from, int to) -{ - return _nm_utils_enum_get_values(type, from, to); -} - -/*****************************************************************************/ - -static gboolean -_nm_utils_is_json_object_no_validation(const char *str, GError **error) -{ - nm_assert(str); - - /* libjansson also requires only utf-8 encoding. */ - if (!g_utf8_validate(str, -1, NULL)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("not valid utf-8")); - return FALSE; - } - while (g_ascii_isspace(str[0])) - str++; - - /* do some very basic validation to see if this might be a JSON object. */ - if (str[0] == '{') { - gsize l; - - l = strlen(str) - 1; - while (l > 0 && g_ascii_isspace(str[l])) - l--; - - if (str[l] == '}') - return TRUE; - } - - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is not a JSON object")); - return FALSE; -} - -/** - * nm_utils_is_json_object: - * @str: the JSON string to test - * @error: optional error reason - * - * Returns: whether the passed string is valid JSON. - * If libnm is not compiled with libjansson support, this check will - * also return %TRUE for possibly invalid inputs. If that is a problem - * for you, you must validate the JSON yourself. - * - * Since: 1.6 - */ -gboolean -nm_utils_is_json_object(const char *str, GError **error) -{ - nm_auto_decref_json nm_json_t *json = NULL; - const NMJsonVt * vt; - nm_json_error_t jerror; - - g_return_val_if_fail(!error || !*error, FALSE); - - if (!str || !str[0]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - str ? _("value is NULL") : _("value is empty")); - return FALSE; - } - - if (!(vt = nm_json_vt())) - return _nm_utils_is_json_object_no_validation(str, error); - - json = vt->nm_json_loads(str, NM_JSON_REJECT_DUPLICATES, &jerror); - if (!json) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid JSON at position %d (%s)"), - jerror.position, - jerror.text); - return FALSE; - } - - /* valid JSON (depending on the definition) can also be a literal. - * Here we only allow objects. */ - if (!nm_json_is_object(json)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("is not a JSON object")); - return FALSE; - } - - return TRUE; -} - -static char * -attribute_unescape(const char *start, const char *end) -{ - char *ret, *dest; - - nm_assert(start <= end); - dest = ret = g_malloc(end - start + 1); - - for (; start < end && *start; start++) { - if (*start == '\\') { - start++; - if (!*start) - break; - } - *dest++ = *start; - } - *dest = '\0'; - - return ret; -} - -gboolean -_nmtst_variant_attribute_spec_assert_sorted(const NMVariantAttributeSpec *const *array, gsize len) -{ - gsize i; - - g_assert(array); - g_assert(len > 0); - g_assert_cmpint(len, ==, NM_PTRARRAY_LEN(array)); - - for (i = 0; i < len; i++) { - nm_assert(array[i]->name); - nm_assert(array[i]->name[0]); - if (i > 0) - nm_assert(strcmp(array[i - 1]->name, array[i]->name) < 0); - } - nm_assert(!array[i]); - - return TRUE; -} - -const NMVariantAttributeSpec * -_nm_variant_attribute_spec_find_binary_search(const NMVariantAttributeSpec *const *array, - gsize len, - const char * name) -{ - gssize idx; - - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMVariantAttributeSpec, name) == 0); - - idx = nm_utils_ptrarray_find_binary_search((gconstpointer *) array, - len, - &name, - nm_strcmp_p_with_data, - NULL, - NULL, - NULL); - if (idx < 0) - return NULL; - return array[idx]; -} - -/** - * nm_utils_parse_variant_attributes: - * @string: the input string - * @attr_separator: the attribute separator character - * @key_value_separator: character separating key and values - * @ignore_unknown: whether unknown attributes should be ignored - * @spec: the attribute format specifiers - * @error: (out) (allow-none): location to store the error on failure - * - * Parse attributes from a string. - * - * Returns: (transfer full) (element-type utf8 GVariant): a #GHashTable mapping - * attribute names to #GVariant values. Warning: the variant are still floating - * references, owned by the hash table. If you take a reference, ensure to sink - * the one of the hash table first. - * - * Since: 1.8 - */ -GHashTable * -nm_utils_parse_variant_attributes(const char * string, - char attr_separator, - char key_value_separator, - gboolean ignore_unknown, - const NMVariantAttributeSpec *const *spec, - GError ** error) -{ - gs_unref_hashtable GHashTable * ht = NULL; - const char * ptr = string, *start = NULL, *sep; - GVariant * variant; - const NMVariantAttributeSpec *const *s; - - g_return_val_if_fail(string, NULL); - g_return_val_if_fail(attr_separator, NULL); - g_return_val_if_fail(key_value_separator, NULL); - g_return_val_if_fail(!error || !*error, NULL); - - ht = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); - - while (TRUE) { - gs_free char *name = NULL, *value = NULL; - - if (!start) - start = ptr; - if (*ptr == '\\') { - ptr++; - if (!*ptr) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unterminated escape sequence")); - return NULL; - } - goto next; - } - if (*ptr == attr_separator || *ptr == '\0') { - if (ptr == start) { - /* multiple separators */ - start = NULL; - goto next; - } - - /* Find the key-value separator */ - for (sep = start; sep != ptr; sep++) { - if (*sep == '\\') { - sep++; - if (!*sep) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unterminated escape sequence")); - return NULL; - } - } - if (*sep == key_value_separator) - break; - } - - name = attribute_unescape(start, sep); - - for (s = spec; *s; s++) { - if (g_hash_table_contains(ht, (*s)->name)) - continue; - if (nm_streq(name, (*s)->name)) - break; - if ((*s)->no_value && g_variant_type_equal((*s)->type, G_VARIANT_TYPE_STRING)) - break; - } - - if (!*s) { - if (ignore_unknown) - goto next; - else { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unknown attribute '%s'"), - name); - return NULL; - } - } - - if ((*s)->no_value) { - if ((*s)->consumes_rest) { - value = g_strdup(start); - ptr = strchr(start, '\0'); - } else { - value = g_steal_pointer(&name); - } - } else { - if (*sep != key_value_separator) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("missing key-value separator '%c' after '%s'"), - key_value_separator, - name); - return NULL; - } - - /* The attribute and key/value separators are the same. Look for the next one. */ - if (ptr == sep) - goto next; - - value = attribute_unescape(sep + 1, ptr); - } - - if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_UINT32)) { - gint64 num = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXUINT32, -1); - - if (num == -1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid uint32 value '%s' for attribute '%s'"), - value, - (*s)->name); - return NULL; - } - variant = g_variant_new_uint32(num); - } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_INT32)) { - gint64 num = - _nm_utils_ascii_str_to_int64(value, 10, G_MININT32, G_MAXINT32, G_MAXINT64); - - if (num == G_MAXINT64) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid int32 value '%s' for attribute '%s'"), - value, - (*s)->name); - return NULL; - } - variant = g_variant_new_int32(num); - } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_UINT64)) { - guint64 num = _nm_utils_ascii_str_to_uint64(value, 10, 0, G_MAXUINT64, G_MAXUINT64); - - if (num == G_MAXUINT64 && errno != 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid uint64 value '%s' for attribute '%s'"), - value, - (*s)->name); - return NULL; - } - variant = g_variant_new_uint64(num); - } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_BYTE)) { - gint64 num = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXUINT8, -1); - - if (num == -1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid uint8 value '%s' for attribute '%s'"), - value, - (*s)->name); - return NULL; - } - variant = g_variant_new_byte((guchar) num); - } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_BOOLEAN)) { - int b; - - b = (*s)->no_value ? TRUE : _nm_utils_ascii_str_to_bool(value, -1); - if (b == -1) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid boolean value '%s' for attribute '%s'"), - value, - (*s)->name); - return NULL; - } - variant = g_variant_new_boolean(b); - } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_STRING)) { - variant = g_variant_new_take_string(g_steal_pointer(&value)); - } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_BYTESTRING)) { - variant = g_variant_new_bytestring(value); - } else { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unsupported attribute '%s' of type '%s'"), - (*s)->name, - (char *) (*s)->type); - return NULL; - } - - g_hash_table_insert(ht, g_strdup((*s)->name), variant); - start = NULL; - } -next: - if (*ptr == '\0') - break; - ptr++; - } - - return g_steal_pointer(&ht); -} - -/* - * nm_utils_format_variant_attributes: - * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values - * @attr_separator: the attribute separator character - * @key_value_separator: character separating key and values - * - * Format attributes to a string. - * - * Returns: (transfer full): the string representing attributes, or %NULL - * in case there are no attributes - * - * Since: 1.8 - */ -char * -nm_utils_format_variant_attributes(GHashTable *attributes, - char attr_separator, - char key_value_separator) -{ - return _nm_utils_format_variant_attributes(attributes, - NULL, - attr_separator, - key_value_separator); -} - -/*****************************************************************************/ - -/* - * nm_utils_get_timestamp_msec(): - * - * Gets current time in milliseconds of CLOCK_BOOTTIME. - * - * Returns: time in milliseconds - * - * Since: 1.12 - */ -gint64 -nm_utils_get_timestamp_msec(void) -{ - gint64 ts; - - ts = nm_utils_clock_gettime_msec(CLOCK_BOOTTIME); - if (ts >= 0) - return ts; - - if (ts == -EINVAL) { - /* The fallback to CLOCK_MONOTONIC is taken only if we're running on a - * criminally old kernel, prior to 2.6.39 (released on 18 May, 2011). - * That happens during buildcheck on old builders, we don't expect to - * be actually runs on kernels that old. */ - ts = nm_utils_clock_gettime_msec(CLOCK_MONOTONIC); - if (ts >= 0) - return ts; - } - - g_return_val_if_reached(-1); -} - -/*****************************************************************************/ - -/** - * nm_utils_version: - * - * Returns: the version ID of the libnm version. That is, the %NM_VERSION - * at runtime. - * - * Since: 1.6.0 - */ -guint -nm_utils_version(void) -{ - return NM_VERSION; -} - -/*****************************************************************************/ - -NM_UTILS_FLAGS2STR_DEFINE(nm_bluetooth_capability_to_string, - NMBluetoothCapabilities, - NM_UTILS_FLAGS2STR(NM_BT_CAPABILITY_NONE, "NONE"), - NM_UTILS_FLAGS2STR(NM_BT_CAPABILITY_DUN, "DUN"), - NM_UTILS_FLAGS2STR(NM_BT_CAPABILITY_NAP, "NAP"), ); - -/*****************************************************************************/ - -/** - * nm_utils_base64secret_decode: - * @base64_key: the (possibly invalid) base64 encode key. - * @required_key_len: the expected (binary) length of the key after - * decoding. If the length does not match, the validation fails. - * @out_key: (allow-none): (out): an optional output buffer for the binary - * key. If given, it will be filled with exactly @required_key_len - * bytes. - * - * Returns: %TRUE if the input key is a valid base64 encoded key - * with @required_key_len bytes. - * - * Since: 1.16 - */ -gboolean -nm_utils_base64secret_decode(const char *base64_key, gsize required_key_len, guint8 *out_key) -{ - nm_auto_free guint8 *bin_arr = NULL; - gsize base64_key_len; - gsize bin_len; - int r; - - if (!base64_key) - return FALSE; - - base64_key_len = strlen(base64_key); - - r = nm_sd_utils_unbase64mem(base64_key, base64_key_len, TRUE, &bin_arr, &bin_len); - if (r < 0) - return FALSE; - if (bin_len != required_key_len) { - nm_explicit_bzero(bin_arr, bin_len); - return FALSE; - } - - if (out_key) - memcpy(out_key, bin_arr, required_key_len); - - nm_explicit_bzero(bin_arr, bin_len); - return TRUE; -} - -gboolean -nm_utils_base64secret_normalize(const char *base64_key, - gsize required_key_len, - char ** out_base64_key_norm) -{ - gs_free guint8 *buf_free = NULL; - guint8 buf_static[200]; - guint8 * buf; - - if (required_key_len > sizeof(buf_static)) { - buf_free = g_new(guint8, required_key_len); - buf = buf_free; - } else - buf = buf_static; - - if (!nm_utils_base64secret_decode(base64_key, required_key_len, buf)) { - NM_SET_OUT(out_base64_key_norm, NULL); - return FALSE; - } - - NM_SET_OUT(out_base64_key_norm, g_base64_encode(buf, required_key_len)); - nm_explicit_bzero(buf, required_key_len); - return TRUE; -} - -static GVariant * -_nm_utils_bridge_vlans_to_dbus(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - gs_unref_ptrarray GPtrArray *vlans = NULL; - GVariantBuilder builder; - guint i; - const char * property_name = sett_info->property_infos[property_idx].name; - - nm_assert(property_name); - - g_object_get(setting, property_name, &vlans, NULL); - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - - if (vlans) { - for (i = 0; i < vlans->len; i++) { - NMBridgeVlan * vlan = vlans->pdata[i]; - GVariantBuilder vlan_builder; - guint16 vid_start, vid_end; - - nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); - - g_variant_builder_init(&vlan_builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add(&vlan_builder, - "{sv}", - "vid-start", - g_variant_new_uint16(vid_start)); - g_variant_builder_add(&vlan_builder, "{sv}", "vid-end", g_variant_new_uint16(vid_end)); - g_variant_builder_add(&vlan_builder, - "{sv}", - "pvid", - g_variant_new_boolean(nm_bridge_vlan_is_pvid(vlan))); - g_variant_builder_add(&vlan_builder, - "{sv}", - "untagged", - g_variant_new_boolean(nm_bridge_vlan_is_untagged(vlan))); - g_variant_builder_add(&builder, "a{sv}", &vlan_builder); - } - } - - return g_variant_builder_end(&builder); -} - -static gboolean -_nm_utils_bridge_vlans_from_dbus(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - gs_unref_ptrarray GPtrArray *vlans = NULL; - GVariantIter vlan_iter; - GVariant * vlan_var; - - g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), FALSE); - - vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); - g_variant_iter_init(&vlan_iter, value); - while (g_variant_iter_next(&vlan_iter, "@a{sv}", &vlan_var)) { - _nm_unused gs_unref_variant GVariant *var_unref = vlan_var; - NMBridgeVlan * vlan; - guint16 vid_start, vid_end; - gboolean pvid = FALSE, untagged = FALSE; - - if (!g_variant_lookup(vlan_var, "vid-start", "q", &vid_start)) - continue; - if (vid_start < NM_BRIDGE_VLAN_VID_MIN || vid_start > NM_BRIDGE_VLAN_VID_MAX) - continue; - - if (!g_variant_lookup(vlan_var, "vid-end", "q", &vid_end)) - continue; - if (vid_end < NM_BRIDGE_VLAN_VID_MIN || vid_end > NM_BRIDGE_VLAN_VID_MAX) - continue; - if (vid_start > vid_end) - continue; - - if (!g_variant_lookup(vlan_var, "pvid", "b", &pvid)) - pvid = FALSE; - if (pvid && vid_start != vid_end) - continue; - if (!g_variant_lookup(vlan_var, "untagged", "b", &untagged)) - untagged = FALSE; - - vlan = nm_bridge_vlan_new(vid_start, vid_end); - nm_bridge_vlan_set_untagged(vlan, untagged); - nm_bridge_vlan_set_pvid(vlan, pvid); - g_ptr_array_add(vlans, vlan); - } - - g_object_set(setting, property, vlans, NULL); - - return TRUE; -} - -const NMSettInfoPropertType nm_sett_info_propert_type_bridge_vlans = { - .dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _nm_utils_bridge_vlans_to_dbus, - .from_dbus_fcn = _nm_utils_bridge_vlans_from_dbus, -}; - -gboolean -_nm_utils_bridge_vlan_verify_list(GPtrArray * vlans, - gboolean check_normalizable, - GError ** error, - const char *setting, - const char *property) -{ - guint i; - gs_unref_hashtable GHashTable *h = NULL; - gboolean pvid_found = FALSE; - - if (!vlans || vlans->len <= 1) - return TRUE; - - if (check_normalizable) { - guint16 vid_prev_end, vid_start, vid_end; - - nm_assert(_nm_utils_bridge_vlan_verify_list(vlans, FALSE, NULL, setting, property)); - - nm_bridge_vlan_get_vid_range(vlans->pdata[0], NULL, &vid_prev_end); - for (i = 1; i < vlans->len; i++) { - const NMBridgeVlan *vlan = vlans->pdata[i]; - - nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); - - if (vid_prev_end > vid_start) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Bridge VLANs %d and %d are not sorted by ascending vid"), - vid_prev_end, - vid_start); - g_prefix_error(error, "%s.%s: ", setting, property); - return FALSE; - } - - vid_prev_end = vid_end; - } - return TRUE; - } - - h = g_hash_table_new(nm_direct_hash, NULL); - for (i = 0; i < vlans->len; i++) { - NMBridgeVlan *vlan = vlans->pdata[i]; - guint16 v, vid_start, vid_end; - - nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); - - for (v = vid_start; v <= vid_end; v++) { - if (!nm_g_hash_table_add(h, GUINT_TO_POINTER(v))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("duplicate bridge VLAN vid %u"), - v); - g_prefix_error(error, "%s.%s: ", setting, property); - return FALSE; - } - } - - if (nm_bridge_vlan_is_pvid(vlan)) { - if (vid_start != vid_end || pvid_found) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("only one VLAN can be the PVID")); - g_prefix_error(error, "%s.%s: ", setting, property); - return FALSE; - } - pvid_found = TRUE; - } - } - - return TRUE; -} - -gboolean -_nm_utils_iaid_verify(const char *str, gint64 *out_value) -{ - gint64 iaid; - - NM_SET_OUT(out_value, -1); - - if (!str || !str[0]) - return FALSE; - - if (NM_IAID_IS_SPECIAL(str)) - return TRUE; - - if (NM_STRCHAR_ALL(str, ch, ch >= '0' && ch <= '9') && (str[0] != '0' || str[1] == '\0') - && (iaid = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT32, -1)) != -1) { - NM_SET_OUT(out_value, iaid); - return TRUE; - } - - return FALSE; -} - -gboolean -_nm_utils_validate_dhcp_hostname_flags(NMDhcpHostnameFlags flags, int addr_family, GError **error) -{ - NMDhcpHostnameFlags unknown; - - unknown = flags; - unknown &= ~(NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE - | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE | NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS); - if (unknown) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("unknown flags 0x%x"), - (guint) unknown); - return FALSE; - } - - if (NM_FLAGS_ALL(flags, - NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE - | NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE)) { - g_set_error_literal( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'fqdn-no-update' and 'fqdn-serv-update' flags cannot be set at the same time")); - return FALSE; - } - - if (NM_FLAGS_HAS(flags, NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS) - && NM_FLAGS_ANY(flags, - NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE | NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED - | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'fqdn-clear-flags' flag is incompatible with other FQDN flags")); - return FALSE; - } - - if (addr_family == AF_INET6 && (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("DHCPv6 does not support the E (encoded) FQDN flag")); - return FALSE; - } - - return TRUE; -} diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h deleted file mode 100644 index 0f8dcda09e..0000000000 --- a/libnm-core/nm-utils.h +++ /dev/null @@ -1,259 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2005 - 2017 Red Hat, Inc. - */ - -#ifndef __NM_UTILS_H__ -#define __NM_UTILS_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include - -#include "nm-core-enum-types.h" -#include "nm-setting-sriov.h" -#include "nm-setting-tc-config.h" -#include "nm-setting-wireless-security.h" - -G_BEGIN_DECLS - -/*****************************************************************************/ - -typedef struct _NMVariantAttributeSpec NMVariantAttributeSpec; - -/* SSID helpers */ -gboolean nm_utils_is_empty_ssid(const guint8 *ssid, gsize len); -const char *nm_utils_escape_ssid(const guint8 *ssid, gsize len); -gboolean nm_utils_same_ssid(const guint8 *ssid1, - gsize len1, - const guint8 *ssid2, - gsize len2, - gboolean ignore_trailing_null); -char * nm_utils_ssid_to_utf8(const guint8 *ssid, gsize len); - -/** - * NMUtilsSecurityType: - * @NMU_SEC_INVALID: unknown or invalid security, placeholder and not used - * @NMU_SEC_NONE: unencrypted and open - * @NMU_SEC_STATIC_WEP: static WEP keys are used for encryption - * @NMU_SEC_LEAP: Cisco LEAP is used for authentication and for generating the - * dynamic WEP keys automatically - * @NMU_SEC_DYNAMIC_WEP: standard 802.1x is used for authentication and - * generating the dynamic WEP keys automatically - * @NMU_SEC_WPA_PSK: WPA1 is used with Pre-Shared Keys (PSK) - * @NMU_SEC_WPA_ENTERPRISE: WPA1 is used with 802.1x authentication - * @NMU_SEC_WPA2_PSK: WPA2/RSN is used with Pre-Shared Keys (PSK) - * @NMU_SEC_WPA2_ENTERPRISE: WPA2 is used with 802.1x authentication - * @NMU_SEC_SAE: is used with WPA3 Enterprise - * @NMU_SEC_OWE: is used with Enhanced Open - * @NMU_SEC_WPA3_SUITE_B_192: is used with WPA3 Enterprise Suite-B 192 bit mode. Since: 1.30. - * - * Describes generic security mechanisms that 802.11 access points may offer. - * Used with nm_utils_security_valid() for checking whether a given access - * point is compatible with a network device. - **/ -typedef enum { - NMU_SEC_INVALID = 0, - NMU_SEC_NONE, - NMU_SEC_STATIC_WEP, - NMU_SEC_LEAP, - NMU_SEC_DYNAMIC_WEP, - NMU_SEC_WPA_PSK, - NMU_SEC_WPA_ENTERPRISE, - NMU_SEC_WPA2_PSK, - NMU_SEC_WPA2_ENTERPRISE, - NMU_SEC_SAE, - NMU_SEC_OWE, - NMU_SEC_WPA3_SUITE_B_192, -} NMUtilsSecurityType; - -gboolean nm_utils_security_valid(NMUtilsSecurityType type, - NMDeviceWifiCapabilities wifi_caps, - gboolean have_ap, - gboolean adhoc, - NM80211ApFlags ap_flags, - NM80211ApSecurityFlags ap_wpa, - NM80211ApSecurityFlags ap_rsn); - -gboolean nm_utils_ap_mode_security_valid(NMUtilsSecurityType type, - NMDeviceWifiCapabilities wifi_caps); - -gboolean nm_utils_wep_key_valid(const char *key, NMWepKeyType wep_type); -gboolean nm_utils_wpa_psk_valid(const char *psk); - -NM_AVAILABLE_IN_1_6 -gboolean nm_utils_is_json_object(const char *str, GError **error); - -GVariant * nm_utils_ip4_dns_to_variant(char **dns); -char ** nm_utils_ip4_dns_from_variant(GVariant *value); -GVariant * nm_utils_ip4_addresses_to_variant(GPtrArray *addresses, const char *gateway); -GPtrArray *nm_utils_ip4_addresses_from_variant(GVariant *value, char **out_gateway); -GVariant * nm_utils_ip4_routes_to_variant(GPtrArray *routes); -GPtrArray *nm_utils_ip4_routes_from_variant(GVariant *value); - -guint32 nm_utils_ip4_netmask_to_prefix(guint32 netmask); -guint32 nm_utils_ip4_prefix_to_netmask(guint32 prefix); -guint32 nm_utils_ip4_get_default_prefix(guint32 ip); - -GVariant * nm_utils_ip6_dns_to_variant(char **dns); -char ** nm_utils_ip6_dns_from_variant(GVariant *value); -GVariant * nm_utils_ip6_addresses_to_variant(GPtrArray *addresses, const char *gateway); -GPtrArray *nm_utils_ip6_addresses_from_variant(GVariant *value, char **out_gateway); -GVariant * nm_utils_ip6_routes_to_variant(GPtrArray *routes); -GPtrArray *nm_utils_ip6_routes_from_variant(GVariant *value); - -GVariant * nm_utils_ip_addresses_to_variant(GPtrArray *addresses); -GPtrArray *nm_utils_ip_addresses_from_variant(GVariant *value, int family); -GVariant * nm_utils_ip_routes_to_variant(GPtrArray *routes); -GPtrArray *nm_utils_ip_routes_from_variant(GVariant *value, int family); - -char *nm_utils_uuid_generate(void); - -gboolean nm_utils_file_is_certificate(const char *filename); -gboolean nm_utils_file_is_private_key(const char *filename, gboolean *out_encrypted); -gboolean nm_utils_file_is_pkcs12(const char *filename); - -typedef gboolean (*NMUtilsFileSearchInPathsPredicate)(const char *filename, gpointer user_data); - -struct stat; - -typedef gboolean (*NMUtilsCheckFilePredicate)(const char * filename, - const struct stat *stat, - gpointer user_data, - GError ** error); - -const char *nm_utils_file_search_in_paths(const char * progname, - const char * try_first, - const char *const * paths, - GFileTest file_test_flags, - NMUtilsFileSearchInPathsPredicate predicate, - gpointer user_data, - GError ** error); - -guint32 nm_utils_wifi_freq_to_channel(guint32 freq); -guint32 nm_utils_wifi_channel_to_freq(guint32 channel, const char *band); -guint32 nm_utils_wifi_find_next_channel(guint32 channel, int direction, char *band); -gboolean nm_utils_wifi_is_channel_valid(guint32 channel, const char *band); -NM_AVAILABLE_IN_1_2 -const guint *nm_utils_wifi_2ghz_freqs(void); -NM_AVAILABLE_IN_1_2 -const guint *nm_utils_wifi_5ghz_freqs(void); - -const char *nm_utils_wifi_strength_bars(guint8 strength); - -/** - * NM_UTILS_HWADDR_LEN_MAX: - * - * The maximum length of hardware addresses handled by NetworkManager itself, - * nm_utils_hwaddr_len(), and nm_utils_hwaddr_aton(). - */ -#define NM_UTILS_HWADDR_LEN_MAX 20 /* INFINIBAND_ALEN */ - -gsize nm_utils_hwaddr_len(int type) G_GNUC_PURE; - -char * nm_utils_hwaddr_ntoa(gconstpointer addr, gsize length); -GByteArray *nm_utils_hwaddr_atoba(const char *asc, gsize length); -guint8 * nm_utils_hwaddr_aton(const char *asc, gpointer buffer, gsize length); - -gboolean nm_utils_hwaddr_valid(const char *asc, gssize length); -char * nm_utils_hwaddr_canonical(const char *asc, gssize length); -gboolean nm_utils_hwaddr_matches(gconstpointer hwaddr1, - gssize hwaddr1_len, - gconstpointer hwaddr2, - gssize hwaddr2_len); - -char * nm_utils_bin2hexstr(gconstpointer src, gsize len, int final_len); -GBytes *nm_utils_hexstr2bin(const char *hex); - -NM_DEPRECATED_IN_1_6_FOR(nm_utils_is_valid_iface_name) -gboolean nm_utils_iface_valid_name(const char *name); -NM_AVAILABLE_IN_1_6 -gboolean nm_utils_is_valid_iface_name(const char *name, GError **error); - -gboolean nm_utils_is_uuid(const char *str); - -/** - * NM_UTILS_INET_ADDRSTRLEN: - * - * Defines the minimal length for a char buffer that is suitable as @dst argument - * for both nm_utils_inet4_ntop() and nm_utils_inet6_ntop(). - **/ -#define NM_UTILS_INET_ADDRSTRLEN INET6_ADDRSTRLEN - -const char *nm_utils_inet4_ntop(guint32 inaddr, char *dst); - -struct in6_addr; -const char *nm_utils_inet6_ntop(const struct in6_addr *in6addr, char *dst); - -gboolean nm_utils_ipaddr_valid(int family, const char *ip); - -gboolean nm_utils_check_virtual_device_compatibility(GType virtual_type, GType other_type); - -NM_AVAILABLE_IN_1_2 -int nm_utils_bond_mode_string_to_int(const char *mode); -NM_AVAILABLE_IN_1_2 -const char *nm_utils_bond_mode_int_to_string(int mode); - -NM_AVAILABLE_IN_1_2 -char *nm_utils_enum_to_str(GType type, int value); - -NM_AVAILABLE_IN_1_2 -gboolean nm_utils_enum_from_str(GType type, const char *str, int *out_value, char **err_token); - -NM_AVAILABLE_IN_1_2 -const char **nm_utils_enum_get_values(GType type, int from, int to); - -NM_AVAILABLE_IN_1_6 -guint nm_utils_version(void); - -NM_AVAILABLE_IN_1_8 -GHashTable *nm_utils_parse_variant_attributes(const char *string, - char attr_separator, - char key_value_separator, - gboolean ignore_unknown, - const NMVariantAttributeSpec *const *spec, - GError ** error); - -NM_AVAILABLE_IN_1_8 -char *nm_utils_format_variant_attributes(GHashTable *attributes, - char attr_separator, - char key_value_separator); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_12 -NMTCQdisc *nm_utils_tc_qdisc_from_str(const char *str, GError **error); -NM_AVAILABLE_IN_1_12 -char *nm_utils_tc_qdisc_to_str(NMTCQdisc *qdisc, GError **error); - -NM_AVAILABLE_IN_1_12 -NMTCAction *nm_utils_tc_action_from_str(const char *str, GError **error); -NM_AVAILABLE_IN_1_12 -char *nm_utils_tc_action_to_str(NMTCAction *action, GError **error); - -NM_AVAILABLE_IN_1_12 -NMTCTfilter *nm_utils_tc_tfilter_from_str(const char *str, GError **error); -NM_AVAILABLE_IN_1_12 -char *nm_utils_tc_tfilter_to_str(NMTCTfilter *tfilter, GError **error); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_14 -char *nm_utils_sriov_vf_to_str(const NMSriovVF *vf, gboolean omit_index, GError **error); -NM_AVAILABLE_IN_1_14 -NMSriovVF *nm_utils_sriov_vf_from_str(const char *str, GError **error); - -/*****************************************************************************/ - -NM_AVAILABLE_IN_1_12 -gint64 nm_utils_get_timestamp_msec(void); - -NM_AVAILABLE_IN_1_16 -gboolean -nm_utils_base64secret_decode(const char *base64_key, gsize required_key_len, guint8 *out_key); - -G_END_DECLS - -#endif /* __NM_UTILS_H__ */ diff --git a/libnm-core/nm-version-macros.h.in b/libnm-core/nm-version-macros.h.in deleted file mode 100644 index 4a6f46e9f0..0000000000 --- a/libnm-core/nm-version-macros.h.in +++ /dev/null @@ -1,91 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011, 2015 Red Hat, Inc. - */ - -#ifndef __NM_VERSION_MACROS_H__ -#define __NM_VERSION_MACROS_H__ - -/* This header must not include glib or libnm. */ - -/** - * NM_MAJOR_VERSION: - * - * Evaluates to the major version number of NetworkManager which this source - * is compiled against. - */ -#define NM_MAJOR_VERSION (@NM_MAJOR_VERSION@) - -/** - * NM_MINOR_VERSION: - * - * Evaluates to the minor version number of NetworkManager which this source - * is compiled against. - */ -#define NM_MINOR_VERSION (@NM_MINOR_VERSION@) - -/** - * NM_MICRO_VERSION: - * - * Evaluates to the micro version number of NetworkManager which this source - * compiled against. - */ -#define NM_MICRO_VERSION (@NM_MICRO_VERSION@) - -/** - * NM_CHECK_VERSION: - * @major: major version (e.g. 1 for version 1.2.5) - * @minor: minor version (e.g. 2 for version 1.2.5) - * @micro: micro version (e.g. 5 for version 1.2.5) - * - * Returns: %TRUE if the version of the NetworkManager header files - * is the same as or newer than the passed-in version. - */ -#define NM_CHECK_VERSION(major,minor,micro) \ - (NM_MAJOR_VERSION > (major) || \ - (NM_MAJOR_VERSION == (major) && NM_MINOR_VERSION > (minor)) || \ - (NM_MAJOR_VERSION == (major) && NM_MINOR_VERSION == (minor) && NM_MICRO_VERSION >= (micro))) - - -#define NM_ENCODE_VERSION(major,minor,micro) ((major) << 16 | (minor) << 8 | (micro)) - -#define NM_VERSION_0_9_8 (NM_ENCODE_VERSION (0, 9, 8)) -#define NM_VERSION_0_9_10 (NM_ENCODE_VERSION (0, 9, 10)) -#define NM_VERSION_1_0 (NM_ENCODE_VERSION (1, 0, 0)) -#define NM_VERSION_1_2 (NM_ENCODE_VERSION (1, 2, 0)) -#define NM_VERSION_1_4 (NM_ENCODE_VERSION (1, 4, 0)) -#define NM_VERSION_1_6 (NM_ENCODE_VERSION (1, 6, 0)) -#define NM_VERSION_1_8 (NM_ENCODE_VERSION (1, 8, 0)) -#define NM_VERSION_1_10 (NM_ENCODE_VERSION (1, 10, 0)) -#define NM_VERSION_1_12 (NM_ENCODE_VERSION (1, 12, 0)) -#define NM_VERSION_1_14 (NM_ENCODE_VERSION (1, 14, 0)) -#define NM_VERSION_1_16 (NM_ENCODE_VERSION (1, 16, 0)) -#define NM_VERSION_1_18 (NM_ENCODE_VERSION (1, 18, 0)) -#define NM_VERSION_1_20 (NM_ENCODE_VERSION (1, 20, 0)) -#define NM_VERSION_1_22 (NM_ENCODE_VERSION (1, 22, 0)) -#define NM_VERSION_1_24 (NM_ENCODE_VERSION (1, 24, 0)) -#define NM_VERSION_1_26 (NM_ENCODE_VERSION (1, 26, 0)) -#define NM_VERSION_1_28 (NM_ENCODE_VERSION (1, 28, 0)) -#define NM_VERSION_1_30 (NM_ENCODE_VERSION (1, 30, 0)) - -/* For releases, NM_API_VERSION is equal to NM_VERSION. - * - * For development builds, NM_API_VERSION is the next - * stable API after NM_VERSION. When you run a development - * version, you are already using the future API, even if - * it is not yet release. Hence, the currently used API - * version is the future one. */ -#define NM_API_VERSION \ - (((NM_MINOR_VERSION % 2) == 1) \ - ? NM_ENCODE_VERSION (NM_MAJOR_VERSION, NM_MINOR_VERSION + 1, 0 ) \ - : NM_ENCODE_VERSION (NM_MAJOR_VERSION, NM_MINOR_VERSION , ((NM_MICRO_VERSION + 1) / 2) * 2)) - -/* deprecated. */ -#define NM_VERSION_CUR_STABLE NM_API_VERSION - -/* deprecated. */ -#define NM_VERSION_NEXT_STABLE NM_API_VERSION - -#define NM_VERSION NM_ENCODE_VERSION (NM_MAJOR_VERSION, NM_MINOR_VERSION, NM_MICRO_VERSION) - -#endif /* __NM_VERSION_MACROS_H__ */ diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h deleted file mode 100644 index 3f1ad3f2eb..0000000000 --- a/libnm-core/nm-version.h +++ /dev/null @@ -1,301 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2011, 2015 Red Hat, Inc. - */ - -#ifndef NM_VERSION_H -#define NM_VERSION_H - -#include - -#include "nm-version-macros.h" - -/* Deprecation / Availability macros */ - -#if !defined(NM_VERSION_MIN_REQUIRED) || (NM_VERSION_MIN_REQUIRED == 0) - #undef NM_VERSION_MIN_REQUIRED - #define NM_VERSION_MIN_REQUIRED (NM_API_VERSION) -#endif - -#if !defined(NM_VERSION_MAX_ALLOWED) || (NM_VERSION_MAX_ALLOWED == 0) - #undef NM_VERSION_MAX_ALLOWED - #define NM_VERSION_MAX_ALLOWED (NM_API_VERSION) -#endif - -/* sanity checks */ -#if NM_VERSION_MIN_REQUIRED > NM_API_VERSION - #error "NM_VERSION_MIN_REQUIRED must be <= NM_API_VERSION" -#endif -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_MIN_REQUIRED - #error "NM_VERSION_MAX_ALLOWED must be >= NM_VERSION_MIN_REQUIRED" -#endif -#if NM_VERSION_MIN_REQUIRED < NM_VERSION_0_9_8 - #error "NM_VERSION_MIN_REQUIRED must be >= NM_VERSION_0_9_8" -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_0_9_10 - #define NM_DEPRECATED_IN_0_9_10 G_DEPRECATED - #define NM_DEPRECATED_IN_0_9_10_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_0_9_10 - #define NM_DEPRECATED_IN_0_9_10_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_0_9_10 - #define NM_AVAILABLE_IN_0_9_10 G_UNAVAILABLE(0.9, 10) -#else - #define NM_AVAILABLE_IN_0_9_10 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_0 - #define NM_DEPRECATED_IN_1_0 G_DEPRECATED - #define NM_DEPRECATED_IN_1_0_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_0 - #define NM_DEPRECATED_IN_1_0_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_0 - #define NM_AVAILABLE_IN_1_0 G_UNAVAILABLE(1, 0) -#else - #define NM_AVAILABLE_IN_1_0 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_2 - #define NM_DEPRECATED_IN_1_2 G_DEPRECATED - #define NM_DEPRECATED_IN_1_2_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_2 - #define NM_DEPRECATED_IN_1_2_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_2 - #define NM_AVAILABLE_IN_1_2 G_UNAVAILABLE(1, 2) -#else - #define NM_AVAILABLE_IN_1_2 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_4 - #define NM_DEPRECATED_IN_1_4 G_DEPRECATED - #define NM_DEPRECATED_IN_1_4_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_4 - #define NM_DEPRECATED_IN_1_4_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_4 - #define NM_AVAILABLE_IN_1_4 G_UNAVAILABLE(1, 4) -#else - #define NM_AVAILABLE_IN_1_4 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_6 - #define NM_DEPRECATED_IN_1_6 G_DEPRECATED - #define NM_DEPRECATED_IN_1_6_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_6 - #define NM_DEPRECATED_IN_1_6_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_6 - #define NM_AVAILABLE_IN_1_6 G_UNAVAILABLE(1, 6) -#else - #define NM_AVAILABLE_IN_1_6 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_8 - #define NM_DEPRECATED_IN_1_8 G_DEPRECATED - #define NM_DEPRECATED_IN_1_8_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_8 - #define NM_DEPRECATED_IN_1_8_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_8 - #define NM_AVAILABLE_IN_1_8 G_UNAVAILABLE(1, 8) -#else - #define NM_AVAILABLE_IN_1_8 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_10 - #define NM_DEPRECATED_IN_1_10 G_DEPRECATED - #define NM_DEPRECATED_IN_1_10_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_10 - #define NM_DEPRECATED_IN_1_10_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_10 - #define NM_AVAILABLE_IN_1_10 G_UNAVAILABLE(1, 10) -#else - #define NM_AVAILABLE_IN_1_10 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_12 - #define NM_DEPRECATED_IN_1_12 G_DEPRECATED - #define NM_DEPRECATED_IN_1_12_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_12 - #define NM_DEPRECATED_IN_1_12_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_12 - #define NM_AVAILABLE_IN_1_12 G_UNAVAILABLE(1, 12) -#else - #define NM_AVAILABLE_IN_1_12 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_14 - #define NM_DEPRECATED_IN_1_14 G_DEPRECATED - #define NM_DEPRECATED_IN_1_14_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_14 - #define NM_DEPRECATED_IN_1_14_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_14 - #define NM_AVAILABLE_IN_1_14 G_UNAVAILABLE(1, 14) -#else - #define NM_AVAILABLE_IN_1_14 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_16 - #define NM_DEPRECATED_IN_1_16 G_DEPRECATED - #define NM_DEPRECATED_IN_1_16_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_16 - #define NM_DEPRECATED_IN_1_16_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_16 - #define NM_AVAILABLE_IN_1_16 G_UNAVAILABLE(1, 16) -#else - #define NM_AVAILABLE_IN_1_16 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_18 - #define NM_DEPRECATED_IN_1_18 G_DEPRECATED - #define NM_DEPRECATED_IN_1_18_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_18 - #define NM_DEPRECATED_IN_1_18_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_18 - #define NM_AVAILABLE_IN_1_18 G_UNAVAILABLE(1, 18) -#else - #define NM_AVAILABLE_IN_1_18 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_20 - #define NM_DEPRECATED_IN_1_20 G_DEPRECATED - #define NM_DEPRECATED_IN_1_20_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_20 - #define NM_DEPRECATED_IN_1_20_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_20 - #define NM_AVAILABLE_IN_1_20 G_UNAVAILABLE(1, 20) -#else - #define NM_AVAILABLE_IN_1_20 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_22 - #define NM_DEPRECATED_IN_1_22 G_DEPRECATED - #define NM_DEPRECATED_IN_1_22_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_22 - #define NM_DEPRECATED_IN_1_22_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_22 - #define NM_AVAILABLE_IN_1_22 G_UNAVAILABLE(1, 22) -#else - #define NM_AVAILABLE_IN_1_22 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_24 - #define NM_DEPRECATED_IN_1_24 G_DEPRECATED - #define NM_DEPRECATED_IN_1_24_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_24 - #define NM_DEPRECATED_IN_1_24_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_24 - #define NM_AVAILABLE_IN_1_24 G_UNAVAILABLE(1, 24) -#else - #define NM_AVAILABLE_IN_1_24 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_26 - #define NM_DEPRECATED_IN_1_26 G_DEPRECATED - #define NM_DEPRECATED_IN_1_26_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_26 - #define NM_DEPRECATED_IN_1_26_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_26 - #define NM_AVAILABLE_IN_1_26 G_UNAVAILABLE(1, 26) -#else - #define NM_AVAILABLE_IN_1_26 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_28 - #define NM_DEPRECATED_IN_1_28 G_DEPRECATED - #define NM_DEPRECATED_IN_1_28_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_28 - #define NM_DEPRECATED_IN_1_28_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_28 - #define NM_AVAILABLE_IN_1_28 G_UNAVAILABLE(1, 28) -#else - #define NM_AVAILABLE_IN_1_28 -#endif - -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_30 - #define NM_DEPRECATED_IN_1_30 G_DEPRECATED - #define NM_DEPRECATED_IN_1_30_FOR(f) G_DEPRECATED_FOR(f) -#else - #define NM_DEPRECATED_IN_1_30 - #define NM_DEPRECATED_IN_1_30_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_30 - #define NM_AVAILABLE_IN_1_30 G_UNAVAILABLE(1, 30) -#else - #define NM_AVAILABLE_IN_1_30 -#endif - -/* - * Synchronous API for calling D-Bus in libnm is deprecated. See - * https://developer.gnome.org/libnm/stable/usage.html#sync-api - * - * Note that "deprecated" here does not really mean that the API is going - * to be removed. We don't break API. Just comment that it is awkward and - * discouraged. The user may: - * - * - continue to use this API. It's deprecated, awkward and discouraged, - * but if it works for you, that's fine. - * - * - use asynchronous API. That's the only sensible way to use D-Bus. - * If libnm lacks a certain asynchronous counterpart, it should be - * added. - * - * - use GDBusConnection directly. There really isn't anything wrong - * with D-Bus or GDBusConnection. This deprecated API is just a wrapper - * around g_dbus_connection_call_sync(). You may call it directly - * without feeling dirty. - * - * The API is marked as deprecated since 1.22, however the macro only starts - * complaining in 1.24. That's intentional, because in 1.22 the asynchronous - * alternative was not yet available. - */ -#define _NM_DEPRECATED_SYNC_METHOD NM_DEPRECATED_IN_1_24 -#define _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY /* NM_DEPRECATED_IN_1_22 */ - -#endif /* NM_VERSION_H */ diff --git a/libnm-core/nm-vpn-dbus-interface.h b/libnm-core/nm-vpn-dbus-interface.h deleted file mode 100644 index c0e23f6fc1..0000000000 --- a/libnm-core/nm-vpn-dbus-interface.h +++ /dev/null @@ -1,302 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2004 Red Hat, Inc. - */ - -/* D-Bus-related definitions for NetworkManager VPN plugins. - * - * Note that although this header is installed as part of libnm, it is also - * used by some external code that does not link to libnm. - */ - -#ifndef __NM_VPN_DBUS_INTERFACE_H__ -#define __NM_VPN_DBUS_INTERFACE_H__ - -#include "nm-dbus-interface.h" - -#ifndef NM_VERSION_H - #define NM_DEPRECATED_IN_1_8_FOR(n) -#endif - -/* - * dbus services details - */ -#define NM_DBUS_PATH_VPN "/org/freedesktop/NetworkManager/VPN/Manager" -#define NM_DBUS_INTERFACE_VPN "org.freedesktop.NetworkManager.VPN.Manager" - -#define NM_DBUS_PATH_VPN_CONNECTION "/org/freedesktop/NetworkManager/VPN/Connection" -#define NM_DBUS_INTERFACE_VPN_CONNECTION "org.freedesktop.NetworkManager.VPN.Connection" - -#define NM_VPN_DBUS_PLUGIN_PATH "/org/freedesktop/NetworkManager/VPN/Plugin" -#define NM_VPN_DBUS_PLUGIN_INTERFACE "org.freedesktop.NetworkManager.VPN.Plugin" - -/* - * VPN Errors - */ -#define NM_DBUS_NO_ACTIVE_VPN_CONNECTION \ - "org.freedesktop.NetworkManager.VPNConnections.NoActiveVPNConnection" -#define NM_DBUS_NO_VPN_CONNECTIONS "org.freedesktop.NetworkManager.VPNConnections.NoVPNConnections" -#define NM_DBUS_INVALID_VPN_CONNECTION \ - "org.freedesktop.NetworkManager.VPNConnections.InvalidVPNConnection" - -#define NM_DBUS_VPN_ERROR_PREFIX "org.freedesktop.NetworkManager.VPN.Error" -#define NM_DBUS_VPN_STARTING_IN_PROGRESS "StartingInProgress" -#define NM_DBUS_VPN_ALREADY_STARTED "AlreadyStarted" -#define NM_DBUS_VPN_STOPPING_IN_PROGRESS "StoppingInProgress" -#define NM_DBUS_VPN_ALREADY_STOPPED "AlreadyStopped" -#define NM_DBUS_VPN_WRONG_STATE "WrongState" -#define NM_DBUS_VPN_BAD_ARGUMENTS "BadArguments" -#define NM_DBUS_VPN_INTERACTIVE_NOT_SUPPORTED "InteractiveNotSupported" - -/* - * VPN daemon signals - */ -#define NM_DBUS_VPN_SIGNAL_LOGIN_BANNER "LoginBanner" -#define NM_DBUS_VPN_SIGNAL_LOGIN_FAILED "LoginFailed" -#define NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED "LaunchFailed" -#define NM_DBUS_VPN_SIGNAL_CONNECT_FAILED "ConnectFailed" -#define NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD "VPNConfigBad" -#define NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD "IPConfigBad" -#define NM_DBUS_VPN_SIGNAL_STATE_CHANGE "StateChange" -#define NM_DBUS_VPN_SIGNAL_IP4_CONFIG "IP4Config" - -/** - * NMVpnServiceState: - * @NM_VPN_SERVICE_STATE_UNKNOWN: The state of the VPN plugin is unknown. - * @NM_VPN_SERVICE_STATE_INIT: The VPN plugin is initialized. - * @NM_VPN_SERVICE_STATE_SHUTDOWN: Not used. - * @NM_VPN_SERVICE_STATE_STARTING: The plugin is attempting to connect to a VPN server. - * @NM_VPN_SERVICE_STATE_STARTED: The plugin has connected to a VPN server. - * @NM_VPN_SERVICE_STATE_STOPPING: The plugin is disconnecting from the VPN server. - * @NM_VPN_SERVICE_STATE_STOPPED: The plugin has disconnected from the VPN server. - * - * VPN daemon states - */ -typedef enum { - NM_VPN_SERVICE_STATE_UNKNOWN = 0, - NM_VPN_SERVICE_STATE_INIT, - NM_VPN_SERVICE_STATE_SHUTDOWN, - NM_VPN_SERVICE_STATE_STARTING, - NM_VPN_SERVICE_STATE_STARTED, - NM_VPN_SERVICE_STATE_STOPPING, - NM_VPN_SERVICE_STATE_STOPPED -} NMVpnServiceState; - -/** - * NMVpnConnectionState: - * @NM_VPN_CONNECTION_STATE_UNKNOWN: The state of the VPN connection is - * unknown. - * @NM_VPN_CONNECTION_STATE_PREPARE: The VPN connection is preparing to - * connect. - * @NM_VPN_CONNECTION_STATE_NEED_AUTH: The VPN connection needs authorization - * credentials. - * @NM_VPN_CONNECTION_STATE_CONNECT: The VPN connection is being established. - * @NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: The VPN connection is getting an IP - * address. - * @NM_VPN_CONNECTION_STATE_ACTIVATED: The VPN connection is active. - * @NM_VPN_CONNECTION_STATE_FAILED: The VPN connection failed. - * @NM_VPN_CONNECTION_STATE_DISCONNECTED: The VPN connection is disconnected. - * - * VPN connection states - */ -typedef enum { - NM_VPN_CONNECTION_STATE_UNKNOWN = 0, - NM_VPN_CONNECTION_STATE_PREPARE, - NM_VPN_CONNECTION_STATE_NEED_AUTH, - NM_VPN_CONNECTION_STATE_CONNECT, - NM_VPN_CONNECTION_STATE_IP_CONFIG_GET, - NM_VPN_CONNECTION_STATE_ACTIVATED, - NM_VPN_CONNECTION_STATE_FAILED, - NM_VPN_CONNECTION_STATE_DISCONNECTED -} NMVpnConnectionState; - -/** - * NMVpnConnectionStateReason: - * @NM_VPN_CONNECTION_STATE_REASON_UNKNOWN: The reason for the VPN connection - * state change is unknown. - * @NM_VPN_CONNECTION_STATE_REASON_NONE: No reason was given for the VPN - * connection state change. - * @NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED: The VPN connection changed - * state because the user disconnected it. - * @NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED: The VPN connection - * changed state because the device it was using was disconnected. - * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED: The service providing the - * VPN connection was stopped. - * @NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID: The IP config of the VPN - * connection was invalid. - * @NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT: The connection attempt to - * the VPN service timed out. - * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT: A timeout occurred - * while starting the service providing the VPN connection. - * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED: Starting the service - * starting the service providing the VPN connection failed. - * @NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS: Necessary secrets for the VPN - * connection were not provided. - * @NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED: Authentication to the VPN - * server failed. - * @NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED: The connection was - * deleted from settings. - * - * VPN connection state reasons - */ -NM_DEPRECATED_IN_1_8_FOR(NMActiveConnectionStateReason) -typedef enum { - NM_VPN_CONNECTION_STATE_REASON_UNKNOWN = 0, - NM_VPN_CONNECTION_STATE_REASON_NONE = 1, - NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED = 2, - NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED = 3, - NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED = 4, - NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID = 5, - NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT = 6, - NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT = 7, - NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED = 8, - NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS = 9, - NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED = 10, - NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED = 11, -} NMVpnConnectionStateReason; - -/** - * NMVpnPluginFailure: - * @NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED: Login failed. - * @NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED: Connect failed. - * @NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG: Invalid IP configuration returned from - * the VPN plugin. - * - * VPN plugin failure reasons - */ -typedef enum { - NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED, - NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED, - NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG -} NMVpnPluginFailure; - -#ifndef NM_VERSION_H - #undef NM_DEPRECATED_IN_1_8_FOR -#endif - -/*** Generic config ***/ - -/* string: VPN interface name (tun0, tap0, etc) */ -#define NM_VPN_PLUGIN_CONFIG_TUNDEV "tundev" - -/* string: Proxy PAC */ -#define NM_VPN_PLUGIN_CONFIG_PROXY_PAC "pac" - -/* string: Login message */ -#define NM_VPN_PLUGIN_CONFIG_BANNER "banner" - -/* uint32 / array of uint8: IP address of the public external VPN gateway (network byte order) */ -#define NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY "gateway" - -/* uint32: Maximum Transfer Unit that the VPN interface should use */ -#define NM_VPN_PLUGIN_CONFIG_MTU "mtu" - -/* boolean: Has IP4 configuration? */ -#define NM_VPN_PLUGIN_CONFIG_HAS_IP4 "has-ip4" - -/* boolean: Has IP6 configuration? */ -#define NM_VPN_PLUGIN_CONFIG_HAS_IP6 "has-ip6" - -/* boolean: If %TRUE the VPN plugin can persist/reconnect the connection over - * link changes and VPN server dropouts. - */ -#define NM_VPN_PLUGIN_CAN_PERSIST "can-persist" - -/*** Ip4Config ***/ - -/* uint32: IP address of the internal gateway of the subnet the VPN interface is - * on, if the VPN uses subnet configuration (network byte order) - */ -#define NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY "internal-gateway" - -/* uint32: internal IP address of the local VPN interface (network byte order) */ -#define NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS "address" - -/* uint32: IP address of the other side of Point-to-Point connection if the VPN - * uses Point-to-Point configuration. (network byte order) - */ -#define NM_VPN_PLUGIN_IP4_CONFIG_PTP "ptp" - -/* uint32: IP prefix of the VPN interface; 1 - 32 inclusive */ -#define NM_VPN_PLUGIN_IP4_CONFIG_PREFIX "prefix" - -/* array of uint32: IP addresses of DNS servers for the VPN (network byte order) */ -#define NM_VPN_PLUGIN_IP4_CONFIG_DNS "dns" - -/* array of uint32: IP addresses of NBNS/WINS servers for the VPN (network byte order) */ -#define NM_VPN_PLUGIN_IP4_CONFIG_NBNS "nbns" - -/* uint32: Message Segment Size that the VPN interface should use */ -#define NM_VPN_PLUGIN_IP4_CONFIG_MSS "mss" - -/* string: DNS domain name */ -#define NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN "domain" - -/* array of strings: DNS domain names */ -#define NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS "domains" - -/* [ip4 routes]: custom routes the client should apply, in the format used - * by nm_utils_ip4_routes_to/from_gvalue - */ -#define NM_VPN_PLUGIN_IP4_CONFIG_ROUTES "routes" - -/* whether the previous IP4 routing configuration should be preserved. */ -#define NM_VPN_PLUGIN_IP4_CONFIG_PRESERVE_ROUTES "preserve-routes" - -/* boolean: prevent this VPN connection from ever getting the default route */ -#define NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT "never-default" - -/* Deprecated */ -#define NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY - -/* Legacy IP4 items; these are included in the IP4 config by older plugins, - * but in the generic config by newer plugins. - */ - -#define NM_VPN_PLUGIN_IP4_CONFIG_BANNER NM_VPN_PLUGIN_CONFIG_BANNER -#define NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY -#define NM_VPN_PLUGIN_IP4_CONFIG_MTU NM_VPN_PLUGIN_CONFIG_MTU -#define NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV NM_VPN_PLUGIN_CONFIG_TUNDEV - -/*** Ip6Config ***/ - -/* array of uint8: IP address of the internal gateway of the subnet the VPN interface is - * on, if the VPN uses subnet configuration (network byte order) - */ -#define NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY "internal-gateway" - -/* array of uint8: internal IP address of the local VPN interface (network byte order) */ -#define NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS "address" - -/* array of uint8: IP address of the other side of Point-to-Point connection if the VPN - * uses Point-to-Point configuration. (network byte order) - */ -#define NM_VPN_PLUGIN_IP6_CONFIG_PTP "ptp" - -/* uint32: prefix length of the VPN interface; 1 - 128 inclusive */ -#define NM_VPN_PLUGIN_IP6_CONFIG_PREFIX "prefix" - -/* array of array of uint8: IP addresses of DNS servers for the VPN (network byte order) */ -#define NM_VPN_PLUGIN_IP6_CONFIG_DNS "dns" - -/* uint32: Message Segment Size that the VPN interface should use */ -#define NM_VPN_PLUGIN_IP6_CONFIG_MSS "mss" - -/* string: DNS domain name */ -#define NM_VPN_PLUGIN_IP6_CONFIG_DOMAIN "domain" - -/* array of strings: DNS domain names */ -#define NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS "domains" - -/* [ip6 routes]: custom routes the client should apply, in the format used - * by nm_utils_ip6_routes_to/from_gvalue - */ -#define NM_VPN_PLUGIN_IP6_CONFIG_ROUTES "routes" - -/* whether the previous IP6 routing configuration should be preserved. */ -#define NM_VPN_PLUGIN_IP6_CONFIG_PRESERVE_ROUTES "preserve-routes" - -/* boolean: prevent this VPN connection from ever getting the default route */ -#define NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT "never-default" - -#endif /* __NM_VPN_DBUS_INTERFACE_H__ */ diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c deleted file mode 100644 index e68bdc24ee..0000000000 --- a/libnm-core/nm-vpn-editor-plugin.c +++ /dev/null @@ -1,518 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2008 - 2010 Red Hat, Inc. - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-vpn-editor-plugin.h" - -#include -#include - -#include "nm-core-internal.h" - -/*****************************************************************************/ - -static void nm_vpn_editor_plugin_default_init(NMVpnEditorPluginInterface *iface); - -G_DEFINE_INTERFACE(NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT) - -static void -nm_vpn_editor_plugin_default_init(NMVpnEditorPluginInterface *iface) -{ - /** - * NMVpnEditorPlugin:name: - * - * Short display name of the VPN plugin. - */ - g_object_interface_install_property( - iface, - g_param_spec_string(NM_VPN_EDITOR_PLUGIN_NAME, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - /** - * NMVpnEditorPlugin:description: - * - * Longer description of the VPN plugin. - */ - g_object_interface_install_property( - iface, - g_param_spec_string(NM_VPN_EDITOR_PLUGIN_DESCRIPTION, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - /** - * NMVpnEditorPlugin:service: - * - * D-Bus service name of the plugin's VPN service. - */ - g_object_interface_install_property( - iface, - g_param_spec_string(NM_VPN_EDITOR_PLUGIN_SERVICE, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); -} - -/*****************************************************************************/ - -typedef struct { - NMVpnPluginInfo *plugin_info; -} NMVpnEditorPluginPrivate; - -static void -_private_destroy(gpointer data) -{ - NMVpnEditorPluginPrivate *priv = data; - - if (priv->plugin_info) - g_object_remove_weak_pointer((GObject *) priv->plugin_info, - (gpointer *) &priv->plugin_info); - - g_slice_free(NMVpnEditorPluginPrivate, priv); -} - -static NMVpnEditorPluginPrivate * -_private_get(NMVpnEditorPlugin *plugin, gboolean create) -{ - static GQuark quark = 0; - NMVpnEditorPluginPrivate *priv; - - nm_assert(NM_IS_VPN_EDITOR_PLUGIN(plugin)); - - if (G_UNLIKELY(quark == 0)) - quark = g_quark_from_string("nm-vpn-editor-plugin-private"); - - priv = g_object_get_qdata((GObject *) plugin, quark); - if (G_LIKELY(priv)) - return priv; - if (!create) - return NULL; - priv = g_slice_new0(NMVpnEditorPluginPrivate); - g_object_set_qdata_full((GObject *) plugin, quark, priv, _private_destroy); - return priv; -} - -#define NM_VPN_EDITOR_PLUGIN_GET_PRIVATE(plugin) _private_get(plugin, TRUE) -#define NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE(plugin) _private_get(plugin, FALSE) - -/*****************************************************************************/ - -/** - * nm_vpn_editor_plugin_get_plugin_info: - * @plugin: the #NMVpnEditorPlugin instance - * - * Returns: (transfer none): if set, return the #NMVpnPluginInfo instance. - * - * Since: 1.4 - */ -NMVpnPluginInfo * -nm_vpn_editor_plugin_get_plugin_info(NMVpnEditorPlugin *plugin) -{ - NMVpnEditorPluginPrivate *priv; - - g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); - - priv = NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE(plugin); - return priv ? priv->plugin_info : NULL; -} - -/** - * nm_vpn_editor_plugin_set_plugin_info: - * @plugin: the #NMVpnEditorPlugin instance - * @plugin_info: (allow-none): a #NMVpnPluginInfo instance or %NULL - * - * Set or clear the plugin-info instance. - * This takes a weak reference on @plugin_info, to avoid circular - * reference as the plugin-info might also reference the editor-plugin. - * - * Since: 1.4 - */ -void -nm_vpn_editor_plugin_set_plugin_info(NMVpnEditorPlugin *plugin, NMVpnPluginInfo *plugin_info) -{ - NMVpnEditorPluginInterface *interface; - NMVpnEditorPluginPrivate * priv; - - g_return_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin)); - - if (!plugin_info) { - priv = NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE(plugin); - if (!priv) - return; - } else { - g_return_if_fail(NM_IS_VPN_PLUGIN_INFO(plugin_info)); - priv = NM_VPN_EDITOR_PLUGIN_GET_PRIVATE(plugin); - } - - if (priv->plugin_info == plugin_info) - return; - if (priv->plugin_info) - g_object_remove_weak_pointer((GObject *) priv->plugin_info, - (gpointer *) &priv->plugin_info); - priv->plugin_info = plugin_info; - if (priv->plugin_info) - g_object_add_weak_pointer((GObject *) priv->plugin_info, (gpointer *) &priv->plugin_info); - - if (plugin_info) { - interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin); - if (interface->notify_plugin_info_set) - interface->notify_plugin_info_set(plugin, plugin_info); - } -} - -/*****************************************************************************/ - -/** - * nm_vpn_editor_plugin_get_vt: - * @plugin: the #NMVpnEditorPlugin - * @vt: (out): buffer to be filled with the VT table of the plugin - * @vt_size: the size of the buffer. Can be 0 to only query the - * size of plugin's VT. - * - * Returns an opaque VT function table for the plugin to extend - * functionality. The actual meaning of NMVpnEditorPluginVT is not - * defined in public API of libnm, instead it must be agreed by - * both the plugin and the caller. See the header-only file - * 'nm-vpn-editor-plugin-call.h' which defines the meaning. - * - * Returns: the actual size of the @plugin's virtual function table. - * - * Since: 1.4 - **/ -gsize -nm_vpn_editor_plugin_get_vt(NMVpnEditorPlugin *plugin, NMVpnEditorPluginVT *vt, gsize vt_size) -{ - const NMVpnEditorPluginVT * p_vt = NULL; - gsize p_vt_size = 0; - NMVpnEditorPluginInterface *interface; - - g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), 0); - - if (vt_size) { - g_return_val_if_fail(vt, 0); - memset(vt, 0, vt_size); - } - - interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin); - if (interface->get_vt) { - p_vt = interface->get_vt(plugin, &p_vt_size); - if (!p_vt) - p_vt_size = 0; - g_return_val_if_fail(p_vt_size, 0); - memcpy(vt, p_vt, MIN(vt_size, p_vt_size)); - } - - return p_vt_size; -} - -/*****************************************************************************/ - -static NMVpnEditorPlugin * -_nm_vpn_editor_plugin_load(const char * plugin_name, - gboolean do_file_checks, - const char * check_service, - int check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - GError ** error) -{ - void * dl_module = NULL; - gboolean loaded_before; - NMVpnEditorPluginFactory factory = NULL; - gs_unref_object NMVpnEditorPlugin *editor_plugin = NULL; - gs_free char * plugin_filename_free = NULL; - const char * plugin_filename; - gs_free_error GError *factory_error = NULL; - gs_free char * plug_name = NULL; - gs_free char * plug_service = NULL; - - g_return_val_if_fail(plugin_name && *plugin_name, NULL); - - /* if @do_file_checks is FALSE, we pass plugin_name directly to - * g_module_open(). - * - * Otherwise, we allow for library names without path component. - * In which case, we prepend the plugin directory and form an - * absolute path. In that case, we perform checks on the file. - * - * One exception is that we don't allow for the "la" suffix. The - * reason is that g_module_open() interprets files with this extension - * special and we don't want that. */ - plugin_filename = plugin_name; - if (do_file_checks) { - if (!strchr(plugin_name, '/') && !g_str_has_suffix(plugin_name, ".la")) { - plugin_filename_free = g_module_build_path(NMVPNDIR, plugin_name); - plugin_filename = plugin_filename_free; - } - } - - dl_module = dlopen(plugin_filename, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); - if (!dl_module && do_file_checks) { - /* If the module is already loaded, we skip the file checks. - * - * _nm_utils_check_module_file() fails with ENOENT if the plugin file - * does not exist. That is relevant, because nm-applet checks for that. */ - if (!_nm_utils_check_module_file(plugin_filename, - check_owner, - check_file, - user_data, - error)) - return NULL; - } - - if (dl_module) { - loaded_before = TRUE; - } else { - loaded_before = FALSE; - dl_module = dlopen(plugin_filename, RTLD_LAZY | RTLD_LOCAL); - } - - if (!dl_module) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("cannot load plugin \"%s\": %s"), - plugin_name, - dlerror() ?: "unknown reason"); - return NULL; - } - - factory = dlsym(dl_module, "nm_vpn_editor_plugin_factory"); - if (!factory) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("failed to load nm_vpn_editor_plugin_factory() from %s (%s)"), - plugin_name, - dlerror()); - dlclose(dl_module); - return NULL; - } - - editor_plugin = factory(&factory_error); - - if (loaded_before) { - /* we want to leak the library, because the factory will register glib - * types, which cannot be unregistered. - * - * However, if the library was already loaded before, we want to return - * our part of the reference count. */ - dlclose(dl_module); - } - - if (!editor_plugin) { - if (factory_error) { - g_propagate_error(error, factory_error); - factory_error = NULL; - } else { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("unknown error initializing plugin %s"), - plugin_name); - } - return NULL; - } - - g_return_val_if_fail(G_IS_OBJECT(editor_plugin), NULL); - - /* Validate plugin properties */ - g_object_get(G_OBJECT(editor_plugin), - NM_VPN_EDITOR_PLUGIN_NAME, - &plug_name, - NM_VPN_EDITOR_PLUGIN_SERVICE, - &plug_service, - NULL); - - if (!plug_name || !*plug_name) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("cannot load VPN plugin in '%s': missing plugin name"), - plugin_name); - return NULL; - } - if (check_service && g_strcmp0(plug_service, check_service) != 0) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("cannot load VPN plugin in '%s': invalid service name"), - plugin_name); - return NULL; - } - - return g_steal_pointer(&editor_plugin); -} - -/** - * nm_vpn_editor_plugin_load_from_file: - * @plugin_name: The path or name of the shared library to load. - * The path must either be an absolute filename to an existing file. - * Alternatively, it can be the name (without path) of a library in the - * plugin directory of NetworkManager. - * @check_service: if not-null, check that the loaded plugin advertises - * the given service. - * @check_owner: if non-negative, check whether the file is owned - * by UID @check_owner or by root. In this case also check that - * the file is not writable by anybody else. - * @check_file: (scope call): optional callback to validate the file prior to - * loading the shared library. - * @user_data: user data for @check_file - * @error: on failure the error reason. - * - * Load the shared library @plugin_name and create a new - * #NMVpnEditorPlugin instance via the #NMVpnEditorPluginFactory - * function. - * - * If @plugin_name is not an absolute path name, it assumes the file - * is in the plugin directory of NetworkManager. In any case, the call - * will do certain checks on the file before passing it to dlopen. - * A consequence for that is, that you cannot omit the ".so" suffix - * as you could for nm_vpn_editor_plugin_load(). - * - * Returns: (transfer full): a new plugin instance or %NULL on error. - * - * Since: 1.2 - */ -NMVpnEditorPlugin * -nm_vpn_editor_plugin_load_from_file(const char * plugin_name, - const char * check_service, - int check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - GError ** error) -{ - return _nm_vpn_editor_plugin_load(plugin_name, - TRUE, - check_service, - check_owner, - check_file, - user_data, - error); -} - -/** - * nm_vpn_editor_plugin_load: - * @plugin_name: The name of the shared library to load. - * This path will be directly passed to dlopen() without - * further checks. - * @check_service: if not-null, check that the loaded plugin advertises - * the given service. - * @error: on failure the error reason. - * - * Load the shared library @plugin_name and create a new - * #NMVpnEditorPlugin instance via the #NMVpnEditorPluginFactory - * function. - * - * This is similar to nm_vpn_editor_plugin_load_from_file(), but - * it does no validation of the plugin name, instead passes it directly - * to dlopen(). If you have the full path to a plugin file, - * nm_vpn_editor_plugin_load_from_file() is preferred. - * - * Returns: (transfer full): a new plugin instance or %NULL on error. - * - * Since: 1.4 - */ -NMVpnEditorPlugin * -nm_vpn_editor_plugin_load(const char *plugin_name, const char *check_service, GError **error) -{ - return _nm_vpn_editor_plugin_load(plugin_name, FALSE, check_service, -1, NULL, NULL, error); -} - -/*****************************************************************************/ - -/** - * nm_vpn_editor_plugin_get_editor: - * @plugin: the #NMVpnEditorPlugin - * @connection: the #NMConnection to be edited - * @error: on return, an error or %NULL - * - * Returns: (transfer full): a new #NMVpnEditor or %NULL on error - */ -NMVpnEditor * -nm_vpn_editor_plugin_get_editor(NMVpnEditorPlugin *plugin, NMConnection *connection, GError **error) -{ - g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); - - return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->get_editor(plugin, connection, error); -} - -NMVpnEditorPluginCapability -nm_vpn_editor_plugin_get_capabilities(NMVpnEditorPlugin *plugin) -{ - g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), 0); - - return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->get_capabilities(plugin); -} - -/** - * nm_vpn_editor_plugin_import: - * @plugin: the #NMVpnEditorPlugin - * @path: full path to the file to attempt to read into a new #NMConnection - * @error: on return, an error or %NULL - * - * Returns: (transfer full): a new #NMConnection imported from @path, or %NULL - * on error or if the file at @path was not recognized by this plugin - */ -NMConnection * -nm_vpn_editor_plugin_import(NMVpnEditorPlugin *plugin, const char *path, GError **error) -{ - g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); - - if (nm_vpn_editor_plugin_get_capabilities(plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) { - g_return_val_if_fail(NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->import_from_file != NULL, - NULL); - return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->import_from_file(plugin, path, error); - } - - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("the plugin does not support import capability")); - return NULL; -} - -gboolean -nm_vpn_editor_plugin_export(NMVpnEditorPlugin *plugin, - const char * path, - NMConnection * connection, - GError ** error) -{ - g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), FALSE); - - if (nm_vpn_editor_plugin_get_capabilities(plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) { - g_return_val_if_fail(NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->export_to_file != NULL, - FALSE); - return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->export_to_file(plugin, - path, - connection, - error); - } - - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("the plugin does not support export capability")); - return FALSE; -} - -char * -nm_vpn_editor_plugin_get_suggested_filename(NMVpnEditorPlugin *plugin, NMConnection *connection) -{ - g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); - - if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->get_suggested_filename) - return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->get_suggested_filename(plugin, - connection); - return NULL; -} diff --git a/libnm-core/nm-vpn-editor-plugin.h b/libnm-core/nm-vpn-editor-plugin.h deleted file mode 100644 index e318da07b8..0000000000 --- a/libnm-core/nm-vpn-editor-plugin.h +++ /dev/null @@ -1,159 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2008 - 2015 Red Hat, Inc. - */ - -#ifndef __NM_VPN_EDITOR_PLUGIN_H__ -#define __NM_VPN_EDITOR_PLUGIN_H__ - -#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) - #error "Only can be included directly." -#endif - -#include -#include - -#include "nm-connection.h" -#include "nm-utils.h" - -G_BEGIN_DECLS - -typedef struct _NMVpnPluginInfo NMVpnPluginInfo; - -typedef struct _NMVpnEditorPlugin NMVpnEditorPlugin; -typedef struct _NMVpnEditor NMVpnEditor; - -/* Plugin's factory function that returns a GObject that implements - * NMVpnEditorPlugin. - */ -#ifndef __GI_SCANNER__ -typedef NMVpnEditorPlugin *(*NMVpnEditorPluginFactory)(GError **error); -NMVpnEditorPlugin *nm_vpn_editor_plugin_factory(GError **error); -#endif - -/*****************************************************************************/ -/* Editor plugin interface */ -/*****************************************************************************/ - -#define NM_TYPE_VPN_EDITOR_PLUGIN (nm_vpn_editor_plugin_get_type()) -#define NM_VPN_EDITOR_PLUGIN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_VPN_EDITOR_PLUGIN, NMVpnEditorPlugin)) -#define NM_IS_VPN_EDITOR_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_VPN_EDITOR_PLUGIN)) -#define NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(obj) \ - (G_TYPE_INSTANCE_GET_INTERFACE((obj), NM_TYPE_VPN_EDITOR_PLUGIN, NMVpnEditorPluginInterface)) - -/** - * NMVpnEditorPluginCapability: - * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE: unknown or no capability - * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT: the plugin can import new connections - * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT: the plugin can export connections - * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6: the plugin supports IPv6 addressing - * - * Flags that indicate certain capabilities of the plugin to editor programs. - **/ -typedef enum /*< flags >*/ { - NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE = 0x00, - NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT = 0x01, - NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT = 0x02, - NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6 = 0x04 -} NMVpnEditorPluginCapability; - -/* Short display name of the VPN plugin */ -#define NM_VPN_EDITOR_PLUGIN_NAME "name" - -/* Longer description of the VPN plugin */ -#define NM_VPN_EDITOR_PLUGIN_DESCRIPTION "description" - -/* D-Bus service name of the plugin's VPN service */ -#define NM_VPN_EDITOR_PLUGIN_SERVICE "service" - -typedef struct _NMVpnEditorPluginVT NMVpnEditorPluginVT; - -/** - * NMVpnEditorPluginInterface: - * @g_iface: the parent interface - * @get_editor: returns an #NMVpnEditor, pre-filled with values from @connection - * if non-%NULL. - * @get_capabilities: returns a bitmask of capabilities. - * @import_from_file: Try to import a connection from the specified path. On - * success, return a partial #NMConnection object. On error, return %NULL and - * set @error with additional information. Note that @error can be %NULL, in - * which case no additional error information should be provided. - * @export_to_file: Export the given connection to the specified path. Return - * %TRUE on success. On error, return %FALSE and set @error with additional - * error information. Note that @error can be %NULL, in which case no - * additional error information should be provided. - * @get_suggested_filename: For a given connection, return a suggested file - * name. Returned value will be %NULL or a suggested file name to be freed by - * the caller. - * @notify_plugin_info_set: A callback to be called when the plugin info is set. - * @get_vt: return a virtual function table to implement further functions in - * the plugin, without requiring to update libnm. Used by nm_vpn_editor_plugin_get_vt(). - * - * Interface for VPN editor plugins. - */ -typedef struct { - GTypeInterface g_iface; - - NMVpnEditor *(*get_editor)(NMVpnEditorPlugin *plugin, NMConnection *connection, GError **error); - - NMVpnEditorPluginCapability (*get_capabilities)(NMVpnEditorPlugin *plugin); - - NMConnection *(*import_from_file)(NMVpnEditorPlugin *plugin, const char *path, GError **error); - - gboolean (*export_to_file)(NMVpnEditorPlugin *plugin, - const char * path, - NMConnection * connection, - GError ** error); - - char *(*get_suggested_filename)(NMVpnEditorPlugin *plugin, NMConnection *connection); - - void (*notify_plugin_info_set)(NMVpnEditorPlugin *plugin, NMVpnPluginInfo *plugin_info); - - const NMVpnEditorPluginVT *(*get_vt)(NMVpnEditorPlugin *plugin, gsize *out_vt_size); -} NMVpnEditorPluginInterface; - -GType nm_vpn_editor_plugin_get_type(void); - -NMVpnEditor *nm_vpn_editor_plugin_get_editor(NMVpnEditorPlugin *plugin, - NMConnection * connection, - GError ** error); - -NMVpnEditorPluginCapability nm_vpn_editor_plugin_get_capabilities(NMVpnEditorPlugin *plugin); - -NM_AVAILABLE_IN_1_4 -gsize -nm_vpn_editor_plugin_get_vt(NMVpnEditorPlugin *plugin, NMVpnEditorPluginVT *vt, gsize vt_size); - -NMConnection * - nm_vpn_editor_plugin_import(NMVpnEditorPlugin *plugin, const char *path, GError **error); -gboolean nm_vpn_editor_plugin_export(NMVpnEditorPlugin *plugin, - const char * path, - NMConnection * connection, - GError ** error); -char * nm_vpn_editor_plugin_get_suggested_filename(NMVpnEditorPlugin *plugin, - NMConnection * connection); - -NM_AVAILABLE_IN_1_2 -NMVpnEditorPlugin *nm_vpn_editor_plugin_load_from_file(const char * plugin_name, - const char * check_service, - int check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - GError ** error); - -NM_AVAILABLE_IN_1_4 -NMVpnEditorPlugin * -nm_vpn_editor_plugin_load(const char *plugin_name, const char *check_service, GError **error); - -NM_AVAILABLE_IN_1_4 -NMVpnPluginInfo *nm_vpn_editor_plugin_get_plugin_info(NMVpnEditorPlugin *plugin); -NM_AVAILABLE_IN_1_4 -void nm_vpn_editor_plugin_set_plugin_info(NMVpnEditorPlugin *plugin, NMVpnPluginInfo *plugin_info); - -#include "nm-vpn-plugin-info.h" - -G_END_DECLS - -#endif /* __NM_VPN_EDITOR_PLUGIN_H__ */ diff --git a/libnm-core/nm-vpn-plugin-info.c b/libnm-core/nm-vpn-plugin-info.c deleted file mode 100644 index cb739510f1..0000000000 --- a/libnm-core/nm-vpn-plugin-info.c +++ /dev/null @@ -1,1354 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-vpn-plugin-info.h" - -#include - -#include "nm-errors.h" -#include "nm-core-internal.h" - -#define DEFAULT_DIR_ETC NMCONFDIR "/VPN" -#define DEFAULT_DIR_LIB NMLIBDIR "/VPN" - -enum { - PROP_0, - PROP_NAME, - PROP_FILENAME, - PROP_KEYFILE, - - LAST_PROP, -}; - -typedef struct { - char * filename; - char * name; - char * service; - char * auth_dialog; - char ** aliases; - GKeyFile *keyfile; - - /* It is convenient for nm_vpn_plugin_info_lookup_property() to return a const char *, - * contrary to what g_key_file_get_string() does. Hence we must cache the returned - * value somewhere... let's put it in an internal hash table. - * This contains a clone of all the strings in keyfile. */ - GHashTable *keys; - - gboolean editor_plugin_loaded; - NMVpnEditorPlugin *editor_plugin; -} NMVpnPluginInfoPrivate; - -/** - * NMVpnPluginInfo: - */ -struct _NMVpnPluginInfo { - GObject parent; - NMVpnPluginInfoPrivate _priv; -}; - -struct _NMVpnPluginInfoClass { - GObjectClass parent; -}; - -#define NM_VPN_PLUGIN_INFO_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMVpnPluginInfo, NM_IS_VPN_PLUGIN_INFO) - -static void nm_vpn_plugin_info_initable_iface_init(GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE(NMVpnPluginInfo, - nm_vpn_plugin_info, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, - nm_vpn_plugin_info_initable_iface_init);) - -/*****************************************************************************/ - -static NMVpnPluginInfo *_list_find_by_service(GSList *list, const char *name, const char *service); - -/*****************************************************************************/ - -/** - * nm_vpn_plugin_info_validate_filename: - * @filename: the filename to check - * - * Regular name files have a certain pattern. That basically means - * they have the file extension "name". Check if @filename - * is valid according to that pattern. - * - * Since: 1.2 - */ -gboolean -nm_vpn_plugin_info_validate_filename(const char *filename) -{ - if (!filename || !g_str_has_suffix(filename, ".name")) - return FALSE; - - /* originally, we didn't do further checks... but here we go. */ - if (filename[0] == '.') { - /* this also rejects name ".name" alone. */ - return FALSE; - } - return TRUE; -} - -static gboolean -nm_vpn_plugin_info_check_file_full(const char * filename, - gboolean check_absolute, - gboolean do_validate_filename, - gint64 check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - struct stat * out_st, - GError ** error) -{ - if (!filename || !*filename) { - g_set_error(error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_FAILED, _("missing filename")); - return FALSE; - } - - if (check_absolute && !g_path_is_absolute(filename)) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("filename must be an absolute path (%s)"), - filename); - return FALSE; - } - - if (do_validate_filename && !nm_vpn_plugin_info_validate_filename(filename)) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("filename has invalid format (%s)"), - filename); - return FALSE; - } - - return _nm_utils_check_file(filename, check_owner, check_file, user_data, out_st, error); -} - -/** - * _nm_vpn_plugin_info_check_file: - * @filename: the file to check - * @check_absolute: if %TRUE, only allow absolute path names. - * @do_validate_filename: if %TRUE, only accept the filename if - * nm_vpn_plugin_info_validate_filename() succeeds. - * @check_owner: if non-negative, only accept the file if the - * owner UID is equal to @check_owner or if the owner is 0. - * In this case, also check that the file is not writable by - * other users. - * @check_file: pass a callback to do your own validation. - * @user_data: user data for @check_file. - * @error: (allow-none) (out): the error reason if the check fails. - * - * Check whether the file exists and is a valid name file (in keyfile format). - * Additionally, also check for file permissions. - * - * Returns: %TRUE if a file @filename exists and has valid permissions. - * - * Since: 1.2 - */ -gboolean -_nm_vpn_plugin_info_check_file(const char * filename, - gboolean check_absolute, - gboolean do_validate_filename, - gint64 check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data, - GError ** error) -{ - return nm_vpn_plugin_info_check_file_full(filename, - check_absolute, - do_validate_filename, - check_owner, - check_file, - user_data, - NULL, - error); -} - -typedef struct { - NMVpnPluginInfo *plugin_info; - struct stat stat; -} LoadDirInfo; - -static int -_sort_files(LoadDirInfo *a, LoadDirInfo *b) -{ - time_t ta, tb; - - ta = MAX(a->stat.st_mtime, a->stat.st_ctime); - tb = MAX(b->stat.st_mtime, b->stat.st_ctime); - if (ta < tb) - return 1; - if (ta > tb) - return -1; - return g_strcmp0(nm_vpn_plugin_info_get_filename(a->plugin_info), - nm_vpn_plugin_info_get_filename(b->plugin_info)); -} - -/** - * _nm_vpn_plugin_info_get_default_dir_etc: - * - * Returns: (transfer none): compile time constant of the default - * VPN plugin directory. - */ -const char * -_nm_vpn_plugin_info_get_default_dir_etc() -{ - return DEFAULT_DIR_ETC; -} - -/** - * _nm_vpn_plugin_info_get_default_dir_lib: - * - * Returns: (transfer none): compile time constant of the default - * VPN plugin directory. - */ -const char * -_nm_vpn_plugin_info_get_default_dir_lib() -{ - return DEFAULT_DIR_LIB; -} - -/** - * _nm_vpn_plugin_info_get_default_dir_user: - * - * Returns: The user can specify a different directory for VPN plugins - * by setting NM_VPN_PLUGIN_DIR environment variable. Return - * that directory. - */ -const char * -_nm_vpn_plugin_info_get_default_dir_user() -{ - return nm_str_not_empty(g_getenv("NM_VPN_PLUGIN_DIR")); -} - -/** - * _nm_vpn_plugin_info_list_load_dir: - * @dirname: the name of the directory to load. - * @do_validate_filename: only consider filenames that have a certain - * pattern (i.e. end with ".name"). - * @check_owner: if set to a non-negative number, check that the file - * owner is either the same uid or 0. In that case, also check - * that the file is not writable by group or other. - * @check_file: (allow-none): callback to check whether the file is valid. - * @user_data: data for @check_file - * - * Iterate over the content of @dirname and load name files. - * - * Returns: (transfer full) (element-type NMVpnPluginInfo): list of loaded plugin infos. - */ -GSList * -_nm_vpn_plugin_info_list_load_dir(const char * dirname, - gboolean do_validate_filename, - gint64 check_owner, - NMUtilsCheckFilePredicate check_file, - gpointer user_data) -{ - GDir * dir; - const char *fn; - GArray * array; - GSList * res = NULL; - guint i; - - g_return_val_if_fail(dirname, NULL); - - if (!dirname[0]) - return NULL; - - dir = g_dir_open(dirname, 0, NULL); - if (!dir) - return NULL; - - array = g_array_new(FALSE, FALSE, sizeof(LoadDirInfo)); - - while ((fn = g_dir_read_name(dir))) { - gs_free char *filename = NULL; - LoadDirInfo info = {0}; - - filename = g_build_filename(dirname, fn, NULL); - if (nm_vpn_plugin_info_check_file_full(filename, - FALSE, - do_validate_filename, - check_owner, - check_file, - user_data, - &info.stat, - NULL)) { - info.plugin_info = nm_vpn_plugin_info_new_from_file(filename, NULL); - if (info.plugin_info) { - g_array_append_val(array, info); - continue; - } - } - } - g_dir_close(dir); - - /* sort the files so that we have a stable behavior. The directory might contain - * duplicate VPNs, so while nm_vpn_plugin_info_list_load() would load them all, the - * caller probably wants to reject duplicates. Having a stable order means we always - * reject the same files in face of duplicates. */ - g_array_sort(array, (GCompareFunc) _sort_files); - - for (i = 0; i < array->len; i++) - res = g_slist_prepend(res, g_array_index(array, LoadDirInfo, i).plugin_info); - - g_array_unref(array); - - return g_slist_reverse(res); -} - -/** - * nm_vpn_plugin_info_list_load: - * - * Returns: (element-type NMVpnPluginInfo) (transfer full): list of plugins - * loaded from the default directories rejecting duplicates. - * - * Since: 1.2 - */ -GSList * -nm_vpn_plugin_info_list_load() -{ - int i; - gint64 uid; - GSList * list = NULL; - GSList * infos, *info; - const char *const dir[] = { - /* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with - * preference to the former. - * - * load user directory with highest priority. */ - _nm_vpn_plugin_info_get_default_dir_user(), - - /* lib directory has higher priority then etc. The reason is that - * etc is deprecated and used by old plugins. We expect newer plugins - * to install their file in lib, where they have higher priority. - * - * Optimally, there are no duplicates anyway, so it doesn't really matter. */ - _nm_vpn_plugin_info_get_default_dir_lib(), - _nm_vpn_plugin_info_get_default_dir_etc(), - }; - - uid = getuid(); - - for (i = 0; i < G_N_ELEMENTS(dir); i++) { - if (!dir[i] || nm_utils_strv_find_first((char **) dir, i, dir[i]) >= 0) - continue; - - infos = _nm_vpn_plugin_info_list_load_dir(dir[i], TRUE, uid, NULL, NULL); - - for (info = infos; info; info = info->next) - nm_vpn_plugin_info_list_add(&list, info->data, NULL); - - g_slist_free_full(infos, g_object_unref); - } - return list; -} - -/** - * nm_vpn_plugin_info_new_search_file: - * @name: (allow-none): the name to search for. Either @name or @service - * must be present. - * @service: (allow-none): the service to search for. Either @name or - * @service must be present. - * - * This has the same effect as doing a full nm_vpn_plugin_info_list_load() - * followed by a search for the first matching VPN plugin info that has the - * given @name and/or @service. - * - * Returns: (transfer full): a newly created instance of plugin info - * or %NULL if no matching value was found. - * - * Since: 1.4 - */ -NMVpnPluginInfo * -nm_vpn_plugin_info_new_search_file(const char *name, const char *service) -{ - NMVpnPluginInfo *info; - GSList * infos; - - if (!name && !service) - g_return_val_if_reached(NULL); - - infos = nm_vpn_plugin_info_list_load(); - info = nm_g_object_ref(_list_find_by_service(infos, name, service)); - g_slist_free_full(infos, g_object_unref); - return info; -} - -/*****************************************************************************/ - -static gboolean -_check_no_conflict(NMVpnPluginInfo *i1, NMVpnPluginInfo *i2, GError **error) -{ - NMVpnPluginInfoPrivate *priv1, *priv2; - uint i; - struct { - const char *group; - const char *key; - } check_list[] = { - {NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "service"}, - {NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM, "plugin"}, - {NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "properties"}, - }; - - priv1 = NM_VPN_PLUGIN_INFO_GET_PRIVATE(i1); - priv2 = NM_VPN_PLUGIN_INFO_GET_PRIVATE(i2); - - for (i = 0; i < G_N_ELEMENTS(check_list); i++) { - gs_free NMUtilsStrStrDictKey *k = NULL; - const char * s1, *s2; - - k = _nm_utils_strstrdictkey_create(check_list[i].group, check_list[i].key); - s1 = g_hash_table_lookup(priv1->keys, k); - if (!s1) - continue; - s2 = g_hash_table_lookup(priv2->keys, k); - if (!s2) - continue; - - if (strcmp(s1, s2) == 0) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("there exists a conflicting plugin (%s) that has the same %s.%s value"), - priv2->name, - check_list[i].group, - check_list[i].key); - return FALSE; - } - } - return TRUE; -} - -/** - * nm_vpn_plugin_info_list_add: - * @list: (element-type NMVpnPluginInfo): list of plugins - * @plugin_info: instance to add - * @error: failure reason - * - * Returns: %TRUE if the plugin was added to @list. This will fail - * to add duplicate plugins. - * - * Since: 1.2 - */ -gboolean -nm_vpn_plugin_info_list_add(GSList **list, NMVpnPluginInfo *plugin_info, GError **error) -{ - GSList * iter; - const char *name; - - g_return_val_if_fail(list, FALSE); - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(plugin_info), FALSE); - - name = nm_vpn_plugin_info_get_name(plugin_info); - for (iter = *list; iter; iter = iter->next) { - if (iter->data == plugin_info) - return TRUE; - - if (strcmp(nm_vpn_plugin_info_get_name(iter->data), name) == 0) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("there exists a conflicting plugin with the same name (%s)"), - name); - return FALSE; - } - - /* the plugin must have unique values for certain properties. E.g. two different - * plugins cannot share the same service type. */ - if (!_check_no_conflict(plugin_info, iter->data, error)) - return FALSE; - } - - *list = g_slist_append(*list, g_object_ref(plugin_info)); - return TRUE; -} - -/** - * nm_vpn_plugin_info_list_remove: - * @list: (element-type NMVpnPluginInfo): list of plugins - * @plugin_info: instance - * - * Remove @plugin_info from @list. - * - * Returns: %TRUE if @plugin_info was in @list and successfully removed. - * - * Since: 1.2 - */ -gboolean -nm_vpn_plugin_info_list_remove(GSList **list, NMVpnPluginInfo *plugin_info) -{ - g_return_val_if_fail(list, FALSE); - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(plugin_info), FALSE); - - if (!g_slist_find(*list, plugin_info)) - return FALSE; - - *list = g_slist_remove(*list, plugin_info); - g_object_unref(plugin_info); - return TRUE; -} - -/** - * nm_vpn_plugin_info_list_find_by_name: - * @list: (element-type NMVpnPluginInfo): list of plugins - * @name: name to search - * - * Returns: (transfer none): the first plugin with a matching @name (or %NULL). - * - * Since: 1.2 - */ -NMVpnPluginInfo * -nm_vpn_plugin_info_list_find_by_name(GSList *list, const char *name) -{ - GSList *iter; - - if (!name) - g_return_val_if_reached(NULL); - - for (iter = list; iter; iter = iter->next) { - if (strcmp(nm_vpn_plugin_info_get_name(iter->data), name) == 0) - return iter->data; - } - return NULL; -} - -/** - * nm_vpn_plugin_info_list_find_by_filename: - * @list: (element-type NMVpnPluginInfo): list of plugins - * @filename: filename to search - * - * Returns: (transfer none): the first plugin with a matching @filename (or %NULL). - * - * Since: 1.2 - */ -NMVpnPluginInfo * -nm_vpn_plugin_info_list_find_by_filename(GSList *list, const char *filename) -{ - GSList *iter; - - if (!filename) - g_return_val_if_reached(NULL); - - for (iter = list; iter; iter = iter->next) { - if (g_strcmp0(nm_vpn_plugin_info_get_filename(iter->data), filename) == 0) - return iter->data; - } - return NULL; -} - -static NMVpnPluginInfo * -_list_find_by_service(GSList *list, const char *name, const char *service) -{ - for (; list; list = list->next) { - NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(list->data); - - if (name && !nm_streq(name, priv->name)) - continue; - if (service && !nm_streq(priv->service, service) - && (nm_utils_strv_find_first(priv->aliases, -1, service) < 0)) - continue; - - return list->data; - } - return NULL; -} - -/** - * nm_vpn_plugin_info_list_find_by_service: - * @list: (element-type NMVpnPluginInfo): list of plugins - * @service: service to search. This can be the main service-type - * or one of the provided aliases. - * - * Returns: (transfer none): the first plugin with a matching @service (or %NULL). - * - * Since: 1.2 - */ -NMVpnPluginInfo * -nm_vpn_plugin_info_list_find_by_service(GSList *list, const char *service) -{ - if (!service) - g_return_val_if_reached(NULL); - return _list_find_by_service(list, NULL, service); -} - -/* known_names are well known short names for the service-type. They all implicitly - * have a prefix "org.freedesktop.NetworkManager." + known_name. */ -static const char *known_names[] = { - "openvpn", - "vpnc", - "pptp", - "openconnect", - "openswan", - "libreswan", - "strongswan", - "ssh", - "l2tp", - "iodine", - "fortisslvpn", -}; - -/** - * nm_vpn_plugin_info_list_find_service_type: - * @list: (element-type NMVpnPluginInfo): a possibly empty #GSList of #NMVpnPluginInfo instances - * @name: a name to lookup the service-type. - * - * A VPN plugin provides one or several service-types, like org.freedesktop.NetworkManager.libreswan - * Certain plugins provide more then one service type, via aliases (org.freedesktop.NetworkManager.openswan). - * This function looks up a service-type (or an alias) based on a name. - * - * Preferably, the name can be a full service-type/alias of an installed - * plugin. Otherwise, it can be the name of a VPN plugin (in which case, the - * primary, non-aliased service-type is returned). Otherwise, it can be - * one of several well known short-names (which is a hard-coded list of - * types in libnm). On success, this returns a full qualified service-type - * (or an alias). It doesn't say, that such an plugin is actually available, - * but it could be retrieved via nm_vpn_plugin_info_list_find_by_service(). - * - * Returns: (transfer full): the resolved service-type or %NULL on failure. - * - * Since: 1.4 - */ -char * -nm_vpn_plugin_info_list_find_service_type(GSList *list, const char *name) -{ - NMVpnPluginInfo *info; - char * n; - - if (!name) - g_return_val_if_reached(NULL); - if (!*name) - return NULL; - - /* First, try to interpret @name as a full service-type (or alias). */ - info = _list_find_by_service(list, NULL, name); - if (info) - return g_strdup(name); - - /* try to interpret @name as plugin name, in which case we return - * the main service-type (not an alias). */ - info = _list_find_by_service(list, name, NULL); - if (info) - return g_strdup(NM_VPN_PLUGIN_INFO_GET_PRIVATE(info)->service); - - /* check the hard-coded list of short-names. They all have the same - * well-known prefix org.freedesktop.NetworkManager and the name. */ - if (nm_utils_strv_find_first((char **) known_names, G_N_ELEMENTS(known_names), name) >= 0) - return g_strdup_printf("%s.%s", NM_DBUS_INTERFACE, name); - - /* try, if there exists a plugin with @name under org.freedesktop.NetworkManager. - * Allow this to be a valid abbreviation. */ - n = g_strdup_printf("%s.%s", NM_DBUS_INTERFACE, name); - if (_list_find_by_service(list, NULL, n)) - return n; - g_free(n); - - /* currently, VPN plugins have no way to define a short-name for their - * alias name, unless the alias name is prefixed by org.freedesktop.NetworkManager. */ - - return NULL; -} - -static const char * -_service_type_get_default_abbreviation(const char *service_type) -{ - if (!g_str_has_prefix(service_type, NM_DBUS_INTERFACE)) - return NULL; - service_type += NM_STRLEN(NM_DBUS_INTERFACE); - if (service_type[0] != '.') - return NULL; - service_type++; - if (!service_type[0]) - return NULL; - return service_type; -} - -/** - * nm_vpn_plugin_info_list_get_service_types: - * @list: (element-type NMVpnPluginInfo): a possibly empty #GSList of #NMVpnPluginInfo - * @only_existing: only include results that are actually in @list. - * Otherwise, the result is extended with a hard-code list or - * well-known plugins - * @with_abbreviations: if %FALSE, only full service types are returned. - * Otherwise, this also includes abbreviated names that can be used - * with nm_vpn_plugin_info_list_find_service_type(). - * - * Returns: (transfer full): a %NULL terminated strv list of strings. - * The list itself and the values must be freed with g_strfreev(). - * - * Since: 1.4 - */ -char ** -nm_vpn_plugin_info_list_get_service_types(GSList * list, - gboolean only_existing, - gboolean with_abbreviations) -{ - GSList * iter; - GPtrArray * l; - guint i, j; - const char *n; - - l = g_ptr_array_sized_new(20); - - for (iter = list; iter; iter = iter->next) { - NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(iter->data); - - g_ptr_array_add(l, g_strdup(priv->service)); - if (priv->aliases) { - for (i = 0; priv->aliases[i]; i++) - g_ptr_array_add(l, g_strdup(priv->aliases[i])); - } - - if (with_abbreviations) { - g_ptr_array_add(l, g_strdup(priv->name)); - n = _service_type_get_default_abbreviation(priv->service); - if (n) - g_ptr_array_add(l, g_strdup(n)); - for (i = 0; priv->aliases && priv->aliases[i]; i++) { - n = _service_type_get_default_abbreviation(priv->aliases[i]); - if (n) - g_ptr_array_add(l, g_strdup(n)); - } - } - } - - if (!only_existing) { - for (i = 0; i < G_N_ELEMENTS(known_names); i++) { - g_ptr_array_add(l, g_strdup_printf("%s.%s", NM_DBUS_INTERFACE, known_names[i])); - if (with_abbreviations) - g_ptr_array_add(l, g_strdup(known_names[i])); - } - } - - if (l->len <= 0) { - g_ptr_array_free(l, TRUE); - return g_new0(char *, 1); - } - - /* sort the result and remove duplicates. */ - g_ptr_array_sort(l, nm_strcmp_p); - for (i = 1, j = 1; i < l->len; i++) { - if (nm_streq(l->pdata[j - 1], l->pdata[i])) - g_free(l->pdata[i]); - else - l->pdata[j++] = l->pdata[i]; - } - - if (j == l->len) - g_ptr_array_add(l, NULL); - else - l->pdata[j] = NULL; - return (char **) g_ptr_array_free(l, FALSE); -} - -/*****************************************************************************/ - -/** - * nm_vpn_plugin_info_get_filename: - * @self: plugin info instance - * - * Returns: (transfer none): the filename. Can be %NULL. - * - * Since: 1.2 - */ -const char * -nm_vpn_plugin_info_get_filename(NMVpnPluginInfo *self) -{ - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - return NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->filename; -} - -/** - * nm_vpn_plugin_info_get_name: - * @self: plugin info instance - * - * Returns: (transfer none): the name. Cannot be %NULL. - * - * Since: 1.2 - */ -const char * -nm_vpn_plugin_info_get_name(NMVpnPluginInfo *self) -{ - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - return NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->name; -} - -/** - * nm_vpn_plugin_info_get_service: - * @self: plugin info instance - * - * Returns: (transfer none): the service. Cannot be %NULL. - * - * Since: 1.4 - */ -const char * -nm_vpn_plugin_info_get_service(NMVpnPluginInfo *self) -{ - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - return NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->service; -} - -/** - * nm_vpn_plugin_info_get_auth_dialog: - * @self: plugin info instance - * - * Returns: the absolute path to the auth-dialog helper or %NULL. - * - * Since: 1.4 - **/ -const char * -nm_vpn_plugin_info_get_auth_dialog(NMVpnPluginInfo *self) -{ - NMVpnPluginInfoPrivate *priv; - - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); - - if (G_UNLIKELY(priv->auth_dialog == NULL)) { - const char *s; - - s = g_hash_table_lookup( - priv->keys, - _nm_utils_strstrdictkey_static(NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "auth-dialog")); - if (!s || !s[0]) - priv->auth_dialog = g_strdup(""); - else if (g_path_is_absolute(s)) - priv->auth_dialog = g_strdup(s); - else { - /* for relative paths, we take the basename and assume it's in LIBEXECDIR. */ - gs_free char *prog_basename = g_path_get_basename(s); - - priv->auth_dialog = g_build_filename(LIBEXECDIR, prog_basename, NULL); - } - } - - return priv->auth_dialog[0] ? priv->auth_dialog : NULL; -} - -/** - * nm_vpn_plugin_info_supports_hints: - * @self: plugin info instance - * - * Returns: %TRUE if the supports hints for secret requests, otherwise %FALSE - * - * Since: 1.4 - */ -gboolean -nm_vpn_plugin_info_supports_hints(NMVpnPluginInfo *self) -{ - const char *s; - - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), FALSE); - - s = nm_vpn_plugin_info_lookup_property(self, - NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, - "supports-hints"); - return _nm_utils_ascii_str_to_bool(s, FALSE); -} - -/** - * nm_vpn_plugin_info_get_plugin: - * @self: plugin info instance - * - * Returns: (transfer none): the plugin. Can be %NULL. - * - * Since: 1.2 - */ -const char * -nm_vpn_plugin_info_get_plugin(NMVpnPluginInfo *self) -{ - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - return g_hash_table_lookup( - NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->keys, - _nm_utils_strstrdictkey_static(NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM, "plugin")); -} - -/** - * nm_vpn_plugin_info_get_program: - * @self: plugin info instance - * - * Returns: (transfer none): the program. Can be %NULL. - * - * Since: 1.2 - */ -const char * -nm_vpn_plugin_info_get_program(NMVpnPluginInfo *self) -{ - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - return g_hash_table_lookup( - NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->keys, - _nm_utils_strstrdictkey_static(NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "program")); -} - -/** - * nm_vpn_plugin_info_supports_multiple: - * @self: plugin info instance - * - * Returns: %TRUE if the service supports multiple instances with different bus names, otherwise %FALSE - * - * Since: 1.2 - */ -gboolean -nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self) -{ - const char *s; - - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), FALSE); - - s = nm_vpn_plugin_info_lookup_property(self, - NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, - "supports-multiple-connections"); - return _nm_utils_ascii_str_to_bool(s, FALSE); -} - -/** - * nm_vpn_plugin_info_get_aliases: - * @self: plugin info instance - * - * Returns: (array zero-terminated=1) (element-type utf8) (transfer none): - * the aliases from the name-file. - * - * Since: 1.4 - */ -const char *const * -nm_vpn_plugin_info_get_aliases(NMVpnPluginInfo *self) -{ - NMVpnPluginInfoPrivate *priv; - - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); - if (priv->aliases) - return (const char *const *) priv->aliases; - - /* For convenience, we always want to return non-NULL, even for empty - * aliases. Hack around that, by making a NULL terminated array using - * the NULL of priv->aliases. */ - return (const char *const *) &priv->aliases; -} - -/** - * nm_vpn_plugin_info_lookup_property: - * @self: plugin info instance - * @group: group name - * @key: name of the property - * - * Returns: (transfer none): #NMVpnPluginInfo is internally a #GKeyFile. Returns the matching - * property. - * - * Since: 1.2 - */ -const char * -nm_vpn_plugin_info_lookup_property(NMVpnPluginInfo *self, const char *group, const char *key) -{ - NMVpnPluginInfoPrivate *priv; - gs_free NMUtilsStrStrDictKey *k = NULL; - - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - g_return_val_if_fail(group, NULL); - g_return_val_if_fail(key, NULL); - - priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); - - k = _nm_utils_strstrdictkey_create(group, key); - return g_hash_table_lookup(priv->keys, k); -} - -/*****************************************************************************/ - -/** - * nm_vpn_plugin_info_get_editor_plugin: - * @self: plugin info instance - * - * Returns: (transfer none): the cached #NMVpnEditorPlugin instance. - * - * Since: 1.2 - */ -NMVpnEditorPlugin * -nm_vpn_plugin_info_get_editor_plugin(NMVpnPluginInfo *self) -{ - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - return NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->editor_plugin; -} - -/** - * nm_vpn_plugin_info_set_editor_plugin: - * @self: plugin info instance - * @plugin: (allow-none): plugin instance - * - * Set the internal plugin instance. If %NULL, only clear the previous instance. - * - * Since: 1.2 - */ -void -nm_vpn_plugin_info_set_editor_plugin(NMVpnPluginInfo *self, NMVpnEditorPlugin *plugin) -{ - NMVpnPluginInfoPrivate *priv; - NMVpnEditorPlugin * old; - - g_return_if_fail(NM_IS_VPN_PLUGIN_INFO(self)); - g_return_if_fail(!plugin || G_IS_OBJECT(plugin)); - - priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); - - if (!plugin) { - priv->editor_plugin_loaded = FALSE; - g_clear_object(&priv->editor_plugin); - } else { - old = priv->editor_plugin; - priv->editor_plugin = g_object_ref(plugin); - priv->editor_plugin_loaded = TRUE; - if (old) - g_object_unref(old); - } -} - -/** - * nm_vpn_plugin_info_load_editor_plugin: - * @self: plugin info instance - * @error: error reason on failure - * - * Returns: (transfer none): loads the plugin and returns the newly created - * instance. The plugin is owned by @self and can be later retrieved again - * via nm_vpn_plugin_info_get_editor_plugin(). You can load the - * plugin only once, unless you reset the state via - * nm_vpn_plugin_info_set_editor_plugin(). - * - * Since: 1.2 - */ -NMVpnEditorPlugin * -nm_vpn_plugin_info_load_editor_plugin(NMVpnPluginInfo *self, GError **error) -{ - NMVpnPluginInfoPrivate *priv; - const char * plugin_filename; - - g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); - - priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); - - if (priv->editor_plugin) - return priv->editor_plugin; - - plugin_filename = nm_vpn_plugin_info_get_plugin(self); - if (!plugin_filename || !*plugin_filename) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("missing \"plugin\" setting")); - return NULL; - } - - /* We only try once to load the plugin. If we previously tried and it was - * unsuccessful, error out immediately. */ - if (priv->editor_plugin_loaded) { - g_set_error(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_FAILED, - _("%s: don't retry loading plugin which already failed previously"), - priv->name); - return NULL; - } - - priv->editor_plugin_loaded = TRUE; - priv->editor_plugin = nm_vpn_editor_plugin_load_from_file(plugin_filename, - nm_vpn_plugin_info_get_service(self), - getuid(), - NULL, - NULL, - error); - if (priv->editor_plugin) - nm_vpn_editor_plugin_set_plugin_info(priv->editor_plugin, self); - return priv->editor_plugin; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_NAME: - g_value_set_string(value, priv->name); - break; - case PROP_FILENAME: - g_value_set_string(value, priv->filename); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_FILENAME: - priv->filename = g_value_dup_string(value); - break; - case PROP_KEYFILE: - priv->keyfile = g_value_dup_boxed(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_vpn_plugin_info_init(NMVpnPluginInfo *plugin) -{} - -static gboolean -init_sync(GInitable *initable, GCancellable *cancellable, GError **error) -{ - NMVpnPluginInfo * self = NM_VPN_PLUGIN_INFO(initable); - NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); - gs_strfreev char ** groups = NULL; - guint i, j; - - if (!priv->keyfile) { - if (!priv->filename) { - g_set_error_literal(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, - _("missing filename to load VPN plugin info")); - return FALSE; - } - priv->keyfile = g_key_file_new(); - if (!g_key_file_load_from_file(priv->keyfile, priv->filename, G_KEY_FILE_NONE, error)) - return FALSE; - } - - /* we reqire at least a "name" */ - priv->name = - g_key_file_get_string(priv->keyfile, NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "name", NULL); - if (!priv->name || !priv->name[0]) { - g_set_error_literal(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, - _("missing name for VPN plugin info")); - return FALSE; - } - - /* we also require "service", because that how we associate NMSettingVpn:service-type with the - * NMVpnPluginInfo. */ - priv->service = g_key_file_get_string(priv->keyfile, - NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, - "service", - NULL); - if (!priv->service || !*priv->service) { - g_set_error_literal(error, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, - _("missing service for VPN plugin info")); - return FALSE; - } - - priv->aliases = g_key_file_get_string_list(priv->keyfile, - NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, - "aliases", - NULL, - NULL); - if (priv->aliases && !priv->aliases[0]) - nm_clear_g_free(&priv->aliases); - - priv->keys = g_hash_table_new_full(_nm_utils_strstrdictkey_hash, - _nm_utils_strstrdictkey_equal, - g_free, - g_free); - groups = g_key_file_get_groups(priv->keyfile, NULL); - for (i = 0; groups && groups[i]; i++) { - gs_strfreev char **keys = NULL; - - keys = g_key_file_get_keys(priv->keyfile, groups[i], NULL, NULL); - for (j = 0; keys && keys[j]; j++) { - char *s; - - /* Lookup the value via get_string(). We want that behavior for all our - * values. */ - s = g_key_file_get_string(priv->keyfile, groups[i], keys[j], NULL); - if (s) - g_hash_table_insert(priv->keys, - _nm_utils_strstrdictkey_create(groups[i], keys[j]), - s); - } - } - - nm_clear_pointer(&priv->keyfile, g_key_file_unref); - - return TRUE; -} - -/** - * nm_vpn_plugin_info_new_from_file: - * @filename: filename to read. - * @error: on failure, the error reason. - * - * Read the plugin info from file @filename. Does not do - * any further verification on the file. You might want to check - * file permissions and ownership of the file. - * - * Returns: %NULL if there is any error or a newly created - * #NMVpnPluginInfo instance. - * - * Since: 1.2 - */ -NMVpnPluginInfo * -nm_vpn_plugin_info_new_from_file(const char *filename, GError **error) -{ - g_return_val_if_fail(filename, NULL); - - return NM_VPN_PLUGIN_INFO(g_initable_new(NM_TYPE_VPN_PLUGIN_INFO, - NULL, - error, - NM_VPN_PLUGIN_INFO_FILENAME, - filename, - NULL)); -} - -/** - * nm_vpn_plugin_info_new_with_data: - * @filename: optional filename. - * @keyfile: inject data for the plugin info instance. - * @error: construction may fail if the keyfile lacks mandatory fields. - * In this case, return the error reason. - * - * This constructor does not read any data from file but - * takes instead a @keyfile argument. - * - * Returns: new plugin info instance. - * - * Since: 1.2 - */ -NMVpnPluginInfo * -nm_vpn_plugin_info_new_with_data(const char *filename, GKeyFile *keyfile, GError **error) -{ - g_return_val_if_fail(keyfile, NULL); - - return NM_VPN_PLUGIN_INFO(g_initable_new(NM_TYPE_VPN_PLUGIN_INFO, - NULL, - error, - NM_VPN_PLUGIN_INFO_FILENAME, - filename, - NM_VPN_PLUGIN_INFO_KEYFILE, - keyfile, - NULL)); -} - -static void -dispose(GObject *object) -{ - NMVpnPluginInfo * self = NM_VPN_PLUGIN_INFO(object); - NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); - - g_clear_object(&priv->editor_plugin); - - G_OBJECT_CLASS(nm_vpn_plugin_info_parent_class)->dispose(object); -} - -static void -finalize(GObject *object) -{ - NMVpnPluginInfo * self = NM_VPN_PLUGIN_INFO(object); - NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); - - g_free(priv->name); - g_free(priv->service); - g_free(priv->auth_dialog); - g_strfreev(priv->aliases); - g_free(priv->filename); - g_hash_table_unref(priv->keys); - - nm_clear_pointer(&priv->keyfile, g_key_file_unref); - - G_OBJECT_CLASS(nm_vpn_plugin_info_parent_class)->finalize(object); -} - -static void -nm_vpn_plugin_info_class_init(NMVpnPluginInfoClass *plugin_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(plugin_class); - - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - /** - * NMVpnPluginInfo:name: - * - * The name of the VPN plugin. - * - * Since: 1.2 - */ - g_object_class_install_property(object_class, - PROP_NAME, - g_param_spec_string(NM_VPN_PLUGIN_INFO_NAME, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - /** - * NMVpnPluginInfo:filename: - * - * The filename from which the info was loaded. - * Can be %NULL if the instance was not loaded from - * a file (i.e. the keyfile instance was passed to the - * constructor). - * - * Since: 1.2 - */ - g_object_class_install_property( - object_class, - PROP_FILENAME, - g_param_spec_string(NM_VPN_PLUGIN_INFO_FILENAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - /** - * NMVpnPluginInfo:keyfile: - * - * Initialize the instance with a different keyfile instance. - * When passing a keyfile instance, the constructor will not - * try to read from filename. - * - * Since: 1.2 - */ - g_object_class_install_property( - object_class, - PROP_KEYFILE, - g_param_spec_boxed(NM_VPN_PLUGIN_INFO_KEYFILE, - "", - "", - G_TYPE_KEY_FILE, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); -} - -static void -nm_vpn_plugin_info_initable_iface_init(GInitableIface *iface) -{ - iface->init = init_sync; -} diff --git a/libnm-core/nm-vpn-plugin-info.h b/libnm-core/nm-vpn-plugin-info.h deleted file mode 100644 index 1e9870c88e..0000000000 --- a/libnm-core/nm-vpn-plugin-info.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_VPN_PLUGIN_INFO_H__ -#define __NM_VPN_PLUGIN_INFO_H__ - -#include -#include - -#include "nm-utils.h" -#include "nm-vpn-editor-plugin.h" - -G_BEGIN_DECLS - -#define NM_TYPE_VPN_PLUGIN_INFO (nm_vpn_plugin_info_get_type()) -#define NM_VPN_PLUGIN_INFO(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfo)) -#define NM_VPN_PLUGIN_INFO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoClass)) -#define NM_IS_VPN_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_VPN_PLUGIN_INFO)) -#define NM_IS_VPN_PLUGIN_INFO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_VPN_PLUGIN_INFO)) -#define NM_VPN_PLUGIN_INFO_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoClass)) - -#define NM_VPN_PLUGIN_INFO_NAME "name" -#define NM_VPN_PLUGIN_INFO_FILENAME "filename" -#define NM_VPN_PLUGIN_INFO_KEYFILE "keyfile" - -#define NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION "VPN Connection" -#define NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM "libnm" -#define NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME "GNOME" - -typedef struct _NMVpnPluginInfoClass NMVpnPluginInfoClass; - -NM_AVAILABLE_IN_1_2 -GType nm_vpn_plugin_info_get_type(void); - -NM_AVAILABLE_IN_1_2 -NMVpnPluginInfo *nm_vpn_plugin_info_new_from_file(const char *filename, GError **error); - -NM_AVAILABLE_IN_1_2 -NMVpnPluginInfo * -nm_vpn_plugin_info_new_with_data(const char *filename, GKeyFile *keyfile, GError **error); - -NM_AVAILABLE_IN_1_4 -NMVpnPluginInfo *nm_vpn_plugin_info_new_search_file(const char *name, const char *service); - -NM_AVAILABLE_IN_1_2 -const char *nm_vpn_plugin_info_get_name(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_2 -const char *nm_vpn_plugin_info_get_filename(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_4 -const char *nm_vpn_plugin_info_get_service(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_2 -const char *nm_vpn_plugin_info_get_plugin(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_2 -const char *nm_vpn_plugin_info_get_program(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_4 -const char *nm_vpn_plugin_info_get_auth_dialog(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_4 -gboolean nm_vpn_plugin_info_supports_hints(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_2 -gboolean nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_4 -const char *const *nm_vpn_plugin_info_get_aliases(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_2 -const char * -nm_vpn_plugin_info_lookup_property(NMVpnPluginInfo *self, const char *group, const char *key); - -NM_AVAILABLE_IN_1_2 -gboolean nm_vpn_plugin_info_validate_filename(const char *filename); - -NM_AVAILABLE_IN_1_2 -GSList *nm_vpn_plugin_info_list_load(void); -NM_AVAILABLE_IN_1_2 -gboolean nm_vpn_plugin_info_list_add(GSList **list, NMVpnPluginInfo *plugin_info, GError **error); -NM_AVAILABLE_IN_1_2 -gboolean nm_vpn_plugin_info_list_remove(GSList **list, NMVpnPluginInfo *plugin_info); -NM_AVAILABLE_IN_1_2 -NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_name(GSList *list, const char *name); -NM_AVAILABLE_IN_1_2 -NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_filename(GSList *list, const char *filename); -NM_AVAILABLE_IN_1_2 -NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_service(GSList *list, const char *service); - -NM_AVAILABLE_IN_1_4 -char *nm_vpn_plugin_info_list_find_service_type(GSList *list, const char *name); -NM_AVAILABLE_IN_1_4 -char **nm_vpn_plugin_info_list_get_service_types(GSList * list, - gboolean only_existing, - gboolean with_abbreviations); - -NM_AVAILABLE_IN_1_2 -NMVpnEditorPlugin *nm_vpn_plugin_info_get_editor_plugin(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_2 -void nm_vpn_plugin_info_set_editor_plugin(NMVpnPluginInfo *self, NMVpnEditorPlugin *plugin); -NM_AVAILABLE_IN_1_2 -NMVpnEditorPlugin *nm_vpn_plugin_info_load_editor_plugin(NMVpnPluginInfo *self, GError **error); - -G_END_DECLS - -#endif /* __NM_VPN_PLUGIN_INFO_H__ */ diff --git a/libnm-core/tests/certs/ca-no-ending-newline.pem b/libnm-core/tests/certs/ca-no-ending-newline.pem deleted file mode 100644 index 664e299aa7..0000000000 --- a/libnm-core/tests/certs/ca-no-ending-newline.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD -VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv -bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv -b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV -UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU -cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds -b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH -iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS -r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 -04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r -GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 -3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P -lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ ------END CERTIFICATE----- \ No newline at end of file diff --git a/libnm-core/tests/certs/pkcs8-decrypted.der b/libnm-core/tests/certs/pkcs8-decrypted.der deleted file mode 100644 index 2cbdeb5e30..0000000000 Binary files a/libnm-core/tests/certs/pkcs8-decrypted.der and /dev/null differ diff --git a/libnm-core/tests/certs/pkcs8-enc-key.pem b/libnm-core/tests/certs/pkcs8-enc-key.pem deleted file mode 100644 index 0d08f2d299..0000000000 --- a/libnm-core/tests/certs/pkcs8-enc-key.pem +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIE6TAbBgkqhkiG9w0BBQMwDgQIwiGFT4Jz6RsCAggABIIEyJNMddDYofbhydUp -J3VyrYIjv3LziJ7dkTXE3+mEYRCQrGLgljWBbib2JOLVCFt8melL6Yv1RcoVR7X7 -vrRqyycu0DumI4f5+Bf4wc234JNVhSaLYsw244fFtcnK2Gyn4IaVmWmrNvrwfX/w -SKcVmO30D5C5PCKzv2bou5FmnJLKdDQV1t816cr9T8pTx7MHvBzSZXbh86334BhF -T3zNwo8j2/+Gq2NBWUn+2GTTV8/r26aIwPcFi4QH6I2ghBwFmFHqU3/PoRm6nkmg -CqJj2Dggy+8zE5qg0iId7lrio0OjCH+Qed6NGwIa2lgv/bhuJVP3FOk4gqamJWHi -WMaq9McmS+03q2iokYeSQGbx85x+I90RTFZKhFx4dkerf6oTC/YoL4F++ff0e91v -sOrQsBkgRhrRtFwa9OFCzbsknlixONdd+ITkyX490xz1wcZTDkKtMDRLIPWa2O0b -MEq75jPYThZ5pF1vc5r+rqPafN7SfI+DDmhzJYEQNRoCWA4pH9Gwv0ayKnOgoj4K -TuFhXvcyWzTnVXmcqEFyf3CRrB0Ti+Z61enupC+FCuYV5lGsx9kJaTumTk2UPD02 -9Ap3asDLozdEPSXBG3+oCM2s01/IJlxtR84C97r9rpmWTc9K6DCBScETe9KnIghW -PU7XFogueG5Gwpe+x+IlTDq+qiyUNVX1uMGDcIaCC3VsoWqZrpnGGBhsovwBaXKt -T9fT2nE27Fd6DRWso4fgos6PPx7RVveu17BTMVQeUq9L8GrV4JNrE3a9aoXdbUhc -6gMiyAqxh/HEyciYoXsR9oVNi+VM0y8q3hL5nIcgDrCZr/c9aQ8+fuQBDXRrmrQd -bR2iwNLCBnbmQmM/vM333VhJ4MSOKd3SGw/j41K+Nr3uP5KRZUwV+5yy3ef/hGxU -i9JjCmSUt2bfWRUFlNaf1hCTYaKD0xnVr1SLFU4snIgh2qKawyqVc9EE2f+FcOM5 -0RtwQ3ku6FOk3cy6/xeKpResCHbWDS6nQaIKYyLukV+gm5MJIhOMkj2z4T1eXGUr -Nu/L7Gz+ps7ct0lM8W82n5lzSEa5/l1eNGM0wtQoAwutFEZp7Nx/IBKK87jVttr6 -82UVJeRk7rO2Mpobfw2LbKwga4rsuLrx3UwVDBWdLx7dNIc1rGoAxhsc72+skFgF -Uztwy4Yv1Uiji4T6v+mObPZD/HiIDL0vF02Pz08rNlgB0DgaTKrpql2FutIuQAdf -AciffQIoh9VGERlJoWuunG/UTxg2XRl2m1vCDrgBMInax+PXCv7/5Vh21AQc3fWP -uf4k6JSy46hYni7VTVKn6C/Di9z7oIrGl/jDkDsaenAbToyX9VWr3s7EBwnhTQ/I -OQ9bkWCagHIQlwJbu4M4/VAbiR26NrcR0C3JXBlPlT0qvFFB8gKbJAQEXtwIFS2h -m2fe0k6mQASMwdbJYXZ/wfsg5PPAWsKtny1aMvi0mTPSD5uRhIfEGEuR+AT4UbEW -BkEIE0lgGly4P1SpunKDQQE6m/e7h8Nl4pi8SMSme3YoX5MJwCP/CNkLBDVenAZI -oBrdoVox86SjwnUozVG192lcEAULlk+3ZGt6T9JXLBQl9hpNtyTC6SFh84R+5RoN -AevNl1bDfO+Vci0uJw== ------END ENCRYPTED PRIVATE KEY----- diff --git a/libnm-core/tests/certs/pkcs8-noenc-key.pem b/libnm-core/tests/certs/pkcs8-noenc-key.pem deleted file mode 100644 index f73fb55ab2..0000000000 --- a/libnm-core/tests/certs/pkcs8-noenc-key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQC80HGgFdlFIL2F -W5rHQ99xOkMrWcZ7an9YurDebAE3M0UwqxM24+5mWbxc8FJ8yYugdMzuI5Nq77IA -DwJpv9ZjMfnKC1VDMj3bmmMdPurfx8pLdLw/jhk3wBaYk6vMvh4z66Yvmb7valGq -Pxh6CRTnekNGI9XA7me4JNBlisl0Qasn9g4pl9PiGJAruEamS4Pk6dSWbfw58bs7 -/Yo5ejyt/Mn1n0Q/r3Gv/lAS0qRvmrW6GE1rMtANMfuGRNlAln21TzNcJzykm+sp -RWptxXEI0NY7u9+RP4M3C1mJxWir7AZDbtinpOZH6vF+92yMzgEYOLK/WZVdSPdW -tROv9xtPAgMBAAECggEBAJAfp+vjYZJjuGaYEuAxjdhW+biYcWn5U7V9484TsSXa -i+DnZOZMO8iCjMaAZuZ7zYmwPlE0dK12w29KBbSEy3eySRIRboa5TgBXq3pCcXRZ -g6/vLlZw+AzXIiha6BODt3g4UwUYnWcQx79lJCDa18sNR1a9ucbn8+Har/wiYT3M -JjTbUT6wR6rKEXchB58ZugYGhOTfugSDQg4U/dwEHPIaJ/wme++JUV5B/tjeGCG3 -F43o2Oos5vjfrDSpUKIYZn+2BdhP434jkwj22wQ2sy0ruU/kQx8nogMTRfP1v4GU -9QmNXj/DB24K388ZxcDmcxBJxrGAJ0MohYFo28DqRBECgYEA6hyKEqe2UbJx/+B6 -8mYgHb+pS2j0M4jPl11q9MMLVxLnDY9xZ85IEyWHQEC0GavPSAois0oiDeGAm32c -j6TFyV3/oPTmZSyV93/agWgnH9Xtc481pbNAb0GMfyotvRRE/+6ti9+Cl7oH9Qmm -ldMk7Hn6sK9t2mUOW8idPjKqlqcCgYEAzne25BryLJoIinbRMZg9KTfxfgUE6EKc -Tk5+9CFQn0/AItQJuKbIUyggYH4psWW5hWq6hFlmMYMR48FKv9ry7pZTB0djaoYD -lN+wSuhzUYWXedkAjvPmekITmf6rbnPfwOZvsr8CGMEUekqJPnPLzsQy+Ea2y/fb -QY4SHe7gExkCgYEAr+1scOJpZvFjK7ckjT3jipd6ADpJsORxo7zG4FImFnQU/6K4 -xRpGHWVJQyaccOIkrW04cGUYPDgmrjJx0ZwwKceijvEaphMgS1JgAHklVY4sl3ea -CAAxPqoSi4lFv94Yj/9rmT4IZD6fNivfbJ20FKUBl37tXX4tkRmr2I64lOcCgYEA -x3eqzrclrmdlxvfBZOuScwbkHP6WXhk0TwbQ6eRhsnfmxP8bITSoJoaGuRJKD2Oa -l0WkSobgDwd0uhecsrvBpTS/pDGY32n3fdWZyNTHzEOHMyWtv23tBcJek5ERaBU0 -X3WBBiw4x1eKBBeMfjR6+xhbsbcHlQiw36V05UxJWMkCgYEAhtcYvrfU4K48IJTU -qp03nvd+dMY3IUTdZNOCh8bswLKyn3aq3MfWF9Vp7kDAI3cfyMpSrAQnmg4nVcn6 -Gf3wakG8bpiSRbJnGN+iLm8JsD+3Vw9KzvKOOQVmpT7xt5Kupx1hWvLHQWvfYgOG -qEtTM8/+LD7W3I7midJNt50CD8A= ------END PRIVATE KEY----- diff --git a/libnm-core/tests/certs/test-aes-128-key.pem b/libnm-core/tests/certs/test-aes-128-key.pem deleted file mode 100644 index aab8f463ca..0000000000 --- a/libnm-core/tests/certs/test-aes-128-key.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-128-CBC,800391B7DD72364B4C2562E0B6AEA000 - -E9dgNCIATOr4CN5c8o6B+8wdqq/I1BLmPmW2qT7YZepoF7E+RUb8ZLjo1VO2XsJw -Ir4EzuH7837zBD9dP5CjlY8cWfR63gZpEWRY5Jub8kzvqiL4UZ0Qr8IHOZxAkKEz -EL1Pn7e+tYt4kA372LPZHWO3vRCgmL1iSJj2/k3avPWAx7NUie4bzGI+00WNv699 -ClKzsJbWB1eiQvYgOr4aVV26oWfa896JkBoGhgZQ6ckqFpsdAos8m46iOSVZrwgq -Y2/d1CvfQod+87c8LRatwAjf+d6YAJJaeMyxjCGuAY6/JyDsorUkM2OlvbTt6WOA -gSPWO8I+Ov6THb4IuPhpIJ30Sl88tc6MlIByW49EWu2G1jPw3L8iqRzZ50Z85dyz -N9yFP91wEwi5F0Zed4iEpg3NVfklEe/VYqCldc5f9fZ84G5V98ZlAdNSqwd/UNBU -iPTflGqVpp1u+J2isOk+Agpj1MCxh2q0RNuvY9KHzOYBScirfbG4DKNbQgS/5Zw7 -3g9YL5Wbo7BczHLiXf/2adu6T8wI1LKRjkeLV9dK1Vw3ZaGy3mB9oFhCgjh9BNHw -wC78CVcUErjtOXdQagiCQn5k5EGeAB97QFROoAFjAmGvq3xCi4EHd9Sk6fcMm7Oi -1fuVR5EXUubF4Llq06lFzQp01s2F73noH49bs3qwdf0n8nrL2XhKB0XCOV/I3K5c -Y3W+YSl361QGjZ/NUcFLIIy+Uro90MmUBNk6af+wGHRJeflpVnK0ATX1PtpNHziz -jiMiIZicjgfVLxl1a5zTl6KUmGWKlZb533adQ0s6q9Qmi5Vk5L5W/GdMjcFtZbM6 -GU7EOkwihMLb3DVsNbm7vb8tUXqe/e5RmXtij8Yb+2a6/M9yaOHa0VjHzdiKHecr -eEYaKQDj7NCWLslNnRRh9GmgXcu2pqBhqRM3HAt3cEaHKKWHTcoWcz11pFwMHNtn -bU9GjGRVc3lCGhVNRiloO0zrKHmcBpDVLw2+ycXXpj/RaBW2fy0xRLKolyla+jEr -zdLzVI61O50ZMycOtPmE7DVZpkokn32hGer1eCOFnsN1lywi4cWLvU0jbQC+CJyw -T9vS8zB3WgOl8rC1AHsfQ4KYajlKleQm89deurQymnt/Qx49SiQA+TpwG9Xvx2TP -3Vc1NwZfM9ZZ1+6xit/rTuS3LhnmhEnGnV5ZyvAdmkCcV2iHjOnLnQWWQn24MHU3 -8Y9D4AdpI5V7Igwr3vH2NZMiw1W2Yc5EJuPAT8nIs5sgOYhXB/QLPJvulvOQhuNC -NPwJ6A505JrVNfHuEaoGUyA+mPeWuLwQo8y8cM6ZdFMG3RrwFNzuYTrc1Z/9GsmA -C0UfHf5dL0r7oWZ1SbpSvsmHYqc8sIypq0ohuLEbpegS/hWP8b2/XDRTjfTiJOrM -4LsUH9PMOJSxDlwS+7e3FdcGfgXfsMgB3aOjQvNpKEolOuv4A5LVFeMrrwtw4Xo1 -EuhstZwyarUTJenDUXzkakhA+8Yw/g2a7RsnANVTkeBuv2PbqFL4zdlsWvcpkz41 -ESxx1siSeU1E9beOII0zSi8vUD0IAevRHaWSlfU2po600IzX1FN97pa4DJV2ycgn ------END RSA PRIVATE KEY----- diff --git a/libnm-core/tests/certs/test-aes-256-key.pem b/libnm-core/tests/certs/test-aes-256-key.pem deleted file mode 100644 index e51bafd3d6..0000000000 --- a/libnm-core/tests/certs/test-aes-256-key.pem +++ /dev/null @@ -1,54 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-256-CBC,5FF6BD2D4E57E8933D4A6814DEF5305A - -9Br+xw6XOg7qUqfeE5PJ4g/PAm7eTcPMb4FzSKkaEosLo6oj4f37TwXuojJZeAmi -1EytpqM1vdYHCLdjg+qYaTIq6mzMZIyoaREokcOhcNrq5S0J39gJLVV9LjiXhCAH -GQgDBnbRT6HGz70AyTRLcW9aj6uBzTv/m92sLUw2txFeBXK8n2AA1oHJTgsFNYjf -/ZvTCE1VMQHDPx31Vn5WXSUHNc0hx4MTIwpHqWI17ohr8IiWCs5HXVfVaqrNeNEw -haD7fg8oNxjLs46/4dDWmfWXhDsMFSweZv03gZdyVjwn1IOqeVGmTdLpllfgOW7E -+XE8Y/d55s5nkOxu6eXNMtWgjclKBGr2iMxxnODmEsUt2WcV98cPS+25o3hOfy3s -NIcfxtWVRFUtjqf3ragyGLuXFqATkj1slj4LVMeewRJ1g+Z6ti0mwBN+ZrYtKdec -FRNb4zr5FW+3SqkIIJVfxJEYJDB4zODhMg8tySEHLKuT0uz42YQ4aoOHTzO5WDBY -2BI7TjRppXcExPnkAk5jqbKA6BjT9KcAVyypfxDKvCeXKdjDcL6ISOBSm6cQBh8D -HxsFzMy9PF6kKNeiNiEsVPnKYvhvs1hTBtp+IAgJ6KZnCDKplZFxo/mBAlV2KyCT -x+Mhmme3fXdLJkvxlVJAoAhwgXvomVCVTGI3JhcQIqVgxPIKYpqlHVFC7JjG+yQX -tvzCPtr9G9+Ofrm6zXjlDD7zNyl/KfFtEWhO2ePHkQlCEuKJnsnRIf/wQ0viG0yY -MH31Z/84o2pKLBKY5fq8+eYuYoP9Rk4W2LpjGMvdkKhEHL26kZofeFyqD+JcaxHc -kQh7/SbWAsREGb9Jp7I2q1mo749mse1oSFIQa5gN3jB0mgHZd6edRYeW2Up+rqEK -k6Xd6uqs7bZd5W9sP7Cf6yJOFEjqFVLQEVEXWSchgeta/JNrjGr3UzLFN2S+vhvX -XgDa41y2UdXHRqj2s864u0ZDPyGXYZnVbvQn/8xHQ7rvxHowpTn+XXUEf0AQnk3j -9h++3McwP8GuVxkwc6o9TfOL+ell5jup7F3SekwEiE3hqY8x87g6X2zD5VSnfCy3 -0t0LmPGI1b3LABeYjA1WEdhoTlHrNLkwOR4gsudrJ5nxIzfGy+IHaloXLJy4YKfX -pJ+qyGRUR42YD9IhiEmmmO1VoJgVEYfBiz50Jg8emddku6eKdmv9IKjiSb2pTbDS -4oUYKg109OOn+krk67dNXofAXrBa8v7QusC0yz9N25H05Xyou1iqpGk+uBrTqEO6 -lW9lWQo57BQU9og40xMKH/xQgIxfQRktUKsPizj8mKil4izo5KgjPSqBeEbj+Q3c -0FKlrpTXQlXfX5Z5esqMuCSiwQEzoJR+V+SUaSVcg1av0k/CJMin4Cr8roai+OjK -lhaQIvx35Bzd02yERYsfpDjmQCXmIeiDm8JtB6znbQPUJ4d8kzWR+5ACOZW/dUss -YhWJRkZpkIwTY+/sDU4mnP2R37MNo+OH4CwZyUDHjlkRPGW+6JBEpnnlI9a/1Vb1 -pjAGpi/8u/luvZGTzCzxQG2dZc5YQR869U+wFsFbLRiD0aP2SpdOH0QxxPOcdR8+ -HWyL01BJBKyK/wZWJhe+63zlk1L5CA0XYpoNkYpMlPNZkcqR7QzUOATfuBgI2aPM -AXaweaAWhpPCDsc2RypIs9DhTiCCkt8tq8Au15hVUKAoshLeewPtv0t75MEC0hVB -z6FVnNlqq0cqqcSVqvUG6JUGtFOGgG3ifEMXggq5k12+wGzY63DLR8dFPNpOL6/1 -nocOayHJIU9M8PP817PzhAUAePRRUKRg8kkbKKeZnCJxoF7O15AFVEJnl9Vyokkz -bULYhzYVx3xh8THMi+5jsnKWPJyMeYHbHH3C658SIw6Ff9fgEWscv5ZkGYdKMg+l -8hBn+++SoqIO+F3lOGco+s8qlYox106lUwJEtORXcBxmkaHSo/X2AVO8Owt4vYli -mjWnY6V9vooBgOuCMcY780pcoj2lSf9JPHDYK0j8t5VumDUSLyLt+tCj0yv/vl5L -9L++vbu2akZRC9ChijYpfhTvXoG36ePhoT7AGGnhpFjjw1VqG80GY4XSODKzH86w -kUcZoErb8swUPYOtsybtuPb+6c/YofQ8GfpVosPZgSRD4+U7v+zA3/z8xF2B0xt6 -uV8hXbropuni8KmbFuKrPZK3p2v2aZ8F0+GITwS75/hbT6D7ruUSr5q4V0VKeE8G -k3QSI0s6+74stPv3S/ByCxu8q51ffYqVw00wzPpEc4SmHEa0R7IczJKXupmDdZZM -1rASSBNzS5TZDBXP6S7npYQ8nHhgXTdCFO7eM3bp24B/i2o0s7+gkKrz0DkEbv9I -UrCJjTL8OIIP4qSLMILzZ8pB28c+zyM482ZqFY/2b7j6WlTiqa9P1adrD1gLxTQ0 -Sw9xY+sY3PAJqcnPA5NjDZL/h5plgHhCqDa9pEtdBVG2Mxcl9bXbphwD1MIzj4gr -xtlW1HUJ/iOhFcXldOJ1MCt++Bm5av4mL5adQ/oUnL5Q0oZZFwqT09k7xe7lZ98N -uj2Lfl8NN7N3ama9KatgbX5g6IALuk/rJN/4KEiiu24m+lR7c5L0pg/cG6LIFjmk -HlTsc0ANCgeZBhDJ8kvjcXDhFOqoYE/+D2VO6ZEHRsDibQ+kjpaH+DiD01/gh0N0 -HM6GGtm3GbOyZUhw5OFz04xzcyFYo2xaqzgaZieAOcrt2s6XyPVf1gww08/HtTMR -gLg14MUQvRXV6kPJfdu4OLZ//b6J0KnzVyLDRdOrWIj2raLWmKwQN9qv05/yskcD -Y6x7wq3v6iZpFjDc53sslhwp2XRsoWT9X5alVspz8WvP/kqgkTdzpPFdp1vIovOQ -kRXdzzKICDGDJUIcTL8cJ3Dv4XqNR/sVyuB4dfndzQQApbdYTDNpwX0VJDBjMkQy -Up6aiUknxa6Cbp7b1ZfUQY8yNBAIZL+R8dmobT3nAHW61DaASHSxn+elCD2Ja/6b -EiWikskyN6crMAv35ILr5ySsZK97ttNNmRoGFbt8bTjRd83Ie+UfH445kCKsY83x -aDCvWm+bbV6M9rSgjhJ3bWOudiw+EBMGvSamSnS7CYnRmwq4t+4bM2sh2nYKY0qw ------END RSA PRIVATE KEY----- diff --git a/libnm-core/tests/certs/test-ca-cert.pem b/libnm-core/tests/certs/test-ca-cert.pem deleted file mode 100644 index ef1be20d2b..0000000000 --- a/libnm-core/tests/certs/test-ca-cert.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEjzCCA3egAwIBAgIJAOvnZPt59yIZMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYD -VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw -FQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UE -AxMEdGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAzMTAx -NTEyMTRaFw0xOTAzMDgxNTEyMTRaMIGLMQswCQYDVQQGEwJVUzESMBAGA1UECBMJ -QmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55 -IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3 -DQEJARYNdGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAKot9j+/+CX1/gZLgJHIXCRgCItKLGnf7qGbgqB9T2ACBqR0jllKWwDKrcWU -xjXNIc+GF9Wnv+lX6G0Okn4Zt3/uRNobL+2b/yOF7M3Td3/9W873zdkQQX930YZc -Rr8uxdRPP5bxiCgtcw632y21sSEbG9mjccAUnV/0jdvfmMNj0i8gN6E0fMBiJ9S3 -FkxX/KFvt9JWE9CtoyL7ki7UIDq+6vj7Gd5N0B3dOa1y+rRHZzKlJPcSXQSEYUS4 -HmKDwiKSVahft8c4tDn7KPi0vex91hlgZVd3usL2E/Vq7o5D9FAZ5kZY0AdFXwdm -J4lO4Mj7ac7GE4vNERNcXVIX59sCAwEAAaOB8zCB8DAdBgNVHQ4EFgQUuDU3Mr7P -T3n1e3Sy8hBauoDFahAwgcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDF -ahChgZGkgY4wgYsxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO -BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQL -EwdUZXN0aW5nMQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRl -c3QuY29tggkA6+dk+3n3IhkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC -AQEAVRG4aALIvCXCiKfe7K+iJxjBVRDFPEf7JWA9LGgbFOn6pNvbxonrR+0BETdc -JV1ET4ct2xsE7QNFIkp9GKRC+6J32zCo8qtLCD5+v436r8TUG2/t2JRMkb9I2XVT -p7RJoot6M0Ltf8KNQUPYh756xmKZ4USfQUwc58MOSDGY8VWEXJOYij9Pf0e0c52t -qiCEjXH7uXiS8Pgq9TYm7AkWSOrglYhSa83x0f8mtT8Q15nBESIHZ6o8FAS2bBgn -B0BkrKRjtBUkuJG3vTox+bYINh2Gxi1JZHWSV1tN5z3hd4VFcKqanW5OgQwToBqp -3nniskIjbH0xjgZf/nVMyLnjxg== ------END CERTIFICATE----- diff --git a/libnm-core/tests/certs/test-cert.p12 b/libnm-core/tests/certs/test-cert.p12 deleted file mode 100644 index ae4a683049..0000000000 Binary files a/libnm-core/tests/certs/test-cert.p12 and /dev/null differ diff --git a/libnm-core/tests/certs/test-key-and-cert.pem b/libnm-core/tests/certs/test-key-and-cert.pem deleted file mode 100644 index dec9aa1b8f..0000000000 --- a/libnm-core/tests/certs/test-key-and-cert.pem +++ /dev/null @@ -1,118 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,4DE0615F23D82107 - -QPNCO5Dobvz9dDhN32KkZRoEifW+HDm2PCbRQhKDiscGwB6LgypvVjHNsZiFKwzz -L4R51UqgQeJx7GSGJqE626e9z9J+UNBhop02aOO2X0eSPdvBzr/uJ6Umiyr1xqD7 -zWf7u9l5kXElDJRhK+87GMBewp4Ie9NeXDjhF8hzC5Kiulen4AH3AYnfH3S7DimU -h8GFMg8inrudrTbcjBhCdPeHG2jCygOxw3InRFz7uaN6LIhOaPQvmvpP4Cc1WRnW -ZPq9o+eU3fPWPD5t+Op/VzYLvKwgBy/yK1rQXUm6ZMO7MhhRJ94ZCsJv+nVWpJlv -QyBlxDKxwfkfYbDELdnnDQdHdMbKatLqa0KhSkgpp8LywBtanPz731tyT0r7b3na -eLdra59lRU7ZQLPEdS3lPZd2O/KQvWf8wbg7MjXS9LxQ7R5HOPu6DNJlwXVZBmmo -cAfu2q8ubU2IePvWLD1GOrBi6hE9TiGvFJkw+wBK+t72sz3njv9Xm/zlxruaEk5m -RW/kybU3FP4PtjriBbskz3/VZaaxuRN7OoOYTkmyHmG1ADgcRUV6fea19qqsBlN8 -xb+SRtoH28oT/JVWU5neE2dbNzk5LeVO+w70NNdR5s5xqkBhbGGaJxvXwNP4ltFr -T06SMh8znOLKwWB00aRtwfU7jOwR3mOleQO4ugIHmau3zp1TqzAHW8XtpuV7qVeI -ESZOZuf0vW43BtNzgLXt1+r+bmsMsRwhnyomL9M0TUyyBdVYY9GkzTG9pOESheRo -RSvAZ8qKGUliTpgBcbt2v1+NqkszcHa6FxuvS8YU4uo5/GqsgTxHTNIB232hIrrZ -EIm6QL9TC5oFXMjy6UNqoCm5Nb8DBJ6aErt7pt7aoktqUW3O3QIzQT3IbZ4nAcTt -lVF4d7j29I9t7bcC8GOVU1neilguZUss4ghJg9x4zI5UZdR7hZ8fbFT47TyxB+j5 -r0YdmjbjVTaSyaN2JGh1wvb4TzawGNVx/U2EJE16HigOtPfsfQRJ3x+FROKBdVa4 -aIFYXkRBeIPxX6n9pcw0lBCsnXo6/5iTjQSk2VqO3rHO/wyWiEjNczhL33dY2A8W -GG5ECMO5SqXZHQQzpABqK94dxe3UC8aEESO5NhEqDuV7qQGol0qPKrUA3wb0jb2e -DrejJ9HS2m1SUDmjpvvmEGy6GN7CRibbKt5rNZdJNNvWArOF5d0F6wkixQLl73oE -lq5gLQQk9n7ClleKLhlQpBCorxilBbzmSUekkJLi0eaZiBBFWBX9udqnUZloXTgO -8qwuO8K/GPR9Jy1/UH2Vh1H+wivaqKTVgEb0NotzgzECgTEFKJafl7rUNs1OZRZ3 -VBjevi6+iDpxVFgF71kXfdUC4ph0E1XDl0ja2rrKQGivMkUhWJ57+4EV5+hBkAnt -G0RV45NwHXLrK2bd8F9PlRk2XHW6mIcFRXsW1DjeBhk/sQjvlO9R01GRSgcXtekJ -tmX17FWrMrzXHpvy1IC3fk4RVnSjpzQ8O+17YE8/la9wVaeZZzHyYFmMT7VXjIhW -QozJQ0vJ2jxJRh5GYn3tpJzdaeRfvTBik0pChNdUTnWP+BJ35xoCTs8iwJbmgVZ1 ------END RSA PRIVATE KEY----- -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: md5WithRSAEncryption - Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=Testing, CN=test/emailAddress=test@test.com - Validity - Not Before: Mar 10 15:13:16 2009 GMT - Not After : Mar 8 15:13:16 2019 GMT - Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=Testing, CN=test1/emailAddress=test@test.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public Key: (2048 bit) - Modulus (2048 bit): - 00:cd:34:b1:2e:b0:04:c6:f4:2b:a2:c0:a0:39:7a: - 82:ed:96:c4:f7:19:83:91:5c:b4:e7:9c:de:ec:48: - ec:2d:e4:51:08:26:42:ac:d3:98:26:7a:72:f7:49: - c2:9e:66:05:c6:47:29:fe:3b:ac:6b:af:6f:5e:a8: - 03:5a:73:33:ba:19:03:00:35:f5:00:bc:a8:be:14: - ce:46:69:e3:6d:ed:34:37:85:55:87:62:b3:b7:c9: - c0:cc:9a:aa:61:05:5b:cd:a2:17:42:d3:e5:6f:1c: - 60:8d:c2:15:41:46:f8:12:54:d0:38:57:e1:fd:8d: - 44:c8:fb:56:b3:b9:6c:e9:f8:9e:21:11:57:1b:8b: - f9:cf:e3:17:e7:d8:fd:ac:d1:01:c6:92:30:f3:2d: - c9:d6:c1:f0:3d:fd:ca:30:dd:75:74:e7:d1:6b:75: - d8:c5:4d:43:61:fe:f6:ad:7e:4c:63:7c:03:17:a2: - 06:8f:d0:8b:69:d3:7a:07:0f:0b:a2:cf:0c:70:38: - ba:cc:55:35:60:84:58:d8:d2:be:1f:ef:76:a9:ba: - ae:6a:dc:08:97:80:de:42:00:b7:d4:ce:9a:b0:36: - 2a:c7:6f:45:04:7c:ea:41:19:d8:b9:19:04:1f:11: - a9:22:80:bd:69:08:15:0d:3c:de:cd:7e:88:6c:0f: - a3:43 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate - X509v3 Subject Key Identifier: - CE:03:7E:EF:E7:DE:C9:87:BF:DE:56:F4:C8:A3:40:F6:C8:6F:05:8C - X509v3 Authority Key Identifier: - keyid:B8:35:37:32:BE:CF:4F:79:F5:7B:74:B2:F2:10:5A:BA:80:C5:6A:10 - DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=Testing/CN=test/emailAddress=test@test.com - serial:EB:E7:64:FB:79:F7:22:19 - - Signature Algorithm: md5WithRSAEncryption - 7a:20:93:63:40:73:7d:33:01:2e:c0:13:52:a4:a7:e1:4d:82: - f4:fb:b2:7b:d0:2b:5a:3f:0e:3c:28:61:71:ab:01:4d:fe:89: - b5:cd:2f:97:59:93:53:9d:51:86:48:dd:b9:e4:73:5e:22:0b: - 12:0d:25:39:76:16:44:06:0c:40:45:21:6b:a6:b1:e0:bf:76: - 1b:36:f3:1e:41:82:57:d9:59:b7:60:40:43:1c:1d:79:f6:48: - 32:5c:4e:e2:06:89:96:41:d2:54:1f:4a:6f:f6:78:a5:3c:02: - 85:21:e2:65:e1:8a:6d:24:19:95:f8:c0:35:ab:bd:ff:3d:f1: - fb:50:2d:30:1e:67:a6:7c:50:f9:d5:77:66:77:5a:14:0f:5c: - cd:21:09:9b:a3:92:57:19:dd:01:a4:18:c5:f9:70:e4:17:43: - 8d:b1:e6:61:e9:50:89:83:4f:ce:a4:57:68:58:40:70:ae:71: - 1c:47:66:d2:30:54:50:ea:3a:87:32:64:3b:18:42:fe:5a:19: - 07:64:f7:f1:b1:10:07:fd:a7:d2:a7:a8:05:79:5b:25:ba:69: - 7b:1a:3e:b1:3e:e4:17:17:01:ba:eb:54:ae:83:00:ed:66:62: - 8d:c0:3e:8a:b4:27:5f:e9:01:ce:20:c3:34:a9:28:c0:6f:c7: - 3b:65:fe:f9 ------BEGIN CERTIFICATE----- -MIIEojCCA4qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCVVMx -EjAQBgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMO -TXkgQ29tcGFueSBMdGQxEDAOBgNVBAsTB1Rlc3RpbmcxDTALBgNVBAMTBHRlc3Qx -HDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMDkwMzEwMTUxMzE2WhcN -MTkwMzA4MTUxMzE2WjB6MQswCQYDVQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJl -MRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzEOMAwG -A1UEAxMFdGVzdDExHDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNNLEusATG9CuiwKA5eoLtlsT3GYOR -XLTnnN7sSOwt5FEIJkKs05gmenL3ScKeZgXGRyn+O6xrr29eqANaczO6GQMANfUA -vKi+FM5GaeNt7TQ3hVWHYrO3ycDMmqphBVvNohdC0+VvHGCNwhVBRvgSVNA4V+H9 -jUTI+1azuWzp+J4hEVcbi/nP4xfn2P2s0QHGkjDzLcnWwfA9/cow3XV059FrddjF -TUNh/vatfkxjfAMXogaP0Itp03oHDwuizwxwOLrMVTVghFjY0r4f73apuq5q3AiX -gN5CALfUzpqwNirHb0UEfOpBGdi5GQQfEakigL1pCBUNPN7NfohsD6NDAgMBAAGj -ggEfMIIBGzAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy -YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUzgN+7+feyYe/3lb0yKNA9shvBYww -gcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDFahChgZGkgY4wgYsxCzAJ -BgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkx -FzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQLEwdUZXN0aW5nMQ0wCwYD -VQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tggkA6+dk+3n3 -IhkwDQYJKoZIhvcNAQEEBQADggEBAHogk2NAc30zAS7AE1Kkp+FNgvT7snvQK1o/ -DjwoYXGrAU3+ibXNL5dZk1OdUYZI3bnkc14iCxINJTl2FkQGDEBFIWumseC/dhs2 -8x5BglfZWbdgQEMcHXn2SDJcTuIGiZZB0lQfSm/2eKU8AoUh4mXhim0kGZX4wDWr -vf898ftQLTAeZ6Z8UPnVd2Z3WhQPXM0hCZujklcZ3QGkGMX5cOQXQ42x5mHpUImD -T86kV2hYQHCucRxHZtIwVFDqOocyZDsYQv5aGQdk9/GxEAf9p9KnqAV5WyW6aXsa -PrE+5BcXAbrrVK6DAO1mYo3APoq0J1/pAc4gwzSpKMBvxztl/vk= ------END CERTIFICATE----- diff --git a/libnm-core/tests/certs/test-key-only-decrypted.der b/libnm-core/tests/certs/test-key-only-decrypted.der deleted file mode 100644 index c8652537a6..0000000000 Binary files a/libnm-core/tests/certs/test-key-only-decrypted.der and /dev/null differ diff --git a/libnm-core/tests/certs/test-key-only-decrypted.pem b/libnm-core/tests/certs/test-key-only-decrypted.pem deleted file mode 100644 index 1a25da5e7d..0000000000 --- a/libnm-core/tests/certs/test-key-only-decrypted.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAztLp+/SkzmaHzIst0sO4+r7qUwiVnidKBHgxoTbS5UL1dvck -cbjTEP23V4ZoKQIb6ZMrr8B+PVgWNBAlhX4oLUL8NH/WTwrntrlAUcjliWDNc1Fj -Z+FZNjFe0IdLXZeKQiLTQvKDYnmERVvYIJfi0TQjXuy/ikF8rYBQ85scUV3kKRzB -xnyhAHAP9nl3AyL1S6t2yiCr4U5TbIZo6dYPbpVLtbXP02zUc9vAPR0gIHKrPiW7 -P81fLXf91wuo6wxzwD90JxdWzzGaqe3BOSfHqul3SPRtVok1XHlb9i+Mn5O8ExzQ -dF8wGxVDcY7/Gt9lZWnCilqrBEqA3iApjUgcgwIDAQABAoIBAQC77HCmepf04ryp -Yhz00NoXG7mWUMqBtXlPrlaKAWKG5dxbiBwZKLK/UYlxgbLK8BuklBCx1Nnfq1Yh -YDp3nTWsSp0WpsF3eJUqNhD3Pu8xcD+9dEo6bUu+LgXUu9oC5Fq/1RzYS7qNk5RX -4Sf0FY4GQLWS3tL7MJ20mE71yg5k7qRbDydOyhTh1m1CpRYONWxSsWVLM8KGRDJp -iF0cdPfD5yoPFpgDk8gwzrnXJH2Wqzv8GvyYykRK5AW7tE50y0rTAM42WZ7YS6aZ -FNMmtYxeyzXLY3LgPP0uko5anz3OXRcqCfHfFANG0y7B9MehbrjMgI6S1BbzFl07 -V1zVQVqhAoGBAPIfrWMlh1fHlRh4iRGXK2Hvxyv2oNz9KvQ4qRaLV9ejRDzdt7Pi -/utbi5LGBuDw9016nXM3I77b6PukHzsHFnWGRnyRSbkMMt6mE17nggmNqcpFWfE8 -E7HcKMhk4gbuo5AHD3Ee1Gac2AUDnzYiE+sS6WI3O9d77cc5ych5jZ+nAoGBANqt -VZCttjY0E+hEyTP37eaE8u0jfdK8AflTJlNUHWKXglES525iu8I/Bso8KaQYsYF3 -SezGRd3KQepQhtMjFKfSpF+tbnboP57Y3XGo8xhbxqV4kRX+XGsVoW3Vg2nPKBrR -+dIY5nMwua+gkHWp9RDcemD2reiIZBVx95fK8dfFAoGAdCSH2pBs/MlrFqLzNTHr -iH4pb0hN39O9YAsx6POMfo79s6izbyHLIID4Ub6WHB7ashrIHjVr+yin+NXAeWMr -/dIcS7Kxx4c3e5/0mMi6kvSWZsWfoF0uIVo3YfEqjyK36OXKHXwpbNN9t+IF5ESy -g0e+FfPiy7nR1Ig+5+CO8+8CgYEAp/75+Ug677FaidouaMpT7gC9UAkwJLFjItQK -YYIBgTi8WOSY/2jCrhwVb1CA/RwrYjbuiARasGUt9oEe0x3kRHnC5e4rKxaJqdMZ -bLRK7a+0EHNrouXiwjG/7s1VQ/ht6wzdS9btVBlezdogoQSMzQNU0SExwa7mlMMV -X3v+B7ECgYAK+Yt4jnLH1LNWoDTU0Ug5hyXsQXV8lVBSnrkvS7GtP6ZA/4OqG7lJ -/bTYFZGoiAGzOnC+YlAqSIu45CEnpr2xBsThQiWUVxspmQD1lEWWFcd77DPUwn3C -59pLgx0AqJE3n6lBOwehiXbFKBdVzX8PfPZpuCK6qc/RiTILktwURA== ------END RSA PRIVATE KEY----- diff --git a/libnm-core/tests/certs/test-key-only.pem b/libnm-core/tests/certs/test-key-only.pem deleted file mode 100644 index 5ef530e9ab..0000000000 --- a/libnm-core/tests/certs/test-key-only.pem +++ /dev/null @@ -1,92 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48 - -KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k -r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+ -PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj -5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/ -amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj -yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR -PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV -xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg -T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab -HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu -Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev -0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB -m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf -rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f -FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S -uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN -vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt -1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh -ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw -l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v -tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm -aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco -0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD -u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj -DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg ------END RSA PRIVATE KEY----- -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: md5WithRSAEncryption - Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com - Validity - Not Before: Feb 2 02:22:25 2009 GMT - Not After : Jan 31 02:22:25 2019 GMT - Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public Key: (2048 bit) - Modulus (2048 bit): - 00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3: - b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36: - d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86: - 68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10: - 25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9: - 40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31: - 5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79: - 84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41: - 7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c: - a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20: - ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5: - cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25: - bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f: - 74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9: - 77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93: - bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df: - 65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48: - 1c:83 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate - X509v3 Subject Key Identifier: - 34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B - X509v3 Authority Key Identifier: - keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E - DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com - serial:E6:4C:5C:96:26:5E:D6:D0 - - Signature Algorithm: md5WithRSAEncryption - 88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c: - a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b: - e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5: - b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4: - 39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2: - ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6: - 76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32: - 4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48: - e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12: - 9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e: - 6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df: - 88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f: - d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16: - a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03: - 6b:80:38:6e - diff --git a/libnm-core/tests/certs/test-tpm2wrapped-key.pem b/libnm-core/tests/certs/test-tpm2wrapped-key.pem deleted file mode 100644 index f3fd271c32..0000000000 --- a/libnm-core/tests/certs/test-tpm2wrapped-key.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN TSS2 PRIVATE KEY----- -MIICEwYGZ4EFCgEDoAMBAQECBQCBAAABBIIBGAEWAAEACwACBEAAAAAQABAIAAAA -AAABAOJdEXw1LO6JWskHBSYQc1NfJAe9DOAyLA4XbXI5asQ8aNbmL51DP9mQQpqq -a1CSRZAIuuorMxyRBBAFpF4OZqjNd/Nskp3iMmifr5yqAYZ3M31MqlBFiiyctqKp -VwIChwsIbKelrsXbty1icP2CH+k4w/nPymPjnfYtgpMe8QW8n6U156ujIdJcISds -QFcl3nrDnD1IumX0/LfanQrRDVSI+m6szvTrdsPMtGeaNMnlz0gx74auo7/CgEjX -69xjPvQpNLHO/nV4EHSdfXH3LamcpWO8aEAVne3MFFA9V0bpv7uKoGhRjssD9kSr -PQzNXfjHpkcOLeH4pzxDMFXDIGUEgeAA3gAgrCL3RRcBryFXToo9ZN3/f4EeeEjK -58ejYomsxqvckhgAEMxbT26fo2h27b4KPlnUpoiL2JPLB0Xz6PJAF8n0YdJUO381 -xhzPTIQop81BxljTLV2C9WGns5bWDPW9ItEbv4UalEwFfxsW4Ma5smLWn3A1UwVN -Z1cW/oUx+3nOCF1TZgbMPszToqCPlpIHd9vO709qpSyULIUkZLHS6PUM7ESY5U81 -f4BITxJR+aYaqErni/FDLsDVP0MQ3CuFHeUDHI0uEzzbfurYFjpp9+caaoWuZzpg -VYV5pjPdgg== ------END TSS2 PRIVATE KEY----- diff --git a/libnm-core/tests/certs/test2-cert.p12 b/libnm-core/tests/certs/test2-cert.p12 deleted file mode 100644 index 9d5732b0a9..0000000000 Binary files a/libnm-core/tests/certs/test2-cert.p12 and /dev/null differ diff --git a/libnm-core/tests/certs/test2_ca_cert.pem b/libnm-core/tests/certs/test2_ca_cert.pem deleted file mode 100644 index 9a487ca4b4..0000000000 --- a/libnm-core/tests/certs/test2_ca_cert.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEpDCCA4ygAwIBAgIJANDnVhixAO1GMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD -VQQGEwJVUzEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czERMA8GA1UEBxMIV2VzdGZv -cmQxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xFDASBgNVBAsTC0VuZ2luZWVyaW5n -MRAwDgYDVQQDEwdlYXB0ZXN0MRgwFgYJKoZIhvcNAQkBFglpdEBpdC5jb20wHhcN -MDcxMTA5MTU0ODI1WhcNMTcxMTA2MTU0ODI1WjCBkjELMAkGA1UEBhMCVVMxFjAU -BgNVBAgTDU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQK -Ew1SZWQgSGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMH -ZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEAz9zRLSiQyQangDgEliEP8xSpnPJS7GjXzrkZS3sk -gZLuVuwoFeZRq3Hsrq/wGd/vM0KUFNmEaMc+47jnuv0UHQcQ45ZACO7s4/Aflhzj -lkmud/z06hVknIzjXmvS6q2ttCviHsXnfokl+wAxuUhsd+le0xjP9H1jXny4YBuS -jP+yGUz7PL4w1sFFghKIPrlB7m4GkFbQRqvH7FSJg86GWopPwJvNvIzhOZiO1a1D -CAAL4Ru3jxtNFxqWT87C/qUEe/2Qb7jtNyqFcKfwZyZh4u1bo0c8bjErlUZERbWz -zM3hTFypuw+i2v+0h3A8/Xb0hTjcHkUoJgfSdbsOLC5TOwIDAQABo4H6MIH3MB0G -A1UdDgQWBBR+UOaH4e8nrEuMcEXJl7UN5r/wDTCBxwYDVR0jBIG/MIG8gBR+UOaH -4e8nrEuMcEXJl7UN5r/wDaGBmKSBlTCBkjELMAkGA1UEBhMCVVMxFjAUBgNVBAgT -DU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQKEw1SZWQg -SGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHZWFwdGVz -dDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tggkA0OdWGLEA7UYwDAYDVR0TBAUw -AwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAmE2jqUymfxN2Vv7bPafoK/EpZwGPxu+z -phRFsgUgWVzidc/GtOxN81LduJ+ow8MEbQIabo4JV/MdKzuPuhAHToAQdeb0LIWa -p59vTIZiVhUt0cMAbQwKcTnfmDnXw9wytvtKgeAXJq0Jd6F+uNXTiR1btlYLZqmF -oSu54cHQlXpUT9z0BnQ8eXd7m0TwfzGQkTHQI7xBa87lZDAkJaTlhv7fR5vPmJYY -0LiXii71ce+4hxdlp7hQfwQ2sb8FPY3RlVboTRD0CvGaWypWhdSZnS790dBXgZOs -NCge6NGuHzW5LtiZE9ppuv8qJysVcIFdAqt8dkx58ksOqFcARCerXw== ------END CERTIFICATE----- diff --git a/libnm-core/tests/certs/test2_key_and_cert.pem b/libnm-core/tests/certs/test2_key_and_cert.pem deleted file mode 100644 index a668596eef..0000000000 --- a/libnm-core/tests/certs/test2_key_and_cert.pem +++ /dev/null @@ -1,119 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,5FA2D6D6242C26D0 - -dyNdbh115sczbUEhiaGYJ6fazyvJss5thPFEmkP6aftYlvXY6vPtc++xFCCktiSd -qFVEyi6oDyV4iGPmX7pCJ0e+pSI6uFNXKFtxh5/+/wXZcOEMCvfu7w2IrvYF2LHY -qJDljcISSRxeINuYO7TETD5fLLRKj2X9vwwkwVN02b2N5jsrm6Bt//WbatqSB3ln -FHyQhVKkvdl9Hr1XNmEfgGfZSxxDoPu1DjhtZ5ja2LZj64C2CXdI0oq2wcAVvQNn -rZeeg9sinQJkz9rwsNaWqlYw4X+YD2JRSwZuvwkWRydYMwgb1XS/jCxtuFF8NXWP -RBAOAZZUy7onzohsJHVVa05wCKQ4klo+PEfI3vn7BeuHyciCc0eFqGRvz8eFDybH -ZdPbU/3vGp+mOB7gd27TptttTCQQy9uM5CIyovNSYsAIw1Z583Ea4q8eXgzkgD6D -isCqkGXMfPbNXU3myQGDnQwWRi2CqX+rXM8PJUhdewLAlmHRz/aYSuql2BRixJKx -eASzmFBYdAjrvafda5D+xTyJwXEwdq/HlqMK9cY28ZbNrzA2Kor2X23EKC1+VG8k -B67OsfUhW27j4u6aV5JdLf87OtF3mHFRR+Lzs7i7LYvJ8ACE+jiIi7PboZjK5Oiv -JqTK0BwDaeNYjkd6jiJh8It/ReMbLk65J3eldOklN0VMPYiqcQnHvSPC2DD1YAy+ -Rv/JVj6TvzvgEAj+hgH6MAAF6u3ARj6+10DlvhUubkOC5RztLKReu8B+427TuuDb -T03gFpHD6X9IqSiq/QfYFyHFojCVSrv6wDZOcHc1s71kpJ8R14YIVe+DrrZN/0D4 -M631jdNg3JARMZXcXTHrghGIdPmOtrsRyTTRZuGoVup/DW9MRzOzCTMSNCX8T+eq -13HMSNQEO9lMwy0sYeO5c7sjHY4K1ubZuVE1mvXq4JLz3YxXJIvgp8TUvqDnAsK+ -Fv63bDoTg5Tq63XvnaKc7Lawneyg5ZAMzPN3nM0/1EZcn/2ICI5c4Yepc5t63EI5 -KytuXx86Mcx234enj3uMeuM22POQ1SnKOef6dFzK/CE8J8eUEY/aDhX4eBl/s3nd -U4+aaFKYz3HTazePayt2SC6rP/KKMmS14q59bOQA1DiWxCvmA2ypRyP87fV5DstH -I53RD5xp1P38iaO8U/divD0W2dkv748s9DQqYrHPtWALT9esxNU07CgB8Zt070si -7pzjQ8FDCZ8ygDmwWGNSBz1nA90Cpd6gAFDrep7HAtDE4qgNfokycpaJZkXBei/U -tC4tWYRbqDEsEbeBHvQRJzzqWzk9e/P4fQoelM3aryKzKLG5z7KvywVifKMLECQ+ -tIpzoRp06nuTA/O+iLFdkCy3JEWszfvvOwTwtIIV6+3s8TU0k9MmzEe3rGL+QqT/ -Tf+9/dN5LK+LWyc99BfmCOrBuFtQmHyEXkfe6EuFYEwj0B2ZfnLCon6cdRujjK7H -IJslC1B/cBVqG3KCrbBzjeygKfJ5Ijo72oXZJOCFTLeJefZKGGWJCp9nG9h9Wrcf -fEN/mj3wBvTa90/PYFj9NuaBtrvMF8Rn9XDeYPq2JGL8YkNdPuO8A+2Yko8wcvST ------END RSA PRIVATE KEY----- -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 2 (0x2) - Signature Algorithm: md5WithRSAEncryption - Issuer: C=US, ST=Massachusetts, L=Westford, O=Red Hat, Inc., OU=Engineering, CN=eaptest/emailAddress=it@it.com - Validity - Not Before: Nov 9 15:50:14 2007 GMT - Not After : Nov 6 15:50:14 2017 GMT - Subject: C=US, ST=Massachusetts, O=Red Hat, Inc., OU=Engineering, CN=client/emailAddress=it@it.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public Key: (2048 bit) - Modulus (2048 bit): - 00:b0:8f:4f:1c:93:d4:43:e7:87:b7:22:33:55:a8: - 35:a1:c4:01:b0:f1:ed:26:23:96:ab:65:c2:c2:54: - db:79:22:03:ad:3f:6f:22:e3:63:3f:f4:21:6d:fa: - 88:c8:8f:1a:ce:55:49:7c:98:33:6a:67:8a:8d:d9: - 34:b0:c3:42:f4:72:a4:45:43:05:72:5d:0c:d3:42: - f8:9c:66:3b:b8:f8:77:ea:f6:b6:94:d7:cc:5d:62: - 34:2a:14:48:0a:bc:65:94:f5:7a:63:98:6c:88:4c: - 25:d8:95:f1:40:3d:00:d2:fb:43:28:fa:02:fb:2c: - 80:b3:e1:33:e7:8c:ce:8a:a0:1b:3d:04:4d:bc:a1: - b6:a2:42:8b:8e:f3:5b:4a:72:34:7d:8d:ba:d8:46: - 22:35:da:5c:f8:dd:fc:6d:9e:59:22:b7:6b:e7:78: - 56:54:9f:4c:d1:e2:4a:23:a3:bc:04:ea:46:6b:70: - 8a:fb:fe:8a:73:ca:36:d5:f3:e9:17:e3:22:d5:b3: - 70:05:e7:f7:37:b7:21:b5:90:53:27:27:ea:36:9b: - 00:ff:35:b0:66:3d:dc:a9:2f:95:d2:21:18:98:4f: - 28:07:09:70:20:a8:b1:82:aa:a5:df:ae:0f:e3:36: - be:68:8c:9e:80:d3:33:d0:f5:84:17:d9:0f:eb:9d: - af:0b - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate - X509v3 Subject Key Identifier: - 71:AB:BB:91:B7:04:DE:43:35:36:07:8A:35:CA:BE:5C:3E:EB:B1:09 - X509v3 Authority Key Identifier: - keyid:7E:50:E6:87:E1:EF:27:AC:4B:8C:70:45:C9:97:B5:0D:E6:BF:F0:0D - DirName:/C=US/ST=Massachusetts/L=Westford/O=Red Hat, Inc./OU=Engineering/CN=eaptest/emailAddress=it@it.com - serial:D0:E7:56:18:B1:00:ED:46 - - Signature Algorithm: md5WithRSAEncryption - ce:43:6d:f7:f8:4a:66:fd:8a:2c:41:a6:e0:03:0e:60:30:d4: - 41:01:ba:46:ba:81:97:64:68:83:25:9c:e1:2c:03:8b:2d:ca: - 85:cf:bc:fa:ca:22:c4:59:28:23:8f:ff:50:94:60:1c:90:dd: - 75:f4:d4:ea:8c:fa:61:61:08:35:4a:8f:aa:a7:e9:3d:76:e9: - 08:28:55:01:c4:03:42:c7:ad:58:bb:ee:94:f7:09:b3:9a:9b: - 8b:d0:25:95:18:a6:22:d5:2c:fc:b7:bb:91:0c:7c:03:7f:9b: - 85:de:b0:e4:95:a8:73:94:27:0a:11:4e:e3:67:ae:2b:cc:e7: - 51:29:10:23:57:5c:3e:e7:ea:47:e0:f0:8f:5b:a2:9f:26:cf: - 7f:b5:7c:44:b1:7b:83:67:3c:41:ae:c6:66:64:e0:d2:ef:57: - a4:5c:1b:94:11:ce:28:e5:91:51:ef:e1:98:b7:3b:9a:cc:f7: - b9:85:76:eb:a8:2b:15:4a:cc:1a:a3:42:fa:be:1c:ce:b8:eb: - ee:12:d7:2f:e4:a8:cf:eb:2a:8f:78:e8:91:88:fa:c2:98:75: - 6a:4c:92:3f:2e:0d:e1:20:39:36:c6:2c:be:67:30:c3:f3:c3: - 65:81:ac:e3:3c:19:6a:21:ee:ea:f5:22:66:74:b2:07:53:7c: - 9a:0c:24:a6 ------BEGIN CERTIFICATE----- -MIIEtDCCA5ygAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBkjELMAkGA1UEBhMCVVMx -FjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYD -VQQKEw1SZWQgSGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UE -AxMHZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tMB4XDTA3MTEwOTE1 -NTAxNFoXDTE3MTEwNjE1NTAxNFowfjELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1h -c3NhY2h1c2V0dHMxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xFDASBgNVBAsTC0Vu -Z2luZWVyaW5nMQ8wDQYDVQQDEwZjbGllbnQxGDAWBgkqhkiG9w0BCQEWCWl0QGl0 -LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALCPTxyT1EPnh7ci -M1WoNaHEAbDx7SYjlqtlwsJU23kiA60/byLjYz/0IW36iMiPGs5VSXyYM2pnio3Z -NLDDQvRypEVDBXJdDNNC+JxmO7j4d+r2tpTXzF1iNCoUSAq8ZZT1emOYbIhMJdiV -8UA9ANL7Qyj6AvssgLPhM+eMzoqgGz0ETbyhtqJCi47zW0pyNH2NuthGIjXaXPjd -/G2eWSK3a+d4VlSfTNHiSiOjvATqRmtwivv+inPKNtXz6RfjItWzcAXn9ze3IbWQ -Uycn6jabAP81sGY93KkvldIhGJhPKAcJcCCosYKqpd+uD+M2vmiMnoDTM9D1hBfZ -D+udrwsCAwEAAaOCASYwggEiMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w -ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRxq7uRtwTeQzU2 -B4o1yr5cPuuxCTCBxwYDVR0jBIG/MIG8gBR+UOaH4e8nrEuMcEXJl7UN5r/wDaGB -mKSBlTCBkjELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxETAP -BgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMRQwEgYDVQQL -EwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJ -aXRAaXQuY29tggkA0OdWGLEA7UYwDQYJKoZIhvcNAQEEBQADggEBAM5Dbff4Smb9 -iixBpuADDmAw1EEBuka6gZdkaIMlnOEsA4styoXPvPrKIsRZKCOP/1CUYByQ3XX0 -1OqM+mFhCDVKj6qn6T126QgoVQHEA0LHrVi77pT3CbOam4vQJZUYpiLVLPy3u5EM -fAN/m4XesOSVqHOUJwoRTuNnrivM51EpECNXXD7n6kfg8I9bop8mz3+1fESxe4Nn -PEGuxmZk4NLvV6RcG5QRzijlkVHv4Zi3O5rM97mFduuoKxVKzBqjQvq+HM646+4S -1y/kqM/rKo946JGI+sKYdWpMkj8uDeEgOTbGLL5nMMPzw2WBrOM8GWoh7ur1ImZ0 -sgdTfJoMJKY= ------END CERTIFICATE----- diff --git a/libnm-core/tests/certs/test_ca_cert.der b/libnm-core/tests/certs/test_ca_cert.der deleted file mode 100644 index e844f65b2c..0000000000 Binary files a/libnm-core/tests/certs/test_ca_cert.der and /dev/null differ diff --git a/libnm-core/tests/certs/test_ca_cert.pem b/libnm-core/tests/certs/test_ca_cert.pem deleted file mode 100644 index faa3fc2905..0000000000 --- a/libnm-core/tests/certs/test_ca_cert.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEhjCCA26gAwIBAgIJAOZMXJYmXtbQMA0GCSqGSIb3DQEBBQUAMIGIMQswCQYD -VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw -FQYDVQQKEw5NeSBDb21wYW55IEx0ZDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxME -dGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAyMDIwMjIx -NTJaFw0xOTAxMzEwMjIxNTJaMIGIMQswCQYDVQQGEwJVUzESMBAGA1UECBMJQmVy -a3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55IEx0 -ZDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3DQEJARYN -dGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANZz -iHfFR6Gqdz5Gq1elSaf7J2tznfialPyMkRoqngSItrM3JWlkfBu3ZIpGSYG8+Z8H -JjaKh/zkCCH73HcjADCocm/XtgxlOlccDtBvfDqifb2dBikcmcfh0tX0o4JU9L+z -WP7sVcUkJG7C5811lA5pAsLVooJxrZnrta6XstGvFgTSxI2Y4Jowf0syM5b/AHIQ -+htsVhSyj1DWM9day3QsEMZl55SCxCLTB6ZIJLF6NmTYwdnzWWTQf4k7kcptZJU8 -Fqv60b/ATvvUf7S+ZMGLopFIIlmc1Kkn7VTseIKy4ycYuDpyimQy3Yw4flC00vhl -hTijH+5dlVOUFrRh0bsCAwEAAaOB8DCB7TAdBgNVHQ4EFgQUUjMuImZ5guVBLo07 -suXM+r6ZM44wgb0GA1UdIwSBtTCBsoAUUjMuImZ5guVBLo07suXM+r6ZM46hgY6k -gYswgYgxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcT -B05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMQ0wCwYDVQQLEwR0ZXN0 -MQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tggkA -5kxcliZe1tAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAZsWzGp9D -10NWf8ts3A9mhcEb8oDgKNpCOZF9gqr2usZygJjY9MX2n0n81T8XaWDk1wZLlcDW -hzIalCY8rpE57Dj3MEmdCmYr3BrAy6GVlc/MO7ffTHxogl9ouScSYo8ETTtNMKCg -zwkDnXjGzmb1e59DIXMVHBBbTmJXJbM8XP9A2azJkVUyE2fSdWksXMP0XklGbW2p -DksJ+8G1IWkyRhnINV5GZLLNAT5gBA6sUv/iqQKwk8r2dsweMPtLoLWZPAaZErYh -sthGy00Q0GJkmkJpQl8QIlPq5vylNcMUhvc8tmzwk+rDVUj3jTJWqFwMtnHAaNyC -FXl9ynWpe5J28w== ------END CERTIFICATE----- diff --git a/libnm-core/tests/certs/test_key_and_cert.pem b/libnm-core/tests/certs/test_key_and_cert.pem deleted file mode 100644 index c00495d0b0..0000000000 --- a/libnm-core/tests/certs/test_key_and_cert.pem +++ /dev/null @@ -1,119 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48 - -KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k -r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+ -PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj -5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/ -amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj -yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR -PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV -xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg -T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab -HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu -Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev -0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB -m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf -rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f -FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S -uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN -vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt -1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh -ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw -l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v -tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm -aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco -0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD -u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj -DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg ------END RSA PRIVATE KEY----- -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: md5WithRSAEncryption - Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com - Validity - Not Before: Feb 2 02:22:25 2009 GMT - Not After : Jan 31 02:22:25 2019 GMT - Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public Key: (2048 bit) - Modulus (2048 bit): - 00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3: - b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36: - d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86: - 68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10: - 25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9: - 40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31: - 5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79: - 84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41: - 7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c: - a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20: - ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5: - cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25: - bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f: - 74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9: - 77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93: - bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df: - 65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48: - 1c:83 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate - X509v3 Subject Key Identifier: - 34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B - X509v3 Authority Key Identifier: - keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E - DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com - serial:E6:4C:5C:96:26:5E:D6:D0 - - Signature Algorithm: md5WithRSAEncryption - 88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c: - a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b: - e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5: - b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4: - 39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2: - ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6: - 76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32: - 4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48: - e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12: - 9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e: - 6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df: - 88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f: - d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16: - a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03: - 6b:80:38:6e ------BEGIN CERTIFICATE----- -MIIErjCCA5agAwIBAgIBATANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCVVMx -EjAQBgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMO -TXkgQ29tcGFueSBMdGQxDTALBgNVBAsTBHRlc3QxDTALBgNVBAMTBHRlc3QxHDAa -BgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMDkwMjAyMDIyMjI1WhcNMTkw -MTMxMDIyMjI1WjCBizELMAkGA1UEBhMCVVMxEjAQBgNVBAgTCUJlcmtzaGlyZTEX -MBUGA1UEChMOTXkgQ29tcGFueSBMdGQxFDASBgNVBAsTC3Rlc3QtY2xpZW50MRQw -EgYDVQQDEwt0ZXN0LWNsaWVudDEjMCEGCSqGSIb3DQEJARYUdGVzdC1jbGllbnRA -dGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO0un79KTO -ZofMiy3Sw7j6vupTCJWeJ0oEeDGhNtLlQvV29yRxuNMQ/bdXhmgpAhvpkyuvwH49 -WBY0ECWFfigtQvw0f9ZPCue2uUBRyOWJYM1zUWNn4Vk2MV7Qh0tdl4pCItNC8oNi -eYRFW9ggl+LRNCNe7L+KQXytgFDzmxxRXeQpHMHGfKEAcA/2eXcDIvVLq3bKIKvh -TlNshmjp1g9ulUu1tc/TbNRz28A9HSAgcqs+Jbs/zV8td/3XC6jrDHPAP3QnF1bP -MZqp7cE5J8eq6XdI9G1WiTVceVv2L4yfk7wTHNB0XzAbFUNxjv8a32VlacKKWqsE -SoDeICmNSByDAgMBAAGjggEcMIIBGDAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf -Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNOlc2PzH -r/dd9BPTghrNUg9Kuwswgb0GA1UdIwSBtTCBsoAUUjMuImZ5guVBLo07suXM+r6Z -M46hgY6kgYswgYgxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO -BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMQ0wCwYDVQQL -EwR0ZXN0MQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3Qu -Y29tggkA5kxcliZe1tAwDQYJKoZIhvcNAQEEBQADggEBAIjE3cVKpo4fNmKAMWsr -hTQNbKfc4Vo83XRX21m+i/J5QC29m+GrDgN1IHUv6pf51H4VdcKC9bE35Isk1O8C -OxlqVrufw6W0xDmgZJZbw6gZdOwLzzPf8xLz4qsdfd4hZM2xoG96d4TUYopQ5nZd -rzrvGocOGjjE+Q0vFOAgMkwucNJxgtXlyRMsTrTIY2UdSOjDVm2IhFdlEx5CSLQD -JXFOEp0aiGXVcSE7Dr43HPCIa0UMDmzlYMuGv79AMMTPlPgcYNQb34gCekV+0cbz -B7mxjypVL753n9FGZAW3Z8WyrIxCj2pRpA0rFqTWOaX4Je1oJRO1Gaxs6ezuA2uA -OG4= ------END CERTIFICATE----- diff --git a/libnm-core/tests/meson.build b/libnm-core/tests/meson.build deleted file mode 100644 index df5209b4dc..0000000000 --- a/libnm-core/tests/meson.build +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later - -enum_sources = gnome.mkenums_simple( - 'nm-core-tests-enum-types', - sources: 'test-general-enums.h', - identifier_prefix: nm_id_prefix, - body_prefix: '#include "libnm-core/nm-default-libnm-core.h"', -) - -test_units = [ - 'test-compare', - 'test-crypto', - 'test-general', - 'test-keyfile', - 'test-secrets', - 'test-setting', - 'test-settings-defaults', -] - -foreach test_unit: test_units - exe = executable( - 'libnm-core-' + test_unit, - [test_unit + '.c'] + enum_sources, - dependencies: [ - libnm_core_dep, - libnm_core_nm_default_dep, - libnm_base_dep, - ], - c_args: [ - '-DG_LOG_DOMAIN="test"', - ], - link_with: libnm_systemd_logging_stub, - ) - - test( - 'libnm-core/' + test_unit, - test_script, - args: test_args + [exe.full_path()], - timeout: default_test_timeout, - ) -endforeach diff --git a/libnm-core/tests/nm-core-tests-enum-types.c.template b/libnm-core/tests/nm-core-tests-enum-types.c.template deleted file mode 100644 index 1160be86dc..0000000000 --- a/libnm-core/tests/nm-core-tests-enum-types.c.template +++ /dev/null @@ -1,35 +0,0 @@ -/*** BEGIN file-header ***/ -#include "config.h" - -#include "nm-core-tests-enum-types.h" - -#include "test-general-enums.h" -/*** END file-header ***/ - -/*** BEGIN value-header ***/ -GType -@enum_name@_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const G@Type@Value values[] = { -/*** END value-header ***/ - -/*** BEGIN value-production ***/ - { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, -/*** END value-production ***/ - -/*** BEGIN value-tail ***/ - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -/*** END value-tail ***/ diff --git a/libnm-core/tests/nm-core-tests-enum-types.h.template b/libnm-core/tests/nm-core-tests-enum-types.h.template deleted file mode 100644 index 62e82b77ae..0000000000 --- a/libnm-core/tests/nm-core-tests-enum-types.h.template +++ /dev/null @@ -1,21 +0,0 @@ -/*** BEGIN file-header ***/ -#ifndef __NM_CORE_TESTS_ENUM_TYPES_H__ -#define __NM_CORE_TESTS_ENUM_TYPES_H__ - -#include - -G_BEGIN_DECLS - -/*** END file-header ***/ - -/*** BEGIN enumeration-production ***/ -GType @enum_name@_get_type (void) G_GNUC_CONST; -#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) - -/*** END enumeration-production ***/ - -/*** BEGIN file-tail ***/ -G_END_DECLS - -#endif /* __NM_CORE_TESTS_ENUM_TYPES_H__ */ -/*** END file-tail ***/ diff --git a/libnm-core/tests/test-compare.c b/libnm-core/tests/test-compare.c deleted file mode 100644 index 27049e875a..0000000000 --- a/libnm-core/tests/test-compare.c +++ /dev/null @@ -1,231 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2014 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include -#include - -#include "nm-property-compare.h" - -#include "nm-utils/nm-test-utils.h" - -static void -compare_ints(void) -{ - GVariant *value1, *value2; - - value1 = g_variant_new_int32(5); - value2 = g_variant_new_int32(5); - g_assert(nm_property_compare(value1, value2) == 0); - - g_variant_unref(value2); - value2 = g_variant_new_int32(10); - g_assert(nm_property_compare(value1, value2) < 0); - - g_variant_unref(value2); - value2 = g_variant_new_int32(-1); - g_assert(nm_property_compare(value1, value2) > 0); - - g_variant_unref(value1); - g_variant_unref(value2); -} - -static void -compare_strings(void) -{ - GVariant * value1, *value2; - const char *str1 = "hello"; - const char *str2 = "world"; - - value1 = g_variant_new_string(str1); - value2 = g_variant_new_string(str1); - g_assert(nm_property_compare(value1, value2) == 0); - - g_variant_unref(value2); - value2 = g_variant_new_string(str2); - g_assert(nm_property_compare(value1, value2) < 0); - - g_assert(nm_property_compare(value2, value1) > 0); - - g_variant_unref(value1); - g_variant_unref(value2); -} - -static void -compare_strv(void) -{ - GVariant * value1, *value2; - const char *const strv1[] = {"foo", "bar", "baz", NULL}; - const char *const strv2[] = {"foo", "bar", "bar", NULL}; - const char *const strv3[] = {"foo", "bar", NULL}; - const char *const strv4[] = {"foo", "bar", "baz", "bam", NULL}; - - value1 = g_variant_new_strv(strv1, -1); - value2 = g_variant_new_strv(strv1, -1); - g_assert(nm_property_compare(value1, value2) == 0); - - g_variant_unref(value2); - value2 = g_variant_new_strv(strv2, -1); - g_assert(nm_property_compare(value1, value2) != 0); - - g_variant_unref(value2); - value2 = g_variant_new_strv(strv3, -1); - g_assert(nm_property_compare(value1, value2) != 0); - - g_variant_unref(value2); - value2 = g_variant_new_strv(strv4, -1); - g_assert(nm_property_compare(value1, value2) != 0); - - g_variant_unref(value1); - g_variant_unref(value2); -} - -static void -compare_arrays(void) -{ - GVariant *value1, *value2; - guint32 array[] = {0, 1, 2, 3, 4}; - - value1 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - array, - G_N_ELEMENTS(array), - sizeof(guint32)); - value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - array, - G_N_ELEMENTS(array), - sizeof(guint32)); - - g_assert(nm_property_compare(value1, value2) == 0); - - g_variant_unref(value2); - value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - array + 1, - G_N_ELEMENTS(array) - 1, - sizeof(guint32)); - g_assert(nm_property_compare(value1, value2) != 0); - - array[0] = 7; - g_variant_unref(value2); - value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - array, - G_N_ELEMENTS(array), - sizeof(guint32)); - g_assert(nm_property_compare(value1, value2) != 0); - - g_variant_unref(value1); - g_variant_unref(value2); -} - -static void -compare_str_hash(void) -{ - GVariant * value1, *value2; - GVariantBuilder builder; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); - g_variant_builder_add(&builder, "{ss}", "key1", "hello"); - g_variant_builder_add(&builder, "{ss}", "key2", "world"); - g_variant_builder_add(&builder, "{ss}", "key3", "!"); - value1 = g_variant_builder_end(&builder); - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); - g_variant_builder_add(&builder, "{ss}", "key3", "!"); - g_variant_builder_add(&builder, "{ss}", "key2", "world"); - g_variant_builder_add(&builder, "{ss}", "key1", "hello"); - value2 = g_variant_builder_end(&builder); - - g_assert(nm_property_compare(value1, value2) == 0); - - g_variant_unref(value2); - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); - g_variant_builder_add(&builder, "{ss}", "key1", "hello"); - g_variant_builder_add(&builder, "{ss}", "key3", "!"); - value2 = g_variant_builder_end(&builder); - - g_assert(nm_property_compare(value1, value2) != 0); - g_assert(nm_property_compare(value2, value1) != 0); - - g_variant_unref(value2); - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); - g_variant_builder_add(&builder, "{ss}", "key1", "hello"); - g_variant_builder_add(&builder, "{ss}", "key2", "moon"); - g_variant_builder_add(&builder, "{ss}", "key3", "!"); - value2 = g_variant_builder_end(&builder); - - g_assert(nm_property_compare(value1, value2) != 0); - - g_variant_unref(value1); - g_variant_unref(value2); -} - -static void -compare_ip6_addresses(void) -{ - GVariant * value1, *value2; - struct in6_addr addr1; - struct in6_addr addr2; - struct in6_addr addr3; - guint32 prefix1 = 64; - guint32 prefix2 = 64; - guint32 prefix3 = 0; - - inet_pton(AF_INET6, "1:2:3:4:5:6:7:8", &addr1); - inet_pton(AF_INET6, "ffff:2:3:4:5:6:7:8", &addr2); - inet_pton(AF_INET6, "::", &addr3); - - value1 = g_variant_new( - "(@ayu@ay)", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr1.s6_addr, 16, 1), - prefix1, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1)); - - value2 = g_variant_new( - "(@ayu@ay)", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr1.s6_addr, 16, 1), - prefix1, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1)); - - g_assert(nm_property_compare(value1, value2) == 0); - - g_variant_unref(value2); - value2 = g_variant_new( - "(@ayu@ay)", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr2.s6_addr, 16, 1), - prefix2, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1)); - - g_assert(nm_property_compare(value1, value2) != 0); - - g_variant_unref(value2); - value2 = g_variant_new( - "(@ayu@ay)", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1), - prefix3, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1)); - - g_assert(nm_property_compare(value1, value2) != 0); - - g_variant_unref(value1); - g_variant_unref(value2); -} - -NMTST_DEFINE(); - -int -main(int argc, char *argv[]) -{ - nmtst_init(&argc, &argv, TRUE); - - g_test_add_func("/libnm/compare/ints", compare_ints); - g_test_add_func("/libnm/compare/strings", compare_strings); - g_test_add_func("/libnm/compare/strv", compare_strv); - g_test_add_func("/libnm/compare/arrays", compare_arrays); - g_test_add_func("/libnm/compare/str_hash", compare_str_hash); - g_test_add_func("/libnm/compare/ip6_addresses", compare_ip6_addresses); - - return g_test_run(); -} diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c deleted file mode 100644 index 4e288b7b65..0000000000 --- a/libnm-core/tests/test-crypto.c +++ /dev/null @@ -1,455 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Dan Williams - * Copyright (C) 2007 - 2011 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include -#include -#include - -#include "nm-crypto-impl.h" -#include "nm-utils.h" -#include "nm-errors.h" -#include "nm-core-internal.h" - -#include "nm-utils/nm-test-utils.h" - -#define TEST_CERT_DIR NM_BUILD_SRCDIR "/libnm-core/tests/certs" - -#if 0 -static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; -static const char *pem_rsa_key_end = "-----END RSA PRIVATE KEY-----"; - -static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----"; -static const char *pem_dsa_key_end = "-----END DSA PRIVATE KEY-----"; - -static void -dump_key_to_pem (const char *key, gsize key_len, int key_type) -{ - char *b64 = NULL; - GString *str = NULL; - const char *start_tag; - const char *end_tag; - char *p; - - switch (key_type) { - case NM_CRYPTO_KEY_TYPE_RSA: - start_tag = pem_rsa_key_begin; - end_tag = pem_rsa_key_end; - break; - case NM_CRYPTO_KEY_TYPE_DSA: - start_tag = pem_dsa_key_begin; - end_tag = pem_dsa_key_end; - break; - default: - g_warning ("Unknown key type %d", key_type); - return; - } - - b64 = g_base64_encode ((const unsigned char *) key, key_len); - if (!b64) { - g_warning ("Couldn't base64 encode the key."); - goto out; - } - - str = g_string_new (NULL); - - g_string_append (str, start_tag); - g_string_append_c (str, '\n'); - - for (p = b64; p < (b64 + strlen (b64)); p += 64) { - g_string_append_len (str, p, strnlen (p, 64)); - g_string_append_c (str, '\n'); - } - - g_string_append (str, end_tag); - g_string_append_c (str, '\n'); - - g_message ("Decrypted private key:\n\n%s", str->str); - -out: - g_free (b64); - if (str) - g_string_free (str, TRUE); -} -#endif - -static void -test_cert(gconstpointer test_data) -{ - gs_free char * path = NULL; - gs_unref_bytes GBytes *cert = NULL; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - GError * error = NULL; - gboolean success; - - path = g_build_filename(TEST_CERT_DIR, (const char *) test_data, NULL); - - success = nm_crypto_load_and_verify_certificate(path, &format, &cert, &error); - nmtst_assert_success(success, error); - g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_X509); - - g_assert(nm_utils_file_is_certificate(path)); -} - -static void -test_load_private_key(const char *path, - const char *password, - const char *decrypted_path, - int expected_error) -{ - NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - gboolean is_encrypted = FALSE; - gs_unref_bytes GBytes *array = NULL; - GError * error = NULL; - - g_assert(nm_utils_file_is_private_key(path, &is_encrypted)); - g_assert(is_encrypted); - - array = nmtst_crypto_decrypt_openssl_private_key(path, password, &key_type, &error); - /* Even if the password is wrong, we should determine the key type */ - g_assert_cmpint(key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); - - if (expected_error != -1) { - g_assert(array == NULL); - g_assert_error(error, NM_CRYPTO_ERROR, expected_error); - g_clear_error(&error); - return; - } - - if (password == NULL) { - g_assert(array == NULL); - g_assert_no_error(error); - return; - } - - g_assert(array != NULL); - - if (decrypted_path) { - gs_free char *contents = NULL; - gsize length; - - /* Compare the crypto decrypted key against a known-good decryption */ - if (!g_file_get_contents(decrypted_path, &contents, &length, NULL)) - g_assert_not_reached(); - g_assert(nm_utils_gbytes_equal_mem(array, contents, length)); - } -} - -static void -test_load_pkcs12(const char *path, const char *password, int expected_error) -{ - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gboolean is_encrypted = FALSE; - GError * error = NULL; - - g_assert(nm_utils_file_is_private_key(path, NULL)); - - format = nm_crypto_verify_private_key(path, password, &is_encrypted, &error); - if (expected_error != -1) { - g_assert_error(error, NM_CRYPTO_ERROR, expected_error); - g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); - g_clear_error(&error); - } else { - g_assert_no_error(error); - g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); - g_assert(is_encrypted); - } -} - -static void -test_load_pkcs12_no_password(const char *path) -{ - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gboolean is_encrypted = FALSE; - GError * error = NULL; - - g_assert(nm_utils_file_is_private_key(path, NULL)); - - /* We should still get a valid returned crypto file format */ - format = nm_crypto_verify_private_key(path, NULL, &is_encrypted, &error); - g_assert_no_error(error); - g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); - g_assert(is_encrypted); -} - -static void -test_is_pkcs12(const char *path, gboolean expect_fail) -{ - gboolean is_pkcs12; - GError * error = NULL; - - is_pkcs12 = nm_crypto_is_pkcs12_file(path, &error); - - if (expect_fail) { - g_assert_error(error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA); - g_assert(!is_pkcs12); - g_clear_error(&error); - } else { - g_assert_no_error(error); - g_assert(is_pkcs12); - } -} - -static void -test_load_pkcs8(const char *path, const char *password, int expected_error) -{ - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gboolean is_encrypted = FALSE; - GError * error = NULL; - - g_assert(nm_utils_file_is_private_key(path, NULL)); - - format = nm_crypto_verify_private_key(path, password, &is_encrypted, &error); - if (expected_error != -1) { - g_assert_error(error, NM_CRYPTO_ERROR, expected_error); - g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); - g_clear_error(&error); - } else { - g_assert_no_error(error); - g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_RAW_KEY); - g_assert(is_encrypted); - } -} - -static void -test_encrypt_private_key(const char *path, const char *password) -{ - NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - gs_unref_bytes GBytes *array = NULL; - gs_unref_bytes GBytes *encrypted = NULL; - gs_unref_bytes GBytes *re_decrypted = NULL; - GError * error = NULL; - - array = nmtst_crypto_decrypt_openssl_private_key(path, password, &key_type, &error); - nmtst_assert_success(array, error); - g_assert_cmpint(key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); - - /* Now re-encrypt the private key */ - encrypted = nmtst_crypto_rsa_key_encrypt(g_bytes_get_data(array, NULL), - g_bytes_get_size(array), - password, - NULL, - &error); - nmtst_assert_success(encrypted, error); - - /* Then re-decrypt the private key */ - key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - re_decrypted = nmtst_crypto_decrypt_openssl_private_key_data(g_bytes_get_data(encrypted, NULL), - g_bytes_get_size(encrypted), - password, - &key_type, - &error); - nmtst_assert_success(re_decrypted, error); - g_assert_cmpint(key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); - - /* Compare the original decrypted key with the re-decrypted key */ - g_assert(g_bytes_equal(array, re_decrypted)); -} - -static void -test_key(gconstpointer test_data) -{ - char **parts, *path, *password, *decrypted_path; - int len; - - parts = g_strsplit((const char *) test_data, ", ", -1); - len = g_strv_length(parts); - if (len != 2 && len != 3) - g_error("wrong number of arguments (, , [])"); - - path = g_build_filename(TEST_CERT_DIR, parts[0], NULL); - password = parts[1]; - decrypted_path = parts[2] ? g_build_filename(TEST_CERT_DIR, parts[2], NULL) : NULL; - - test_is_pkcs12(path, TRUE); - test_load_private_key(path, password, decrypted_path, -1); - test_load_private_key(path, "blahblahblah", NULL, NM_CRYPTO_ERROR_DECRYPTION_FAILED); - test_load_private_key(path, NULL, NULL, -1); - test_encrypt_private_key(path, password); - - g_free(path); - g_free(decrypted_path); - g_strfreev(parts); -} - -static void -test_key_decrypted(gconstpointer test_data) -{ - const char *file = (const char *) test_data; - gboolean is_encrypted = FALSE; - char * path; - - path = g_build_filename(TEST_CERT_DIR, file, NULL); - - g_assert(nm_utils_file_is_private_key(path, &is_encrypted)); - g_assert(!is_encrypted); - - g_free(path); -} - -static void -test_pkcs12(gconstpointer test_data) -{ - char **parts, *path, *password; - - parts = g_strsplit((const char *) test_data, ", ", -1); - if (g_strv_length(parts) != 2) - g_error("wrong number of arguments (, )"); - - path = g_build_filename(TEST_CERT_DIR, parts[0], NULL); - password = parts[1]; - - test_is_pkcs12(path, FALSE); - test_load_pkcs12(path, password, -1); - test_load_pkcs12(path, "blahblahblah", NM_CRYPTO_ERROR_DECRYPTION_FAILED); - test_load_pkcs12_no_password(path); - - g_free(path); - g_strfreev(parts); -} - -static void -test_pkcs8(gconstpointer test_data) -{ - char **parts, *path, *password; - - parts = g_strsplit((const char *) test_data, ", ", -1); - if (g_strv_length(parts) != 2) - g_error("wrong number of arguments (, )"); - - path = g_build_filename(TEST_CERT_DIR, parts[0], NULL); - password = parts[1]; - - test_is_pkcs12(path, TRUE); - /* Note: NSS and gnutls < 3.5.4 don't support all the ciphers that openssl - * can use with PKCS#8 and thus the password can't be actually verified with - * such libraries. - */ - test_load_pkcs8(path, password, -1); - - g_free(path); - g_strfreev(parts); -} - -#define SALT "sodium chloride" -#define SHORT_PASSWORD "short" -#define LONG_PASSWORD "this is a longer password than the short one" -#define SHORT_DIGEST 16 -#define LONG_DIGEST 57 - -struct { - const char *salt, *password; - gsize digest_size; - const char *result; -} md5_tests[] = { - {NULL, SHORT_PASSWORD, SHORT_DIGEST, "4f09daa9d95bcb166a302407a0e0babe"}, - {NULL, - SHORT_PASSWORD, - LONG_DIGEST, - "4f09daa9d95bcb166a302407a0e0babeb7d62e5baf706830d007c253f0fe7584ad7e92dc00a599ec277293c298ae7" - "0ee3904c348e23be61c91"}, - {SALT, SHORT_PASSWORD, SHORT_DIGEST, "774771f7292210233b5724991d1f9894"}, - {SALT, - SHORT_PASSWORD, - LONG_DIGEST, - "774771f7292210233b5724991d1f98941a6ffdb45e4dc7fa04b1fa6aceed379c1ade0577bc8f261d109942ed57369" - "21c052664d72e0d5bade9"}, - {NULL, LONG_PASSWORD, SHORT_DIGEST, "e9c03517f81ff29bb777dac21fb1699c"}, - {NULL, - LONG_PASSWORD, - LONG_DIGEST, - "e9c03517f81ff29bb777dac21fb1699c50968c7ccd8db4f0a59d00ffd87b05876d45f25a927d51a8400c35af60fbd" - "64584349a8b7435d62fd9"}, - {SALT, LONG_PASSWORD, SHORT_DIGEST, "4e5c076e2f85f5e03994acbf3a9e10d6"}, - {SALT, - LONG_PASSWORD, - LONG_DIGEST, - "4e5c076e2f85f5e03994acbf3a9e10d61a6969c9fdf47ae8b1f7e2725b3767b05cc974bfcb5344b630c91761e015e" - "09d7794b5065662533bc9"}, - {NULL, "", SHORT_DIGEST, "d41d8cd98f00b204e9800998ecf8427e"}, - {SALT, "", SHORT_DIGEST, "7df1e0494c977195005d82a1809685e4"}, -}; - -static void -test_md5(void) -{ - char digest[LONG_DIGEST], *hex; - int i; - - for (i = 0; i < G_N_ELEMENTS(md5_tests); i++) { - memset(digest, 0, sizeof(digest)); - nm_crypto_md5_hash((const guint8 *) md5_tests[i].salt, - /* nm_crypto_md5_hash() used to clamp salt_len to 8. It - * doesn't any more, so we need to do it here now to - * get output that matches md5_tests[i].result. - */ - md5_tests[i].salt ? 8 : 0, - (const guint8 *) md5_tests[i].password, - strlen(md5_tests[i].password), - (guint8 *) digest, - md5_tests[i].digest_size); - - hex = nm_utils_bin2hexstr(digest, md5_tests[i].digest_size, -1); - g_assert_cmpstr(hex, ==, md5_tests[i].result); - g_free(hex); - } -} - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - GError * error = NULL; - gboolean success; - int ret; - - nmtst_init(&argc, &argv, TRUE); - - success = _nm_crypto_init(&error); - g_assert_no_error(error); - g_assert(success); - - g_test_add_data_func("/libnm/crypto/cert/pem", "test_ca_cert.pem", test_cert); - g_test_add_data_func("/libnm/crypto/cert/pem-2", "test2_ca_cert.pem", test_cert); - g_test_add_data_func("/libnm/crypto/cert/der", "test_ca_cert.der", test_cert); - g_test_add_data_func("/libnm/crypto/cert/pem-no-ending-newline", - "ca-no-ending-newline.pem", - test_cert); - g_test_add_data_func("/libnm/crypto/cert/pem-combined", "test_key_and_cert.pem", test_cert); - g_test_add_data_func("/libnm/crypto/cert/pem-combined-2", "test2_key_and_cert.pem", test_cert); - - g_test_add_data_func("/libnm/crypto/key/padding-6", - "test_key_and_cert.pem, test, test-key-only-decrypted.der", - test_key); - g_test_add_data_func("/libnm/crypto/key/key-only", - "test-key-only.pem, test, test-key-only-decrypted.der", - test_key); - g_test_add_data_func("/libnm/crypto/key/padding-8", - "test2_key_and_cert.pem, 12345testing", - test_key); - g_test_add_data_func("/libnm/crypto/key/aes-128", - "test-aes-128-key.pem, test-aes-password", - test_key); - g_test_add_data_func("/libnm/crypto/key/aes-256", - "test-aes-256-key.pem, test-aes-password", - test_key); - g_test_add_data_func("/libnm/crypto/key/decrypted", - "test-key-only-decrypted.pem", - test_key_decrypted); - - g_test_add_data_func("/libnm/crypto/PKCS#12/1", "test-cert.p12, test", test_pkcs12); - g_test_add_data_func("/libnm/crypto/PKCS#12/2", "test2-cert.p12, 12345testing", test_pkcs12); - - g_test_add_data_func("/libnm/crypto/PKCS#8", "pkcs8-enc-key.pem, 1234567890", test_pkcs8); - - g_test_add_func("/libnm/crypto/md5", test_md5); - - ret = g_test_run(); - - return ret; -} diff --git a/libnm-core/tests/test-general-enums.h b/libnm-core/tests/test-general-enums.h deleted file mode 100644 index b3163e2330..0000000000 --- a/libnm-core/tests/test-general-enums.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef _NM_TEST_GENERAL_ENUMS_H_ -#define _NM_TEST_GENERAL_ENUMS_H_ - -typedef enum { - NM_TEST_GENERAL_BOOL_ENUM_NO = 0, - NM_TEST_GENERAL_BOOL_ENUM_YES = 1, - NM_TEST_GENERAL_BOOL_ENUM_MAYBE = 2, - NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN = 3, - NM_TEST_GENERAL_BOOL_ENUM_INVALID = 4, /*< skip >*/ - NM_TEST_GENERAL_BOOL_ENUM_67 = 67, - NM_TEST_GENERAL_BOOL_ENUM_46 = 64, -} NMTestGeneralBoolEnum; - -typedef enum { - NM_TEST_GENERAL_META_FLAGS_NONE = 0, - NM_TEST_GENERAL_META_FLAGS_FOO = (1 << 0), - NM_TEST_GENERAL_META_FLAGS_BAR = (1 << 1), - NM_TEST_GENERAL_META_FLAGS_BAZ = (1 << 2), - NM_TEST_GENERAL_META_FLAGS_0x8 = (1 << 3), - NM_TEST_GENERAL_META_FLAGS_0x4 = (1 << 4), -} NMTestGeneralMetaFlags; - -typedef enum { /*< flags >*/ - NM_TEST_GENERAL_COLOR_FLAGS_WHITE = 1, /*< skip >*/ - NM_TEST_GENERAL_COLOR_FLAGS_BLUE = 2, - NM_TEST_GENERAL_COLOR_FLAGS_RED = 4, - NM_TEST_GENERAL_COLOR_FLAGS_GREEN = 8, -} NMTestGeneralColorFlags; - -#endif /* _NM_TEST_GENERAL_ENUMS_H_ */ diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c deleted file mode 100644 index 885319fc16..0000000000 --- a/libnm-core/tests/test-general.c +++ /dev/null @@ -1,10654 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2008 - 2018 Red Hat, Inc. - */ - -#define NM_GLIB_COMPAT_H_TEST - -#include "libnm-core/nm-default-libnm-core.h" - -#include -#include -#include -#include -#include - -#include "nm-std-aux/c-list-util.h" -#include "nm-glib-aux/nm-enum-utils.h" -#include "nm-glib-aux/nm-str-buf.h" -#include "nm-glib-aux/nm-json-aux.h" -#include "nm-base/nm-base.h" -#include "systemd/nm-sd-utils-shared.h" - -#include "nm-utils.h" -#include "nm-setting-private.h" -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-core-internal.h" -#include "nm-core-tests-enum-types.h" -#include "nm-team-utils.h" - -#include "nm-setting-8021x.h" -#include "nm-setting-adsl.h" -#include "nm-setting-bluetooth.h" -#include "nm-setting-bond.h" -#include "nm-setting-bridge.h" -#include "nm-setting-bridge-port.h" -#include "nm-setting-cdma.h" -#include "nm-setting-connection.h" -#include "nm-setting-ethtool.h" -#include "nm-setting-generic.h" -#include "nm-setting-gsm.h" -#include "nm-setting-infiniband.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-setting-olpc-mesh.h" -#include "nm-setting-ppp.h" -#include "nm-setting-pppoe.h" -#include "nm-setting-serial.h" -#include "nm-setting-team.h" -#include "nm-setting-team-port.h" -#include "nm-setting-user.h" -#include "nm-setting-vlan.h" -#include "nm-setting-vpn.h" -#include "nm-setting-wimax.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireless.h" -#include "nm-setting-wireless-security.h" -#include "nm-setting-wpan.h" -#include "nm-simple-connection.h" -#include "nm-keyfile-internal.h" -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-base/nm-ethtool-base.h" -#include "nm-base/nm-ethtool-utils-base.h" - -#include "test-general-enums.h" - -#include "nm-utils/nm-test-utils.h" - -/* When passing a "bool" typed argument to a variadic function that - * expects a gboolean, the compiler will promote the integer type - * to have at least size (int). That way: - * g_object_set (obj, PROP_BOOL, bool_val, NULL); - * will just work correctly. */ -G_STATIC_ASSERT(sizeof(gboolean) == sizeof(int)); -G_STATIC_ASSERT(sizeof(bool) <= sizeof(int)); - -/*****************************************************************************/ - -/* NM_UTILS_HWADDR_LEN_MAX is public API of libnm(-core) and _NM_UTILS_HWADDR_LEN_MAX - * is internal API. They are the same, but the latter can be used without including libnm-core. */ -G_STATIC_ASSERT(NM_UTILS_HWADDR_LEN_MAX == _NM_UTILS_HWADDR_LEN_MAX); - -/*****************************************************************************/ - -static void -test_nm_ascii_spaces(void) -{ - int i; - const char *const S = NM_ASCII_SPACES; - - for (i = 0; S[i]; i++) - g_assert(!strchr(&S[i + 1], S[i])); - - for (i = 0; S[i] != '\0'; i++) - g_assert(g_ascii_isspace(S[i])); - - g_assert(!g_ascii_isspace((char) 0)); - for (i = 1; i < 0x100; i++) { - if (g_ascii_isspace((char) i)) - g_assert(strchr(S, (char) i)); - else - g_assert(!strchr(S, (char) i)); - } -} - -/*****************************************************************************/ - -static void -test_wired_wake_on_lan_enum(void) -{ - nm_auto_unref_gtypeclass GFlagsClass *flags_class = NULL; - gs_unref_hashtable GHashTable *vals = g_hash_table_new(nm_direct_hash, NULL); - guint i; - - G_STATIC_ASSERT_EXPR(sizeof(NMSettingWiredWakeOnLan) == sizeof(_NMSettingWiredWakeOnLan)); - G_STATIC_ASSERT_EXPR(sizeof(NMSettingWiredWakeOnLan) < sizeof(gint64)); - - G_STATIC_ASSERT_EXPR(sizeof(NMSettingWiredWakeOnLan) < sizeof(gint64)); - g_assert((((gint64)((NMSettingWiredWakeOnLan) -1)) < 0) - == (((gint64)((_NMSettingWiredWakeOnLan) -1)) < 0)); - -#define _E(n) \ - G_STMT_START \ - { \ - G_STATIC_ASSERT_EXPR(n == (gint64) _##n); \ - G_STATIC_ASSERT_EXPR(_##n == (gint64) n); \ - g_assert(_##n == _NM_SETTING_WIRED_WAKE_ON_LAN_CAST(n)); \ - if (!g_hash_table_add(vals, GUINT_TO_POINTER(n))) \ - g_assert_not_reached(); \ - } \ - G_STMT_END - _E(NM_SETTING_WIRED_WAKE_ON_LAN_NONE); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_PHY); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_ARP); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_ALL); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE); - _E(NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS); -#undef _E - - flags_class = G_FLAGS_CLASS(g_type_class_ref(NM_TYPE_SETTING_WIRED_WAKE_ON_LAN)); - for (i = 0; i < flags_class->n_values; i++) { - const GFlagsValue *value = &flags_class->values[i]; - - if (!g_hash_table_contains(vals, GUINT_TO_POINTER(value->value))) { - g_error("The enum value %s from NMSettingWiredWakeOnLan is not checked for " - "_NMSettingWiredWakeOnLan", - value->value_name); - } - } -} - -/*****************************************************************************/ - -typedef struct _nm_packed { - int v0; - char v1; - double v2; - guint8 v3; -} TestHashStruct; - -static void -_test_hash_struct(int v0, char v1, double v2, guint8 v3) -{ - const TestHashStruct s = { - .v0 = v0, - .v1 = v1, - .v2 = v2, - .v3 = v3, - }; - NMHashState h; - guint hh; - - nm_hash_init(&h, 100); - nm_hash_update(&h, &s, sizeof(s)); - hh = nm_hash_complete(&h); - - nm_hash_init(&h, 100); - nm_hash_update_val(&h, v0); - nm_hash_update_val(&h, v1); - nm_hash_update_val(&h, v2); - nm_hash_update_val(&h, v3); - g_assert_cmpint(hh, ==, nm_hash_complete(&h)); - - nm_hash_init(&h, 100); - nm_hash_update_vals(&h, v0, v1, v2, v3); - g_assert_cmpint(hh, ==, nm_hash_complete(&h)); -} - -static guint -_test_hash_str(const char *str) -{ - NMHashState h; - guint v, v2; - const guint SEED = 10; - - nm_hash_init(&h, SEED); - nm_hash_update_str0(&h, str); - v = nm_hash_complete(&h); - - /* assert that hashing a string and a buffer yields the - * same result. - * - * I think that is a desirable property. */ - nm_hash_init(&h, SEED); - nm_hash_update_mem(&h, str, strlen(str)); - v2 = nm_hash_complete(&h); - - g_assert(v == v2); - return v; -} - -#define _test_hash_vals(type, ...) \ - G_STMT_START \ - { \ - NMHashState h0, h1, h2, h3; \ - const type v[] = {__VA_ARGS__}; \ - guint h; \ - guint i; \ - \ - nm_hash_init(&h0, 10); \ - nm_hash_init(&h1, 10); \ - nm_hash_init(&h2, 10); \ - nm_hash_init(&h3, 10); \ - \ - /* assert that it doesn't matter, whether we hash the values individually, - * or all at once, or via the convenience macros nm_hash_update_val() - * and nm_hash_update_vals(). */ \ - for (i = 0; i < G_N_ELEMENTS(v); i++) { \ - nm_hash_update(&h0, &v[i], sizeof(type)); \ - nm_hash_update_val(&h1, v[i]); \ - } \ - nm_hash_update_vals(&h2, __VA_ARGS__); \ - nm_hash_update(&h3, v, sizeof(v)); \ - \ - h = nm_hash_complete(&h0); \ - g_assert_cmpint(h, ==, nm_hash_complete(&h1)); \ - g_assert_cmpint(h, ==, nm_hash_complete(&h2)); \ - g_assert_cmpint(h, ==, nm_hash_complete(&h3)); \ - } \ - G_STMT_END - -static void -test_nm_hash(void) -{ - g_assert(nm_hash_static(0)); - g_assert(nm_hash_static(777)); - - g_assert(nm_hash_str(NULL)); - g_assert(nm_hash_str("")); - g_assert(nm_hash_str("a")); - - g_assert(nm_hash_ptr(NULL)); - g_assert(nm_hash_ptr("")); - g_assert(nm_hash_ptr("a")); - - _test_hash_str(""); - _test_hash_str("a"); - _test_hash_str("aa"); - _test_hash_str("diceros bicornis longipes"); - - /* assert that nm_hash_update_vals() is the same as calling nm_hash_update_val() multiple times. */ - _test_hash_vals(int, 1); - _test_hash_vals(int, 1, 2); - _test_hash_vals(int, 1, 2, 3); - _test_hash_vals(int, 1, 2, 3, 4); - _test_hash_vals(long, 1l); - _test_hash_vals(long, 1l, 2l, 3l, 4l, 5l); - - _test_hash_struct(10, 'a', 5.4, 7); - _test_hash_struct(-10, '\0', -5.4e49, 255); - - g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 1, 0), ==, 0x002); - g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 1, 1), ==, 0x003); - g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 1, 1, 0, 0, 0, 0), ==, 0x030); - g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 1, 1, 0, 0, 0, 1), ==, 0x031); - g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); - g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); - g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 0, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); - g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 1, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x131); -} - -/*****************************************************************************/ - -static void -test_nm_g_slice_free_fcn(void) -{ - gpointer p; - struct { - char a1; - char a2; - } xx; - - p = g_slice_new(gint64); - (nm_g_slice_free_fcn(gint64))(p); - - p = g_slice_new(gint32); - (nm_g_slice_free_fcn(gint32))(p); - - p = g_slice_new(int); - (nm_g_slice_free_fcn(int))(p); - - p = g_slice_new(gint64); - nm_g_slice_free_fcn_gint64(p); - - p = g_slice_alloc(sizeof(xx)); - (nm_g_slice_free_fcn(xx))(p); -} - -/*****************************************************************************/ - -static void -_do_test_nm_utils_strsplit_set_f_one(NMUtilsStrsplitSetFlags flags, - const char * str, - gsize words_len, - const char *const * exp_words) -{ -#define DELIMITERS " \n" -#define DELIMITERS_C ' ', '\n' - - gs_free const char **words = NULL; - gsize i, j, k; - const gboolean f_allow_escaping = - NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING); - const gboolean f_preserve_empty = - NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY); - const char * s1; - gsize initial_offset; - gs_strfreev char **words_g = NULL; - - g_assert(!NM_FLAGS_ANY(flags, - ~(NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING - | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY))); - - /* assert that the expected words are valid (and don't contain unescaped delimiters). */ - for (i = 0; i < words_len; i++) { - const char *w = exp_words[i]; - - g_assert(w); - if (!f_preserve_empty) - g_assert(w[0]); - for (k = 0; w[k];) { - if (f_allow_escaping && w[k] == '\\') { - k++; - if (w[k] == '\0') - break; - k++; - continue; - } - g_assert(!NM_IN_SET(w[k], DELIMITERS_C)); - k++; - } - if (!f_allow_escaping) - g_assert(!NM_STRCHAR_ANY(w, ch, NM_IN_SET(ch, DELIMITERS_C))); - } - - initial_offset = (f_preserve_empty || !str) ? 0u : strspn(str, DELIMITERS); - - /* first compare our expected values with what g_strsplit_set() would - * do. */ - words_g = str ? g_strsplit_set(str, DELIMITERS, -1) : NULL; - if (str == NULL) { - g_assert_cmpint(words_len, ==, 0); - g_assert(!words_g); - } else if (nm_streq0(str, "")) { - g_assert_cmpint(words_len, ==, 0); - g_assert(words_g); - g_assert(!words_g[0]); - } else { - g_assert(words_g); - g_assert(words_g[0]); - if (!f_allow_escaping) { - if (!f_preserve_empty) { - for (i = 0, j = 0; words_g[i]; i++) { - if (words_g[i][0] == '\0') - g_free(words_g[i]); - else - words_g[j++] = words_g[i]; - } - words_g[j] = NULL; - } - if (f_preserve_empty) - g_assert_cmpint(words_len, >, 0); - for (i = 0; i < words_len; i++) { - g_assert(exp_words[i]); - g_assert_cmpstr(exp_words[i], ==, words_g[i]); - } - g_assert(words_g[words_len] == NULL); - g_assert_cmpint(NM_PTRARRAY_LEN(words_g), ==, words_len); - g_assert(nm_utils_strv_cmp_n(exp_words, words_len, words_g, -1) == 0); - } - } - - if (flags == NM_UTILS_STRSPLIT_SET_FLAGS_NONE && nmtst_get_rand_bool()) - words = nm_utils_strsplit_set(str, DELIMITERS); - else if (flags == NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY && nmtst_get_rand_bool()) - words = nm_utils_strsplit_set_with_empty(str, DELIMITERS); - else - words = nm_utils_strsplit_set_full(str, DELIMITERS, flags); - - g_assert_cmpint(NM_PTRARRAY_LEN(words), ==, words_len); - - if (words_len == 0) { - g_assert(!words); - g_assert(!str || NM_STRCHAR_ALL(str, ch, NM_IN_SET(ch, DELIMITERS_C))); - return; - } - - g_assert(words); - for (i = 0; i < words_len; i++) - g_assert_cmpstr(exp_words[i], ==, words[i]); - g_assert(words[words_len] == NULL); - - g_assert(nm_utils_strv_cmp_n(exp_words, words_len, words, -1) == 0); - - s1 = words[0]; - g_assert(s1 >= (char *) &words[words_len + 1]); - s1 = &s1[strlen(str)]; - for (i = 1; i < words_len; i++) { - g_assert(&(words[i - 1])[strlen(words[i - 1])] < words[i]); - g_assert(words[i] <= s1); - } - - /* while strsplit removes all delimiters, we can relatively easily find them - * in the original string. Assert that the original string and the pointer offsets - * of words correspond. In particular, find idx_delim_after and idx_delim_before - * to determine which delimiter was after/before a word. */ - { - gsize idx_word_start; - gsize idx_delim_after_old = G_MAXSIZE; - - idx_word_start = initial_offset; - for (i = 0; i < words_len; i++) { - const gsize l_i = strlen(words[i]); - gsize idx_delim_after; - gsize idx_delim_before; - - /* find the delimiter *after* words[i]. We can do that by looking at the next - * word and calculating the pointer difference. - * - * The delimiter after the very last word is '\0' and requires strlen() to find. */ - idx_delim_after = initial_offset + ((words[i] - words[0]) + l_i); - if (idx_delim_after != idx_word_start + l_i) { - g_assert(!f_preserve_empty); - g_assert_cmpint(idx_word_start + l_i, <, idx_delim_after); - idx_word_start = idx_delim_after - l_i; - } - if (i + 1 < words_len) { - gsize x = initial_offset + ((words[i + 1] - words[0]) - 1); - - if (idx_delim_after != x) { - g_assert(!f_preserve_empty); - g_assert_cmpint(idx_delim_after, <, x); - for (k = idx_delim_after; k <= x; k++) - g_assert(NM_IN_SET(str[k], DELIMITERS_C)); - } - g_assert(NM_IN_SET(str[idx_delim_after], DELIMITERS_C)); - } else { - if (f_preserve_empty) - g_assert(NM_IN_SET(str[idx_delim_after], '\0')); - else - g_assert(NM_IN_SET(str[idx_delim_after], '\0', DELIMITERS_C)); - } - - /* find the delimiter *before* words[i]. */ - if (i == 0) { - /* there is only a delimiter *before*, with !f_preserve_empty and leading - * delimiters. */ - idx_delim_before = G_MAXSIZE; - if (initial_offset > 0) { - g_assert(!f_preserve_empty); - idx_delim_before = initial_offset - 1; - } - } else - idx_delim_before = initial_offset + (words[i] - words[0]) - 1; - if (idx_delim_before != G_MAXSIZE) - g_assert(NM_IN_SET(str[idx_delim_before], DELIMITERS_C)); - if (idx_delim_after_old != idx_delim_before) { - g_assert(!f_preserve_empty); - if (i == 0) { - g_assert_cmpint(initial_offset, >, 0); - g_assert_cmpint(idx_delim_before, !=, G_MAXSIZE); - g_assert_cmpint(idx_delim_before, ==, initial_offset - 1); - } else { - g_assert_cmpint(idx_delim_after_old, !=, G_MAXSIZE); - g_assert_cmpint(idx_delim_before, !=, G_MAXSIZE); - g_assert_cmpint(idx_delim_after_old, <, idx_delim_before); - for (k = idx_delim_after_old; k <= idx_delim_before; k++) - g_assert(NM_IN_SET(str[k], DELIMITERS_C)); - } - } - - for (k = 0; k < l_i;) { - if (f_allow_escaping && str[idx_word_start + k] == '\\') { - k++; - if (k >= l_i) - break; - k++; - continue; - } - g_assert(!NM_IN_SET(str[idx_word_start + k], DELIMITERS_C)); - k++; - } - g_assert(strncmp(words[i], &str[idx_word_start], l_i) == 0); - - if (i > 0) { - const char *s = &(words[i - 1])[strlen(words[i - 1]) + 1]; - - if (s != words[i]) { - g_assert(!f_preserve_empty); - g_assert(s < words[i]); - } - } - - idx_word_start += l_i + 1; - idx_delim_after_old = idx_delim_after; - } - } -} - -static void -_do_test_nm_utils_strsplit_set_f(NMUtilsStrsplitSetFlags flags, - const char * str, - gsize words_len, - const char *const * exp_words) -{ - _do_test_nm_utils_strsplit_set_f_one(flags, str, words_len, exp_words); - - if (NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY)) { - gs_unref_ptrarray GPtrArray *exp_words2 = NULL; - gsize k; - - exp_words2 = g_ptr_array_new(); - for (k = 0; k < words_len; k++) { - if (exp_words[k][0] != '\0') - g_ptr_array_add(exp_words2, (gpointer) exp_words[k]); - } - - _do_test_nm_utils_strsplit_set_f_one(flags & (~NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY), - str, - exp_words2->len, - (const char *const *) exp_words2->pdata); - } -} - -#define do_test_nm_utils_strsplit_set_f(flags, str, ...) \ - _do_test_nm_utils_strsplit_set_f(flags, str, NM_NARG(__VA_ARGS__), NM_MAKE_STRV(__VA_ARGS__)) - -#define do_test_nm_utils_strsplit_set(allow_escaping, str, ...) \ - do_test_nm_utils_strsplit_set_f((allow_escaping) ? NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING \ - : NM_UTILS_STRSPLIT_SET_FLAGS_NONE, \ - str, \ - ##__VA_ARGS__) - -static void -_do_test_nm_utils_strsplit_set_simple(NMUtilsStrsplitSetFlags flags, - const char * str, - gsize words_len, - const char *const * exp_words) -{ - gs_free const char **tokens = NULL; - gsize n_tokens; - - tokens = nm_utils_strsplit_set_full(str, DELIMITERS, flags); - - if (!tokens) { - g_assert_cmpint(words_len, ==, 0); - return; - } - - g_assert(str && str[0]); - g_assert_cmpint(words_len, >, 0); - n_tokens = NM_PTRARRAY_LEN(tokens); - - if (nm_utils_strv_cmp_n(exp_words, words_len, tokens, -1) != 0) { - gsize i; - - g_print(">>> split \"%s\" (flags %x) got %zu tokens (%zu expected)\n", - str, - (guint) flags, - n_tokens, - words_len); - for (i = 0; i < NM_MAX(n_tokens, words_len); i++) { - const char *s1 = i < n_tokens ? tokens[i] : NULL; - const char *s2 = i < words_len ? exp_words[i] : NULL; - - g_print(">>> [%zu]: %s - %s%s%s vs. %s%s%s\n", - i, - nm_streq0(s1, s2) ? "same" : "diff", - NM_PRINT_FMT_QUOTE_STRING(s1), - NM_PRINT_FMT_QUOTE_STRING(s2)); - } - g_assert_not_reached(); - } - g_assert_cmpint(words_len, ==, NM_PTRARRAY_LEN(tokens)); -} -#define do_test_nm_utils_strsplit_set_simple(flags, str, ...) \ - _do_test_nm_utils_strsplit_set_simple((flags), \ - (str), \ - NM_NARG(__VA_ARGS__), \ - NM_MAKE_STRV(__VA_ARGS__)) - -static void -test_nm_utils_strsplit_set(void) -{ - gs_unref_ptrarray GPtrArray *words_exp = NULL; - guint test_run; - - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_NONE, NULL); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_NONE, ""); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_NONE, " "); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_NONE, "a b", "a", "b"); - - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, NULL); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, ""); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, " ", "", ""); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, " ", "", "", ""); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "a ", "a", "", ""); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, - "a b", - "a", - "", - "b"); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, - " ab b", - "", - "ab", - "", - "b"); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, - "ab b", - "ab", - "", - "b"); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "abb", "abb"); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, - "abb bb ", - "abb", - "", - "bb", - ""); - do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, - "abb bcb ", - "abb", - "bcb", - ""); - - do_test_nm_utils_strsplit_set(FALSE, NULL); - do_test_nm_utils_strsplit_set(FALSE, ""); - do_test_nm_utils_strsplit_set(FALSE, "\n"); - do_test_nm_utils_strsplit_set(TRUE, " \t\n", "\t"); - do_test_nm_utils_strsplit_set(FALSE, "a", "a"); - do_test_nm_utils_strsplit_set(FALSE, "a b", "a", "b"); - do_test_nm_utils_strsplit_set(FALSE, "a\rb", "a\rb"); - do_test_nm_utils_strsplit_set(FALSE, " a\rb ", "a\rb"); - do_test_nm_utils_strsplit_set(FALSE, " a bbbd afds ere", "a", "bbbd", "afds", "ere"); - do_test_nm_utils_strsplit_set(FALSE, - "1 2 3 4 5 6 7 8 9 0 " - "1 2 3 4 5 6 7 8 9 0 " - "1 2 3 4 5 6 7 8 9 0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "0"); - do_test_nm_utils_strsplit_set(TRUE, "\\", "\\"); - do_test_nm_utils_strsplit_set(TRUE, "\\ ", "\\ "); - do_test_nm_utils_strsplit_set(TRUE, "\\\\", "\\\\"); - do_test_nm_utils_strsplit_set(TRUE, "\\\t", "\\\t"); - do_test_nm_utils_strsplit_set(TRUE, "foo\\", "foo\\"); - do_test_nm_utils_strsplit_set(TRUE, "bar foo\\", "bar", "foo\\"); - do_test_nm_utils_strsplit_set(TRUE, "\\ a b\\ \\ c", "\\ a", "b\\ \\ ", "c"); - - words_exp = g_ptr_array_new_with_free_func(g_free); - for (test_run = 0; test_run < 100; test_run++) { - gboolean f_allow_escaping = nmtst_get_rand_bool(); - guint words_len = nmtst_get_rand_uint32() % 100; - gs_free char *str = NULL; - guint i; - - g_ptr_array_set_size(words_exp, 0); - for (i = 0; i < words_len; i++) { - guint word_len; - char *word; - guint j; - - word_len = nmtst_get_rand_uint32(); - if ((word_len % 100) < 30) - word_len = 0; - else - word_len = (word_len >> 10) % 100; - word = g_new(char, word_len + 3); - for (j = 0; j < word_len;) { - guint32 p = nmtst_get_rand_uint32(); - static const char delimiters_arr[] = {DELIMITERS_C}; - static const char regular_chars[] = "abcdefghijklmnopqrstuvwxyz"; - - if (!f_allow_escaping || (p % 1000) < 700) { - if (((p >> 20) % 100) < 20) - word[j++] = '\\'; - word[j++] = regular_chars[(p >> 11) % (G_N_ELEMENTS(regular_chars) - 1)]; - continue; - } - word[j++] = '\\'; - word[j++] = delimiters_arr[(p >> 11) % G_N_ELEMENTS(delimiters_arr)]; - } - word[j] = '\0'; - g_ptr_array_add(words_exp, word); - } - g_ptr_array_add(words_exp, NULL); - - str = g_strjoinv(" ", (char **) words_exp->pdata); - - if (str[0] == '\0' && words_len > 0) { - g_assert(words_len == 1); - g_assert_cmpstr(words_exp->pdata[0], ==, ""); - words_len = 0; - } - - _do_test_nm_utils_strsplit_set_f((f_allow_escaping - ? NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING - : NM_UTILS_STRSPLIT_SET_FLAGS_NONE) - | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, - str, - words_len, - (const char *const *) words_exp->pdata); - } - - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "\t", "\t"); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED - | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, - "\t"); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED - | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP - | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, - "\t", - ""); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED - | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP - | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, - "\t\\\t\t\t\\\t", - "\t\t\t\t"); - - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "\ta", "\ta"); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED - | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, - "\ta", - "a"); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, - "\ta\\ b\t\\ ", - "\ta b\t "); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED - | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, - "\ta\\ b\t\\ \t", - "a b\t "); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "a\\ b", "a ", "b"); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, - "\ta\\ b", - "\ta ", - "b"); - do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED - | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, - "\ta\\ b", - "a ", - "b"); -} - -/*****************************************************************************/ - -static char * -_escaped_tokens_create_random_word_full(const char *const *tokens, gsize n_tokens, gsize len) -{ - GString *gstr = g_string_new(NULL); - gsize i; - char random_token[2] = {0}; - - for (i = 0; i < len; i++) { - const char *token = tokens[nmtst_get_rand_uint32() % n_tokens]; - - if (!token[0]) { - do { - random_token[0] = nmtst_get_rand_uint32(); - } while (random_token[0] == '\0'); - token = random_token; - } - g_string_append(gstr, token); - } - - /* reallocate the string, so that we don't have any excess memory from - * the GString buffer. This is so that valgrind may better detect an out - * or range access. */ - return nm_str_realloc(g_string_free(gstr, FALSE)); -} - -/* set to 1 to exclude characters that are annoying to see in the debugger - * and printf() output. */ -#define ESCAPED_TOKENS_ONLY_NICE_CHARS 0 - -static char * -_escaped_tokens_create_random_whitespace(void) -{ - static const char *tokens[] = { - " ", -#if !ESCAPED_TOKENS_ONLY_NICE_CHARS - "\n", - "\t", - "\r", - "\f", -#endif - }; - - return _escaped_tokens_create_random_word_full(tokens, - G_N_ELEMENTS(tokens), - nmtst_get_rand_word_length(NULL) / 4u); -} - -static char * -_escaped_tokens_create_random_word(void) -{ - static const char *tokens[] = { - "a", - "b", - "c", - " ", - ",", - "=", - "\\", -#if !ESCAPED_TOKENS_ONLY_NICE_CHARS - "\n", - "\f", - ":", - "", -#endif - }; - - return _escaped_tokens_create_random_word_full(tokens, - G_N_ELEMENTS(tokens), - nmtst_get_rand_word_length(NULL)); -} - -static void -_escaped_tokens_str_append_delimiter(GString *str, gboolean strict, gboolean needs_delimiter) -{ - guint len = nmtst_get_rand_word_length(NULL) / 10u; - char *s; - -again: - if (!strict) { - g_string_append(str, (s = _escaped_tokens_create_random_whitespace())); - nm_clear_g_free(&s); - } - - if (needs_delimiter) - g_string_append_c(str, ','); - - if (!strict) { - g_string_append(str, (s = _escaped_tokens_create_random_whitespace())); - nm_clear_g_free(&s); - if (len-- > 0) { - needs_delimiter = TRUE; - goto again; - } - } -} - -static void -_escaped_tokens_split(char *str, const char **out_key, const char **out_val) -{ - const char *key; - const char *val; - gsize len = strlen(str); - - g_assert(str); - - nm_utils_escaped_tokens_options_split(str, &key, &val); - g_assert(key); - g_assert(key == str); - if (val) { - g_assert(val > str); - g_assert(val > key); - g_assert(val <= &str[len]); - } - NM_SET_OUT(out_key, key); - NM_SET_OUT(out_val, val); -} - -static void -_escaped_tokens_combine(GString * combined, - const char *key, - const char *val, - gboolean strict, - gboolean allow_append_delimiter_before, - gboolean needs_delimiter_after) -{ - gs_free char *escaped_key = NULL; - gs_free char *escaped_val = NULL; - - if (allow_append_delimiter_before) - _escaped_tokens_str_append_delimiter(combined, strict, FALSE); - g_string_append(combined, nm_utils_escaped_tokens_options_escape_key(key, &escaped_key)); - if (val) { - char *s; - - if (!strict) { - g_string_append(combined, (s = _escaped_tokens_create_random_whitespace())); - nm_clear_g_free(&s); - } - g_string_append_c(combined, '='); - if (!strict) { - g_string_append(combined, (s = _escaped_tokens_create_random_whitespace())); - nm_clear_g_free(&s); - } - g_string_append(combined, nm_utils_escaped_tokens_options_escape_val(val, &escaped_val)); - } - _escaped_tokens_str_append_delimiter(combined, strict, needs_delimiter_after); -} - -static void -_escaped_tokens_check_one_impl(const char * expected_key, - const char * expected_val, - const char * expected_combination, - const char *const *other, - gsize n_other) -{ - nm_auto_free_gstring GString *combined = g_string_new(NULL); - gsize i; - - g_assert(expected_key); - g_assert(expected_combination); - g_assert(other); - - _escaped_tokens_combine(combined, expected_key, expected_val, TRUE, TRUE, FALSE); - - g_assert_cmpstr(combined->str, ==, expected_combination); - - for (i = 0; i < n_other + 2u; i++) { - nm_auto_free_gstring GString *str0 = NULL; - gs_free const char ** strv_split = NULL; - gs_free char * strv_split0 = NULL; - const char * comb; - const char * key; - const char * val; - - if (i == 0) - comb = expected_combination; - else if (i == 1) { - _escaped_tokens_combine(nm_gstring_prepare(&str0), - expected_key, - expected_val, - FALSE, - TRUE, - FALSE); - comb = str0->str; - } else - comb = other[i - 2]; - - strv_split = nm_utils_escaped_tokens_options_split_list(comb); - if (!strv_split) { - g_assert_cmpstr(expected_key, ==, ""); - g_assert_cmpstr(expected_val, ==, NULL); - continue; - } - g_assert(expected_val || expected_key[0]); - - g_assert_cmpuint(NM_PTRARRAY_LEN(strv_split), ==, 1u); - - strv_split0 = g_strdup(strv_split[0]); - - _escaped_tokens_split(strv_split0, &key, &val); - g_assert_cmpstr(key, ==, expected_key); - g_assert_cmpstr(val, ==, expected_val); - } -} - -#define _escaped_tokens_check_one(expected_key, expected_val, expected_combination, ...) \ - _escaped_tokens_check_one_impl(expected_key, \ - expected_val, \ - expected_combination, \ - NM_MAKE_STRV(__VA_ARGS__), \ - NM_NARG(__VA_ARGS__)) - -static void -test_nm_utils_escaped_tokens(void) -{ - int i_run; - - for (i_run = 0; i_run < 1000; i_run++) { - const guint num_options = nmtst_get_rand_word_length(NULL); - gs_unref_ptrarray GPtrArray *options = g_ptr_array_new_with_free_func(g_free); - nm_auto_free_gstring GString *combined = g_string_new(NULL); - gs_free const char ** strv_split = NULL; - guint i_option; - guint i; - - /* Generate a list of random words for option key-value pairs. */ - for (i_option = 0; i_option < 2u * num_options; i_option++) { - char *word = NULL; - - if (i_option % 2u == 1 && nmtst_get_rand_uint32() % 5 == 0 - && strlen(options->pdata[options->len - 1]) > 0u) { - /* For some options, leave the value unset and only generate a key. - * - * If key is "", then we cannot do that, because the test below would try - * to append "" to the combined list, which the parser then would drop. - * Only test omitting the value, if strlen() of the key is positive. */ - } else - word = _escaped_tokens_create_random_word(); - g_ptr_array_add(options, word); - } - - /* Combine the options in one comma separated list, with proper escaping. */ - for (i_option = 0; i_option < num_options; i_option++) { - _escaped_tokens_combine(combined, - options->pdata[2u * i_option + 0u], - options->pdata[2u * i_option + 1u], - FALSE, - i_option == 0, - i_option != num_options - 1); - } - - /* ensure that we can split and parse the options without difference. */ - strv_split = nm_utils_escaped_tokens_options_split_list(combined->str); - for (i_option = 0; i_option < num_options; i_option++) { - const char * expected_key = options->pdata[2u * i_option + 0u]; - const char * expected_val = options->pdata[2u * i_option + 1u]; - gs_free char *s_split = - i_option < NM_PTRARRAY_LEN(strv_split) ? g_strdup(strv_split[i_option]) : NULL; - const char *key = NULL; - const char *val = NULL; - - if (s_split) - _escaped_tokens_split(s_split, &key, &val); - - if (!nm_streq0(key, expected_key) || !nm_streq0(val, expected_val)) { - g_print(">>> ASSERTION IS ABOUT TO FAIL for item %5d of %5d\n", - i_option, - num_options); - g_print(">>> combined = \"%s\"\n", combined->str); - g_print(">>> %c parsed[%5d].key = \"%s\"\n", - nm_streq(key, expected_key) ? ' ' : 'X', - i_option, - key); - g_print(">>> %c parsed[%5d].val = %s%s%s\n", - nm_streq0(val, expected_val) ? ' ' : 'X', - i_option, - NM_PRINT_FMT_QUOTE_STRING(val)); - for (i = 0; i < num_options; i++) { - g_print(">>> %c original[%5d].key = \"%s\"\n", - i == i_option ? '*' : ' ', - i, - (char *) options->pdata[2u * i + 0u]); - g_print(">>> %c original[%5d].val = %s%s%s\n", - i == i_option ? '*' : ' ', - i, - NM_PRINT_FMT_QUOTE_STRING((char *) options->pdata[2u * i + 1u])); - } - for (i = 0; i < NM_PTRARRAY_LEN(strv_split); i++) - g_print(">>> split[%5d] = \"%s\"\n", i, strv_split[i]); - } - - g_assert_cmpstr(key, ==, expected_key); - g_assert_cmpstr(val, ==, expected_val); - } - g_assert_cmpint(NM_PTRARRAY_LEN(strv_split), ==, num_options); - - /* Above we show a full round-trip of random option key-value pairs, that they can - * without loss escape, concatenate, split-list, and split. This proofed that every - * option key-value pair can be represented as a combined string and parsed back. - * - * Now, just check that we can also parse arbitrary random words in nm_utils_escaped_tokens_options_split(). - * split() is a non-injective surjective function. As we check the round-trip above for random words, where - * options-split() is the last step, we show that every random word can be the output of the function - * (which shows, the surjective part). - * - * But multiple random input arguments, may map to the same output argument (non-injective). - * Just test whether we can handle random input words without crashing. For that, just use the - * above generate list of random words. - */ - for (i = 0; i < 1u + 2u * i_option; i++) { - gs_free char *str = NULL; - const char * cstr; - - if (i == 0) - cstr = combined->str; - else - cstr = options->pdata[i - 1u]; - if (!cstr) - continue; - - str = g_strdup(cstr); - _escaped_tokens_split(str, NULL, NULL); - } - } - - _escaped_tokens_check_one("", NULL, ""); - _escaped_tokens_check_one("", "", "=", " ="); - _escaped_tokens_check_one("a", "b", "a=b", "a = b"); - _escaped_tokens_check_one("a\\=", "b\\=", "a\\\\\\==b\\\\=", "a\\\\\\==b\\\\\\="); - _escaped_tokens_check_one("\\=", "\\=", "\\\\\\==\\\\=", "\\\\\\==\\\\\\="); - _escaped_tokens_check_one(" ", "bb=", "\\ =bb=", "\\ =bb\\="); - _escaped_tokens_check_one(" ", "bb\\=", "\\ =bb\\\\=", "\\ =bb\\\\\\="); - _escaped_tokens_check_one("a b", "a b", "a b=a b"); - _escaped_tokens_check_one("a b", "a b", "a b=a b"); - _escaped_tokens_check_one("a = b", "a = b", "a \\= b=a = b", "a \\= b=a \\= b"); -} - -/*****************************************************************************/ - -typedef struct { - int val; - CList lst; -} CListSort; - -static int -_c_list_sort_cmp(const CList *lst_a, const CList *lst_b, const void *user_data) -{ - const CListSort *a, *b; - - g_assert(lst_a); - g_assert(lst_b); - g_assert(lst_a != lst_b); - - a = c_list_entry(lst_a, CListSort, lst); - b = c_list_entry(lst_b, CListSort, lst); - - if (a->val < b->val) - return -1; - if (a->val > b->val) - return 1; - return 0; -} - -static void -_do_test_c_list_sort(CListSort *elements, guint n_list, gboolean headless) -{ - CList head, *iter, *iter_prev, *lst; - guint i; - const CListSort *el_prev; - CListSort * el; - - c_list_init(&head); - for (i = 0; i < n_list; i++) { - el = &elements[i]; - el->val = nmtst_get_rand_uint32() % (2 * n_list); - c_list_link_tail(&head, &el->lst); - } - - if (headless) { - lst = head.next; - c_list_unlink_stale(&head); - lst = c_list_sort_headless(lst, _c_list_sort_cmp, NULL); - g_assert(lst); - g_assert(lst->next); - g_assert(lst->prev); - g_assert(c_list_length(lst) == n_list - 1); - iter_prev = lst->prev; - for (iter = lst; iter != lst; iter = iter->next) { - g_assert(iter); - g_assert(iter->next); - g_assert(iter->prev == iter_prev); - } - c_list_link_before(lst, &head); - } else - c_list_sort(&head, _c_list_sort_cmp, NULL); - - g_assert(!c_list_is_empty(&head)); - g_assert(c_list_length(&head) == n_list); - - el_prev = NULL; - c_list_for_each (iter, &head) { - el = c_list_entry(iter, CListSort, lst); - g_assert(el >= elements && el < &elements[n_list]); - if (el_prev) { - if (el_prev->val == el->val) - g_assert(el_prev < el); - else - g_assert(el_prev->val < el->val); - g_assert(iter->prev == &el_prev->lst); - g_assert(el_prev->lst.next == iter); - } - el_prev = el; - } - g_assert(head.prev == &el_prev->lst); -} - -static void -test_c_list_sort(void) -{ - const guint N_ELEMENTS = 10000; - guint n_list, repeat; - gs_free CListSort *elements = NULL; - - { - CList head; - - c_list_init(&head); - c_list_sort(&head, _c_list_sort_cmp, NULL); - g_assert(c_list_length(&head) == 0); - g_assert(c_list_is_empty(&head)); - } - - elements = g_new0(CListSort, N_ELEMENTS); - for (n_list = 1; n_list < N_ELEMENTS; n_list++) { - if (n_list > 150) { - n_list += nmtst_get_rand_uint32() % n_list; - if (n_list >= N_ELEMENTS) - break; - } - { - const guint N_REPEAT = n_list > 50 ? 1 : 5; - - for (repeat = 0; repeat < N_REPEAT; repeat++) - _do_test_c_list_sort(elements, n_list, nmtst_get_rand_uint32() % 2); - } - } -} - -/*****************************************************************************/ - -typedef struct { - NMDedupMultiObj parent; - guint val; - guint other; -} DedupObj; - -static const NMDedupMultiObjClass dedup_obj_class; - -static DedupObj * -_dedup_obj_assert(const NMDedupMultiObj *obj) -{ - DedupObj *o; - - g_assert(obj); - o = (DedupObj *) obj; - g_assert(o->parent.klass == &dedup_obj_class); - g_assert(o->parent._ref_count > 0); - g_assert(o->val > 0); - return o; -} - -static const NMDedupMultiObj * -_dedup_obj_clone(const NMDedupMultiObj *obj) -{ - DedupObj *o, *o2; - - o = _dedup_obj_assert(obj); - o2 = g_slice_new0(DedupObj); - o2->parent.klass = &dedup_obj_class; - o2->parent._ref_count = 1; - o2->val = o->val; - o2->other = o->other; - return (NMDedupMultiObj *) o2; -} - -static void -_dedup_obj_destroy(NMDedupMultiObj *obj) -{ - DedupObj *o = (DedupObj *) obj; - - g_assert(o->parent._ref_count == 0); - o->parent._ref_count = 1; - o = _dedup_obj_assert(obj); - g_slice_free(DedupObj, o); -} - -static void -_dedup_obj_full_hash_update(const NMDedupMultiObj *obj, NMHashState *h) -{ - const DedupObj *o; - - o = _dedup_obj_assert(obj); - nm_hash_update_vals(h, o->val, o->other); -} - -static gboolean -_dedup_obj_full_equal(const NMDedupMultiObj *obj_a, const NMDedupMultiObj *obj_b) -{ - const DedupObj *o_a = _dedup_obj_assert(obj_a); - const DedupObj *o_b = _dedup_obj_assert(obj_b); - - return o_a->val == o_b->val && o_a->other == o_b->other; -} - -static const NMDedupMultiObjClass dedup_obj_class = { - .obj_clone = _dedup_obj_clone, - .obj_destroy = _dedup_obj_destroy, - .obj_full_hash_update = _dedup_obj_full_hash_update, - .obj_full_equal = _dedup_obj_full_equal, -}; - -#define DEDUP_OBJ_INIT(val_val, other_other) \ - (&((DedupObj){ \ - .parent = \ - { \ - .klass = &dedup_obj_class, \ - ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, \ - }, \ - .val = (val_val), \ - .other = (other_other), \ - })) - -typedef struct { - NMDedupMultiIdxType parent; - guint partition_size; - guint val_mod; -} DedupIdxType; - -static const NMDedupMultiIdxTypeClass dedup_idx_type_class; - -static const DedupIdxType * -_dedup_idx_assert(const NMDedupMultiIdxType *idx_type) -{ - DedupIdxType *t; - - g_assert(idx_type); - t = (DedupIdxType *) idx_type; - g_assert(t->parent.klass == &dedup_idx_type_class); - g_assert(t->partition_size > 0); - g_assert(t->val_mod > 0); - return t; -} - -static void -_dedup_idx_obj_id_hash_update(const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj * obj, - NMHashState * h) -{ - const DedupIdxType *t; - const DedupObj * o; - - t = _dedup_idx_assert(idx_type); - o = _dedup_obj_assert(obj); - - nm_hash_update_val(h, o->val / t->partition_size); - nm_hash_update_val(h, o->val % t->val_mod); -} - -static gboolean -_dedup_idx_obj_id_equal(const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj * obj_a, - const NMDedupMultiObj * obj_b) -{ - const DedupIdxType *t; - const DedupObj * o_a; - const DedupObj * o_b; - - t = _dedup_idx_assert(idx_type); - o_a = _dedup_obj_assert(obj_a); - o_b = _dedup_obj_assert(obj_b); - - return (o_a->val / t->partition_size) == (o_b->val / t->partition_size) - && (o_a->val % t->val_mod) == (o_b->val % t->val_mod); -} - -static void -_dedup_idx_obj_partition_hash_update(const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj * obj, - NMHashState * h) -{ - const DedupIdxType *t; - const DedupObj * o; - - t = _dedup_idx_assert(idx_type); - o = _dedup_obj_assert(obj); - - nm_hash_update_val(h, o->val / t->partition_size); -} - -static gboolean -_dedup_idx_obj_partition_equal(const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj * obj_a, - const NMDedupMultiObj * obj_b) -{ - const DedupIdxType *t; - const DedupObj * o_a; - const DedupObj * o_b; - - t = _dedup_idx_assert(idx_type); - o_a = _dedup_obj_assert(obj_a); - o_b = _dedup_obj_assert(obj_b); - - return (o_a->val / t->partition_size) == (o_b->val / t->partition_size); -} - -static const NMDedupMultiIdxTypeClass dedup_idx_type_class = { - .idx_obj_id_hash_update = _dedup_idx_obj_id_hash_update, - .idx_obj_id_equal = _dedup_idx_obj_id_equal, - .idx_obj_partition_hash_update = _dedup_idx_obj_partition_hash_update, - .idx_obj_partition_equal = _dedup_idx_obj_partition_equal, -}; - -static const DedupIdxType * -DEDUP_IDX_TYPE_INIT(DedupIdxType *idx_type, guint partition_size, guint val_mod) -{ - nm_dedup_multi_idx_type_init((NMDedupMultiIdxType *) idx_type, &dedup_idx_type_class); - idx_type->val_mod = val_mod; - idx_type->partition_size = partition_size; - return idx_type; -} - -static gboolean -_dedup_idx_add(NMDedupMultiIndex * idx, - const DedupIdxType * idx_type, - const DedupObj * obj, - NMDedupMultiIdxMode mode, - const NMDedupMultiEntry **out_entry) -{ - g_assert(idx); - _dedup_idx_assert((NMDedupMultiIdxType *) idx_type); - if (obj) - _dedup_obj_assert((NMDedupMultiObj *) obj); - return nm_dedup_multi_index_add(idx, - (NMDedupMultiIdxType *) idx_type, - obj, - mode, - out_entry, - NULL); -} - -static void -_dedup_head_entry_assert(const NMDedupMultiHeadEntry *entry) -{ - g_assert(entry); - g_assert(entry->len > 0); - g_assert(entry->len == c_list_length(&entry->lst_entries_head)); - g_assert(entry->idx_type); - g_assert(entry->is_head); -} - -static const DedupObj * -_dedup_entry_assert(const NMDedupMultiEntry *entry) -{ - g_assert(entry); - g_assert(!c_list_is_empty(&entry->lst_entries)); - g_assert(entry->head); - g_assert(!entry->is_head); - g_assert(entry->head != (gpointer) entry); - _dedup_head_entry_assert(entry->head); - return _dedup_obj_assert(entry->obj); -} - -static const DedupIdxType * -_dedup_entry_get_idx_type(const NMDedupMultiEntry *entry) -{ - _dedup_entry_assert(entry); - - g_assert(entry->head); - g_assert(entry->head->idx_type); - return _dedup_idx_assert(entry->head->idx_type); -} - -static void -_dedup_entry_assert_all(const NMDedupMultiEntry *entry, - gssize expected_idx, - const DedupObj *const * expected_obj) -{ - gsize n, i; - CList *iter; - - g_assert(entry); - _dedup_entry_assert(entry); - - g_assert(expected_obj); - n = NM_PTRARRAY_LEN(expected_obj); - - g_assert(n == c_list_length(&entry->lst_entries)); - - g_assert(expected_idx >= -1 && expected_idx < n); - g_assert(entry->head); - if (expected_idx == -1) - g_assert(entry->head == (gpointer) entry); - else - g_assert(entry->head != (gpointer) entry); - - i = 0; - c_list_for_each (iter, &entry->head->lst_entries_head) { - const NMDedupMultiEntry *entry_current = c_list_entry(iter, NMDedupMultiEntry, lst_entries); - const DedupObj * obj_current; - const DedupIdxType * idx_type = _dedup_entry_get_idx_type(entry_current); - - obj_current = _dedup_entry_assert(entry_current); - g_assert(obj_current); - g_assert(i < n); - if (expected_idx == i) - g_assert(entry_current == entry); - g_assert(idx_type->parent.klass->idx_obj_partition_equal( - &idx_type->parent, - entry_current->obj, - c_list_entry(entry->head->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj)); - i++; - } -} -#define _dedup_entry_assert_all(entry, expected_idx, ...) \ - _dedup_entry_assert_all(entry, expected_idx, (const DedupObj *const[]){__VA_ARGS__, NULL}) - -static void -test_dedup_multi(void) -{ - NMDedupMultiIndex * idx; - DedupIdxType IDX_20_3_a_stack; - const DedupIdxType *const IDX_20_3_a = DEDUP_IDX_TYPE_INIT(&IDX_20_3_a_stack, 20, 3); - const NMDedupMultiEntry * entry1; - - idx = nm_dedup_multi_index_new(); - - g_assert(_dedup_idx_add(idx, - IDX_20_3_a, - DEDUP_OBJ_INIT(1, 1), - NM_DEDUP_MULTI_IDX_MODE_APPEND, - &entry1)); - _dedup_entry_assert_all(entry1, 0, DEDUP_OBJ_INIT(1, 1)); - - g_assert(nm_dedup_multi_index_obj_find(idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT(1, 1))); - g_assert(!nm_dedup_multi_index_obj_find(idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT(1, 2))); - - g_assert(_dedup_idx_add(idx, - IDX_20_3_a, - DEDUP_OBJ_INIT(1, 2), - NM_DEDUP_MULTI_IDX_MODE_APPEND, - &entry1)); - _dedup_entry_assert_all(entry1, 0, DEDUP_OBJ_INIT(1, 2)); - - g_assert(!nm_dedup_multi_index_obj_find(idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT(1, 1))); - g_assert(nm_dedup_multi_index_obj_find(idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT(1, 2))); - - g_assert(_dedup_idx_add(idx, - IDX_20_3_a, - DEDUP_OBJ_INIT(2, 2), - NM_DEDUP_MULTI_IDX_MODE_APPEND, - &entry1)); - _dedup_entry_assert_all(entry1, 1, DEDUP_OBJ_INIT(1, 2), DEDUP_OBJ_INIT(2, 2)); - - nm_dedup_multi_index_unref(idx); -} - -/*****************************************************************************/ - -static NMConnection * -_connection_new_from_dbus(GVariant *dict, GError **error) -{ - return _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, error); -} - -static void -vpn_check_func(const char *key, const char *value, gpointer user_data) -{ - if (!strcmp(key, "foobar1")) { - g_assert_cmpstr(value, ==, "blahblah1"); - return; - } - - if (!strcmp(key, "foobar2")) { - g_assert_cmpstr(value, ==, "blahblah2"); - return; - } - - if (!strcmp(key, "foobar3")) { - g_assert_cmpstr(value, ==, "blahblah3"); - return; - } - - if (!strcmp(key, "foobar4")) { - g_assert_cmpstr(value, ==, "blahblah4"); - return; - } - - g_assert_not_reached(); -} - -static void -vpn_check_empty_func(const char *key, const char *value, gpointer user_data) -{ - g_assert_not_reached(); -} - -static void -test_setting_vpn_items(void) -{ - gs_unref_object NMConnection *connection = NULL; - NMSettingVpn * s_vpn; - - connection = - nmtst_create_minimal_connection("vpn-items", NULL, NM_SETTING_VPN_SETTING_NAME, NULL); - - s_vpn = nm_connection_get_setting_vpn(connection); - - nm_setting_vpn_add_data_item(s_vpn, "foobar1", "blahblah1"); - nm_setting_vpn_add_data_item(s_vpn, "foobar2", "blahblah2"); - nm_setting_vpn_add_data_item(s_vpn, "foobar3", "blahblah3"); - nm_setting_vpn_add_data_item(s_vpn, "foobar4", "blahblah4"); - - /* Ensure that added values are all present */ - nm_setting_vpn_foreach_data_item(s_vpn, vpn_check_func, NULL); - nm_setting_vpn_remove_data_item(s_vpn, "foobar1"); - nm_setting_vpn_remove_data_item(s_vpn, "foobar2"); - nm_setting_vpn_remove_data_item(s_vpn, "foobar3"); - nm_setting_vpn_remove_data_item(s_vpn, "foobar4"); - - g_assert(!_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); - g_assert(!_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - nm_setting_vpn_add_secret(s_vpn, "foobar1", "blahblah1"); - - g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); - g_assert(_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - nm_setting_vpn_add_secret(s_vpn, "foobar2", "blahblah2"); - nm_setting_vpn_add_secret(s_vpn, "foobar3", "blahblah3"); - nm_setting_vpn_add_secret(s_vpn, "foobar4", "blahblah4"); - - /* Ensure that added values are all present */ - nm_setting_vpn_foreach_secret(s_vpn, vpn_check_func, NULL); - nm_setting_vpn_remove_secret(s_vpn, "foobar1"); - nm_setting_vpn_remove_secret(s_vpn, "foobar2"); - nm_setting_vpn_remove_secret(s_vpn, "foobar3"); - - g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); - g_assert(_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - nm_setting_vpn_add_data_item(s_vpn, "foobar4-flags", "blahblah4"); - - g_assert(_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - nm_setting_vpn_add_data_item(s_vpn, "foobar4-flags", "2"); - - g_assert(!_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - nm_setting_vpn_remove_secret(s_vpn, "foobar4"); - - g_assert(!_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); - g_assert(!_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - nm_setting_vpn_remove_data_item(s_vpn, "foobar4-flags"); - - /* Try to add some blank values and make sure they are rejected */ - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); - nm_setting_vpn_add_data_item(s_vpn, NULL, NULL); - g_test_assert_expected_messages(); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); - nm_setting_vpn_add_data_item(s_vpn, "", ""); - g_test_assert_expected_messages(); - - nm_setting_vpn_add_data_item(s_vpn, "foobar1", ""); - g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, "foobar1"), ==, ""); - - nm_setting_vpn_add_data_item(s_vpn, "foobar1", NULL); - g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, "foobar1"), ==, NULL); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); - nm_setting_vpn_add_data_item(s_vpn, NULL, "blahblah1"); - g_test_assert_expected_messages(); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); - nm_setting_vpn_add_data_item(s_vpn, "", "blahblah1"); - g_test_assert_expected_messages(); - - nm_setting_vpn_foreach_data_item(s_vpn, vpn_check_empty_func, NULL); - - /* Try to add some blank secrets and make sure they are rejected */ - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); - nm_setting_vpn_add_secret(s_vpn, NULL, NULL); - g_test_assert_expected_messages(); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); - nm_setting_vpn_add_secret(s_vpn, "", ""); - g_test_assert_expected_messages(); - - nm_setting_vpn_add_secret(s_vpn, "foobar1", ""); - - nm_setting_vpn_add_secret(s_vpn, "foobar1", NULL); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); - nm_setting_vpn_add_secret(s_vpn, NULL, "blahblah1"); - g_test_assert_expected_messages(); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); - nm_setting_vpn_add_secret(s_vpn, "", "blahblah1"); - g_test_assert_expected_messages(); - - nm_setting_vpn_foreach_secret(s_vpn, vpn_check_empty_func, NULL); -} - -static void -test_setting_vpn_update_secrets(void) -{ - NMConnection * connection; - NMSettingVpn * s_vpn; - GVariantBuilder settings_builder, vpn_builder, secrets_builder; - GVariant * settings; - gboolean success; - GError * error = NULL; - const char * tmp; - const char * key1 = "foobar"; - const char * key2 = "blahblah"; - const char * val1 = "value1"; - const char * val2 = "value2"; - - connection = nm_simple_connection_new(); - s_vpn = (NMSettingVpn *) nm_setting_vpn_new(); - nm_connection_add_setting(connection, NM_SETTING(s_vpn)); - - g_variant_builder_init(&settings_builder, NM_VARIANT_TYPE_CONNECTION); - g_variant_builder_init(&vpn_builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_init(&secrets_builder, G_VARIANT_TYPE("a{ss}")); - - g_variant_builder_add(&secrets_builder, "{ss}", key1, val1); - g_variant_builder_add(&secrets_builder, "{ss}", key2, val2); - - g_variant_builder_add(&vpn_builder, - "{sv}", - NM_SETTING_VPN_SECRETS, - g_variant_builder_end(&secrets_builder)); - g_variant_builder_add(&settings_builder, "{sa{sv}}", NM_SETTING_VPN_SETTING_NAME, &vpn_builder); - settings = g_variant_builder_end(&settings_builder); - - success = - nm_connection_update_secrets(connection, NM_SETTING_VPN_SETTING_NAME, settings, &error); - g_assert_no_error(error); - g_assert(success); - - /* Read the secrets back out */ - tmp = nm_setting_vpn_get_secret(s_vpn, key1); - g_assert(tmp); - g_assert_cmpstr(tmp, ==, val1); - - tmp = nm_setting_vpn_get_secret(s_vpn, key2); - g_assert(tmp); - g_assert_cmpstr(tmp, ==, val2); - - g_variant_unref(settings); - g_object_unref(connection); -} - -#define TO_DEL_NUM 50 -typedef struct { - NMSettingVpn *s_vpn; - char * to_del[TO_DEL_NUM]; - guint called; -} IterInfo; - -static void -del_iter_func(const char *key, const char *value, gpointer user_data) -{ - IterInfo *info = user_data; - int i; - - /* Record how many times this function gets called; it should get called - * exactly as many times as there are keys in the hash table, regardless - * of what keys we delete from the table. - */ - info->called++; - - /* During the iteration, remove a bunch of stuff from the table */ - if (info->called == 1) { - for (i = 0; i < TO_DEL_NUM; i++) - nm_setting_vpn_remove_data_item(info->s_vpn, info->to_del[i]); - } -} - -static void -test_setting_vpn_modify_during_foreach(void) -{ - NMSettingVpn *s_vpn; - IterInfo info; - char * key, *val; - int i, u = 0; - - s_vpn = (NMSettingVpn *) nm_setting_vpn_new(); - g_assert(s_vpn); - - for (i = 0; i < TO_DEL_NUM * 2; i++) { - key = g_strdup_printf("adsfasdfadf%d", i); - val = g_strdup_printf("42263236236awt%d", i); - nm_setting_vpn_add_data_item(s_vpn, key, val); - - /* Cache some keys to delete */ - if (i % 2) - info.to_del[u++] = g_strdup(key); - - g_free(key); - g_free(val); - } - - /* Iterate over current table keys */ - info.s_vpn = s_vpn; - info.called = 0; - nm_setting_vpn_foreach_data_item(s_vpn, del_iter_func, &info); - - /* Make sure all the things we removed during iteration are really gone */ - for (i = 0; i < TO_DEL_NUM; i++) { - g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, info.to_del[i]), ==, NULL); - g_free(info.to_del[i]); - } - - /* And make sure the foreach callback was called the same number of times - * as there were keys in the table at the beginning of the foreach. - */ - g_assert_cmpint(info.called, ==, TO_DEL_NUM * 2); - - g_object_unref(s_vpn); -} - -static void -test_setting_ip4_config_labels(void) -{ - NMSettingIPConfig *s_ip4; - NMIPAddress * addr; - GVariant * label; - GPtrArray * addrs; - char ** labels; - NMConnection * conn; - GVariant * dict, *dict2, *setting_dict, *value; - GError * error = NULL; - - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(s_ip4), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NULL); - - /* addr 1 */ - addr = nm_ip_address_new(AF_INET, "1.2.3.4", 24, &error); - g_assert_no_error(error); - - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); - - addr = nm_setting_ip_config_get_address(s_ip4, 0); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label == NULL); - - /* The 'address-labels' property should be omitted from the serialization if - * there are no non-NULL labels. - */ - conn = nmtst_create_minimal_connection("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - nm_connection_add_setting(conn, nm_setting_duplicate(NM_SETTING(s_ip4))); - dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); - g_object_unref(conn); - - setting_dict = - g_variant_lookup_value(dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - g_assert(setting_dict != NULL); - - value = g_variant_lookup_value(setting_dict, "address-labels", NULL); - g_assert(value == NULL); - - g_variant_unref(setting_dict); - g_variant_unref(dict); - - /* Now back to constructing the original s_ip4... */ - - /* addr 2 */ - addr = nm_ip_address_new(AF_INET, "2.3.4.5", 24, &error); - g_assert_no_error(error); - nm_ip_address_set_attribute(addr, - NM_IP_ADDRESS_ATTRIBUTE_LABEL, - g_variant_new_string("eth0:1")); - - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); - - addr = nm_setting_ip_config_get_address(s_ip4, 1); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label != NULL); - g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); - - /* addr 3 */ - addr = nm_ip_address_new(AF_INET, "3.4.5.6", 24, &error); - g_assert_no_error(error); - nm_ip_address_set_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL, NULL); - - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); - - addr = nm_setting_ip_config_get_address(s_ip4, 2); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label == NULL); - - /* Remove addr 1 and re-verify remaining addresses */ - nm_setting_ip_config_remove_address(s_ip4, 0); - nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); - - addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "2.3.4.5"); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label != NULL); - g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); - - addr = nm_setting_ip_config_get_address(s_ip4, 1); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "3.4.5.6"); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label == NULL); - - /* If we serialize as the daemon, the labels should appear in the D-Bus - * serialization under both 'address-labels' and 'address-data'. - */ - conn = nmtst_create_minimal_connection("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - nm_connection_add_setting(conn, NM_SETTING(s_ip4)); - _nm_utils_is_manager_process = TRUE; - dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); - _nm_utils_is_manager_process = FALSE; - g_object_unref(conn); - - setting_dict = - g_variant_lookup_value(dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - g_assert(setting_dict != NULL); - - value = g_variant_lookup_value(setting_dict, "address-labels", G_VARIANT_TYPE_STRING_ARRAY); - g_assert(value != NULL); - g_variant_get(value, "^as", &labels); - g_assert_cmpint(g_strv_length(labels), ==, 2); - g_assert_cmpstr(labels[0], ==, "eth0:1"); - g_assert_cmpstr(labels[1], ==, ""); - g_variant_unref(value); - g_strfreev(labels); - - value = g_variant_lookup_value(setting_dict, "address-data", G_VARIANT_TYPE("aa{sv}")); - addrs = nm_utils_ip_addresses_from_variant(value, AF_INET); - g_variant_unref(value); - g_assert(addrs != NULL); - g_assert_cmpint(addrs->len, ==, 2); - addr = addrs->pdata[0]; - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label != NULL); - g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); - addr = addrs->pdata[1]; - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label == NULL); - g_ptr_array_unref(addrs); - - g_variant_unref(setting_dict); - - /* We should be able to deserialize the labels from either 'address-labels' - * or 'address-data'. - */ - dict2 = g_variant_ref(dict); - - NMTST_VARIANT_EDITOR( - dict, NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-data");); - conn = _connection_new_from_dbus(dict, &error); - g_assert_no_error(error); - g_variant_unref(dict); - - s_ip4 = nm_connection_get_setting_ip4_config(conn); - - addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "2.3.4.5"); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label != NULL); - g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); - - addr = nm_setting_ip_config_get_address(s_ip4, 1); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "3.4.5.6"); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label == NULL); - - g_object_unref(conn); - - NMTST_VARIANT_EDITOR( - dict2, NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-labels");); - conn = _connection_new_from_dbus(dict2, &error); - g_assert_no_error(error); - g_variant_unref(dict2); - - s_ip4 = nm_connection_get_setting_ip4_config(conn); - - addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "2.3.4.5"); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); - - addr = nm_setting_ip_config_get_address(s_ip4, 1); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "3.4.5.6"); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label == NULL); - - /* Test explicit property assignment */ - g_object_get(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); - - nm_setting_ip_config_clear_addresses(s_ip4); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 0); - - g_object_set(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); - g_ptr_array_unref(addrs); - nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 2); - - addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "2.3.4.5"); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label != NULL); - g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); - - addr = nm_setting_ip_config_get_address(s_ip4, 1); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "3.4.5.6"); - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - g_assert(label == NULL); - - g_object_unref(conn); -} - -static void -test_setting_ip4_config_address_data(void) -{ - NMSettingIPConfig *s_ip4; - NMIPAddress * addr; - GPtrArray * addrs; - NMConnection * conn; - GVariant * dict, *setting_dict, *value; - GError * error = NULL; - - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(s_ip4), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NULL); - - /* addr 1 */ - addr = nm_ip_address_new(AF_INET, "1.2.3.4", 24, &error); - g_assert_no_error(error); - nm_ip_address_set_attribute(addr, "one", g_variant_new_string("foo")); - nm_ip_address_set_attribute(addr, "two", g_variant_new_int32(42)); - - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); - - /* addr 2 */ - addr = nm_ip_address_new(AF_INET, "2.3.4.5", 24, &error); - g_assert_no_error(error); - - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); - - /* The client-side D-Bus serialization should include the attributes in - * "address-data", and should not have an "addresses" property. - */ - conn = nmtst_create_minimal_connection("address-data test", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - NULL); - nm_connection_add_setting(conn, NM_SETTING(s_ip4)); - dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); - - setting_dict = - g_variant_lookup_value(dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - g_assert(setting_dict != NULL); - - value = g_variant_lookup_value(setting_dict, "addresses", NULL); - g_assert(value == NULL); - - value = g_variant_lookup_value(setting_dict, "address-data", G_VARIANT_TYPE("aa{sv}")); - addrs = nm_utils_ip_addresses_from_variant(value, AF_INET); - g_variant_unref(value); - g_assert(addrs != NULL); - g_assert_cmpint(addrs->len, ==, 2); - - addr = addrs->pdata[0]; - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "1.2.3.4"); - value = nm_ip_address_get_attribute(addr, "one"); - g_assert(value != NULL); - g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "foo"); - value = nm_ip_address_get_attribute(addr, "two"); - g_assert(value != NULL); - g_assert_cmpint(g_variant_get_int32(value), ==, 42); - - g_ptr_array_unref(addrs); - g_variant_unref(setting_dict); - g_variant_unref(dict); - - /* The daemon-side serialization should include both 'addresses' and 'address-data' */ - _nm_utils_is_manager_process = TRUE; - dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); - _nm_utils_is_manager_process = FALSE; - - setting_dict = - g_variant_lookup_value(dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - g_assert(setting_dict != NULL); - - value = g_variant_lookup_value(setting_dict, "addresses", G_VARIANT_TYPE("aau")); - g_assert(value != NULL); - g_variant_unref(value); - - value = g_variant_lookup_value(setting_dict, "address-data", G_VARIANT_TYPE("aa{sv}")); - g_assert(value != NULL); - g_variant_unref(value); - - g_variant_unref(setting_dict); - g_object_unref(conn); - - /* When we reserialize that dictionary as a client, 'address-data' will be preferred. */ - conn = _connection_new_from_dbus(dict, &error); - g_assert_no_error(error); - - s_ip4 = nm_connection_get_setting_ip4_config(conn); - - addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "1.2.3.4"); - value = nm_ip_address_get_attribute(addr, "one"); - g_assert(value != NULL); - g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "foo"); - value = nm_ip_address_get_attribute(addr, "two"); - g_assert(value != NULL); - g_assert_cmpint(g_variant_get_int32(value), ==, 42); - - /* But on the server side, 'addresses' will have precedence. */ - _nm_utils_is_manager_process = TRUE; - conn = _connection_new_from_dbus(dict, &error); - _nm_utils_is_manager_process = FALSE; - g_assert_no_error(error); - g_variant_unref(dict); - - s_ip4 = nm_connection_get_setting_ip4_config(conn); - - addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "1.2.3.4"); - value = nm_ip_address_get_attribute(addr, "one"); - g_assert(value == NULL); - value = nm_ip_address_get_attribute(addr, "two"); - g_assert(value == NULL); - - g_object_unref(conn); -} - -static void -test_setting_ip_route_attributes(void) -{ - GVariant *variant; - gboolean res, known; - -#define TEST_ATTR(name, type, value, family, exp_res, exp_known) \ - variant = g_variant_new_##type(value); \ - res = nm_ip_route_attribute_validate(name, variant, family, &known, NULL); \ - g_assert(res == exp_res); \ - g_assert(known == exp_known); \ - g_variant_unref(variant); - - TEST_ATTR("foo", uint32, 12, AF_INET, FALSE, FALSE); - - TEST_ATTR("tos", byte, 127, AF_INET, TRUE, TRUE); - TEST_ATTR("tos", string, "0x28", AF_INET, FALSE, TRUE); - - TEST_ATTR("cwnd", uint32, 10, AF_INET, TRUE, TRUE); - TEST_ATTR("cwnd", string, "11", AF_INET, FALSE, TRUE); - - TEST_ATTR("lock-mtu", boolean, TRUE, AF_INET, TRUE, TRUE); - TEST_ATTR("lock-mtu", uint32, 1, AF_INET, FALSE, TRUE); - - TEST_ATTR("from", string, "fd01::1", AF_INET6, TRUE, TRUE); - TEST_ATTR("from", string, "fd01::1/64", AF_INET6, TRUE, TRUE); - TEST_ATTR("from", string, "fd01::1/128", AF_INET6, TRUE, TRUE); - TEST_ATTR("from", string, "fd01::1/129", AF_INET6, FALSE, TRUE); - TEST_ATTR("from", string, "fd01::1/a", AF_INET6, FALSE, TRUE); - TEST_ATTR("from", string, "abc/64", AF_INET6, FALSE, TRUE); - TEST_ATTR("from", string, "1.2.3.4", AF_INET, FALSE, TRUE); - TEST_ATTR("from", string, "1.2.3.4", AF_INET6, FALSE, TRUE); - - TEST_ATTR("src", string, "1.2.3.4", AF_INET, TRUE, TRUE); - TEST_ATTR("src", string, "1.2.3.4", AF_INET6, FALSE, TRUE); - TEST_ATTR("src", string, "1.2.3.0/24", AF_INET, FALSE, TRUE); - TEST_ATTR("src", string, "fd01::12", AF_INET6, TRUE, TRUE); - - TEST_ATTR("type", string, "local", AF_INET, TRUE, TRUE); - TEST_ATTR("type", string, "local", AF_INET6, TRUE, TRUE); - TEST_ATTR("type", string, "unicast", AF_INET, TRUE, TRUE); - TEST_ATTR("type", string, "unicast", AF_INET6, TRUE, TRUE); - -#undef TEST_ATTR -} - -static void -test_setting_gsm_apn_spaces(void) -{ - gs_unref_object NMSettingGsm *s_gsm = NULL; - const char * tmp; - - s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); - g_assert(s_gsm); - - /* Trailing space */ - g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar ", NULL); - tmp = nm_setting_gsm_get_apn(s_gsm); - g_assert_cmpstr(tmp, ==, "foobar"); - - /* Leading space */ - g_object_set(s_gsm, NM_SETTING_GSM_APN, " foobar", NULL); - tmp = nm_setting_gsm_get_apn(s_gsm); - g_assert_cmpstr(tmp, ==, "foobar"); -} - -static void -test_setting_gsm_apn_bad_chars(void) -{ - gs_unref_object NMSettingGsm *s_gsm = NULL; - - s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); - g_assert(s_gsm); - - /* Make sure a valid APN works */ - g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar123.-baz", NULL); - g_assert(nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); - - /* Random invalid chars */ - g_object_set(s_gsm, NM_SETTING_GSM_APN, "@#%$@#%@#%", NULL); - g_assert(!nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); - - /* Spaces */ - g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar baz", NULL); - g_assert(!nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); - - /* 0 characters long */ - g_object_set(s_gsm, NM_SETTING_GSM_APN, "", NULL); - g_assert(nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); - - /* 65-character long */ - g_object_set(s_gsm, - NM_SETTING_GSM_APN, - "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl1", - NULL); - g_assert(!nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); -} - -static void -test_setting_gsm_apn_underscore(void) -{ - gs_unref_object NMSettingGsm *s_gsm = NULL; - - s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); - g_assert(s_gsm); - - /* 65-character long */ - g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar_baz", NULL); - nmtst_assert_setting_verifies(NM_SETTING(s_gsm)); -} - -static void -test_setting_gsm_without_number(void) -{ - gs_unref_object NMSettingGsm *s_gsm = NULL; - - s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); - g_assert(s_gsm); - - g_object_set(s_gsm, NM_SETTING_GSM_NUMBER, NULL, NULL); - nmtst_assert_setting_verifies(NM_SETTING(s_gsm)); - - g_object_set(s_gsm, NM_SETTING_GSM_NUMBER, "", NULL); - nmtst_assert_setting_verify_fails(NM_SETTING(s_gsm), - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); -} - -static void -test_setting_gsm_sim_operator_id(void) -{ - gs_unref_object NMSettingGsm *s_gsm = NULL; - - s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); - g_assert(s_gsm); - - /* Valid */ - g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "12345", NULL); - nmtst_assert_setting_verifies(NM_SETTING(s_gsm)); - - g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "123456", NULL); - nmtst_assert_setting_verifies(NM_SETTING(s_gsm)); - - /* Invalid */ - g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "", NULL); - nmtst_assert_setting_verify_fails(NM_SETTING(s_gsm), - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - - g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, " ", NULL); - nmtst_assert_setting_verify_fails(NM_SETTING(s_gsm), - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - - g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "abcdef", NULL); - nmtst_assert_setting_verify_fails(NM_SETTING(s_gsm), - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); -} - -static NMSettingWirelessSecurity * -make_test_wsec_setting(const char *detail) -{ - NMSettingWirelessSecurity *s_wsec; - - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - g_assert(s_wsec); - - g_object_set(s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "wpa-psk", - NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, - "foobarbaz", - NM_SETTING_WIRELESS_SECURITY_PSK, - "random psk", - NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, - "aaaaaaaaaa", - NULL); - return s_wsec; -} - -static gboolean -_variant_contains(GVariant *vardict, const char *key) -{ - gs_unref_variant GVariant *value = NULL; - - value = g_variant_lookup_value(vardict, key, NULL); - return !!value; -} - -static void -test_setting_to_dbus_all(void) -{ - NMSettingWirelessSecurity *s_wsec; - GVariant * dict; - - s_wsec = make_test_wsec_setting("setting-to-dbus-all"); - - dict = _nm_setting_to_dbus(NM_SETTING(s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); - - /* Make sure all keys are there */ - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)); - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME)); - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_PSK)); - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0)); - - g_variant_unref(dict); - g_object_unref(s_wsec); -} - -static void -test_setting_to_dbus_no_secrets(void) -{ - NMSettingWirelessSecurity *s_wsec; - GVariant * dict; - - s_wsec = make_test_wsec_setting("setting-to-dbus-no-secrets"); - - dict = _nm_setting_to_dbus(NM_SETTING(s_wsec), NULL, NM_CONNECTION_SERIALIZE_NO_SECRETS, NULL); - - /* Make sure non-secret keys are there */ - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)); - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME)); - - /* Make sure secrets are not there */ - g_assert(!_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_PSK)); - g_assert(!_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0)); - - g_variant_unref(dict); - g_object_unref(s_wsec); -} - -static void -test_setting_to_dbus_only_secrets(void) -{ - NMSettingWirelessSecurity *s_wsec; - GVariant * dict; - - s_wsec = make_test_wsec_setting("setting-to-dbus-only-secrets"); - - dict = - _nm_setting_to_dbus(NM_SETTING(s_wsec), NULL, NM_CONNECTION_SERIALIZE_ONLY_SECRETS, NULL); - - /* Make sure non-secret keys are not there */ - g_assert(!_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)); - g_assert(!_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME)); - - /* Make sure secrets are there */ - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_PSK)); - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0)); - - g_variant_unref(dict); - g_object_unref(s_wsec); -} - -static void -test_setting_to_dbus_transform(void) -{ - NMSetting * s_wired; - GVariant * dict, *val; - const char * test_mac_address = "11:22:33:44:55:66"; - const guint8 *dbus_mac_address; - guint8 cmp_mac_address[ETH_ALEN]; - gsize len; - - s_wired = nm_setting_wired_new(); - g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, test_mac_address, NULL); - - g_assert_cmpstr(nm_setting_wired_get_mac_address(NM_SETTING_WIRED(s_wired)), - ==, - test_mac_address); - - dict = _nm_setting_to_dbus(s_wired, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); - g_assert(dict != NULL); - - val = g_variant_lookup_value(dict, NM_SETTING_WIRED_MAC_ADDRESS, G_VARIANT_TYPE_BYTESTRING); - g_assert(val != NULL); - - dbus_mac_address = g_variant_get_fixed_array(val, &len, 1); - g_assert_cmpint(len, ==, ETH_ALEN); - - nm_utils_hwaddr_aton(test_mac_address, cmp_mac_address, ETH_ALEN); - g_assert(memcmp(dbus_mac_address, cmp_mac_address, ETH_ALEN) == 0); - - g_variant_unref(val); - g_variant_unref(dict); - g_object_unref(s_wired); -} - -static void -test_setting_to_dbus_enum(void) -{ - NMSetting *s_ip6, *s_wsec, *s_serial; - GVariant * dict, *val; - - /* enum */ - s_ip6 = nm_setting_ip6_config_new(); - g_object_set(s_ip6, - NM_SETTING_IP6_CONFIG_IP6_PRIVACY, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, - NULL); - - dict = _nm_setting_to_dbus(s_ip6, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); - g_assert(dict != NULL); - - val = g_variant_lookup_value(dict, NM_SETTING_IP6_CONFIG_IP6_PRIVACY, G_VARIANT_TYPE_INT32); - g_assert(val != NULL); - g_assert_cmpint(g_variant_get_int32(val), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); - g_variant_unref(val); - - g_variant_unref(dict); - g_object_unref(s_ip6); - - /* flags (and a transformed enum) */ - s_wsec = nm_setting_wireless_security_new(); - g_object_set(s_wsec, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, - NM_WEP_KEY_TYPE_KEY, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, - (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED), - NULL); - - dict = _nm_setting_to_dbus(s_wsec, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); - g_assert(dict != NULL); - - val = g_variant_lookup_value(dict, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, - G_VARIANT_TYPE_UINT32); - g_assert(val != NULL); - g_assert_cmpint(g_variant_get_uint32(val), ==, NM_WEP_KEY_TYPE_KEY); - g_variant_unref(val); - - val = g_variant_lookup_value(dict, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, - G_VARIANT_TYPE_UINT32); - g_assert(val != NULL); - g_assert_cmpint(g_variant_get_uint32(val), - ==, - (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED)); - g_variant_unref(val); - - g_variant_unref(dict); - g_object_unref(s_wsec); - - /* another transformed enum */ - s_serial = nm_setting_serial_new(); - g_object_set(s_serial, NM_SETTING_SERIAL_PARITY, NM_SETTING_SERIAL_PARITY_ODD, NULL); - - dict = _nm_setting_to_dbus(s_serial, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); - g_assert(dict != NULL); - - val = g_variant_lookup_value(dict, NM_SETTING_SERIAL_PARITY, G_VARIANT_TYPE_BYTE); - g_assert(val != NULL); - g_assert_cmpint(g_variant_get_byte(val), ==, 'o'); - g_variant_unref(val); - - g_variant_unref(dict); - g_object_unref(s_serial); -} - -static void -test_connection_to_dbus_setting_name(void) -{ - NMConnection * connection; - NMSettingWirelessSecurity *s_wsec; - GVariant * dict; - - connection = nm_simple_connection_new(); - s_wsec = make_test_wsec_setting("connection-to-dbus-setting-name"); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - - g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); - g_assert(_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - g_object_set(s_wsec, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NULL); - - g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); - g_assert(!_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - g_object_set(s_wsec, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - NULL); - - g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); - g_assert(_nm_connection_aggregate(connection, - NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, - NULL)); - - dict = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); - - /* Make sure the keys of the first level dict are setting names, not - * the GType name of the setting objects. - */ - g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME)); - - g_variant_unref(dict); - g_object_unref(connection); -} - -static void -test_connection_to_dbus_deprecated_props(void) -{ - NMConnection * connection; - NMSetting * s_wireless; - GBytes * ssid; - NMSettingWirelessSecurity *s_wsec; - GVariant * dict, *wireless_dict, *sec_val; - - connection = nmtst_create_minimal_connection("test-connection-to-dbus-deprecated-props", - NULL, - NM_SETTING_WIRELESS_SETTING_NAME, - NULL); - - s_wireless = nm_setting_wireless_new(); - ssid = g_bytes_new("1234567", 7); - g_object_set(s_wireless, NM_SETTING_WIRELESS_SSID, ssid, NULL); - g_bytes_unref(ssid); - nm_connection_add_setting(connection, s_wireless); - - /* Serialization should not have an 802-11-wireless.security property */ - dict = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); - g_assert(dict != NULL); - - wireless_dict = - g_variant_lookup_value(dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - g_assert(wireless_dict != NULL); - - sec_val = g_variant_lookup_value(wireless_dict, "security", NULL); - g_assert(sec_val == NULL); - - g_variant_unref(wireless_dict); - g_variant_unref(dict); - - /* Now add an NMSettingWirelessSecurity and try again */ - s_wsec = make_test_wsec_setting("test-connection-to-dbus-deprecated-props"); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - - dict = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); - g_assert(dict != NULL); - - wireless_dict = - g_variant_lookup_value(dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - g_assert(wireless_dict != NULL); - - sec_val = g_variant_lookup_value(wireless_dict, "security", NULL); - g_assert(g_variant_is_of_type(sec_val, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr(g_variant_get_string(sec_val, NULL), - ==, - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); - - g_variant_unref(sec_val); - g_variant_unref(wireless_dict); - g_variant_unref(dict); - g_object_unref(connection); -} - -static void -test_setting_new_from_dbus(void) -{ - NMSettingWirelessSecurity *s_wsec; - GVariant * dict; - - s_wsec = make_test_wsec_setting("setting-new-from-dbus"); - dict = _nm_setting_to_dbus(NM_SETTING(s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); - g_object_unref(s_wsec); - - s_wsec = - (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus(NM_TYPE_SETTING_WIRELESS_SECURITY, - dict, - NULL, - NM_SETTING_PARSE_FLAGS_NONE, - NULL); - g_variant_unref(dict); - - g_assert(s_wsec); - g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "wpa-psk"); - g_assert_cmpstr(nm_setting_wireless_security_get_leap_username(s_wsec), ==, "foobarbaz"); - g_assert_cmpstr(nm_setting_wireless_security_get_psk(s_wsec), ==, "random psk"); - g_object_unref(s_wsec); -} - -static void -test_setting_new_from_dbus_transform(void) -{ - NMSetting * s_wired; - GVariant * dict; - GVariantBuilder builder; - const char * test_mac_address = "11:22:33:44:55:66"; - guint8 dbus_mac_address[ETH_ALEN]; - GError * error = NULL; - - nm_utils_hwaddr_aton(test_mac_address, dbus_mac_address, ETH_ALEN); - - g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_add( - &builder, - "{sv}", - NM_SETTING_WIRED_MAC_ADDRESS, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, dbus_mac_address, ETH_ALEN, 1)); - dict = g_variant_builder_end(&builder); - - s_wired = _nm_setting_new_from_dbus(NM_TYPE_SETTING_WIRED, - dict, - NULL, - NM_SETTING_PARSE_FLAGS_NONE, - &error); - g_assert_no_error(error); - - g_assert_cmpstr(nm_setting_wired_get_mac_address(NM_SETTING_WIRED(s_wired)), - ==, - test_mac_address); - - g_variant_unref(dict); - g_object_unref(s_wired); -} - -static void -test_setting_new_from_dbus_enum(void) -{ - NMSettingIP6Config * s_ip6; - NMSettingWirelessSecurity *s_wsec; - NMSettingSerial * s_serial; - GVariant * dict; - GVariantBuilder builder; - GError * error = NULL; - - /* enum */ - g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_add(&builder, - "{sv}", - NM_SETTING_IP6_CONFIG_IP6_PRIVACY, - g_variant_new_int32(NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR)); - dict = g_variant_builder_end(&builder); - - s_ip6 = (NMSettingIP6Config *) _nm_setting_new_from_dbus(NM_TYPE_SETTING_IP6_CONFIG, - dict, - NULL, - NM_SETTING_PARSE_FLAGS_NONE, - &error); - g_assert_no_error(error); - - g_assert_cmpint(nm_setting_ip6_config_get_ip6_privacy(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); - - g_variant_unref(dict); - g_object_unref(s_ip6); - - /* flags (and a transformed enum) */ - g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_add(&builder, - "{sv}", - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, - g_variant_new_uint32(NM_WEP_KEY_TYPE_KEY)); - g_variant_builder_add(&builder, - "{sv}", - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, - g_variant_new_uint32(NM_SETTING_SECRET_FLAG_AGENT_OWNED - | NM_SETTING_SECRET_FLAG_NOT_SAVED)); - dict = g_variant_builder_end(&builder); - - s_wsec = - (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus(NM_TYPE_SETTING_WIRELESS_SECURITY, - dict, - NULL, - NM_SETTING_PARSE_FLAGS_NONE, - &error); - g_assert_no_error(error); - - g_assert_cmpint(nm_setting_wireless_security_get_wep_key_type(s_wsec), ==, NM_WEP_KEY_TYPE_KEY); - g_assert_cmpint(nm_setting_wireless_security_get_wep_key_flags(s_wsec), - ==, - (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED)); - - g_variant_unref(dict); - g_object_unref(s_wsec); - - /* another transformed enum */ - g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_add(&builder, "{sv}", NM_SETTING_SERIAL_PARITY, g_variant_new_byte('E')); - dict = g_variant_builder_end(&builder); - - s_serial = (NMSettingSerial *) _nm_setting_new_from_dbus(NM_TYPE_SETTING_SERIAL, - dict, - NULL, - NM_SETTING_PARSE_FLAGS_NONE, - &error); - g_assert_no_error(error); - - g_assert_cmpint(nm_setting_serial_get_parity(s_serial), ==, NM_SETTING_SERIAL_PARITY_EVEN); - - g_variant_unref(dict); - g_object_unref(s_serial); -} - -static void -test_setting_new_from_dbus_bad(void) -{ - NMSetting * setting; - NMConnection *conn; - GBytes * ssid; - GPtrArray * addrs; - GVariant * orig_dict, *dict; - GError * error = NULL; - - /* We want to test: - * - ordinary scalar properties - * - string properties - * - GBytes-valued properties (which are handled specially by set_property_from_dbus()) - * - enum/flags-valued properties - * - overridden properties - * - transformed properties - * - * No single setting class has examples of all of these, so we need two settings. - */ - - conn = nm_simple_connection_new(); - - setting = nm_setting_connection_new(); - g_object_set(setting, - NM_SETTING_CONNECTION_ID, - "test", - NM_SETTING_CONNECTION_UUID, - "83c5a841-1759-4cdb-bfce-8d4087956497", - NULL); - nm_connection_add_setting(conn, setting); - - setting = nm_setting_wireless_new(); - ssid = g_bytes_new("my-ssid", 7); - g_object_set(setting, - /* scalar */ - NM_SETTING_WIRELESS_RATE, - 100, - /* string */ - NM_SETTING_WIRELESS_MODE, - NM_SETTING_WIRELESS_MODE_INFRA, - /* GBytes */ - NM_SETTING_WIRELESS_SSID, - ssid, - /* transformed */ - NM_SETTING_WIRELESS_BSSID, - "00:11:22:33:44:55", - NULL); - g_bytes_unref(ssid); - nm_connection_add_setting(conn, setting); - - setting = nm_setting_ip6_config_new(); - addrs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); - g_ptr_array_add(addrs, nm_ip_address_new(AF_INET6, "1234::5678", 64, NULL)); - g_object_set(setting, - /* enum */ - NM_SETTING_IP6_CONFIG_IP6_PRIVACY, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR, - /* overridden */ - NM_SETTING_IP_CONFIG_ADDRESSES, - addrs, - /* (needed in order to verify()) */ - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NULL); - g_ptr_array_unref(addrs); - nm_connection_add_setting(conn, setting); - - orig_dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); - g_object_unref(conn); - - /* sanity-check */ - conn = _connection_new_from_dbus(orig_dict, &error); - g_assert_no_error(error); - g_assert(conn); - g_object_unref(conn); - - /* Compatible mismatches */ - - dict = g_variant_ref(orig_dict); - NMTST_VARIANT_EDITOR(dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_RATE, - "i", - 10);); - conn = _connection_new_from_dbus(dict, &error); - g_assert(conn); - g_assert_no_error(error); - setting = nm_connection_get_setting(conn, NM_TYPE_SETTING_WIRELESS); - g_assert(setting); - g_assert_cmpint(nm_setting_wireless_get_rate(NM_SETTING_WIRELESS(setting)), ==, 10); - g_object_unref(conn); - g_variant_unref(dict); - - dict = g_variant_ref(orig_dict); - NMTST_VARIANT_EDITOR( - dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_IP6_PRIVACY, - "i", - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);); - conn = _connection_new_from_dbus(dict, &error); - g_assert(conn); - g_assert_no_error(error); - setting = nm_connection_get_setting(conn, NM_TYPE_SETTING_IP6_CONFIG); - g_assert(setting); - g_assert_cmpint(nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(setting)), - ==, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); - g_object_unref(conn); - g_variant_unref(dict); - - /* Incompatible mismatches */ - - dict = g_variant_ref(orig_dict); - NMTST_VARIANT_EDITOR(dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_RATE, - "s", - "ten");); - conn = _connection_new_from_dbus(dict, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "802-11-wireless.rate:")); - g_clear_error(&error); - g_variant_unref(dict); - - dict = g_variant_ref(orig_dict); - NMTST_VARIANT_EDITOR(dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MODE, - "b", - FALSE);); - conn = _connection_new_from_dbus(dict, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "802-11-wireless.mode:")); - g_clear_error(&error); - g_variant_unref(dict); - - dict = g_variant_ref(orig_dict); - NMTST_VARIANT_EDITOR(dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_SSID, - "s", - "fred");); - conn = _connection_new_from_dbus(dict, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "802-11-wireless.ssid:")); - g_clear_error(&error); - g_variant_unref(dict); - - dict = g_variant_ref(orig_dict); - NMTST_VARIANT_EDITOR(dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_BSSID, - "i", - 42);); - conn = _connection_new_from_dbus(dict, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "802-11-wireless.bssid:")); - g_clear_error(&error); - g_variant_unref(dict); - - dict = g_variant_ref(orig_dict); - NMTST_VARIANT_EDITOR(dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_IP6_PRIVACY, - "s", - "private");); - conn = _connection_new_from_dbus(dict, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "ipv6.ip6-privacy:")); - g_clear_error(&error); - g_variant_unref(dict); - - dict = g_variant_ref(orig_dict); - NMTST_VARIANT_EDITOR(dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_ADDRESSES, - "s", - "1234::5678");); - conn = _connection_new_from_dbus(dict, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "ipv6.addresses:")); - g_clear_error(&error); - g_variant_unref(dict); - - g_variant_unref(orig_dict); -} - -static NMConnection * -new_test_connection(void) -{ - NMConnection *connection; - NMSetting * setting; - char * uuid; - guint64 timestamp = time(NULL); - - connection = nm_simple_connection_new(); - - setting = nm_setting_connection_new(); - uuid = nm_utils_uuid_generate(); - g_object_set(G_OBJECT(setting), - NM_SETTING_CONNECTION_ID, - "foobar", - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_CONNECTION_TIMESTAMP, - timestamp, - NULL); - g_free(uuid); - nm_connection_add_setting(connection, setting); - - setting = nm_setting_wired_new(); - g_object_set(G_OBJECT(setting), NM_SETTING_WIRED_MTU, 1592, NULL); - nm_connection_add_setting(connection, setting); - - setting = nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(setting), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, - "eyeofthetiger", - NULL); - nm_connection_add_setting(connection, setting); - - return connection; -} - -static GVariant * -new_connection_dict(char ** out_uuid, - const char **out_expected_id, - const char **out_expected_ip6_method) -{ - GVariantBuilder conn_builder, setting_builder; - - g_variant_builder_init(&conn_builder, NM_VARIANT_TYPE_CONNECTION); - - *out_uuid = nm_utils_uuid_generate(); - *out_expected_id = "My happy connection"; - *out_expected_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL; - - /* Connection setting */ - g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_add(&setting_builder, - "{sv}", - NM_SETTING_NAME, - g_variant_new_string(NM_SETTING_CONNECTION_SETTING_NAME)); - g_variant_builder_add(&setting_builder, - "{sv}", - NM_SETTING_CONNECTION_ID, - g_variant_new_string(*out_expected_id)); - g_variant_builder_add(&setting_builder, - "{sv}", - NM_SETTING_CONNECTION_UUID, - g_variant_new_string(*out_uuid)); - g_variant_builder_add(&setting_builder, - "{sv}", - NM_SETTING_CONNECTION_TYPE, - g_variant_new_string(NM_SETTING_WIRED_SETTING_NAME)); - - g_variant_builder_add(&conn_builder, - "{sa{sv}}", - NM_SETTING_CONNECTION_SETTING_NAME, - &setting_builder); - - /* Wired setting */ - g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_add(&conn_builder, - "{sa{sv}}", - NM_SETTING_WIRED_SETTING_NAME, - &setting_builder); - - /* IP6 */ - g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_add(&setting_builder, - "{sv}", - NM_SETTING_IP_CONFIG_METHOD, - g_variant_new_string(*out_expected_ip6_method)); - g_variant_builder_add(&conn_builder, - "{sa{sv}}", - NM_SETTING_IP6_CONFIG_SETTING_NAME, - &setting_builder); - - return g_variant_builder_end(&conn_builder); -} - -static void -test_connection_replace_settings(void) -{ - NMConnection * connection; - GVariant * new_settings; - GError * error = NULL; - gboolean success; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip6; - char * uuid = NULL; - const char * expected_id = NULL, *expected_method = NULL; - - connection = new_test_connection(); - - new_settings = new_connection_dict(&uuid, &expected_id, &expected_method); - g_assert(new_settings); - - /* Replace settings and test */ - success = nm_connection_replace_settings(connection, new_settings, &error); - g_assert_no_error(error); - g_assert(success); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); - g_assert_cmpstr(nm_setting_connection_get_uuid(s_con), ==, uuid); - - g_assert(nm_connection_get_setting_wired(connection)); - g_assert(!nm_connection_get_setting_ip4_config(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), ==, expected_method); - - g_free(uuid); - g_variant_unref(new_settings); - g_object_unref(connection); -} - -static void -test_connection_replace_settings_from_connection(void) -{ - NMConnection * connection, *replacement; - NMSettingConnection *s_con; - NMSetting * setting; - GBytes * ssid; - char * uuid = NULL; - const char * expected_id = "Awesome connection"; - - connection = new_test_connection(); - g_assert(connection); - - replacement = nm_simple_connection_new(); - g_assert(replacement); - - /* New connection setting */ - setting = nm_setting_connection_new(); - g_assert(setting); - - uuid = nm_utils_uuid_generate(); - g_object_set(setting, - NM_SETTING_CONNECTION_ID, - expected_id, - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRELESS_SETTING_NAME, - NULL); - nm_connection_add_setting(replacement, setting); - - /* New wifi setting */ - setting = nm_setting_wireless_new(); - g_assert(setting); - - ssid = g_bytes_new("1234567", 7); - g_object_set(setting, - NM_SETTING_WIRELESS_SSID, - ssid, - NM_SETTING_WIRELESS_MODE, - "infrastructure", - NULL); - g_bytes_unref(ssid); - nm_connection_add_setting(replacement, setting); - - /* Replace settings and test */ - nm_connection_replace_settings_from_connection(connection, replacement); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); - g_assert_cmpstr(nm_setting_connection_get_uuid(s_con), ==, uuid); - - g_assert(!nm_connection_get_setting_wired(connection)); - g_assert(!nm_connection_get_setting_ip6_config(connection)); - g_assert(nm_connection_get_setting_wireless(connection)); - - g_free(uuid); - g_object_unref(replacement); - g_object_unref(connection); -} - -static void -test_connection_replace_settings_bad(void) -{ - NMConnection * connection, *new_connection; - GVariant * new_settings; - GVariantBuilder builder, setting_builder; - GError * error = NULL; - gboolean success; - NMSettingConnection *s_con; - - new_connection = new_test_connection(); - g_assert(nm_connection_verify(new_connection, NULL)); - s_con = nm_connection_get_setting_connection(new_connection); - g_object_set(s_con, - NM_SETTING_CONNECTION_UUID, - NULL, - NM_SETTING_CONNECTION_ID, - "bad-connection", - NULL); - g_assert(!nm_connection_verify(new_connection, NULL)); - - /* nm_connection_replace_settings_from_connection() should succeed */ - connection = new_test_connection(); - nm_connection_replace_settings_from_connection(connection, new_connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "bad-connection"); - g_assert(!nm_connection_verify(connection, NULL)); - g_object_unref(connection); - - /* nm_connection_replace_settings() should succeed */ - new_settings = nm_connection_to_dbus(new_connection, NM_CONNECTION_SERIALIZE_ALL); - g_assert(new_settings != NULL); - - connection = new_test_connection(); - success = nm_connection_replace_settings(connection, new_settings, &error); - g_assert_no_error(error); - g_assert(success); - - g_assert_cmpstr(nm_connection_get_id(connection), ==, "bad-connection"); - g_assert(!nm_connection_verify(connection, NULL)); - g_object_unref(connection); - g_variant_unref(new_settings); - - /* But given an invalid dict, it should fail */ - g_variant_builder_init(&builder, NM_VARIANT_TYPE_CONNECTION); - g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); - g_variant_builder_add(&builder, "{sa{sv}}", "ip-over-avian-carrier", &setting_builder); - new_settings = g_variant_builder_end(&builder); - - connection = new_test_connection(); - success = nm_connection_replace_settings(connection, new_settings, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING); - g_clear_error(&error); - g_assert(!success); - - g_assert(nm_connection_verify(connection, NULL)); - g_object_unref(connection); - - g_variant_unref(new_settings); - g_object_unref(new_connection); -} - -static void -test_connection_new_from_dbus(void) -{ - NMConnection * connection; - GVariant * new_settings; - GError * error = NULL; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip6; - char * uuid = NULL; - const char * expected_id = NULL, *expected_method = NULL; - - new_settings = new_connection_dict(&uuid, &expected_id, &expected_method); - g_assert(new_settings); - - /* Replace settings and test */ - connection = _connection_new_from_dbus(new_settings, &error); - g_assert_no_error(error); - g_assert(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); - g_assert_cmpstr(nm_setting_connection_get_uuid(s_con), ==, uuid); - - g_assert(nm_connection_get_setting_wired(connection)); - g_assert(nm_connection_get_setting_ip4_config(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), ==, expected_method); - - g_free(uuid); - g_variant_unref(new_settings); - g_object_unref(connection); -} - -static void -check_permission(NMSettingConnection *s_con, guint32 idx, const char *expected_uname) -{ - gboolean success; - const char *ptype = NULL, *pitem = NULL, *detail = NULL; - - success = nm_setting_connection_get_permission(s_con, idx, &ptype, &pitem, &detail); - g_assert(success); - - g_assert_cmpstr(ptype, ==, "user"); - - g_assert(pitem); - g_assert_cmpstr(pitem, ==, expected_uname); - - g_assert(!detail); -} - -#define TEST_UNAME "asdfasfasdf" - -static void -test_setting_connection_permissions_helpers(void) -{ - NMSettingConnection *s_con; - gboolean success; - char buf[9] = {0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00}; - char ** perms; - const char * expected_perm = "user:" TEST_UNAME ":"; - - s_con = NM_SETTING_CONNECTION(nm_setting_connection_new()); - - /* Ensure a bad [type] is rejected */ - success = nm_setting_connection_add_permission(s_con, "foobar", "blah", NULL); - g_assert(!success); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); - - /* Ensure a bad [type] is rejected */ - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(ptype)); - success = nm_setting_connection_add_permission(s_con, NULL, "blah", NULL); - g_test_assert_expected_messages(); - g_assert(!success); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); - - /* Ensure a bad [item] is rejected */ - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(pitem)); - success = nm_setting_connection_add_permission(s_con, "user", NULL, NULL); - g_test_assert_expected_messages(); - g_assert(!success); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); - - /* Ensure a bad [item] is rejected */ - success = nm_setting_connection_add_permission(s_con, "user", "", NULL); - g_assert(!success); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); - - /* Ensure an [item] with ':' is rejected */ - success = nm_setting_connection_add_permission(s_con, "user", "ad:asdf", NULL); - g_assert(!success); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); - - /* Ensure a non-UTF-8 [item] is rejected */ - success = nm_setting_connection_add_permission(s_con, "user", buf, NULL); - g_assert(!success); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); - - /* Ensure a non-NULL [detail] is rejected */ - success = nm_setting_connection_add_permission(s_con, "user", "dafasdf", "asdf"); - g_assert(!success); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); - - /* Ensure a valid call results in success */ - success = nm_setting_connection_add_permission(s_con, "user", TEST_UNAME, NULL); - g_assert(success); - - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - - check_permission(s_con, 0, TEST_UNAME); - - /* Check the actual GObject property just to be paranoid */ - g_object_get(G_OBJECT(s_con), NM_SETTING_CONNECTION_PERMISSIONS, &perms, NULL); - g_assert(perms); - g_assert_cmpint(g_strv_length(perms), ==, 1); - g_assert_cmpstr(perms[0], ==, expected_perm); - g_strfreev(perms); - - /* Now remove that permission and ensure we have 0 permissions */ - nm_setting_connection_remove_permission(s_con, 0); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); - - g_object_unref(s_con); -} - -static void -add_permission_property(NMSettingConnection *s_con, - const char * ptype, - const char * pitem, - int pitem_len, - const char * detail) -{ - GString *str; - char * perms[2]; - - str = g_string_sized_new(50); - if (ptype) - g_string_append(str, ptype); - g_string_append_c(str, ':'); - - if (pitem) { - if (pitem_len >= 0) - g_string_append_len(str, pitem, pitem_len); - else - g_string_append(str, pitem); - } - - g_string_append_c(str, ':'); - - if (detail) - g_string_append(str, detail); - - perms[0] = str->str; - perms[1] = NULL; - g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_PERMISSIONS, perms, NULL); - - g_string_free(str, TRUE); -} - -static void -test_setting_connection_permissions_property(void) -{ - gs_unref_object NMSettingConnection *s_con = NULL; - gboolean success; - char buf[9] = {0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00}; - - s_con = NM_SETTING_CONNECTION(nm_setting_connection_new()); - -#define _assert_permission_invalid_at_idx(s_con, idx, expected_item) \ - G_STMT_START \ - { \ - NMSettingConnection *_s_con = (s_con); \ - guint _idx = (idx); \ - const char * _ptype; \ - const char * _pitem; \ - const char * _detail; \ - const char ** _p_ptype = nmtst_get_rand_bool() ? &_ptype : NULL; \ - const char ** _p_pitem = nmtst_get_rand_bool() ? &_pitem : NULL; \ - const char ** _p_detail = nmtst_get_rand_bool() ? &_detail : NULL; \ - \ - g_assert_cmpint(_idx, <, nm_setting_connection_get_num_permissions(_s_con)); \ - g_assert( \ - nm_setting_connection_get_permission(_s_con, _idx, _p_ptype, _p_pitem, _p_detail)); \ - if (_p_ptype) \ - g_assert_cmpstr(_ptype, ==, "invalid"); \ - if (_p_pitem) { \ - const char *_expected_item = (expected_item); \ - \ - if (!_expected_item) \ - g_assert_cmpstr(_pitem, !=, NULL); \ - else \ - g_assert_cmpstr(_pitem, ==, _expected_item); \ - } \ - if (_p_detail) \ - g_assert_cmpstr(_detail, ==, NULL); \ - } \ - G_STMT_END - - /* Ensure a bad [type] is rejected */ - add_permission_property(s_con, "foobar", "blah", -1, NULL); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - _assert_permission_invalid_at_idx(s_con, 0, "foobar:blah:"); - - /* Ensure a bad [type] is rejected */ - add_permission_property(s_con, NULL, "blah", -1, NULL); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - _assert_permission_invalid_at_idx(s_con, 0, ":blah:"); - - /* Ensure a bad [item] is rejected */ - add_permission_property(s_con, "user", NULL, -1, NULL); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - _assert_permission_invalid_at_idx(s_con, 0, "user::"); - - /* Ensure a bad [item] is rejected */ - add_permission_property(s_con, "user", "", -1, NULL); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - _assert_permission_invalid_at_idx(s_con, 0, "user::"); - - /* Ensure an [item] with ':' in the middle is rejected */ - add_permission_property(s_con, "user", "ad:asdf", -1, NULL); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - _assert_permission_invalid_at_idx(s_con, 0, "user:ad:asdf:"); - - /* Ensure an [item] with ':' at the end is rejected */ - add_permission_property(s_con, "user", "adasdfaf:", -1, NULL); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - _assert_permission_invalid_at_idx(s_con, 0, "user:adasdfaf::"); - - /* Ensure a non-UTF-8 [item] is rejected */ - add_permission_property(s_con, "user", buf, (int) sizeof(buf), NULL); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - _assert_permission_invalid_at_idx(s_con, 0, NULL); - - /* Ensure a non-NULL [detail] is rejected */ - add_permission_property(s_con, "user", "dafasdf", -1, "asdf"); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - _assert_permission_invalid_at_idx(s_con, 0, "user:dafasdf:asdf"); - - /* Ensure a valid call results in success */ - success = nm_setting_connection_add_permission(s_con, "user", TEST_UNAME, NULL); - g_assert(success); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 2); - _assert_permission_invalid_at_idx(s_con, 0, "user:dafasdf:asdf"); - check_permission(s_con, 1, TEST_UNAME); - - /* Now remove that permission and ensure we have 0 permissions */ - nm_setting_connection_remove_permission(s_con, 0); - g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); -} - -static void -test_connection_compare_same(void) -{ - NMConnection *a, *b; - - a = new_test_connection(); - b = nm_simple_connection_new_clone(a); - g_assert(nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); - g_object_unref(a); - g_object_unref(b); -} - -static void -test_connection_compare_key_only_in_a(void) -{ - NMConnection * a, *b; - NMSettingConnection *s_con; - - a = new_test_connection(); - b = nm_simple_connection_new_clone(a); - s_con = (NMSettingConnection *) nm_connection_get_setting(b, NM_TYPE_SETTING_CONNECTION); - g_assert(s_con); - g_object_set(s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL); - - g_assert(!nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); - g_object_unref(a); - g_object_unref(b); -} - -static void -test_connection_compare_setting_only_in_a(void) -{ - NMConnection *a, *b; - - a = new_test_connection(); - b = nm_simple_connection_new_clone(a); - nm_connection_remove_setting(b, NM_TYPE_SETTING_IP4_CONFIG); - g_assert(!nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); - g_object_unref(a); - g_object_unref(b); -} - -static void -test_connection_compare_key_only_in_b(void) -{ - NMConnection * a, *b; - NMSettingConnection *s_con; - - a = new_test_connection(); - b = nm_simple_connection_new_clone(a); - s_con = (NMSettingConnection *) nm_connection_get_setting(b, NM_TYPE_SETTING_CONNECTION); - g_assert(s_con); - g_object_set(s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL); - - g_assert(!nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); - g_object_unref(a); - g_object_unref(b); -} - -static void -test_connection_compare_setting_only_in_b(void) -{ - NMConnection *a, *b; - - a = new_test_connection(); - b = nm_simple_connection_new_clone(a); - nm_connection_remove_setting(a, NM_TYPE_SETTING_IP4_CONFIG); - g_assert(!nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); - g_object_unref(a); - g_object_unref(b); -} - -typedef struct { - const char *key_name; - guint32 result; -} DiffKey; - -typedef struct { - const char *name; - DiffKey keys[30]; -} DiffSetting; - -#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) - -static void -ensure_diffs(GHashTable *diffs, const DiffSetting *check, gsize n_check) -{ - guint i; - - g_assert(g_hash_table_size(diffs) == n_check); - - /* Loop through the settings */ - for (i = 0; i < n_check; i++) { - GHashTable *setting_hash; - guint z = 0; - - setting_hash = g_hash_table_lookup(diffs, check[i].name); - g_assert(setting_hash); - - /* Get the number of keys to check */ - while (check[i].keys[z].key_name) - z++; - g_assert(g_hash_table_size(setting_hash) == z); - - /* Now compare the actual keys */ - for (z = 0; check[i].keys[z].key_name; z++) { - NMSettingDiffResult result; - - result = GPOINTER_TO_UINT(g_hash_table_lookup(setting_hash, check[i].keys[z].key_name)); - g_assert(result == check[i].keys[z].result); - } - } -} - -static void -test_connection_diff_a_only(void) -{ - NMConnection * connection; - GHashTable * out_diffs = NULL; - gboolean same; - const DiffSetting settings[] = { - {NM_SETTING_CONNECTION_SETTING_NAME, - {{NM_SETTING_CONNECTION_ID, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_UUID, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_STABLE_ID, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_TYPE, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_TIMESTAMP, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_AUTOCONNECT, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_MULTI_CONNECT, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_READ_ONLY, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_PERMISSIONS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_ZONE, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_MASTER, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_SECONDARIES, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_METERED, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_LLDP, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_AUTH_RETRIES, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_MDNS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_LLMNR, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_MUD_URL, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A}, - {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}}}, - {NM_SETTING_WIRED_SETTING_NAME, - { - {NM_SETTING_WIRED_PORT, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_SPEED, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_DUPLEX, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_AUTO_NEGOTIATE, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_CLONED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_MTU, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_S390_SUBCHANNELS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_S390_NETTYPE, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_S390_OPTIONS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_WAKE_ON_LAN, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, NM_SETTING_DIFF_RESULT_IN_A}, - {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, - }}, - {NM_SETTING_IP4_CONFIG_SETTING_NAME, - { - {NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DNS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DNS_SEARCH, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DNS_OPTIONS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_ADDRESSES, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_GATEWAY, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_ROUTE_METRIC, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_ROUTE_TABLE, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_ROUTING_RULES, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP4_CONFIG_DHCP_FQDN, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_NEVER_DEFAULT, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_MAY_FAIL, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DAD_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DNS_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DHCP_IAID, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER, NM_SETTING_DIFF_RESULT_IN_A}, - {NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS, NM_SETTING_DIFF_RESULT_IN_A}, - {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, - }}, - }; - - connection = new_test_connection(); - - same = nm_connection_diff(connection, NULL, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs); - g_assert(same == FALSE); - g_assert(out_diffs != NULL); - g_assert(g_hash_table_size(out_diffs) > 0); - - ensure_diffs(out_diffs, settings, ARRAY_LEN(settings)); - - g_hash_table_destroy(out_diffs); - g_object_unref(connection); -} - -static void -test_connection_diff_same(void) -{ - NMConnection *a, *b; - GHashTable * out_diffs = NULL; - gboolean same; - - a = new_test_connection(); - b = nm_simple_connection_new_clone(a); - - same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs); - g_assert(same == TRUE); - g_assert(out_diffs == NULL); - g_object_unref(a); - g_object_unref(b); -} - -static void -test_connection_diff_different(void) -{ - NMConnection * a, *b; - GHashTable * out_diffs = NULL; - NMSettingIPConfig *s_ip4; - gboolean same; - const DiffSetting settings[] = { - {NM_SETTING_IP4_CONFIG_SETTING_NAME, - { - {NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B}, - {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, - }}, - }; - - a = new_test_connection(); - b = nm_simple_connection_new_clone(a); - s_ip4 = nm_connection_get_setting_ip4_config(a); - g_assert(s_ip4); - g_object_set(G_OBJECT(s_ip4), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NULL); - - same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs); - g_assert(same == FALSE); - g_assert(out_diffs != NULL); - g_assert(g_hash_table_size(out_diffs) > 0); - - ensure_diffs(out_diffs, settings, ARRAY_LEN(settings)); - - g_hash_table_destroy(out_diffs); - g_object_unref(a); - g_object_unref(b); -} - -static void -test_connection_diff_no_secrets(void) -{ - NMConnection * a, *b; - GHashTable * out_diffs = NULL; - NMSetting * s_pppoe; - gboolean same; - const DiffSetting settings[] = { - {NM_SETTING_PPPOE_SETTING_NAME, - { - {NM_SETTING_PPPOE_PASSWORD, NM_SETTING_DIFF_RESULT_IN_B}, - {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, - }}, - }; - - a = new_test_connection(); - s_pppoe = nm_setting_pppoe_new(); - g_object_set(G_OBJECT(s_pppoe), NM_SETTING_PPPOE_USERNAME, "thomas", NULL); - nm_connection_add_setting(a, s_pppoe); - - b = nm_simple_connection_new_clone(a); - - /* Add a secret to B */ - s_pppoe = NM_SETTING(nm_connection_get_setting_pppoe(b)); - g_assert(s_pppoe); - g_object_set(G_OBJECT(s_pppoe), NM_SETTING_PPPOE_PASSWORD, "secretpassword", NULL); - - /* Make sure the diff returns no results as secrets are ignored */ - same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &out_diffs); - g_assert(same == TRUE); - g_assert(out_diffs == NULL); - - /* Now make sure the diff returns results if secrets are not ignored */ - same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs); - g_assert(same == FALSE); - g_assert(out_diffs != NULL); - g_assert(g_hash_table_size(out_diffs) > 0); - - ensure_diffs(out_diffs, settings, ARRAY_LEN(settings)); - - g_hash_table_destroy(out_diffs); - g_object_unref(a); - g_object_unref(b); -} - -static void -test_connection_diff_inferrable(void) -{ - NMConnection * a, *b; - GHashTable * out_diffs = NULL; - gboolean same; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - char * uuid; - const DiffSetting settings[] = { - {NM_SETTING_CONNECTION_SETTING_NAME, - { - {NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A}, - {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, - }}, - }; - - a = new_test_connection(); - b = nm_simple_connection_new_clone(a); - - /* Change the UUID, wired MTU, and set ignore-auto-dns */ - s_con = nm_connection_get_setting_connection(a); - g_assert(s_con); - uuid = nm_utils_uuid_generate(); - g_object_set(G_OBJECT(s_con), - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_ID, - "really neat connection", - NULL); - g_free(uuid); - - s_wired = nm_connection_get_setting_wired(a); - g_assert(s_wired); - g_object_set(G_OBJECT(s_wired), NM_SETTING_WIRED_MTU, 300, NULL); - - s_ip4 = nm_connection_get_setting_ip4_config(a); - g_assert(s_ip4); - g_object_set(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE, NULL); - - /* Make sure the diff returns no results as secrets are ignored */ - same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs); - g_assert(same == TRUE); - g_assert(out_diffs == NULL); - - /* And change a INFERRABLE property to ensure that it shows up in the diff results */ - g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, "usb0", NULL); - - /* Make sure the diff returns no results as secrets are ignored */ - same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs); - g_assert(same == FALSE); - g_assert(out_diffs != NULL); - g_assert(g_hash_table_size(out_diffs) > 0); - - ensure_diffs(out_diffs, settings, ARRAY_LEN(settings)); - - g_hash_table_destroy(out_diffs); - g_object_unref(a); - g_object_unref(b); -} - -static void -add_generic_settings(NMConnection *connection, const char *ctype) -{ - NMSetting *setting; - char * uuid; - - uuid = nm_utils_uuid_generate(); - - setting = nm_setting_connection_new(); - g_object_set(setting, - NM_SETTING_CONNECTION_ID, - "asdfasdfadf", - NM_SETTING_CONNECTION_TYPE, - ctype, - NM_SETTING_CONNECTION_UUID, - uuid, - NULL); - nm_connection_add_setting(connection, setting); - - g_free(uuid); - - setting = nm_setting_ip4_config_new(); - g_object_set(setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - nm_connection_add_setting(connection, setting); - - setting = nm_setting_ip6_config_new(); - g_object_set(setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); - nm_connection_add_setting(connection, setting); -} - -static void -test_connection_good_base_types(void) -{ - NMConnection *connection; - NMSetting * setting; - gboolean success; - GError * error = NULL; - GBytes * ssid; - const char * bdaddr = "11:22:33:44:55:66"; - - /* Try a basic wired connection */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_WIRED_SETTING_NAME); - setting = nm_setting_wired_new(); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_no_error(error); - g_assert(success); - g_object_unref(connection); - - /* Try a wired PPPoE connection */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_PPPOE_SETTING_NAME); - setting = nm_setting_pppoe_new(); - g_object_set(setting, NM_SETTING_PPPOE_USERNAME, "bob smith", NULL); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_no_error(error); - g_assert(success); - g_object_unref(connection); - - /* Wifi connection */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_WIRELESS_SETTING_NAME); - - setting = nm_setting_wireless_new(); - ssid = g_bytes_new("1234567", 7); - g_object_set(setting, - NM_SETTING_WIRELESS_SSID, - ssid, - NM_SETTING_WIRELESS_MODE, - "infrastructure", - NULL); - g_bytes_unref(ssid); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_no_error(error); - g_assert(success); - g_object_unref(connection); - - /* Bluetooth connection */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_BLUETOOTH_SETTING_NAME); - - setting = nm_setting_bluetooth_new(); - g_object_set(setting, - NM_SETTING_BLUETOOTH_BDADDR, - bdaddr, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_BLUETOOTH_TYPE_PANU, - NULL); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_no_error(error); - g_assert(success); - g_object_unref(connection); - - /* WiMAX connection */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_WIMAX_SETTING_NAME); - setting = nm_setting_wimax_new(); - g_object_set(setting, NM_SETTING_WIMAX_NETWORK_NAME, "CLEAR", NULL); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_no_error(error); - g_assert(success); - g_object_unref(connection); - - /* GSM connection */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_GSM_SETTING_NAME); - - setting = nm_setting_gsm_new(); - g_object_set(setting, NM_SETTING_GSM_APN, "metered.billing.sucks", NULL); - nm_connection_add_setting(connection, setting); - - /* CDMA connection */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_CDMA_SETTING_NAME); - - setting = nm_setting_cdma_new(); - g_object_set(setting, - NM_SETTING_CDMA_NUMBER, - "#777", - NM_SETTING_CDMA_USERNAME, - "foobar@vzw.com", - NULL); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_no_error(error); - g_assert(success); - g_object_unref(connection); -} - -static void -test_connection_bad_base_types(void) -{ - NMConnection *connection; - NMSetting * setting; - gboolean success; - GError * error = NULL; - - /* Test various non-base connection types to make sure they are rejected; - * using a fake 'wired' connection so the rest of it verifies - */ - - /* Connection setting */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_CONNECTION_SETTING_NAME); - setting = nm_setting_wired_new(); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "connection.type: ")); - g_assert(success == FALSE); - g_object_unref(connection); - g_clear_error(&error); - - /* PPP setting */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_PPP_SETTING_NAME); - setting = nm_setting_wired_new(); - nm_connection_add_setting(connection, setting); - setting = nm_setting_ppp_new(); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "connection.type: ")); - g_assert(success == FALSE); - g_object_unref(connection); - g_clear_error(&error); - - /* Serial setting */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_SERIAL_SETTING_NAME); - setting = nm_setting_wired_new(); - nm_connection_add_setting(connection, setting); - setting = nm_setting_serial_new(); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "connection.type: ")); - g_assert(success == FALSE); - g_object_unref(connection); - g_clear_error(&error); - - /* IP4 setting */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_IP4_CONFIG_SETTING_NAME); - setting = nm_setting_wired_new(); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "connection.type: ")); - g_assert(success == FALSE); - g_object_unref(connection); - g_clear_error(&error); - - /* IP6 setting */ - connection = nm_simple_connection_new(); - add_generic_settings(connection, NM_SETTING_IP6_CONFIG_SETTING_NAME); - setting = nm_setting_wired_new(); - nm_connection_add_setting(connection, setting); - - success = nm_connection_verify(connection, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(g_str_has_prefix(error->message, "connection.type: ")); - g_assert(success == FALSE); - g_object_unref(connection); - g_clear_error(&error); -} - -static void -test_setting_compare_id(void) -{ - gs_unref_object NMSetting *old = NULL, *new = NULL; - gboolean success; - - old = nm_setting_connection_new(); - g_object_set(old, - NM_SETTING_CONNECTION_ID, - "really awesome cool connection", - NM_SETTING_CONNECTION_UUID, - "fbbd59d5-acab-4e30-8f86-258d272617e7", - NM_SETTING_CONNECTION_AUTOCONNECT, - FALSE, - NULL); - - new = nm_setting_duplicate(old); - g_object_set(new, NM_SETTING_CONNECTION_ID, "some different connection id", NULL); - - /* First make sure they are different */ - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(success == FALSE); - - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_IGNORE_ID); - g_assert(success); -} - -static void -test_setting_compare_addresses(void) -{ - gs_unref_object NMSetting *s1 = NULL, *s2 = NULL; - gboolean success; - NMIPAddress * a; - GHashTable * result = NULL; - - s1 = nm_setting_ip4_config_new(); - s2 = nm_setting_ip4_config_new(); - - a = nm_ip_address_new(AF_INET, "192.168.7.5", 24, NULL); - - nm_ip_address_set_attribute(a, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string("xoxoxo")); - nm_setting_ip_config_add_address((NMSettingIPConfig *) s1, a); - - nm_ip_address_set_attribute(a, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string("hello")); - nm_setting_ip_config_add_address((NMSettingIPConfig *) s2, a); - - nm_ip_address_unref(a); - - if (nmtst_get_rand_uint32() % 2) - NM_SWAP(&s1, &s2); - - success = nm_setting_compare(s1, s2, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(!success); - - success = nm_setting_diff(s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result); - g_assert(!success); - nm_clear_pointer(&result, g_hash_table_unref); -} - -static void -test_setting_compare_routes(void) -{ - gs_unref_object NMSetting *s1 = NULL, *s2 = NULL; - gboolean success; - NMIPRoute * r; - GHashTable * result = NULL; - - s1 = nm_setting_ip4_config_new(); - s2 = nm_setting_ip4_config_new(); - - r = nm_ip_route_new(AF_INET, "192.168.12.0", 24, "192.168.11.1", 473, NULL); - - nm_ip_route_set_attribute(r, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string("xoxoxo")); - nm_setting_ip_config_add_route((NMSettingIPConfig *) s1, r); - - nm_ip_route_set_attribute(r, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string("hello")); - nm_setting_ip_config_add_route((NMSettingIPConfig *) s2, r); - - nm_ip_route_unref(r); - - if (nmtst_get_rand_uint32() % 2) - NM_SWAP(&s1, &s2); - - success = nm_setting_compare(s1, s2, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(!success); - - success = nm_setting_diff(s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result); - g_assert(!success); - nm_clear_pointer(&result, g_hash_table_unref); -} - -static void -test_setting_compare_wired_cloned_mac_address(void) -{ - gs_unref_object NMSetting *old = NULL, *new = NULL; - gboolean success; - gs_free char * str1 = NULL; - - old = nm_setting_wired_new(); - g_object_set(old, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "stable", NULL); - - g_assert_cmpstr("stable", ==, nm_setting_wired_get_cloned_mac_address((NMSettingWired *) old)); - g_object_get(old, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); - g_assert_cmpstr("stable", ==, str1); - nm_clear_g_free(&str1); - - new = nm_setting_duplicate(old); - g_object_set(new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL); - - g_assert_cmpstr("11:22:33:44:55:66", - ==, - nm_setting_wired_get_cloned_mac_address((NMSettingWired *) new)); - g_object_get(new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); - g_assert_cmpstr("11:22:33:44:55:66", ==, str1); - nm_clear_g_free(&str1); - - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(!success); - g_clear_object(&new); - - new = nm_setting_duplicate(old); - g_object_set(new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "stable-bia", NULL); - - g_assert_cmpstr("stable-bia", - ==, - nm_setting_wired_get_cloned_mac_address((NMSettingWired *) new)); - g_object_get(new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); - g_assert_cmpstr("stable-bia", ==, str1); - nm_clear_g_free(&str1); - - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(!success); - g_clear_object(&new); -} - -static void -test_setting_compare_wireless_cloned_mac_address(void) -{ - gs_unref_object NMSetting *old = NULL, *new = NULL; - gboolean success; - gs_free char * str1 = NULL; - - old = nm_setting_wireless_new(); - g_object_set(old, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "stable", NULL); - - g_assert_cmpstr("stable", - ==, - nm_setting_wireless_get_cloned_mac_address((NMSettingWireless *) old)); - g_object_get(old, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); - g_assert_cmpstr("stable", ==, str1); - nm_clear_g_free(&str1); - - new = nm_setting_duplicate(old); - g_object_set(new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL); - - g_assert_cmpstr("11:22:33:44:55:66", - ==, - nm_setting_wireless_get_cloned_mac_address((NMSettingWireless *) new)); - g_object_get(new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); - g_assert_cmpstr("11:22:33:44:55:66", ==, str1); - nm_clear_g_free(&str1); - - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(!success); - g_clear_object(&new); - - new = nm_setting_duplicate(old); - g_object_set(new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "stable-bia", NULL); - - g_assert_cmpstr("stable-bia", - ==, - nm_setting_wireless_get_cloned_mac_address((NMSettingWireless *) new)); - g_object_get(new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); - g_assert_cmpstr("stable-bia", ==, str1); - nm_clear_g_free(&str1); - - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(!success); - g_clear_object(&new); -} - -static void -test_setting_compare_timestamp(void) -{ - gs_unref_object NMSetting *old = NULL, *new = NULL; - gboolean success; - - old = nm_setting_connection_new(); - g_object_set(old, - NM_SETTING_CONNECTION_ID, - "ignore timestamp connection", - NM_SETTING_CONNECTION_UUID, - "b047a198-0e0a-4f0e-a653-eea09bb35e40", - NM_SETTING_CONNECTION_AUTOCONNECT, - FALSE, - NM_SETTING_CONNECTION_TIMESTAMP, - (guint64) 1234567890, - NULL); - - new = nm_setting_duplicate(old); - g_object_set(new, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 1416316539, NULL); - - /* First make sure they are different */ - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(success == FALSE); - - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP); - g_assert(success); -} - -typedef struct { - NMSettingSecretFlags secret_flags; - NMSettingCompareFlags comp_flags; - gboolean remove_secret; -} TestDataCompareSecrets; - -static TestDataCompareSecrets * -test_data_compare_secrets_new(NMSettingSecretFlags secret_flags, - NMSettingCompareFlags comp_flags, - gboolean remove_secret) -{ - TestDataCompareSecrets *data = g_new0(TestDataCompareSecrets, 1); - - data->secret_flags = secret_flags; - data->comp_flags = comp_flags; - data->remove_secret = remove_secret; - return data; -} - -static void -_test_compare_secrets_check_diff(NMSetting * a, - NMSetting * b, - NMSettingCompareFlags flags, - gboolean exp_same_psk, - gboolean exp_same_psk_flags) -{ - gs_unref_hashtable GHashTable *h = NULL; - NMSettingDiffResult _RESULT_IN_A = NM_SETTING_DIFF_RESULT_IN_A; - NMSettingDiffResult _RESULT_IN_B = NM_SETTING_DIFF_RESULT_IN_B; - gboolean invert_results; - gboolean diff_result; - NMSettingSecretFlags a_psk_flags = - nm_setting_wireless_security_get_psk_flags(NM_SETTING_WIRELESS_SECURITY(a)); - NMSettingSecretFlags b_psk_flags = - nm_setting_wireless_security_get_psk_flags(NM_SETTING_WIRELESS_SECURITY(b)); - const char *a_psk = nm_setting_wireless_security_get_psk(NM_SETTING_WIRELESS_SECURITY(a)); - const char *b_psk = nm_setting_wireless_security_get_psk(NM_SETTING_WIRELESS_SECURITY(b)); - - g_assert(NM_IS_SETTING_WIRELESS_SECURITY(a)); - g_assert(NM_IS_SETTING_WIRELESS_SECURITY(b)); - - invert_results = nmtst_get_rand_bool(); - if (invert_results) { - _RESULT_IN_A = NM_SETTING_DIFF_RESULT_IN_B; - _RESULT_IN_B = NM_SETTING_DIFF_RESULT_IN_A; - } - - diff_result = nm_setting_diff(a, b, flags, invert_results, &h); - - g_assert(exp_same_psk_flags == (a_psk_flags == b_psk_flags)); - - if (nm_streq0(a_psk, b_psk)) - g_assert(exp_same_psk); - else { - if (flags == NM_SETTING_COMPARE_FLAG_EXACT) - g_assert(!exp_same_psk); - else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) { - if (!NM_FLAGS_HAS(a_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED) - && !NM_FLAGS_HAS(b_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) - g_assert(!exp_same_psk); - else if (!NM_FLAGS_HAS(a_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED) - && NM_FLAGS_HAS(b_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) - g_assert(!exp_same_psk); - else - g_assert(exp_same_psk); - } else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) { - if (!NM_FLAGS_HAS(a_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED) - && !NM_FLAGS_HAS(b_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)) - g_assert(!exp_same_psk); - else if (!NM_FLAGS_HAS(a_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED) - && NM_FLAGS_HAS(b_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)) - g_assert(!exp_same_psk); - else - g_assert(exp_same_psk); - } else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) - g_assert(exp_same_psk); - else - g_assert_not_reached(); - } - - g_assert(diff_result == (exp_same_psk && exp_same_psk_flags)); - g_assert(diff_result == (!h)); - - if (!diff_result) { - if (flags == NM_SETTING_COMPARE_FLAG_EXACT) - g_assert(!exp_same_psk); - else if (NM_IN_SET(flags, - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) - && (a_psk_flags != b_psk_flags) - && nm_setting_wireless_security_get_psk_flags(NM_SETTING_WIRELESS_SECURITY(a)) - == NM_SETTING_SECRET_FLAG_NONE) - g_assert(!exp_same_psk); - else - g_assert(exp_same_psk); - - g_assert((!exp_same_psk) == g_hash_table_contains(h, NM_SETTING_WIRELESS_SECURITY_PSK)); - if (!exp_same_psk) { - if (nm_setting_wireless_security_get_psk(NM_SETTING_WIRELESS_SECURITY(a))) - g_assert_cmpint( - GPOINTER_TO_UINT(g_hash_table_lookup(h, NM_SETTING_WIRELESS_SECURITY_PSK)), - ==, - _RESULT_IN_A); - else - g_assert_cmpint( - GPOINTER_TO_UINT(g_hash_table_lookup(h, NM_SETTING_WIRELESS_SECURITY_PSK)), - ==, - _RESULT_IN_B); - } - - g_assert((!exp_same_psk_flags) - == g_hash_table_contains(h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)); - if (!exp_same_psk_flags) { - if (nm_setting_wireless_security_get_psk_flags(NM_SETTING_WIRELESS_SECURITY(a)) - != NM_SETTING_SECRET_FLAG_NONE) - g_assert_cmpint(GPOINTER_TO_UINT( - g_hash_table_lookup(h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)), - ==, - _RESULT_IN_A); - else - g_assert_cmpint(GPOINTER_TO_UINT( - g_hash_table_lookup(h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)), - ==, - _RESULT_IN_B); - } - - g_assert_cmpint(g_hash_table_size(h), ==, (!exp_same_psk) + (!exp_same_psk_flags)); - } - - g_assert(diff_result == nm_setting_compare(a, b, flags)); - g_assert(diff_result == nm_setting_compare(b, a, flags)); -} - -static void -test_setting_compare_secrets(gconstpointer test_data) -{ - const TestDataCompareSecrets *data = test_data; - gs_unref_object NMConnection *conn_old = NULL; - gs_unref_object NMConnection *conn_new = NULL; - gs_unref_object NMSetting *old = NULL; - gs_unref_object NMSetting *new = NULL; - - /* Make sure that a connection with transient/unsaved secrets compares - * successfully to the same connection without those secrets. - */ - - old = nm_setting_wireless_security_new(); - g_object_set(old, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "wpa-psk", - NM_SETTING_WIRELESS_SECURITY_PSK, - "really cool psk", - NULL); - nm_setting_set_secret_flags(old, NM_SETTING_WIRELESS_SECURITY_PSK, data->secret_flags, NULL); - - new = nm_setting_duplicate(old); - if (data->remove_secret) - g_object_set(new, NM_SETTING_WIRELESS_SECURITY_PSK, NULL, NULL); - - g_assert((!data->remove_secret) == nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT)); - g_assert((!data->remove_secret) == nm_setting_compare(new, old, NM_SETTING_COMPARE_FLAG_EXACT)); - - _test_compare_secrets_check_diff(old, - new, - NM_SETTING_COMPARE_FLAG_EXACT, - !data->remove_secret, - TRUE); - _test_compare_secrets_check_diff(new, - old, - NM_SETTING_COMPARE_FLAG_EXACT, - !data->remove_secret, - TRUE); - - g_assert(nm_setting_compare(old, new, data->comp_flags)); - g_assert(nm_setting_compare(new, old, data->comp_flags)); - - _test_compare_secrets_check_diff(old, new, data->comp_flags, TRUE, TRUE); - _test_compare_secrets_check_diff(new, old, data->comp_flags, TRUE, TRUE); - - /* OK. Try again, but this time not only change the secret, also let the secret flags differ... */ - if (data->secret_flags != NM_SETTING_SECRET_FLAG_NONE) { - nm_setting_set_secret_flags(new, - NM_SETTING_WIRELESS_SECURITY_PSK, - NM_SETTING_SECRET_FLAG_NONE, - NULL); - - _test_compare_secrets_check_diff(old, new, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, FALSE); - _test_compare_secrets_check_diff(new, old, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, FALSE); - - _test_compare_secrets_check_diff(old, new, data->comp_flags, TRUE, FALSE); - _test_compare_secrets_check_diff(new, old, data->comp_flags, FALSE, FALSE); - - nm_setting_set_secret_flags(new, - NM_SETTING_WIRELESS_SECURITY_PSK, - data->secret_flags, - NULL); - } - - conn_old = nmtst_create_minimal_connection("test-compare-secrets", - NULL, - NM_SETTING_WIRELESS_SETTING_NAME, - NULL); - nm_connection_add_setting(conn_old, nm_setting_duplicate(old)); - conn_new = nm_simple_connection_new_clone(conn_old); - nm_connection_add_setting(conn_new, nm_setting_duplicate(new)); - - g_assert((!data->remove_secret) - == nm_connection_compare(conn_old, conn_new, NM_SETTING_COMPARE_FLAG_EXACT)); - g_assert((!data->remove_secret) - == nm_connection_compare(conn_new, conn_old, NM_SETTING_COMPARE_FLAG_EXACT)); - - g_assert(nm_connection_compare(conn_old, conn_new, data->comp_flags)); - g_assert(nm_connection_compare(conn_new, conn_old, data->comp_flags)); -} - -static void -test_setting_compare_vpn_secrets(gconstpointer test_data) -{ - const TestDataCompareSecrets *data = test_data; - gs_unref_object NMSetting *old = NULL, *new = NULL; - gboolean success; - - /* Make sure that a connection with transient/unsaved secrets compares - * successfully to the same connection without those secrets. - */ - - old = nm_setting_vpn_new(); - nm_setting_vpn_add_secret(NM_SETTING_VPN(old), "foobarbaz", "really secret password"); - nm_setting_vpn_add_secret(NM_SETTING_VPN(old), "asdfasdfasdf", "really adfasdfasdfasdf"); - nm_setting_vpn_add_secret(NM_SETTING_VPN(old), "0123456778", "abcdefghijklmnpqrstuvqxyz"); - nm_setting_vpn_add_secret(NM_SETTING_VPN(old), - "borkbork", - "yet another really secret password"); - nm_setting_set_secret_flags(old, "borkbork", data->secret_flags, NULL); - - /* Clear "borkbork" from the duplicated setting */ - new = nm_setting_duplicate(old); - if (data->remove_secret) { - nm_setting_vpn_remove_secret(NM_SETTING_VPN(new), "borkbork"); - - /* First make sure they are different */ - success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert(success == FALSE); - } - - success = nm_setting_compare(old, new, data->comp_flags); - g_assert(success); -} - -static void -test_hwaddr_aton_ether_normal(void) -{ - guint8 buf[100]; - guint8 expected[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; - - g_assert(nm_utils_hwaddr_aton("00:11:22:33:44:55", buf, ETH_ALEN) != NULL); - g_assert(memcmp(buf, expected, sizeof(expected)) == 0); -} - -static void -test_hwaddr_aton_ib_normal(void) -{ - guint8 buf[100]; - const char *source = "00:11:22:33:44:55:66:77:88:99:01:12:23:34:45:56:67:78:89:90"; - guint8 expected[INFINIBAND_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, - 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x90}; - - g_assert(nm_utils_hwaddr_aton(source, buf, INFINIBAND_ALEN) != NULL); - g_assert(memcmp(buf, expected, sizeof(expected)) == 0); -} - -static void -test_hwaddr_aton_no_leading_zeros(void) -{ - guint8 buf[100]; - guint8 expected[ETH_ALEN] = {0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05}; - - g_assert(nm_utils_hwaddr_aton("0:1a:2B:3:44:5", buf, ETH_ALEN) != NULL); - g_assert(memcmp(buf, expected, sizeof(expected)) == 0); -} - -static void -test_hwaddr_aton_malformed(void) -{ - guint8 buf[100]; - - g_assert(nm_utils_hwaddr_aton("0:1a:2B:3:a@%%", buf, ETH_ALEN) == NULL); -} - -static void -test_hwaddr_equal(void) -{ - const char * string = "00:1a:2b:03:44:05"; - const char * upper_string = "00:1A:2B:03:44:05"; - const char * bad_string = "0:1a:2b:3:44:5"; - const guint8 binary[ETH_ALEN] = {0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05}; - const char * other_string = "1a:2b:03:44:05:00"; - const guint8 other_binary[ETH_ALEN] = {0x1A, 0x2B, 0x03, 0x44, 0x05, 0x00}; - const char * long_string = "00:1a:2b:03:44:05:06:07"; - const guint8 long_binary[8] = {0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05, 0x06, 0x07}; - const char * null_string = "00:00:00:00:00:00"; - const guint8 null_binary[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - g_assert(nm_utils_hwaddr_matches(string, -1, string, -1)); - g_assert(nm_utils_hwaddr_matches(string, -1, upper_string, -1)); - g_assert(nm_utils_hwaddr_matches(string, -1, bad_string, -1)); - g_assert(nm_utils_hwaddr_matches(string, -1, binary, sizeof(binary))); - g_assert(!nm_utils_hwaddr_matches(string, -1, other_string, -1)); - g_assert(!nm_utils_hwaddr_matches(string, -1, other_binary, sizeof(other_binary))); - g_assert(!nm_utils_hwaddr_matches(string, -1, long_string, -1)); - g_assert(!nm_utils_hwaddr_matches(string, -1, long_binary, sizeof(long_binary))); - g_assert(!nm_utils_hwaddr_matches(string, -1, null_string, -1)); - g_assert(!nm_utils_hwaddr_matches(string, -1, null_binary, sizeof(null_binary))); - g_assert(!nm_utils_hwaddr_matches(string, -1, NULL, ETH_ALEN)); - - g_assert(nm_utils_hwaddr_matches(binary, sizeof(binary), string, -1)); - g_assert(nm_utils_hwaddr_matches(binary, sizeof(binary), upper_string, -1)); - g_assert(nm_utils_hwaddr_matches(binary, sizeof(binary), bad_string, -1)); - g_assert(nm_utils_hwaddr_matches(binary, sizeof(binary), binary, sizeof(binary))); - g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), other_string, -1)); - g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), other_binary, sizeof(other_binary))); - g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), long_string, -1)); - g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), long_binary, sizeof(long_binary))); - g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), null_string, -1)); - g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), null_binary, sizeof(null_binary))); - g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), NULL, ETH_ALEN)); - - g_assert(!nm_utils_hwaddr_matches(null_string, -1, string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_string, -1, upper_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_string, -1, bad_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_string, -1, binary, sizeof(binary))); - g_assert(!nm_utils_hwaddr_matches(null_string, -1, other_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_string, -1, other_binary, sizeof(other_binary))); - g_assert(!nm_utils_hwaddr_matches(null_string, -1, long_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_string, -1, long_binary, sizeof(long_binary))); - g_assert(nm_utils_hwaddr_matches(null_string, -1, null_string, -1)); - g_assert(nm_utils_hwaddr_matches(null_string, -1, null_binary, sizeof(null_binary))); - g_assert(nm_utils_hwaddr_matches(null_string, -1, NULL, ETH_ALEN)); - - g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), upper_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), bad_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), binary, sizeof(binary))); - g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), other_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_binary, - sizeof(null_binary), - other_binary, - sizeof(other_binary))); - g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), long_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_binary, - sizeof(null_binary), - long_binary, - sizeof(long_binary))); - g_assert(nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), null_string, -1)); - g_assert(nm_utils_hwaddr_matches(null_binary, - sizeof(null_binary), - null_binary, - sizeof(null_binary))); - g_assert(nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), NULL, ETH_ALEN)); - - g_assert(!nm_utils_hwaddr_matches(NULL, -1, NULL, -1)); - g_assert(!nm_utils_hwaddr_matches(NULL, -1, string, -1)); - g_assert(!nm_utils_hwaddr_matches(string, -1, NULL, -1)); - g_assert(!nm_utils_hwaddr_matches(NULL, -1, null_string, -1)); - g_assert(!nm_utils_hwaddr_matches(null_string, -1, NULL, -1)); - g_assert(!nm_utils_hwaddr_matches(NULL, -1, binary, sizeof(binary))); - g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), NULL, -1)); - g_assert(!nm_utils_hwaddr_matches(NULL, -1, null_binary, sizeof(null_binary))); - g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), NULL, -1)); -} - -static void -test_hwaddr_canonical(void) -{ - const char *string = "00:1A:2B:03:44:05"; - const char *lower_string = "00:1a:2b:03:44:05"; - const char *short_string = "0:1a:2b:3:44:5"; - const char *hyphen_string = "00-1a-2b-03-44-05"; - const char *invalid_string = "00:1A:2B"; - char * canonical; - - canonical = nm_utils_hwaddr_canonical(string, ETH_ALEN); - g_assert_cmpstr(canonical, ==, string); - g_free(canonical); - - canonical = nm_utils_hwaddr_canonical(lower_string, ETH_ALEN); - g_assert_cmpstr(canonical, ==, string); - g_free(canonical); - - canonical = nm_utils_hwaddr_canonical(short_string, ETH_ALEN); - g_assert_cmpstr(canonical, ==, string); - g_free(canonical); - - canonical = nm_utils_hwaddr_canonical(hyphen_string, ETH_ALEN); - g_assert_cmpstr(canonical, ==, string); - g_free(canonical); - - canonical = nm_utils_hwaddr_canonical(invalid_string, ETH_ALEN); - g_assert_cmpstr(canonical, ==, NULL); - - canonical = nm_utils_hwaddr_canonical(invalid_string, -1); - g_assert_cmpstr(canonical, ==, invalid_string); - g_free(canonical); -} - -static void -test_connection_changed_cb(NMConnection *connection, gboolean *data) -{ - *data = TRUE; -} - -static guint32 -_netmask_to_prefix(guint32 netmask) -{ - guint32 prefix; - guint8 v; - const guint8 *p = (guint8 *) &netmask; - - if (p[3]) { - prefix = 24; - v = p[3]; - } else if (p[2]) { - prefix = 16; - v = p[2]; - } else if (p[1]) { - prefix = 8; - v = p[1]; - } else { - prefix = 0; - v = p[0]; - } - - while (v) { - prefix++; - v <<= 1; - } - - g_assert_cmpint(prefix, <=, 32); - - /* we re-implemented the netmask-to-prefix code differently. Check - * that they agree. */ - g_assert_cmpint(prefix, ==, nm_utils_ip4_netmask_to_prefix(netmask)); - - return prefix; -} - -static void -test_ip4_prefix_to_netmask(void) -{ - int i; - - for (i = 0; i <= 32; i++) { - guint32 netmask = _nm_utils_ip4_prefix_to_netmask(i); - int plen = _netmask_to_prefix(netmask); - - g_assert_cmpint(i, ==, plen); - { - guint32 msk = 0x80000000; - guint32 netmask2 = 0; - guint32 prefix = i; - while (prefix > 0) { - netmask2 |= msk; - msk >>= 1; - prefix--; - } - g_assert_cmpint(netmask, ==, (guint32) htonl(netmask2)); - } - } -} - -static void -test_ip4_netmask_to_prefix(void) -{ - int i, j; - - GRand *rand = g_rand_new(); - - g_rand_set_seed(rand, 1); - - for (i = 2; i <= 32; i++) { - guint32 netmask = _nm_utils_ip4_prefix_to_netmask(i); - guint32 netmask_lowest_bit = netmask & ~_nm_utils_ip4_prefix_to_netmask(i - 1); - - g_assert_cmpint(i, ==, _netmask_to_prefix(netmask)); - - for (j = 0; j < 2 * i; j++) { - guint32 r = g_rand_int(rand); - guint32 netmask_holey; - guint32 prefix_holey; - - netmask_holey = (netmask & r) | netmask_lowest_bit; - - if (netmask_holey == netmask) - continue; - - /* create an invalid netmask with holes and check that the function - * returns the longest prefix. */ - prefix_holey = _netmask_to_prefix(netmask_holey); - - g_assert_cmpint(i, ==, prefix_holey); - } - } - - g_rand_free(rand); -} - -#define ASSERT_CHANGED(statement) \ - G_STMT_START \ - { \ - changed = FALSE; \ - statement; \ - g_assert(changed); \ - } \ - G_STMT_END - -#define ASSERT_UNCHANGED(statement) \ - G_STMT_START \ - { \ - changed = FALSE; \ - statement; \ - g_assert(!changed); \ - } \ - G_STMT_END - -static void -test_connection_changed_signal(void) -{ - NMConnection *connection; - gboolean changed = FALSE; - - connection = new_test_connection(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - /* Add new setting */ - ASSERT_CHANGED(nm_connection_add_setting(connection, nm_setting_vlan_new())); - - /* Remove existing setting */ - ASSERT_CHANGED(nm_connection_remove_setting(connection, NM_TYPE_SETTING_VLAN)); - - /* Remove non-existing setting */ - ASSERT_UNCHANGED(nm_connection_remove_setting(connection, NM_TYPE_SETTING_VLAN)); - - g_object_unref(connection); -} - -static void -test_setting_connection_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSettingConnection *s_con; - gs_free char * uuid = NULL; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - - ASSERT_CHANGED(g_object_set(s_con, NM_SETTING_CONNECTION_ID, "adfadfasdfaf", NULL)); - - ASSERT_CHANGED(nm_setting_connection_add_permission(s_con, "user", "billsmith", NULL)); - ASSERT_CHANGED(nm_setting_connection_remove_permission(s_con, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx < nm_g_array_len(priv->permissions))); - ASSERT_UNCHANGED(nm_setting_connection_remove_permission(s_con, 1)); - g_test_assert_expected_messages(); - - uuid = nm_utils_uuid_generate(); - ASSERT_CHANGED(nm_setting_connection_add_secondary(s_con, uuid)); - ASSERT_CHANGED(nm_setting_connection_remove_secondary(s_con, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); - ASSERT_UNCHANGED(nm_setting_connection_remove_secondary(s_con, 1)); - g_test_assert_expected_messages(); - - g_object_unref(connection); -} - -static void -test_setting_bond_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSettingBond *s_bond; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_bond = (NMSettingBond *) nm_setting_bond_new(); - nm_connection_add_setting(connection, NM_SETTING(s_bond)); - - ASSERT_CHANGED(nm_setting_bond_add_option(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10")); - ASSERT_CHANGED(nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY)); - ASSERT_UNCHANGED(nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_UPDELAY)); - - g_object_unref(connection); -} - -static void -test_setting_ip4_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSettingIPConfig *s_ip4; - NMIPAddress * addr; - NMIPRoute * route; - GError * error = NULL; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - - ASSERT_CHANGED(nm_setting_ip_config_add_dns(s_ip4, "11.22.0.0")); - ASSERT_CHANGED(nm_setting_ip_config_remove_dns(s_ip4, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns(s_ip4, 1)); - g_test_assert_expected_messages(); - - nm_setting_ip_config_add_dns(s_ip4, "33.44.0.0"); - ASSERT_CHANGED(nm_setting_ip_config_clear_dns(s_ip4)); - - ASSERT_CHANGED(nm_setting_ip_config_add_dns_search(s_ip4, "foobar.com")); - ASSERT_CHANGED(nm_setting_ip_config_remove_dns_search(s_ip4, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_search->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_search(s_ip4, 1)); - g_test_assert_expected_messages(); - - ASSERT_CHANGED(nm_setting_ip_config_add_dns_search(s_ip4, "foobar.com")); - ASSERT_CHANGED(nm_setting_ip_config_clear_dns_searches(s_ip4)); - - addr = nm_ip_address_new(AF_INET, "22.33.0.0", 24, &error); - g_assert_no_error(error); - ASSERT_CHANGED(nm_setting_ip_config_add_address(s_ip4, addr)); - ASSERT_CHANGED(nm_setting_ip_config_remove_address(s_ip4, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->addresses->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_address(s_ip4, 1)); - g_test_assert_expected_messages(); - - nm_setting_ip_config_add_address(s_ip4, addr); - ASSERT_CHANGED(nm_setting_ip_config_clear_addresses(s_ip4)); - - route = nm_ip_route_new(AF_INET, "22.33.0.0", 24, NULL, 0, &error); - g_assert_no_error(error); - - ASSERT_CHANGED(nm_setting_ip_config_add_route(s_ip4, route)); - ASSERT_CHANGED(nm_setting_ip_config_remove_route(s_ip4, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->routes->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_route(s_ip4, 1)); - g_test_assert_expected_messages(); - - nm_setting_ip_config_add_route(s_ip4, route); - ASSERT_CHANGED(nm_setting_ip_config_clear_routes(s_ip4)); - - ASSERT_CHANGED(nm_setting_ip_config_add_dns_option(s_ip4, "debug")); - ASSERT_CHANGED(nm_setting_ip_config_remove_dns_option(s_ip4, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_options->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_option(s_ip4, 1)); - g_test_assert_expected_messages(); - - nm_ip_address_unref(addr); - nm_ip_route_unref(route); - g_object_unref(connection); -} - -static void -test_setting_ip6_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSettingIPConfig *s_ip6; - NMIPAddress * addr; - NMIPRoute * route; - GError * error = NULL; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - - ASSERT_CHANGED(nm_setting_ip_config_add_dns(s_ip6, "1:2:3::4:5:6")); - ASSERT_CHANGED(nm_setting_ip_config_remove_dns(s_ip6, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns(s_ip6, 1)); - g_test_assert_expected_messages(); - - nm_setting_ip_config_add_dns(s_ip6, "1:2:3::4:5:6"); - ASSERT_CHANGED(nm_setting_ip_config_clear_dns(s_ip6)); - - ASSERT_CHANGED(nm_setting_ip_config_add_dns_search(s_ip6, "foobar.com")); - ASSERT_CHANGED(nm_setting_ip_config_remove_dns_search(s_ip6, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_search->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_search(s_ip6, 1)); - g_test_assert_expected_messages(); - - nm_setting_ip_config_add_dns_search(s_ip6, "foobar.com"); - ASSERT_CHANGED(nm_setting_ip_config_clear_dns_searches(s_ip6)); - - addr = nm_ip_address_new(AF_INET6, "1:2:3::4:5:6", 64, &error); - g_assert_no_error(error); - - ASSERT_CHANGED(nm_setting_ip_config_add_address(s_ip6, addr)); - ASSERT_CHANGED(nm_setting_ip_config_remove_address(s_ip6, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->addresses->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_address(s_ip6, 1)); - g_test_assert_expected_messages(); - - nm_setting_ip_config_add_address(s_ip6, addr); - ASSERT_CHANGED(nm_setting_ip_config_clear_addresses(s_ip6)); - - route = nm_ip_route_new(AF_INET6, "1:2:3::4:5:6", 128, NULL, 0, &error); - g_assert_no_error(error); - - ASSERT_CHANGED(nm_setting_ip_config_add_route(s_ip6, route)); - ASSERT_CHANGED(nm_setting_ip_config_remove_route(s_ip6, 0)); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->routes->len)); - ASSERT_UNCHANGED(nm_setting_ip_config_remove_route(s_ip6, 1)); - g_test_assert_expected_messages(); - - nm_setting_ip_config_add_route(s_ip6, route); - ASSERT_CHANGED(nm_setting_ip_config_clear_routes(s_ip6)); - - nm_ip_address_unref(addr); - nm_ip_route_unref(route); - g_object_unref(connection); -} - -static void -test_setting_vlan_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSettingVlan *s_vlan; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_vlan = (NMSettingVlan *) nm_setting_vlan_new(); - nm_connection_add_setting(connection, NM_SETTING(s_vlan)); - - ASSERT_CHANGED(nm_setting_vlan_add_priority(s_vlan, NM_VLAN_INGRESS_MAP, 1, 3)); - ASSERT_CHANGED(nm_setting_vlan_remove_priority(s_vlan, NM_VLAN_INGRESS_MAP, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx < g_slist_length(list))); - ASSERT_UNCHANGED(nm_setting_vlan_remove_priority(s_vlan, NM_VLAN_INGRESS_MAP, 1)); - g_test_assert_expected_messages(); - ASSERT_CHANGED(nm_setting_vlan_add_priority_str(s_vlan, NM_VLAN_INGRESS_MAP, "1:3")); - ASSERT_CHANGED(nm_setting_vlan_clear_priorities(s_vlan, NM_VLAN_INGRESS_MAP)); - - ASSERT_CHANGED(nm_setting_vlan_add_priority(s_vlan, NM_VLAN_EGRESS_MAP, 1, 3)); - ASSERT_CHANGED(nm_setting_vlan_remove_priority(s_vlan, NM_VLAN_EGRESS_MAP, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx < g_slist_length(list))); - ASSERT_UNCHANGED(nm_setting_vlan_remove_priority(s_vlan, NM_VLAN_EGRESS_MAP, 1)); - g_test_assert_expected_messages(); - ASSERT_CHANGED(nm_setting_vlan_add_priority_str(s_vlan, NM_VLAN_EGRESS_MAP, "1:3")); - ASSERT_CHANGED(nm_setting_vlan_clear_priorities(s_vlan, NM_VLAN_EGRESS_MAP)); - - g_object_unref(connection); -} - -static void -test_setting_vpn_changed_signal(void) -{ - NMConnection *connection; - gboolean changed = FALSE; - NMSettingVpn *s_vpn; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_vpn = (NMSettingVpn *) nm_setting_vpn_new(); - nm_connection_add_setting(connection, NM_SETTING(s_vpn)); - - ASSERT_CHANGED(nm_setting_vpn_add_data_item(s_vpn, "foobar", "baz")); - ASSERT_CHANGED(nm_setting_vpn_remove_data_item(s_vpn, "foobar")); - ASSERT_UNCHANGED(nm_setting_vpn_remove_data_item(s_vpn, "not added")); - - ASSERT_CHANGED(nm_setting_vpn_add_secret(s_vpn, "foobar", "baz")); - ASSERT_CHANGED(nm_setting_vpn_remove_secret(s_vpn, "foobar")); - ASSERT_UNCHANGED(nm_setting_vpn_remove_secret(s_vpn, "not added")); - - g_object_unref(connection); -} - -static void -test_setting_wired_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSettingWired *s_wired; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - ASSERT_CHANGED(nm_setting_wired_add_s390_option(s_wired, "portno", "1")); - ASSERT_CHANGED(nm_setting_wired_remove_s390_option(s_wired, "portno")); - ASSERT_UNCHANGED(nm_setting_wired_remove_s390_option(s_wired, "layer2")); - - g_object_unref(connection); -} - -static void -test_setting_wireless_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSettingWireless *s_wifi; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ASSERT_CHANGED(nm_setting_wireless_add_seen_bssid(s_wifi, "00:11:22:33:44:55")); - - g_object_unref(connection); -} - -static void -test_setting_wireless_security_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSettingWirelessSecurity *s_wsec; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - - /* Protos */ - ASSERT_CHANGED(nm_setting_wireless_security_add_proto(s_wsec, "wpa")); - ASSERT_CHANGED(nm_setting_wireless_security_remove_proto(s_wsec, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); - ASSERT_UNCHANGED(nm_setting_wireless_security_remove_proto(s_wsec, 1)); - g_test_assert_expected_messages(); - - nm_setting_wireless_security_add_proto(s_wsec, "wep"); - ASSERT_CHANGED(nm_setting_wireless_security_clear_protos(s_wsec)); - - /* Pairwise ciphers */ - ASSERT_CHANGED(nm_setting_wireless_security_add_pairwise(s_wsec, "tkip")); - ASSERT_CHANGED(nm_setting_wireless_security_remove_pairwise(s_wsec, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); - ASSERT_UNCHANGED(nm_setting_wireless_security_remove_pairwise(s_wsec, 1)); - g_test_assert_expected_messages(); - - nm_setting_wireless_security_add_pairwise(s_wsec, "tkip"); - ASSERT_CHANGED(nm_setting_wireless_security_clear_pairwise(s_wsec)); - - /* Group ciphers */ - ASSERT_CHANGED(nm_setting_wireless_security_add_group(s_wsec, "ccmp")); - ASSERT_CHANGED(nm_setting_wireless_security_remove_group(s_wsec, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); - ASSERT_UNCHANGED(nm_setting_wireless_security_remove_group(s_wsec, 1)); - g_test_assert_expected_messages(); - - nm_setting_wireless_security_add_group(s_wsec, "tkip"); - ASSERT_CHANGED(nm_setting_wireless_security_clear_groups(s_wsec)); - - /* WEP key secret flags */ - ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec), - "wep-key0", - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - NULL))); - ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec), - "wep-key1", - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - NULL))); - ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec), - "wep-key2", - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - NULL))); - ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec), - "wep-key3", - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - NULL))); - - g_object_unref(connection); -} - -static void -test_setting_802_1x_changed_signal(void) -{ - NMConnection * connection; - gboolean changed = FALSE; - NMSetting8021x *s_8021x; - - connection = nm_simple_connection_new(); - g_signal_connect(connection, - NM_CONNECTION_CHANGED, - (GCallback) test_connection_changed_cb, - &changed); - - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); - - /* EAP methods */ - ASSERT_CHANGED(nm_setting_802_1x_add_eap_method(s_8021x, "tls")); - ASSERT_CHANGED(nm_setting_802_1x_remove_eap_method(s_8021x, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); - ASSERT_UNCHANGED(nm_setting_802_1x_remove_eap_method(s_8021x, 1)); - g_test_assert_expected_messages(); - - nm_setting_802_1x_add_eap_method(s_8021x, "ttls"); - ASSERT_CHANGED(nm_setting_802_1x_clear_eap_methods(s_8021x)); - - /* alternate subject matches */ - ASSERT_CHANGED(nm_setting_802_1x_add_altsubject_match(s_8021x, "EMAIL:server@example.com")); - ASSERT_CHANGED(nm_setting_802_1x_remove_altsubject_match(s_8021x, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); - ASSERT_UNCHANGED(nm_setting_802_1x_remove_altsubject_match(s_8021x, 1)); - g_test_assert_expected_messages(); - - nm_setting_802_1x_add_altsubject_match(s_8021x, "EMAIL:server@example.com"); - ASSERT_CHANGED(nm_setting_802_1x_clear_altsubject_matches(s_8021x)); - - /* phase2 alternate subject matches */ - ASSERT_CHANGED( - nm_setting_802_1x_add_phase2_altsubject_match(s_8021x, "EMAIL:server@example.com")); - ASSERT_CHANGED(nm_setting_802_1x_remove_phase2_altsubject_match(s_8021x, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); - ASSERT_UNCHANGED(nm_setting_802_1x_remove_phase2_altsubject_match(s_8021x, 1)); - g_test_assert_expected_messages(); - - nm_setting_802_1x_add_phase2_altsubject_match(s_8021x, "EMAIL:server@example.com"); - ASSERT_CHANGED(nm_setting_802_1x_clear_phase2_altsubject_matches(s_8021x)); - - g_object_unref(connection); -} - -static void -test_setting_old_uuid(void) -{ - gs_unref_object NMSetting *setting = NULL; - - /* NetworkManager-0.9.4.0 generated 40-character UUIDs with no dashes, - * like this one. Test that we maintain compatibility. */ - const char *uuid = "f43bec2cdd60e5da381ebb1eb1fa39f3cc52660c"; - - setting = nm_setting_connection_new(); - g_object_set(G_OBJECT(setting), - NM_SETTING_CONNECTION_ID, - "uuidtest", - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRED_SETTING_NAME, - NULL); - - nmtst_assert_setting_verifies(NM_SETTING(setting)); -} - -/*****************************************************************************/ - -static void -test_connection_normalize_uuid(void) -{ - gs_unref_object NMConnection *con = NULL; - - con = nmtst_create_minimal_connection("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - - nmtst_assert_connection_verifies_and_normalizable(con); - - g_object_set(nm_connection_get_setting_connection(con), NM_SETTING_CONNECTION_UUID, NULL, NULL); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); -} - -/*****************************************************************************/ - -/* - * Test normalization of interface-name - */ -static void -test_connection_normalize_virtual_iface_name(void) -{ - NMConnection * con = NULL; - NMSettingConnection *s_con; - NMSettingVlan * s_vlan; - GVariant * connection_dict, *setting_dict, *var; - GError * error = NULL; - const char * IFACE_NAME = "iface"; - const char * IFACE_VIRT = "iface-X"; - - con = nmtst_create_minimal_connection("test1", - "22001632-bbb4-4616-b277-363dce3dfb5b", - NM_SETTING_VLAN_SETTING_NAME, - &s_con); - - nm_connection_add_setting(con, - g_object_new(NM_TYPE_SETTING_IP4_CONFIG, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NULL)); - - nm_connection_add_setting(con, - g_object_new(NM_TYPE_SETTING_IP6_CONFIG, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NULL)); - - s_vlan = nm_connection_get_setting_vlan(con); - - g_object_set(G_OBJECT(s_vlan), NM_SETTING_VLAN_PARENT, "eth0", NULL); - - g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, IFACE_NAME, NULL); - - g_assert_cmpstr(nm_connection_get_interface_name(con), ==, IFACE_NAME); - - connection_dict = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); - g_object_unref(con); - - /* Serialized form should include vlan.interface-name as well. */ - setting_dict = g_variant_lookup_value(connection_dict, - NM_SETTING_VLAN_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - g_assert(setting_dict != NULL); - var = g_variant_lookup_value(setting_dict, "interface-name", NULL); - g_assert(var != NULL); - g_assert(g_variant_is_of_type(var, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr(g_variant_get_string(var, NULL), ==, IFACE_NAME); - - g_variant_unref(setting_dict); - g_variant_unref(var); - - /* If vlan.interface-name will be ignored. */ - NMTST_VARIANT_EDITOR( - connection_dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_VLAN_SETTING_NAME, - "interface-name", - "s", - ":::this-is-not-a-valid-interface-name:::");); - - con = _connection_new_from_dbus(connection_dict, &error); - nmtst_assert_success(con, error); - g_assert_cmpstr(nm_connection_get_interface_name(con), ==, IFACE_NAME); - g_clear_object(&con); - - /* If vlan.interface-name is valid, but doesn't match, it will be ignored. */ - NMTST_VARIANT_EDITOR(connection_dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_VLAN_SETTING_NAME, - "interface-name", - "s", - IFACE_VIRT);); - - con = _connection_new_from_dbus(connection_dict, &error); - g_assert_no_error(error); - - g_assert_cmpstr(nm_connection_get_interface_name(con), ==, IFACE_NAME); - s_con = nm_connection_get_setting_connection(con); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, IFACE_NAME); - g_object_unref(con); - - /* But removing connection.interface-name should result in vlan.connection-name - * being "promoted". - */ - NMTST_VARIANT_EDITOR(connection_dict, - NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_INTERFACE_NAME);); - - con = _connection_new_from_dbus(connection_dict, &error); - g_assert_no_error(error); - - g_assert_cmpstr(nm_connection_get_interface_name(con), ==, IFACE_VIRT); - s_con = nm_connection_get_setting_connection(con); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, IFACE_VIRT); - g_object_unref(con); - - g_variant_unref(connection_dict); -} - -static void -_test_connection_normalize_type_normalizable_setting( - const char *type, - void (*prepare_normalizable_fcn)(NMConnection *con)) -{ - NMSettingConnection *s_con; - NMSetting * s_base; - GType base_type; - gs_unref_object NMConnection *con = NULL; - gs_free char * id = g_strdup_printf("%s[%s]", G_STRFUNC, type); - - base_type = nm_setting_lookup_type(type); - g_assert(base_type != G_TYPE_INVALID); - g_assert(_nm_setting_type_get_base_type_priority(base_type) != NM_SETTING_PRIORITY_INVALID); - - con = nmtst_create_minimal_connection(id, NULL, NULL, &s_con); - - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - - g_object_set(s_con, NM_SETTING_CONNECTION_TYPE, type, NULL); - - if (prepare_normalizable_fcn) - prepare_normalizable_fcn(con); - - g_assert(!nm_connection_get_setting_by_name(con, type)); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING); - nmtst_connection_normalize(con); - - s_base = nm_connection_get_setting_by_name(con, type); - g_assert(s_base); - g_assert(G_OBJECT_TYPE(s_base) == base_type); -} - -static void -_test_connection_normalize_type_unnormalizable_setting(const char *type) -{ - NMSettingConnection *s_con; - GType base_type; - gs_unref_object NMConnection *con = NULL; - gs_free char * id = g_strdup_printf("%s[%s]", G_STRFUNC, type); - - base_type = nm_setting_lookup_type(type); - g_assert(base_type != G_TYPE_INVALID); - g_assert(_nm_setting_type_get_base_type_priority(base_type) != NM_SETTING_PRIORITY_INVALID); - - con = nmtst_create_minimal_connection(id, NULL, NULL, &s_con); - - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - - g_object_set(s_con, NM_SETTING_CONNECTION_TYPE, type, NULL); - - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING); -} - -static void -_test_connection_normalize_type_normalizable_type(const char *type, - NMSetting *(*add_setting_fcn)(NMConnection *con)) -{ - NMSettingConnection *s_con; - NMSetting * s_base; - GType base_type; - gs_unref_object NMConnection *con = NULL; - gs_free char * id = g_strdup_printf("%s[%s]", G_STRFUNC, type); - - base_type = nm_setting_lookup_type(type); - g_assert(base_type != G_TYPE_INVALID); - g_assert(_nm_setting_type_get_base_type_priority(base_type) != NM_SETTING_PRIORITY_INVALID); - - con = nmtst_create_minimal_connection(id, NULL, NULL, &s_con); - - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - - if (add_setting_fcn) - s_base = add_setting_fcn(con); - else { - s_base = g_object_new(base_type, NULL); - nm_connection_add_setting(con, s_base); - } - - g_assert(!nm_setting_connection_get_connection_type(s_con)); - g_assert(nm_connection_get_setting_by_name(con, type) == s_base); - - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - nmtst_connection_normalize(con); - - g_assert_cmpstr(nm_connection_get_connection_type(con), ==, type); - g_assert(nm_connection_get_setting_by_name(con, type) == s_base); -} - -static NMSetting * -_add_setting_fcn_adsl(NMConnection *con) -{ - NMSetting *setting; - - setting = g_object_new(NM_TYPE_SETTING_ADSL, - NM_SETTING_ADSL_USERNAME, - "test-user", - NM_SETTING_ADSL_PROTOCOL, - NM_SETTING_ADSL_PROTOCOL_PPPOA, - NM_SETTING_ADSL_ENCAPSULATION, - NM_SETTING_ADSL_ENCAPSULATION_VCMUX, - NULL); - - nm_connection_add_setting(con, setting); - return setting; -} - -static NMSetting * -_add_setting_fcn_bluetooth(NMConnection *con) -{ - NMSetting *setting; - - setting = g_object_new(NM_TYPE_SETTING_BLUETOOTH, - NM_SETTING_BLUETOOTH_BDADDR, - "11:22:33:44:55:66", - NM_SETTING_BLUETOOTH_TYPE, - NM_SETTING_BLUETOOTH_TYPE_PANU, - NULL); - - nm_connection_add_setting(con, setting); - return setting; -} - -static NMSetting * -_add_setting_fcn_bond(NMConnection *con) -{ - NMSetting * setting; - NMSettingConnection *s_con; - - setting = g_object_new(NM_TYPE_SETTING_BOND, NULL); - - nm_connection_add_setting(con, setting); - - s_con = nm_connection_get_setting_connection(con); - - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bond", NULL); - - return setting; -} - -static NMSetting * -_add_setting_fcn_bridge(NMConnection *con) -{ - NMSetting * setting; - NMSettingConnection *s_con; - - setting = g_object_new(NM_TYPE_SETTING_BRIDGE, NULL); - - nm_connection_add_setting(con, setting); - - s_con = nm_connection_get_setting_connection(con); - - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bridge", NULL); - - return setting; -} - -static NMSetting * -_add_setting_fcn_cdma(NMConnection *con) -{ - NMSetting *setting; - - setting = g_object_new(NM_TYPE_SETTING_CDMA, NM_SETTING_CDMA_NUMBER, "test-number", NULL); - - nm_connection_add_setting(con, setting); - return setting; -} - -static NMSetting * -_add_setting_fcn_infiniband(NMConnection *con) -{ - NMSetting *setting; - - setting = g_object_new(NM_TYPE_SETTING_INFINIBAND, - NM_SETTING_INFINIBAND_TRANSPORT_MODE, - "connected", - NULL); - - nm_connection_add_setting(con, setting); - return setting; -} - -static NMSetting * -_add_setting_fcn_olpc_mesh(NMConnection *con) -{ - NMSetting * setting; - const char *ssid_data = "ssid-test"; - GBytes * ssid; - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - setting = g_object_new(NM_TYPE_SETTING_OLPC_MESH, - NM_SETTING_OLPC_MESH_SSID, - ssid, - NM_SETTING_OLPC_MESH_CHANNEL, - 1, - NULL); - g_bytes_unref(ssid); - - nm_connection_add_setting(con, setting); - return setting; -} - -static NMSetting * -_add_setting_fcn_team(NMConnection *con) -{ - NMSetting * setting; - NMSettingConnection *s_con; - - setting = g_object_new(NM_TYPE_SETTING_TEAM, NULL); - - nm_connection_add_setting(con, setting); - - s_con = nm_connection_get_setting_connection(con); - - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "test-team", NULL); - - return setting; -} - -static NMSetting * -_add_setting_fcn_vlan(NMConnection *con) -{ - NMSetting *setting; - - setting = g_object_new(NM_TYPE_SETTING_VLAN, NM_SETTING_VLAN_PARENT, "test-parent", NULL); - - nm_connection_add_setting(con, setting); - return setting; -} - -static NMSetting * -_add_setting_fcn_vpn(NMConnection *con) -{ - NMSetting *setting; - - setting = g_object_new(NM_TYPE_SETTING_VPN, - NM_SETTING_VPN_SERVICE_TYPE, - "test-vpn-service-type", - NULL); - - nm_connection_add_setting(con, setting); - return setting; -} - -static NMSetting * -_add_setting_fcn_wimax(NMConnection *con) -{ - NMSetting *setting; - - setting = - g_object_new(NM_TYPE_SETTING_WIMAX, NM_SETTING_WIMAX_NETWORK_NAME, "test-network", NULL); - - nm_connection_add_setting(con, setting); - return setting; -} - -static NMSetting * -_add_setting_fcn_wireless(NMConnection *con) -{ - NMSetting * setting; - const char *ssid_data = "ssid-test"; - GBytes * ssid; - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - setting = g_object_new(NM_TYPE_SETTING_WIRELESS, NM_SETTING_WIRELESS_SSID, ssid, NULL); - g_bytes_unref(ssid); - - nm_connection_add_setting(con, setting); - return setting; -} - -static void -_prepare_normalizable_fcn_vlan(NMConnection *con) -{ - nm_connection_add_setting(con, - g_object_new(NM_TYPE_SETTING_WIRED, - NM_SETTING_WIRED_MAC_ADDRESS, - "11:22:33:44:55:66", - NULL)); -} - -static void -test_connection_normalize_type(void) -{ - guint i; - struct { - const char *type; - gboolean normalizable; - NMSetting *(*add_setting_fcn)(NMConnection *con); - void (*prepare_normalizable_fcn)(NMConnection *con); - } types[] = { - {NM_SETTING_GENERIC_SETTING_NAME, TRUE}, - {NM_SETTING_GSM_SETTING_NAME, TRUE}, - {NM_SETTING_WIRED_SETTING_NAME, TRUE}, - {NM_SETTING_VLAN_SETTING_NAME, TRUE, _add_setting_fcn_vlan, _prepare_normalizable_fcn_vlan}, - - {NM_SETTING_ADSL_SETTING_NAME, FALSE, _add_setting_fcn_adsl}, - {NM_SETTING_BLUETOOTH_SETTING_NAME, FALSE, _add_setting_fcn_bluetooth}, - {NM_SETTING_BOND_SETTING_NAME, FALSE, _add_setting_fcn_bond}, - {NM_SETTING_BRIDGE_SETTING_NAME, FALSE, _add_setting_fcn_bridge}, - {NM_SETTING_CDMA_SETTING_NAME, FALSE, _add_setting_fcn_cdma}, - {NM_SETTING_INFINIBAND_SETTING_NAME, FALSE, _add_setting_fcn_infiniband}, - {NM_SETTING_OLPC_MESH_SETTING_NAME, FALSE, _add_setting_fcn_olpc_mesh}, - {NM_SETTING_TEAM_SETTING_NAME, FALSE, _add_setting_fcn_team}, - {NM_SETTING_VLAN_SETTING_NAME, FALSE, _add_setting_fcn_vlan}, - {NM_SETTING_VPN_SETTING_NAME, FALSE, _add_setting_fcn_vpn}, - {NM_SETTING_WIMAX_SETTING_NAME, FALSE, _add_setting_fcn_wimax}, - {NM_SETTING_WIRELESS_SETTING_NAME, FALSE, _add_setting_fcn_wireless}, - {0}, - }; - - for (i = 0; types[i].type; i++) { - const char *type = types[i].type; - - if (types[i].normalizable) - _test_connection_normalize_type_normalizable_setting(type, - types[i].prepare_normalizable_fcn); - else - _test_connection_normalize_type_unnormalizable_setting(type); - _test_connection_normalize_type_normalizable_type(type, types[i].add_setting_fcn); - } -} - -static void -test_connection_normalize_slave_type_1(void) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingConnection * s_con; - - con = nmtst_create_minimal_connection("test_connection_normalize_slave_type_1", - "cc4cd5df-45dc-483e-b291-6b76c2338ecb", - NM_SETTING_WIRED_SETTING_NAME, - &s_con); - - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - "invalid-type", - NULL); - - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); - - g_object_set(s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, "bridge", NULL); - - g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING); - nmtst_connection_normalize(con); - g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); -} - -static void -test_connection_normalize_slave_type_2(void) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingConnection * s_con; - - con = nmtst_create_minimal_connection("test_connection_normalize_slave_type_2", - "40bea008-ca72-439a-946b-e65f827656f9", - NM_SETTING_WIRED_SETTING_NAME, - &s_con); - - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - "invalid-type", - NULL); - - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); - - g_object_set(s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, NULL, NULL); - nm_connection_add_setting(con, nm_setting_bridge_port_new()); - - g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NULL); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - nmtst_connection_normalize(con); - g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); -} - -static void -test_connection_normalize_infiniband_mtu(void) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingInfiniband * s_infini; - guint mtu_regular = nmtst_rand_select(2044, 2045, 65520); - - con = nmtst_create_minimal_connection("test_connection_normalize_infiniband_mtu", - NULL, - NM_SETTING_INFINIBAND_SETTING_NAME, - NULL); - - s_infini = nm_connection_get_setting_infiniband(con); - g_object_set(s_infini, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected", NULL); - nmtst_assert_connection_verifies_and_normalizable(con); - - g_object_set(s_infini, - NM_SETTING_INFINIBAND_TRANSPORT_MODE, - "datagram", - NM_SETTING_INFINIBAND_MTU, - (guint) mtu_regular, - NULL); - nmtst_assert_connection_verifies_and_normalizable(con); - nmtst_connection_normalize(con); - g_assert_cmpint(mtu_regular, ==, nm_setting_infiniband_get_mtu(s_infini)); - - g_object_set(s_infini, - NM_SETTING_INFINIBAND_TRANSPORT_MODE, - "datagram", - NM_SETTING_INFINIBAND_MTU, - (guint) 65521, - NULL); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - nmtst_connection_normalize(con); - g_assert_cmpint(65520, ==, nm_setting_infiniband_get_mtu(s_infini)); - - g_object_set(s_infini, - NM_SETTING_INFINIBAND_TRANSPORT_MODE, - "connected", - NM_SETTING_INFINIBAND_MTU, - (guint) mtu_regular, - NULL); - nmtst_assert_connection_verifies_without_normalization(con); - g_assert_cmpint(mtu_regular, ==, nm_setting_infiniband_get_mtu(s_infini)); - - g_object_set(s_infini, - NM_SETTING_INFINIBAND_TRANSPORT_MODE, - "connected", - NM_SETTING_INFINIBAND_MTU, - (guint) 65521, - NULL); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - nmtst_connection_normalize(con); - g_assert_cmpint(65520, ==, nm_setting_infiniband_get_mtu(s_infini)); -} - -static void -test_connection_normalize_gateway_never_default(void) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingIPConfig * s_ip4, *s_ip6; - NMIPAddress * addr; - gs_free_error GError *error = NULL; - - con = nmtst_create_minimal_connection("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - nmtst_assert_connection_verifies_and_normalizable(con); - - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(s_ip4), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NULL); - - addr = nm_ip_address_new(AF_INET, "1.1.1.1", 24, &error); - g_assert_no_error(error); - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_GATEWAY, - "1.1.1.254", - NM_SETTING_IP_CONFIG_NEVER_DEFAULT, - FALSE, - NULL); - - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); - - nm_connection_add_setting(con, (NMSetting *) s_ip4); - nm_connection_add_setting(con, (NMSetting *) s_ip6); - nm_connection_add_setting(con, nm_setting_proxy_new()); - - nmtst_assert_connection_verifies_without_normalization(con); - g_assert_cmpstr("1.1.1.254", ==, nm_setting_ip_config_get_gateway(s_ip4)); - - /* Now set never-default to TRUE and check that the gateway is - * removed during normalization - * */ - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_NEVER_DEFAULT, TRUE, NULL); - - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - nmtst_connection_normalize(con); - g_assert_cmpstr(NULL, ==, nm_setting_ip_config_get_gateway(s_ip4)); -} - -static void -test_connection_normalize_may_fail(void) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingIPConfig * s_ip4, *s_ip6; - - con = nmtst_create_minimal_connection("test2", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - nmtst_assert_connection_verifies_and_normalizable(con); - - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(s_ip4), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, - FALSE, - NULL); - - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, - FALSE, - NULL); - - nm_connection_add_setting(con, (NMSetting *) s_ip4); - nm_connection_add_setting(con, (NMSetting *) s_ip6); - - nmtst_assert_connection_verifies_and_normalizable(con); - - /* Now set method=disabled/ignore and check that may-fail becomes TRUE - * after normalization - * */ - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); - - nmtst_assert_connection_verifies(con); - nmtst_connection_normalize(con); - g_assert_cmpint(nm_setting_ip_config_get_may_fail(s_ip4), ==, TRUE); - g_assert_cmpint(nm_setting_ip_config_get_may_fail(s_ip6), ==, TRUE); -} - -static void -test_connection_normalize_shared_addresses(void) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingIPConfig * s_ip4, *s_ip6; - NMIPAddress * addr; - gs_free_error GError *error = NULL; - - con = nmtst_create_minimal_connection("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - nmtst_assert_connection_verifies_and_normalizable(con); - - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(s_ip4), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_SHARED, - NULL); - - addr = nm_ip_address_new(AF_INET, "1.1.1.1", 24, &error); - g_assert_no_error(error); - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); - - nm_connection_add_setting(con, (NMSetting *) s_ip4); - nm_connection_add_setting(con, (NMSetting *) s_ip6); - - nmtst_assert_connection_verifies_and_normalizable(con); - - /* Now we add other addresses and check that they are - * removed during normalization - * */ - addr = nm_ip_address_new(AF_INET, "2.2.2.2", 24, &error); - g_assert_no_error(error); - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - - addr = nm_ip_address_new(AF_INET, "3.3.3.3", 24, &error); - g_assert_no_error(error); - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - nmtst_connection_normalize(con); - g_assert_cmpuint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "1.1.1.1"); -} - -static void -test_connection_normalize_ovs_interface_type_system(gconstpointer test_data) -{ - const guint TEST_CASE = GPOINTER_TO_UINT(test_data); - gs_unref_object NMConnection *con = NULL; - NMSettingConnection * s_con; - NMSettingOvsInterface * s_ovs_if; - - con = nmtst_create_minimal_connection("test_connection_normalize_ovs_interface_type_system", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - &s_con); - - switch (TEST_CASE) { - case 1: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING); - - nmtst_connection_normalize(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - s_ovs_if = nm_connection_get_setting_ovs_interface(con); - g_assert(s_ovs_if); - g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "system"); - break; - case 2: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - - s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); - nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); - - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - - nmtst_connection_normalize(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); - g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "system"); - break; - case 3: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - - s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); - nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); - - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); - nmtst_assert_connection_verifies_without_normalization(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - break; - case 4: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - - s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); - nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); - - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); - /* the setting doesn't verify, because the interface-type must be "system". */ - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - break; - case 5: - g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL); - - s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); - nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); - - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - nmtst_connection_normalize(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_assert(s_con == nm_connection_get_setting_connection(con)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_OVS_PORT_SETTING_NAME); - break; - case 6: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_BRIDGE_SETTING_NAME, - NULL); - - s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); - nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); - - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - break; - case 7: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_BRIDGE_SETTING_NAME, - NULL); - - nm_connection_add_setting(con, nm_setting_bridge_port_new()); - - s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); - nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); - - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - break; - default: - g_assert_not_reached(); - break; - } -} - -static void -test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_data) -{ - const guint TEST_CASE = GPOINTER_TO_UINT(test_data); - gs_unref_object NMConnection *con = NULL; - NMSettingConnection * s_con; - NMSettingOvsInterface * s_ovs_if; - NMSettingOvsPatch * s_ovs_patch; - NMSettingIP4Config * s_ip4; - NMSettingIP6Config * s_ip6; - - con = nmtst_create_minimal_connection( - "test_connection_normalize_ovs_interface_type_ovs_interface", - NULL, - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - &s_con); - s_ovs_if = nm_connection_get_setting_ovs_interface(con); - g_assert(s_ovs_if); - - switch (TEST_CASE) { - case 1: - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - break; - case 2: - g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - nmtst_connection_normalize(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_assert(s_con == nm_connection_get_setting_connection(con)); - g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_OVS_PORT_SETTING_NAME); - g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal"); - break; - case 3: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - nmtst_connection_normalize(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_assert(s_con == nm_connection_get_setting_connection(con)); - g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_OVS_PORT_SETTING_NAME); - g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal"); - break; - case 4: - g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); - nmtst_assert_connection_verifies_after_normalization(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - nmtst_connection_normalize(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_assert(s_con == nm_connection_get_setting_connection(con)); - g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_OVS_PORT_SETTING_NAME); - g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal"); - break; - case 5: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); - nm_connection_add_setting(con, nm_setting_ip4_config_new()); - nm_connection_add_setting(con, nm_setting_ip6_config_new()); - nm_connection_add_setting(con, nm_setting_proxy_new()); - s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(con)); - s_ip6 = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(con)); - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, "auto", NULL); - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, "auto", NULL); - nmtst_assert_connection_verifies_without_normalization(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - break; - case 6: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); - nmtst_assert_connection_verifies_and_normalizable(con); - nmtst_connection_normalize(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME); - g_assert(s_con == nm_connection_get_setting_connection(con)); - g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_OVS_PORT_SETTING_NAME); - g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal"); - break; - case 7: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - break; - case 8: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "bogus", NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - break; - case 9: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING); - break; - case 10: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); - nm_connection_add_setting(con, nm_setting_ovs_patch_new()); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - break; - case 11: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_CONNECTION_INTERFACE_NAME, - "adsf", - NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); - nm_connection_add_setting(con, nm_setting_ovs_patch_new()); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY); - break; - case 12: - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_CONNECTION_INTERFACE_NAME, - "adsf", - NULL); - g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); - s_ovs_patch = NM_SETTING_OVS_PATCH(nm_setting_ovs_patch_new()); - nm_connection_add_setting(con, NM_SETTING(s_ovs_patch)); - g_object_set(s_ovs_patch, NM_SETTING_OVS_PATCH_PEER, "1.2.3.4", NULL); - nmtst_assert_connection_verifies_and_normalizable(con); - nmtst_connection_normalize(con); - nmtst_assert_connection_has_settings(con, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_PATCH_SETTING_NAME); - g_assert(s_con == nm_connection_get_setting_connection(con)); - g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_OVS_PORT_SETTING_NAME); - g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "patch"); - break; - default: - g_assert_not_reached(); - } -} - -static void -test_setting_ip4_gateway(void) -{ - NMConnection * conn; - NMSettingIPConfig *s_ip4; - NMIPAddress * addr; - GVariant * conn_dict, *ip4_dict, *value; - GVariantIter iter; - GVariant * addr_var; - guint32 addr_vals_0[] = {htonl(0xc0a8010a), 0x00000018, htonl(0x00000000)}; - guint32 addr_vals_1[] = {htonl(0xc0a8010b), 0x00000018, htonl(0xc0a80101)}; - GVariantBuilder addrs_builder; - GError * error = NULL; - - nmtst_assert_ip4_address(addr_vals_0[0], "192.168.1.10"); - - /* When serializing on the daemon side, ipv4.gateway is copied to the first - * entry of ipv4.addresses - */ - conn = nmtst_create_minimal_connection("test_setting_ip4_gateway", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - NULL); - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NM_SETTING_IP_CONFIG_GATEWAY, - "192.168.1.1", - NULL); - nm_connection_add_setting(conn, NM_SETTING(s_ip4)); - - addr = nm_ip_address_new(AF_INET, "192.168.1.10", 24, &error); - g_assert_no_error(error); - nm_setting_ip_config_add_address(s_ip4, addr); - nm_ip_address_unref(addr); - - _nm_utils_is_manager_process = TRUE; - conn_dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); - _nm_utils_is_manager_process = FALSE; - g_object_unref(conn); - - ip4_dict = g_variant_lookup_value(conn_dict, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - g_assert(ip4_dict != NULL); - - value = g_variant_lookup_value(ip4_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING); - g_assert(value != NULL); - g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "192.168.1.1"); - g_variant_unref(value); - - value = g_variant_lookup_value(ip4_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE("aau")); - g_assert(value != NULL); - - g_variant_iter_init(&iter, value); - while (g_variant_iter_next(&iter, "@au", &addr_var)) { - const guint32 *addr_array; - gsize length; - - addr_array = g_variant_get_fixed_array(addr_var, &length, sizeof(guint32)); - g_assert_cmpint(length, ==, 3); - nmtst_assert_ip4_address(addr_array[2], "192.168.1.1"); - g_variant_unref(addr_var); - } - g_variant_unref(value); - - g_variant_unref(ip4_dict); - - /* When deserializing an old-style connection, the first non-0 gateway in - * ipv4.addresses is copied to :gateway. - */ - NMTST_VARIANT_EDITOR( - conn_dict, - NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_GATEWAY); - NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-data");); - - conn = _connection_new_from_dbus(conn_dict, &error); - g_assert_no_error(error); - - s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config(conn); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.1.1"); - - g_object_unref(conn); - - /* Try again with the gateway in the second address. */ - g_variant_builder_init(&addrs_builder, G_VARIANT_TYPE("aau")); - g_variant_builder_add(&addrs_builder, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, addr_vals_0, 3, 4)); - g_variant_builder_add(&addrs_builder, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, addr_vals_1, 3, 4)); - - NMTST_VARIANT_EDITOR(conn_dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, - "addresses", - "aau", - &addrs_builder);); - - conn = _connection_new_from_dbus(conn_dict, &error); - g_assert_no_error(error); - g_variant_unref(conn_dict); - - s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config(conn); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.1.1"); - - g_object_unref(conn); -} - -static void -test_setting_ip6_gateway(void) -{ - NMConnection * conn; - NMSettingIPConfig *s_ip6; - NMIPAddress * addr; - GVariant * conn_dict, *ip6_dict, *value; - GVariantIter iter; - GVariant * gateway_var; - GVariantBuilder addrs_builder; - guint8 addr_bytes_0[] = {0xab, - 0xcd, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x0a}; - guint8 addr_bytes_1[] = {0xab, - 0xcd, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x0b}; - guint8 gateway_bytes_1[] = {0xab, - 0xcd, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x01}; - GError * error = NULL; - - /* When serializing on the daemon side, ipv6.gateway is copied to the first - * entry of ipv6.addresses - */ - conn = nmtst_create_minimal_connection("test_setting_ip6_gateway", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - NULL); - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_MANUAL, - NM_SETTING_IP_CONFIG_GATEWAY, - "abcd::1", - NULL); - nm_connection_add_setting(conn, NM_SETTING(s_ip6)); - - addr = nm_ip_address_new(AF_INET6, "abcd::10", 64, &error); - g_assert_no_error(error); - nm_setting_ip_config_add_address(s_ip6, addr); - nm_ip_address_unref(addr); - - _nm_utils_is_manager_process = TRUE; - conn_dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); - _nm_utils_is_manager_process = FALSE; - g_object_unref(conn); - - ip6_dict = g_variant_lookup_value(conn_dict, - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_VARIANT_TYPE_SETTING); - g_assert(ip6_dict != NULL); - - value = g_variant_lookup_value(ip6_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING); - g_assert(value != NULL); - g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "abcd::1"); - g_variant_unref(value); - - value = g_variant_lookup_value(ip6_dict, - NM_SETTING_IP_CONFIG_ADDRESSES, - G_VARIANT_TYPE("a(ayuay)")); - g_assert(value != NULL); - - g_variant_iter_init(&iter, value); - while (g_variant_iter_next(&iter, "(@ayu@ay)", NULL, NULL, &gateway_var)) { - const guint8 *gateway_bytes; - gsize length; - - gateway_bytes = g_variant_get_fixed_array(gateway_var, &length, 1); - g_assert_cmpint(length, ==, 16); - nmtst_assert_ip6_address((struct in6_addr *) gateway_bytes, "abcd::1"); - g_variant_unref(gateway_var); - } - g_variant_unref(value); - - g_variant_unref(ip6_dict); - - /* When deserializing an old-style connection, the first non-0 gateway in - * ipv6.addresses is copied to :gateway. - */ - NMTST_VARIANT_EDITOR( - conn_dict, - NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_IP_CONFIG_GATEWAY); - NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, "address-data");); - - conn = _connection_new_from_dbus(conn_dict, &error); - g_assert_no_error(error); - - s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config(conn); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "abcd::1"); - - g_object_unref(conn); - - /* Try again with the gateway in the second address. */ - g_variant_builder_init(&addrs_builder, G_VARIANT_TYPE("a(ayuay)")); - g_variant_builder_add(&addrs_builder, - "(@ayu@ay)", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, addr_bytes_0, 16, 1), - 64, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, &in6addr_any, 16, 1)); - g_variant_builder_add(&addrs_builder, - "(@ayu@ay)", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, addr_bytes_1, 16, 1), - 64, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, gateway_bytes_1, 16, 1)); - - NMTST_VARIANT_EDITOR(conn_dict, - NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, - "addresses", - "a(ayuay)", - &addrs_builder);); - - conn = _connection_new_from_dbus(conn_dict, &error); - g_assert_no_error(error); - g_variant_unref(conn_dict); - - s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config(conn); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "abcd::1"); - - g_object_unref(conn); -} - -typedef struct { - const char * str; - const guint8 expected[20]; - const guint expected_len; -} HexItem; - -static void -test_setting_compare_default_strv(void) -{ - gs_unref_object NMConnection *c1 = NULL, *c2 = NULL; - char ** strv; - NMSettingIPConfig * s_ip2, *s_ip1; - gboolean compare; - GHashTable * out_settings = NULL; - - c1 = nmtst_create_minimal_connection("test_compare_default_strv", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - NULL); - nmtst_assert_connection_verifies_and_normalizable(c1); - nmtst_connection_normalize(c1); - - c2 = nm_simple_connection_new_clone(c1); - nmtst_assert_connection_verifies_without_normalization(c2); - - nmtst_assert_connection_equals(c1, FALSE, c2, FALSE); - - s_ip1 = nm_connection_get_setting_ip4_config(c1); - s_ip2 = nm_connection_get_setting_ip4_config(c2); - - nm_setting_ip_config_clear_dns_options(s_ip2, FALSE); - g_object_get(G_OBJECT(s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL); - g_assert(!strv); - nmtst_assert_connection_equals(c1, FALSE, c2, FALSE); - - nm_setting_ip_config_clear_dns_options(s_ip2, TRUE); - g_object_get(G_OBJECT(s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL); - g_assert(strv && !strv[0]); - g_strfreev(strv); - - compare = nm_setting_diff((NMSetting *) s_ip1, - (NMSetting *) s_ip2, - NM_SETTING_COMPARE_FLAG_EXACT, - FALSE, - &out_settings); - g_assert(!compare); - g_assert(out_settings); - g_assert(g_hash_table_contains(out_settings, NM_SETTING_IP_CONFIG_DNS_OPTIONS)); - g_hash_table_unref(out_settings); - out_settings = NULL; - - compare = nm_connection_diff(c1, c2, NM_SETTING_COMPARE_FLAG_EXACT, &out_settings); - g_assert(!compare); - g_assert(out_settings); - g_hash_table_unref(out_settings); - out_settings = NULL; -} - -/*****************************************************************************/ - -static void -test_setting_user_data(void) -{ - gs_unref_object NMSettingUser *s_user = NULL; - - s_user = NM_SETTING_USER(nm_setting_user_new()); -} - -/*****************************************************************************/ - -typedef union { - struct sockaddr sa; - struct sockaddr_in in; - struct sockaddr_in6 in6; -} SockAddrUnion; - -static void -_sock_addr_endpoint(const char *endpoint, const char *host, gint32 port) -{ - nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL; - const char * s_endpoint; - const char * s_host; - gint32 s_port; - SockAddrUnion sockaddr = {}; - - g_assert(endpoint); - g_assert((!host) == (port == -1)); - g_assert(port >= -1 && port <= G_MAXUINT16); - - ep = nm_sock_addr_endpoint_new(endpoint); - g_assert(ep); - - s_endpoint = nm_sock_addr_endpoint_get_endpoint(ep); - s_host = nm_sock_addr_endpoint_get_host(ep); - s_port = nm_sock_addr_endpoint_get_port(ep); - g_assert_cmpstr(endpoint, ==, s_endpoint); - g_assert_cmpstr(host, ==, s_host); - g_assert_cmpint(port, ==, s_port); - - g_assert(!nm_sock_addr_endpoint_get_fixed_sockaddr(ep, &sockaddr)); - - if (endpoint[0] != ' ') { - gs_free char *endpoint2 = NULL; - - /* also test with a leading space */ - endpoint2 = g_strdup_printf(" %s", endpoint); - _sock_addr_endpoint(endpoint2, host, port); - } - - if (endpoint[0] && endpoint[strlen(endpoint) - 1] != ' ') { - gs_free char *endpoint2 = NULL; - - /* also test with a trailing space */ - endpoint2 = g_strdup_printf("%s ", endpoint); - _sock_addr_endpoint(endpoint2, host, port); - } -} - -static void -_sock_addr_endpoint_fixed(const char *endpoint, const char *host, guint16 port, guint scope_id) -{ - nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL; - const char * s_endpoint; - const char * s_host; - gint32 s_port; - int addr_family; - NMIPAddr addrbin; - SockAddrUnion sockaddr = {}; - - g_assert(endpoint); - g_assert(host); - g_assert(port > 0); - - if (!nm_utils_parse_inaddr_bin(AF_UNSPEC, host, &addr_family, &addrbin)) - g_assert_not_reached(); - - ep = nm_sock_addr_endpoint_new(endpoint); - g_assert(ep); - - s_endpoint = nm_sock_addr_endpoint_get_endpoint(ep); - s_host = nm_sock_addr_endpoint_get_host(ep); - s_port = nm_sock_addr_endpoint_get_port(ep); - g_assert_cmpstr(endpoint, ==, s_endpoint); - g_assert_cmpstr(NULL, !=, s_host); - g_assert_cmpint(port, ==, s_port); - - if (!nm_sock_addr_endpoint_get_fixed_sockaddr(ep, &sockaddr)) - g_assert_not_reached(); - - g_assert_cmpint(sockaddr.sa.sa_family, ==, addr_family); - if (addr_family == AF_INET) { - const SockAddrUnion s = { - .in = - { - .sin_family = AF_INET, - .sin_addr = addrbin.addr4_struct, - .sin_port = htons(port), - }, - }; - - g_assert_cmpint(sockaddr.in.sin_addr.s_addr, ==, addrbin.addr4); - g_assert_cmpint(sockaddr.in.sin_port, ==, htons(port)); - g_assert(memcmp(&s, &sockaddr, sizeof(s.in)) == 0); - } else if (addr_family == AF_INET6) { - const SockAddrUnion s = { - .in6 = - { - .sin6_family = AF_INET6, - .sin6_addr = addrbin.addr6, - .sin6_scope_id = scope_id, - .sin6_port = htons(port), - }, - }; - - g_assert(memcmp(&sockaddr.in6.sin6_addr, &addrbin, sizeof(addrbin.addr6)) == 0); - g_assert_cmpint(sockaddr.in6.sin6_port, ==, htons(port)); - g_assert_cmpint(sockaddr.in6.sin6_scope_id, ==, scope_id); - g_assert_cmpint(sockaddr.in6.sin6_flowinfo, ==, 0); - g_assert(memcmp(&s, &sockaddr, sizeof(s.in6)) == 0); - } else - g_assert_not_reached(); -} - -static void -test_sock_addr_endpoint(void) -{ - _sock_addr_endpoint("", NULL, -1); - _sock_addr_endpoint(":", NULL, -1); - _sock_addr_endpoint("a", NULL, -1); - _sock_addr_endpoint("a:", NULL, -1); - _sock_addr_endpoint(":a", NULL, -1); - _sock_addr_endpoint("[]:a", NULL, -1); - _sock_addr_endpoint("[]a", NULL, -1); - _sock_addr_endpoint("[]:", NULL, -1); - _sock_addr_endpoint("[a]b", NULL, -1); - _sock_addr_endpoint("[a:b", NULL, -1); - _sock_addr_endpoint("[a[:b", NULL, -1); - _sock_addr_endpoint("a:6", "a", 6); - _sock_addr_endpoint("a:6", "a", 6); - _sock_addr_endpoint("[a]:6", "a", 6); - _sock_addr_endpoint("[a]:6", "a", 6); - _sock_addr_endpoint("[a]:655", "a", 655); - _sock_addr_endpoint("[ab]:][6", NULL, -1); - _sock_addr_endpoint("[ab]:]:[6", NULL, -1); - _sock_addr_endpoint("[a[]:b", NULL, -1); - _sock_addr_endpoint("[192.169.6.x]:6", "192.169.6.x", 6); - _sock_addr_endpoint("[192.169.6.x]:0", NULL, -1); - _sock_addr_endpoint("192.169.6.7:0", NULL, -1); - - _sock_addr_endpoint_fixed("192.169.6.7:6", "192.169.6.7", 6, 0); - _sock_addr_endpoint_fixed("[192.169.6.7]:6", "192.169.6.7", 6, 0); - _sock_addr_endpoint_fixed("[a:b::]:6", "a:b::", 6, 0); - _sock_addr_endpoint_fixed("[a:b::%7]:6", "a:b::", 6, 7); - _sock_addr_endpoint_fixed("a:b::1%75:6", "a:b::1", 6, 75); - _sock_addr_endpoint_fixed("a:b::1%0:64", "a:b::1", 64, 0); -} - -/*****************************************************************************/ - -static void -test_hexstr2bin(void) -{ - static const HexItem items[] = { - {"aaBBCCddDD10496a", {0xaa, 0xbb, 0xcc, 0xdd, 0xdd, 0x10, 0x49, 0x6a}, 8}, - {"aa:bb:cc:dd:10:49:6a", {0xaa, 0xbb, 0xcc, 0xdd, 0x10, 0x49, 0x6a}, 7}, - {"0xccddeeff", {0xcc, 0xdd, 0xee, 0xff}, 4}, - {"1:2:66:77:80", {0x01, 0x02, 0x66, 0x77, 0x80}, 5}, - {"e", {0x0e}, 1}, - {"ef", {0xef}, 1}, - {"efa"}, - {"efad", {0xef, 0xad}, 2}, - {"ef:a", {0xef, 0x0a}, 2}, - {"aabb1199:"}, - {":aabb1199"}, - {"aabb$$dd"}, - {"aab:ccc:ddd"}, - {"aab::ccc:ddd"}, - }; - guint i; - - for (i = 0; i < G_N_ELEMENTS(items); i++) { - gs_unref_bytes GBytes *b = NULL; - - b = nm_utils_hexstr2bin(items[i].str); - if (items[i].expected_len) - g_assert(b); - else - g_assert(!b); - g_assert(nm_utils_gbytes_equal_mem(b, items[i].expected, items[i].expected_len)); - } -} - -/*****************************************************************************/ - -static void -_do_strquote(const char *str, gsize buf_len, const char *expected) -{ - char canary = (char) nmtst_get_rand_uint32(); - gs_free char *buf_full = g_malloc(buf_len + 2); - char * buf = &buf_full[1]; - const char * b; - - buf[-1] = canary; - buf[buf_len] = canary; - - if (buf_len == 0) { - b = nm_strquote(NULL, 0, str); - g_assert(b == NULL); - g_assert(expected == NULL); - b = nm_strquote(buf, 0, str); - g_assert(b == buf); - } else { - b = nm_strquote(buf, buf_len, str); - g_assert(b == buf); - g_assert(strlen(b) < buf_len); - g_assert_cmpstr(expected, ==, b); - } - - g_assert(buf[-1] == canary); - g_assert(buf[buf_len] == canary); -} - -static void -test_nm_strquote(void) -{ - _do_strquote(NULL, 0, NULL); - _do_strquote("", 0, NULL); - _do_strquote("a", 0, NULL); - _do_strquote("ab", 0, NULL); - - _do_strquote(NULL, 1, ""); - _do_strquote(NULL, 2, "("); - _do_strquote(NULL, 3, "(n"); - _do_strquote(NULL, 4, "(nu"); - _do_strquote(NULL, 5, "(nul"); - _do_strquote(NULL, 6, "(null"); - _do_strquote(NULL, 7, "(null)"); - _do_strquote(NULL, 8, "(null)"); - _do_strquote(NULL, 100, "(null)"); - - _do_strquote("", 1, ""); - _do_strquote("", 2, "^"); - _do_strquote("", 3, "\"\""); - _do_strquote("", 4, "\"\""); - _do_strquote("", 5, "\"\""); - _do_strquote("", 100, "\"\""); - - _do_strquote("a", 1, ""); - _do_strquote("a", 2, "^"); - _do_strquote("a", 3, "\"^"); - _do_strquote("a", 4, "\"a\""); - _do_strquote("a", 5, "\"a\""); - _do_strquote("a", 6, "\"a\""); - _do_strquote("a", 100, "\"a\""); - - _do_strquote("ab", 1, ""); - _do_strquote("ab", 2, "^"); - _do_strquote("ab", 3, "\"^"); - _do_strquote("ab", 4, "\"a^"); - _do_strquote("ab", 5, "\"ab\""); - _do_strquote("ab", 6, "\"ab\""); - _do_strquote("ab", 7, "\"ab\""); - _do_strquote("ab", 100, "\"ab\""); - - _do_strquote("abc", 1, ""); - _do_strquote("abc", 2, "^"); - _do_strquote("abc", 3, "\"^"); - _do_strquote("abc", 4, "\"a^"); - _do_strquote("abc", 5, "\"ab^"); - _do_strquote("abc", 6, "\"abc\""); - _do_strquote("abc", 7, "\"abc\""); - _do_strquote("abc", 100, "\"abc\""); -} - -/*****************************************************************************/ - -#define UUID_NS_ZERO "00000000-0000-0000-0000-000000000000" -#define UUID_NS_DNS "6ba7b810-9dad-11d1-80b4-00c04fd430c8" -#define UUID_NS_URL "6ba7b811-9dad-11d1-80b4-00c04fd430c8" -#define UUID_NS_OID "6ba7b812-9dad-11d1-80b4-00c04fd430c8" -#define UUID_NS_X500 "6ba7b814-9dad-11d1-80b4-00c04fd430c8" - -static const NMUuid * -_uuid(const char *str) -{ - static NMUuid u; - - g_assert(str); - g_assert(_nm_utils_uuid_parse(str, &u)); - return &u; -} - -static void -_test_uuid(int uuid_type, - const char *expected_uuid, - const char *str, - gssize slen, - gpointer type_args) -{ - gs_free char *uuid_test = NULL; - - uuid_test = nm_utils_uuid_generate_from_string(str, slen, uuid_type, type_args); - - g_assert(uuid_test); - g_assert(nm_utils_is_uuid(uuid_test)); - - if (!nm_streq(uuid_test, expected_uuid)) { - g_error("UUID test failed: type=%d; text=%s, len=%lld, ns=%s, uuid=%s, expected=%s", - uuid_type, - str, - (long long) slen, - NM_IN_SET(uuid_type, NM_UTILS_UUID_TYPE_VERSION3, NM_UTILS_UUID_TYPE_VERSION5) - ? (((const char *) type_args) ?: "(all-zero)") - : (type_args ? "(unknown)" : "(null)"), - uuid_test, - expected_uuid); - } - - if (slen < 0) { - /* also test that passing slen==-1 yields the same result as passing strlen(str). */ - _test_uuid(uuid_type, expected_uuid, str, strlen(str), type_args); - } else if (str && slen == 0) { - /* also test if we accept NULL for slen==0 */ - _test_uuid(uuid_type, expected_uuid, NULL, 0, type_args); - } - - if (NM_IN_SET(uuid_type, NM_UTILS_UUID_TYPE_VERSION3, NM_UTILS_UUID_TYPE_VERSION5) - && !type_args) { - /* For version3 and version5, a missing @type_args is equal to UUID_NS_ZERO */ - _test_uuid(uuid_type, expected_uuid, str, slen, UUID_NS_ZERO); - } -} - -typedef struct { - const char *uuid3; - const char *uuid5; -} ExpectedUuids; - -static void -test_nm_utils_uuid_generate_from_string(void) -{ - const ExpectedUuids zero_uuids[] = { - { - .uuid3 = "19826852-5007-3022-a72a-212f66e9fac3", - .uuid5 = "b6c54489-38a0-5f50-a60a-fd8d76219cae", - }, - { - .uuid3 = "9153af2e-fc8e-34f3-9e8b-81f73b33d0cb", - .uuid5 = "11116e73-1c03-5de6-9130-5f9925ae8ab4", - }, - { - .uuid3 = "2f06a3ae-d78d-30d7-b898-088a0e0b76f6", - .uuid5 = "1087ebe8-1ef8-5d97-8873-735b4949004d", - }, - { - .uuid3 = "aca948e0-1468-3a51-9f2e-c688a484efd7", - .uuid5 = "7e57d004-2b97-5e7a-b45f-5387367791cd", - }, - { - .uuid3 = "b74e537a-53e8-3808-9abd-58546a6542bd", - .uuid5 = "1dd80df1-492c-5dc5-aec2-6bf0e104f923", - }, - { - .uuid3 = "1b00958a-7d76-3d08-8aba-c66c5828658c", - .uuid5 = "f797f61e-a392-5acf-af25-b46057f1c8e8", - }, - { - .uuid3 = "7ba18f7d-c9cf-3b48-a89e-ad79243135cc", - .uuid5 = "e02c9780-2fc5-5d57-b92f-4cc3a64bff16", - }, - { - .uuid3 = "9baf0978-1a60-35c5-9e9b-bec8d259fd4e", - .uuid5 = "94167980-f909-527e-a4af-bc3155f586d3", - }, - { - .uuid3 = "588668c0-7631-39c7-9976-c7d414adf7ba", - .uuid5 = "9e3eefda-b56e-56bd-8a3a-0b8009d4a536", - }, - { - .uuid3 = "8edb3613-9612-3b32-9dd7-0a01aa8ed453", - .uuid5 = "9b75648e-d38c-54e8-adee-1fb295a079c9", - }, - { - .uuid3 = "f3b34394-63a5-3773-9014-1f8a50d765b8", - .uuid5 = "dd56b598-9e74-58c3-b3e8-2c623780b8ed", - }, - { - .uuid3 = "0572965f-05b8-342b-b225-d5c29d449eee", - .uuid5 = "5666449a-fb7e-55b7-ae9f-0552e6513a10", - }, - { - .uuid3 = "6f7177c3-77b0-3f42-82a8-7031e25fcccf", - .uuid5 = "10b38db9-82fc-528e-9ddb-1f09b7dbf907", - }, - { - .uuid3 = "d1e0f845-bc1b-368c-b8c8-49ab0b9e486b", - .uuid5 = "85492596-9468-5845-9c7f-d4ae999cb751", - }, - { - .uuid3 = "46371ea3-c8a3-34d8-b2cf-2fa90bda4378", - .uuid5 = "22b1c0dd-aa5d-54a4-8768-5adfd0d112bd", - }, - { - .uuid3 = "f1e6b499-9b68-343b-a5c5-ece7acc49a68", - .uuid5 = "9cc429f8-200e-52a3-9e3b-ef134afa1e29", - }, - { - .uuid3 = "9ed06458-c712-31dd-aba5-6cf79879fabe", - .uuid5 = "3949f95c-5d76-5ee2-af60-8e2d8fcf649d", - }, - { - .uuid3 = "4ddd5cd7-bc83-36aa-909c-4e660f57c830", - .uuid5 = "0e994a02-069b-58fb-b3a4-d7dc94e90fca", - }, - { - .uuid3 = "335fa537-0909-395d-a696-6f41827dcbeb", - .uuid5 = "17db3a41-de9b-5c6b-904d-833943209b3c", - }, - { - .uuid3 = "dbd58444-05ad-3edd-adc7-4393ecbcb43c", - .uuid5 = "1bd906f2-05f9-5ab5-a39a-4c17a188f886", - }, - { - .uuid3 = "a1c62d82-d13c-361b-8f4e-ca91bc2f7fc5", - .uuid5 = "ce6550fd-95b7-57e4-9aa7-461522666be4", - }, - { - .uuid3 = "e943d83e-3f82-307f-81ed-b7a7bcd0743e", - .uuid5 = "04aa09ee-b420-57ac-8a23-5d99907fb0a1", - }, - { - .uuid3 = "cabf46dd-9f09-375c-8f6e-f2a8cf114709", - .uuid5 = "8ece2c62-0c31-5c55-b7c6-155381e3780e", - }, - { - .uuid3 = "19beddf3-f2fb-340f-96ac-4f394960b7a7", - .uuid5 = "5762a9f9-9a21-59ab-b0d2-2cb90027ef7f", - }, - { - .uuid3 = "08d835c2-f4ca-394c-ba7f-2494d8b60c6c", - .uuid5 = "23c8409d-4b5f-5b6a-b946-41e49bad6c78", - }, - { - .uuid3 = "3b8c6847-5331-35bf-9cd9-ced50e53cd7c", - .uuid5 = "e8e396be-95d5-5569-8edc-e0b64c2b7613", - }, - { - .uuid3 = "e601f160-484b-3254-8f3b-0a25c7203d8a", - .uuid5 = "bc8b3cbc-ad5b-5808-a1b0-e0f7a1ad68a3", - }, - { - .uuid3 = "e5e492ed-5349-379d-b7de-a370a51e44a3", - .uuid5 = "62c5ed3f-9afa-59ad-874f-a9dd8afc69d4", - }, - { - .uuid3 = "c40111f6-fe97-305e-bfce-7db730c3d2ec", - .uuid5 = "66877a72-7243-59ed-b9e3-b5023b6da9c2", - }, - { - .uuid3 = "21e18ea8-95c2-362b-9ca9-25d6a0ff2dff", - .uuid5 = "49a49eee-7e86-5d66-837a-8a8810cb5562", - }, - { - .uuid3 = "adab623b-1343-307f-80d8-58d005376ad9", - .uuid5 = "e4a2a7ed-3bf3-53cf-a2bb-154dbb39a38c", - }, - { - .uuid3 = "67e9fc7c-dafe-356d-ac1a-a63ce3f44813", - .uuid5 = "50cacfc9-f5d2-52dd-897c-a25a0927b816", - }, - { - .uuid3 = "36cc7f20-126c-3e40-94e7-737ac7486547", - .uuid5 = "ca629991-3f2b-5e86-9bb7-37a335f7d809", - }, - { - .uuid3 = "fe282996-ac5e-3d13-b478-5def30007a8e", - .uuid5 = "c1adf8a7-f72a-58ae-82d5-d18807f12e2e", - }, - { - .uuid3 = "3bfe339c-05ae-3233-a1a5-ebf1ead589db", - .uuid5 = "6120c3cd-24e1-5ce4-987b-f8bfee2e4633", - }, - { - .uuid3 = "d1d90bc7-da4a-3cd7-a7c8-a1a89765d8ee", - .uuid5 = "433d6a26-c319-5fcf-9a30-5ec6ad59d109", - }, - { - .uuid3 = "10b88a02-0102-359b-81e9-7e3b0ff7d25e", - .uuid5 = "77d228d9-1b96-59e2-a07e-a8fdd4f62884", - }, - { - .uuid3 = "7da5e4f2-6df0-3aca-a1b0-b7f8b1340e1d", - .uuid5 = "698259bf-a32b-5e00-9ec6-88b12278c4ad", - }, - { - .uuid3 = "cbe24d98-ca20-3058-86b6-24a6b36ceff0", - .uuid5 = "60dbca63-704f-5666-9f64-f4e1a630c4aa", - }, - { - .uuid3 = "04d84e6a-b793-3993-afbf-bae7cfc42b49", - .uuid5 = "79d63ec0-a39d-557d-8299-f4c97acfadc3", - }, - { - .uuid3 = "fdd157d8-a537-350a-9cc9-1930e8666c63", - .uuid5 = "7df7f75e-a146-5a76-828b-bac052db312b", - }, - { - .uuid3 = "0bea36bb-24a7-3ee6-a98d-116433c14cd4", - .uuid5 = "2bcca2e9-2879-53e3-b09d-cbbfd58771b2", - }, - { - .uuid3 = "52b040a4-1b84-32d2-b758-f82386f7e0f0", - .uuid5 = "cb7bdca3-e9f7-50cd-b72e-73cb9ff24f62", - }, - { - .uuid3 = "0f0a4e26-e034-3021-acf2-4e886af43092", - .uuid5 = "8e428e2b-5da3-5368-b760-5ca07ccbd819", - }, - { - .uuid3 = "819d3cd1-afe5-3e4a-9f0c-945e25d09879", - .uuid5 = "f340ef4d-139c-567a-b0fc-7c495336674e", - }, - { - .uuid3 = "e7df1a3b-c9f8-3e5a-88d6-ba72b2a0f27b", - .uuid5 = "7e3f5fd2-3c93-58d6-9f35-6e0192445b11", - }, - { - .uuid3 = "0854bedf-74ba-3f2b-b823-dc2c90d27c76", - .uuid5 = "bc112b6b-c5de-5ee9-b816-808792743a20", - }, - { - .uuid3 = "a1b8c3ba-f821-32ef-a3fd-b97b3855efa8", - .uuid5 = "47f8f82d-9fcd-553c-90c5-3f3cb3ad00ad", - }, - { - .uuid3 = "9458f819-079b-3033-9430-ba10f576c067", - .uuid5 = "bee5c091-5f01-51fa-86bb-e9488fd3b4da", - }, - { - .uuid3 = "8e1f240a-e386-3e00-866a-6f9da1e3503f", - .uuid5 = "8ea92cea-d741-566f-a44a-d51e65b4c5e4", - }, - }; - const ExpectedUuids dns_uuids[] = { - { - .uuid3 = "4385125b-dd1e-3025-880f-3311517cc8d5", - .uuid5 = "6af613b6-569c-5c22-9c37-2ed93f31d3af", - }, - { - .uuid3 = "afd0b036-625a-3aa8-b639-9dc8c8fff0ff", - .uuid5 = "b04965e6-a9bb-591f-8f8a-1adcb2c8dc39", - }, - { - .uuid3 = "9c45c2f1-1761-3daa-ad31-1ff8703ae846", - .uuid5 = "4b166dbe-d99d-5091-abdd-95b83330ed3a", - }, - { - .uuid3 = "15e0ba07-10e4-3d7f-aaff-c00fed873c88", - .uuid5 = "98123fde-012f-5ff3-8b50-881449dac91a", - }, - { - .uuid3 = "bc27b4db-bc0f-34f9-ae8e-4b72f2d51b60", - .uuid5 = "6ed955c6-506a-5343-9be4-2c0afae02eef", - }, - { - .uuid3 = "7586bfed-b8b8-3bb3-9c95-09a4a79dc0f7", - .uuid5 = "c8691da2-158a-5ed6-8537-0e6f140801f2", - }, - { - .uuid3 = "881430b6-8d28-3175-b87d-e81f2f5978c6", - .uuid5 = "a6c4fc8f-6950-51de-a9ae-2c519c465071", - }, - { - .uuid3 = "24075675-98ae-354e-89ca-0126a9ad36e3", - .uuid5 = "a9f96b98-dd44-5216-ab0d-dbfc6b262edf", - }, - { - .uuid3 = "2c269ea4-dbfd-32dd-9bd7-a5c22677d18b", - .uuid5 = "e99caacd-6c45-5906-bd9f-b79e62f25963", - }, - { - .uuid3 = "44eb0948-118f-3f28-87e4-f61c8f889aba", - .uuid5 = "e4d80b30-151e-51b5-9f4f-18a3b82718e6", - }, - { - .uuid3 = "fc72beeb-f790-36ee-a73d-33888c9d8880", - .uuid5 = "0159d6c7-973f-5e7a-a9a0-d195d0ea6fe2", - }, - { - .uuid3 = "1e46afa2-6176-3cd3-9750-3015846723df", - .uuid5 = "7fef88f7-411d-5669-b42d-bf5fc7f9b58b", - }, - { - .uuid3 = "0042b01d-95bd-343f-bd9f-3186bfd63508", - .uuid5 = "52524d6e-10dc-5261-aa36-8b2efcbaa5f0", - }, - { - .uuid3 = "115ff52f-d605-3b4b-98fe-c0ea57f4930c", - .uuid5 = "91c274f2-9a0d-5ce6-ac3d-7529f452df21", - }, - { - .uuid3 = "ed0221e8-ac7d-393b-821d-25183567885b", - .uuid5 = "0ff1e264-520d-543a-87dd-181a491e667e", - }, - { - .uuid3 = "508ef333-85a6-314c-bcf3-17ddc32b2216", - .uuid5 = "23986425-d3a5-5e13-8bab-299745777a8d", - }, - { - .uuid3 = "a4715ee0-524a-37cc-beb2-a0b5030757b7", - .uuid5 = "c15b38c9-9a3e-543c-a703-dd742f25b4d5", - }, - { - .uuid3 = "d1c72756-aaec-3470-a2f2-97415f44d72f", - .uuid5 = "db680066-c83d-5ed7-89a4-1d79466ea62d", - }, - { - .uuid3 = "7aec2f01-586e-3d53-b8f3-6cf7e6b649a4", - .uuid5 = "cadb7952-2bba-5609-88d4-8e47ec4e7920", - }, - { - .uuid3 = "3d234b88-8d6f-319a-91ea-edb6059fc825", - .uuid5 = "35140057-a2a4-5adb-a500-46f8ed8b66a9", - }, - { - .uuid3 = "d2568554-93ec-30c7-9e15-f383be19e5bb", - .uuid5 = "66e549b7-01e2-5d07-98d5-430f74d8d3b2", - }, - { - .uuid3 = "800e59a7-dd0f-3114-8e58-ab7e213895ca", - .uuid5 = "292c8e99-2378-55aa-83d8-350e0ac3f1cc", - }, - { - .uuid3 = "3b7d03f0-e067-3d72-84f4-e410ac36ef57", - .uuid5 = "0e3b230a-0509-55d8-96a0-9875f387a2be", - }, - { - .uuid3 = "8762be68-de95-391a-94a0-c5fd0446e037", - .uuid5 = "4c507660-a83b-55c0-9b2b-83eccb07723d", - }, - { - .uuid3 = "2bd8b4c9-01af-3cd0-aced-94ee6e2004b8", - .uuid5 = "a1b9b633-da11-58be-b1a9-5cfa2848f186", - }, - { - .uuid3 = "a627d6a4-394a-33f5-b68e-22bfb6488d01", - .uuid5 = "c2708a8b-120a-56f5-a30d-990048af87cc", - }, - { - .uuid3 = "6a592510-17d9-3925-b321-4a8d4927f8d0", - .uuid5 = "e7263999-68b6-5a23-b530-af25b7efd632", - }, - { - .uuid3 = "9ee72491-59c4-333c-bb93-fe733a842fdb", - .uuid5 = "ce1ae2d5-3454-5952-97ff-36ff935bcfe9", - }, - { - .uuid3 = "2591c62c-0a9d-3c28-97bc-fa0401556a3c", - .uuid5 = "33677b87-bc8d-5ff6-9a25-fe60225e4bf0", - }, - { - .uuid3 = "7912be1e-4562-373b-92e2-3d6d2123bc8e", - .uuid5 = "ed2305ae-e8f9-5387-b860-3d80ae6c02f7", - }, - { - .uuid3 = "09370cda-89a4-3a48-b592-9c0486e0d5e4", - .uuid5 = "604ed872-ae2d-5d91-8e3e-572f3a3aaaa5", - }, - { - .uuid3 = "de5980d3-a137-373c-850b-ca3e5f100779", - .uuid5 = "8f8173d9-2f8d-5636-a693-24d9f79ba651", - }, - { - .uuid3 = "9441501d-f633-365a-8955-9df443edc762", - .uuid5 = "36eb8d4d-b854-51f1-9fdf-3735964225d5", - }, - { - .uuid3 = "434ada18-13ce-3c08-8b40-a1a1ae030569", - .uuid5 = "3493b6ca-f84b-56a9-97cc-c0bd1c46c4c0", - }, - { - .uuid3 = "a13b6160-bd23-3710-a150-41d800dd30b4", - .uuid5 = "f413ea13-fcd9-5b44-9d22-1fa1f7b063a5", - }, - { - .uuid3 = "73a67c12-c5f0-3288-ad6a-c78aea0917b0", - .uuid5 = "f468d924-d23b-56c2-b90f-3d1cf4b45337", - }, - { - .uuid3 = "a126ee4f-a222-357d-b71b-7d3f226c559f", - .uuid5 = "8828c9d6-ed76-5c09-bf64-ba9e9cd90896", - }, - { - .uuid3 = "48f4f36b-b015-3137-9b6e-351bb175c7f7", - .uuid5 = "facb7618-55ca-5c30-9cba-fd567b6c0611", - }, - { - .uuid3 = "3fe8f6a3-fe4a-3487-89d6-dd06c6ad02e3", - .uuid5 = "96f3de0e-6412-5434-b406-67ef3352ab85", - }, - { - .uuid3 = "d68fa2d4-adc9-3b20-ac77-42585cd1d59f", - .uuid5 = "9ebacb89-40ab-52b3-93a2-9054611d8f55", - }, - { - .uuid3 = "819f86a3-31d5-3e72-a83e-142c3a3e4832", - .uuid5 = "681046ff-9129-5ade-b11c-769864e02184", - }, - { - .uuid3 = "9957b433-ddc8-3113-a3e6-5512cf13dab1", - .uuid5 = "c13d0b5d-1ca3-57b6-a23f-8586bca44928", - }, - { - .uuid3 = "5aab6e0c-b7d3-379c-92e3-2bfbb5572511", - .uuid5 = "7c411b5e-9d3f-50b5-9c28-62096e41c4ed", - }, - { - .uuid3 = "11c8ff30-3a7d-3547-80a7-d61b8abeeda8", - .uuid5 = "f825aafe-6696-5121-b263-6b2c408b7f43", - }, - { - .uuid3 = "98799b9f-1c5e-30b3-930f-e412b862cbe4", - .uuid5 = "f2b4caea-61c3-5bed-8ce7-d8b9d16e129e", - }, - { - .uuid3 = "9bdf2544-31d8-3555-94b0-6a749118a996", - .uuid5 = "3593855a-6557-5736-8cab-172c6987f949", - }, - { - .uuid3 = "ddcfb9b3-e990-3985-9021-546a2711e7e5", - .uuid5 = "36392431-d554-5385-b876-7bc6e1cb26b3", - }, - { - .uuid3 = "190d7a78-1484-3136-80a6-40f28852785c", - .uuid5 = "7e645493-0898-5501-8155-e8578b4f5224", - }, - { - .uuid3 = "6ed693e4-7dc0-3210-856b-a6eb4cc73e13", - .uuid5 = "14dc6a81-0491-5683-baaf-7582a61c5798", - }, - { - .uuid3 = "b6a14b21-e73a-3ce2-9076-a804c434f5c6", - .uuid5 = "883e0a9c-e3b3-5f9c-8073-2913cbbb99ec", - }, - }; - char i_str[30]; - guint i; - - _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, "d41d8cd9-8f00-b204-e980-0998ecf8427e", "", -1, NULL); - _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, "0cc175b9-c0f1-b6a8-31c3-99e269772661", "a", -1, NULL); - _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, "098f6bcd-4621-d373-cade-4e832627b4f6", "test", -1, NULL); - _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, "70350f60-27bc-e371-3f6b-76473084309b", "a\0b", 3, NULL); - _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, - "59c0547b-7fe2-1c15-2cce-e328e8bf6742", - "/etc/NetworkManager/system-connections/em1", - -1, - NULL); - - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, "4ae71336-e44b-39bf-b9d2-752e234818a5", "", -1, NULL); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, "0531103a-d8fc-3dd4-b972-d98e4750994e", "a", -1, NULL); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "96e17d7a-ac89-38cf-95e1-bf5098da34e1", - "test", - -1, - NULL); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "8156568e-4ae6-3f34-a93e-18e2c6cbbf78", - "a\0b", - 3, - NULL); - - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "c87ee674-4ddc-3efe-a74e-dfe25da5d7b3", - "", - -1, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "4c104dd0-4821-30d5-9ce3-0e7a1f8b7c0d", - "a", - -1, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "45a113ac-c7f2-30b0-90a5-a399ab912716", - "test", - -1, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "002a0ada-f547-375a-bab5-896a11d1927e", - "a\0b", - 3, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "9a75f5f2-195e-31a9-9d07-8c18b5d3b285", - "test123", - -1, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "ec794efe-a384-3b11-a0b6-ec8995bc6acc", - "x", - -1, - UUID_NS_DNS); - - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "a7650b9f-f19f-5300-8a13-91160ea8de2c", - "a\0b", - 3, - NULL); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "4f3f2898-69e3-5a0d-820a-c4e87987dbce", - "a", - -1, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "05b16a01-46c6-56dd-bd6e-c6dfb4a1427a", - "x", - -1, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "c9ed566a-6b79-5d3a-b2b7-96a936b48cf3", - "test123", - -1, - UUID_NS_DNS); - - for (i = 0; i < G_N_ELEMENTS(zero_uuids); i++) { - nm_sprintf_buf(i_str, "%u", i), - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, zero_uuids[i].uuid3, i_str, -1, NULL); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, zero_uuids[i].uuid5, i_str, -1, NULL); - } - for (i = 0; i < G_N_ELEMENTS(dns_uuids); i++) { - nm_sprintf_buf(i_str, "%u", i), - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, dns_uuids[i].uuid3, i_str, -1, UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, dns_uuids[i].uuid5, i_str, -1, UUID_NS_DNS); - } - - /* examples from cpython unit tests: */ - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "6fa459ea-ee8a-3ca4-894e-db77e160355e", - "python.org", - -1, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "886313e1-3b8a-5372-9b90-0c9aee199e5d", - "python.org", - -1, - UUID_NS_DNS); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "9fe8e8c4-aaa8-32a9-a55c-4535a88b748d", - "http://python.org/", - -1, - UUID_NS_URL); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "4c565f0d-3f5a-5890-b41b-20cf47701c5e", - "http://python.org/", - -1, - UUID_NS_URL); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "dd1a1cef-13d5-368a-ad82-eca71acd4cd1", - "1.3.6.1", - -1, - UUID_NS_OID); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "1447fa61-5277-5fef-a9b3-fbc6e44f4af3", - "1.3.6.1", - -1, - UUID_NS_OID); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, - "658d3002-db6b-3040-a1d1-8ddd7d189a4d", - "c=ca", - -1, - UUID_NS_X500); - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "cc957dd1-a972-5349-98cd-874190002798", - "c=ca", - -1, - UUID_NS_X500); - - _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, - "74738ff5-5367-5958-9aee-98fffdcd1876", - "www.example.org", - -1, - UUID_NS_DNS); -} - -/*****************************************************************************/ - -static void -__test_uuid(const char *expected_uuid, const char *str, gssize slen, char *uuid_test) -{ - g_assert(uuid_test); - g_assert(nm_utils_is_uuid(uuid_test)); - - if (strcmp(uuid_test, expected_uuid)) { - g_error("UUID test failed (1): text=%s, len=%lld, expected=%s, uuid_test=%s", - str, - (long long) slen, - expected_uuid, - uuid_test); - } - g_free(uuid_test); - - uuid_test = nm_utils_uuid_generate_from_string(str, - slen, - NM_UTILS_UUID_TYPE_VERSION3, - NM_UTILS_UUID_NS); - - g_assert(uuid_test); - g_assert(nm_utils_is_uuid(uuid_test)); - - if (strcmp(uuid_test, expected_uuid)) { - g_error("UUID test failed (2): text=%s; len=%lld, expected=%s, uuid2=%s", - str, - (long long) slen, - expected_uuid, - uuid_test); - } - g_free(uuid_test); -} - -#define _test_uuid(expected_uuid, str, strlen, ...) \ - __test_uuid(expected_uuid, str, strlen, _nm_utils_uuid_generate_from_strings(__VA_ARGS__, NULL)) - -static void -test_nm_utils_uuid_generate_from_strings(void) -{ - const NMUuid uuid0 = {}; - - g_assert_cmpmem(&uuid0, sizeof(uuid0), _uuid("00000000-0000-0000-0000-000000000000"), 16); - - g_assert(nm_utils_uuid_is_null(NULL)); - g_assert(nm_utils_uuid_is_null(&uuid0)); - g_assert(nm_utils_uuid_is_null(_uuid("00000000-0000-0000-0000-000000000000"))); - g_assert(!nm_utils_uuid_is_null(_uuid("10000000-0000-0000-0000-000000000000"))); - - _test_uuid("b07c334a-399b-32de-8d50-58e4e08f98e3", "", 0, NULL); - _test_uuid("b8a426cb-bcb5-30a3-bd8f-6786fea72df9", "\0", 1, ""); - _test_uuid("12a4a982-7aae-39e1-951e-41aeb1250959", "a\0", 2, "a"); - _test_uuid("69e22c7e-f89f-3a43-b239-1cb52ed8db69", "aa\0", 3, "aa"); - _test_uuid("59829fd3-5ad5-3d90-a7b0-4911747e4088", "\0\0", 2, "", ""); - _test_uuid("01ad0e06-6c50-3384-8d86-ddab81421425", "a\0\0", 3, "a", ""); - _test_uuid("e1ed8647-9ed3-3ec8-8c6d-e8204524d71d", "aa\0\0", 4, "aa", ""); - _test_uuid("fb1c7cd6-275c-3489-9382-83b900da8af0", "\0a\0", 3, "", "a"); - _test_uuid("5d79494e-c4ba-31a6-80a2-d6016ccd7e17", "a\0a\0", 4, "a", "a"); - _test_uuid("fd698d86-1b60-3ebe-855f-7aada9950a8d", "aa\0a\0", 5, "aa", "a"); - _test_uuid("8c573b48-0f01-30ba-bb94-c5f59f4fe517", "\0aa\0", 4, "", "aa"); - _test_uuid("2bdd3d46-eb83-3c53-a41b-a724d04b5544", "a\0aa\0", 5, "a", "aa"); - _test_uuid("13d4b780-07c1-3ba7-b449-81c4844ef039", "aa\0aa\0", 6, "aa", "aa"); - _test_uuid("dd265bf7-c05a-3037-9939-b9629858a477", "a\0b\0", 4, "a", "b"); -} - -/*****************************************************************************/ - -static void -test_nm_utils_ascii_str_to_int64_check(const char *str, - guint base, - gint64 min, - gint64 max, - gint64 fallback, - int exp_errno, - gint64 exp_val) -{ - gint64 v; - - errno = 1; - v = _nm_utils_ascii_str_to_int64(str, base, min, max, fallback); - g_assert_cmpint(errno, ==, exp_errno); - g_assert_cmpint(v, ==, exp_val); -} - -static void -test_nm_utils_ascii_str_to_int64_do(const char *str, - guint base, - gint64 min, - gint64 max, - gint64 fallback, - int exp_errno, - gint64 exp_val) -{ - const char * sign = ""; - const char * val; - static const char *whitespaces[] = { - "", - " ", - "\r\n\t", - " \r\n\t ", - " \r\n\t \t\r\n\t", - NULL, - }; - static const char *nulls[] = { - "", - "0", - "00", - "0000", - "0000000000000000", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000000000", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000", - NULL, - }; - const char **ws_pre, **ws_post, **null; - guint i; - - if (str == NULL || exp_errno != 0) { - test_nm_utils_ascii_str_to_int64_check(str, base, min, max, fallback, exp_errno, exp_val); - return; - } - - if (strncmp(str, "-", 1) == 0) - sign = "-"; - - val = str + strlen(sign); - - for (ws_pre = whitespaces; *ws_pre; ws_pre++) { - for (ws_post = whitespaces; *ws_post; ws_post++) { - for (null = nulls; *null; null++) { - for (i = 0;; i++) { - char * s; - const char *str_base = ""; - - if (base == 16) { - if (i == 1) - str_base = "0x"; - else if (i > 1) - break; - } else if (base == 8) { - if (i == 1) - str_base = "0"; - else if (i > 1) - break; - } else if (base == 0) { - if (i > 0) - break; - /* with base==0, a leading zero would be interpreted as octal. Only test without *null */ - if ((*null)[0]) - break; - } else { - if (i > 0) - break; - } - - s = g_strdup_printf("%s%s%s%s%s%s", - *ws_pre, - sign, - str_base, - *null, - val, - *ws_post); - - test_nm_utils_ascii_str_to_int64_check(s, - base, - min, - max, - fallback, - exp_errno, - exp_val); - g_free(s); - } - } - } - } -} - -static void -test_nm_utils_ascii_str_to_int64(void) -{ - test_nm_utils_ascii_str_to_int64_do(NULL, 10, 0, 10000, -1, EINVAL, -1); - test_nm_utils_ascii_str_to_int64_do("", 10, 0, 10000, -1, EINVAL, -1); - test_nm_utils_ascii_str_to_int64_do("1x", 10, 0, 10000, -1, EINVAL, -1); - test_nm_utils_ascii_str_to_int64_do("4711", 10, 0, 10000, -1, 0, 4711); - test_nm_utils_ascii_str_to_int64_do("10000", 10, 0, 10000, -1, 0, 10000); - test_nm_utils_ascii_str_to_int64_do("10001", 10, 0, 10000, -1, ERANGE, -1); - test_nm_utils_ascii_str_to_int64_do("FF", 16, 0, 10000, -1, 0, 255); - test_nm_utils_ascii_str_to_int64_do("FF", 10, 0, 10000, -2, EINVAL, -2); - test_nm_utils_ascii_str_to_int64_do("9223372036854775807", - 10, - 0, - G_MAXINT64, - -2, - 0, - G_MAXINT64); - test_nm_utils_ascii_str_to_int64_do("7FFFFFFFFFFFFFFF", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64); - test_nm_utils_ascii_str_to_int64_do("9223372036854775808", 10, 0, G_MAXINT64, -2, ERANGE, -2); - test_nm_utils_ascii_str_to_int64_do("-9223372036854775808", - 10, - G_MININT64, - 0, - -2, - 0, - G_MININT64); - test_nm_utils_ascii_str_to_int64_do("-9223372036854775808", - 10, - G_MININT64 + 1, - 0, - -2, - ERANGE, - -2); - test_nm_utils_ascii_str_to_int64_do("-9223372036854775809", 10, G_MININT64, 0, -2, ERANGE, -2); - test_nm_utils_ascii_str_to_int64_do("1.0", 10, 1, 1, -1, EINVAL, -1); - test_nm_utils_ascii_str_to_int64_do("1x0", 16, -10, 10, -100, EINVAL, -100); - test_nm_utils_ascii_str_to_int64_do("0", 16, -10, 10, -100, 0, 0); - test_nm_utils_ascii_str_to_int64_do("10001111", 2, -1000, 1000, -100000, 0, 0x8F); - test_nm_utils_ascii_str_to_int64_do("-10001111", 2, -1000, 1000, -100000, 0, -0x8F); - test_nm_utils_ascii_str_to_int64_do("1111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7F); - test_nm_utils_ascii_str_to_int64_do("111111111111111", - 2, - G_MININT64, - G_MAXINT64, - -1, - 0, - 0x7FFF); - test_nm_utils_ascii_str_to_int64_do("11111111111111111111111111111111111111111111111", - 2, - G_MININT64, - G_MAXINT64, - -1, - 0, - 0x7FFFFFFFFFFF); - test_nm_utils_ascii_str_to_int64_do( - "111111111111111111111111111111111111111111111111111111111111111", - 2, - G_MININT64, - G_MAXINT64, - -1, - 0, - 0x7FFFFFFFFFFFFFFF); - test_nm_utils_ascii_str_to_int64_do( - "100000000000000000000000000000000000000000000000000000000000000", - 2, - G_MININT64, - G_MAXINT64, - -1, - 0, - 0x4000000000000000); - test_nm_utils_ascii_str_to_int64_do( - "1000000000000000000000000000000000000000000000000000000000000000", - 2, - G_MININT64, - G_MAXINT64, - -1, - ERANGE, - -1); - test_nm_utils_ascii_str_to_int64_do( - "-100000000000000000000000000000000000000000000000000000000000000", - 2, - G_MININT64, - G_MAXINT64, - -1, - 0, - -0x4000000000000000); - test_nm_utils_ascii_str_to_int64_do( - "111111111111111111111111111111111111111111111111111111111111111", - 2, - G_MININT64, - G_MAXINT64, - -1, - 0, - 0x7FFFFFFFFFFFFFFF); - test_nm_utils_ascii_str_to_int64_do( - "-100000000000000000000000000000000000000000000000000000000000000", - 2, - G_MININT64, - G_MAXINT64, - -1, - 0, - -0x4000000000000000); - test_nm_utils_ascii_str_to_int64_do("0x70", 10, G_MININT64, G_MAXINT64, -1, EINVAL, -1); - test_nm_utils_ascii_str_to_int64_do("4711", 0, G_MININT64, G_MAXINT64, -1, 0, 4711); - test_nm_utils_ascii_str_to_int64_do("04711", 0, G_MININT64, G_MAXINT64, -1, 0, 04711); - test_nm_utils_ascii_str_to_int64_do("0x4711", 0, G_MININT64, G_MAXINT64, -1, 0, 0x4711); - test_nm_utils_ascii_str_to_int64_do("080", 0, G_MININT64, G_MAXINT64, -1, EINVAL, -1); - test_nm_utils_ascii_str_to_int64_do("070", 0, G_MININT64, G_MAXINT64, -1, 0, 7 * 8); - test_nm_utils_ascii_str_to_int64_do("0x70", 0, G_MININT64, G_MAXINT64, -1, 0, 0x70); - - g_assert_cmpint(21, ==, _nm_utils_ascii_str_to_int64("025", 0, 0, 1000, -1)); - g_assert_cmpint(21, ==, _nm_utils_ascii_str_to_int64("0025", 0, 0, 1000, -1)); - g_assert_cmpint(25, ==, _nm_utils_ascii_str_to_int64("025", 10, 0, 1000, -1)); - g_assert_cmpint(25, ==, _nm_utils_ascii_str_to_int64("0025", 10, 0, 1000, -1)); -} - -/*****************************************************************************/ - -static void -test_nm_utils_strstrdictkey(void) -{ -#define _VALUES_STATIC(_v1, _v2) \ - { \ - .v1 = _v1, .v2 = _v2, .v_static = _nm_utils_strstrdictkey_static(_v1, _v2), \ - } - const struct { - const char * v1; - const char * v2; - NMUtilsStrStrDictKey *v_static; - } * val1, *val2, - values[] = { - {NULL, NULL}, - {"", NULL}, - {NULL, ""}, - {"a", NULL}, - {NULL, "a"}, - _VALUES_STATIC("", ""), - _VALUES_STATIC("a", ""), - _VALUES_STATIC("", "a"), - _VALUES_STATIC("a", "b"), - }; - guint i, j; - - for (i = 0; i < G_N_ELEMENTS(values); i++) { - gs_free NMUtilsStrStrDictKey *key1 = NULL; - - val1 = &values[i]; - - key1 = _nm_utils_strstrdictkey_create(val1->v1, val1->v2); - if (val1->v_static) { - g_assert(_nm_utils_strstrdictkey_equal(key1, val1->v_static)); - g_assert(_nm_utils_strstrdictkey_equal(val1->v_static, key1)); - g_assert_cmpint(_nm_utils_strstrdictkey_hash(key1), - ==, - _nm_utils_strstrdictkey_hash(val1->v_static)); - } - - for (j = 0; j < G_N_ELEMENTS(values); j++) { - gs_free NMUtilsStrStrDictKey *key2 = NULL; - - val2 = &values[j]; - key2 = _nm_utils_strstrdictkey_create(val2->v1, val2->v2); - if (i != j) { - g_assert(!_nm_utils_strstrdictkey_equal(key1, key2)); - g_assert(!_nm_utils_strstrdictkey_equal(key2, key1)); - } - } - } -} - -/*****************************************************************************/ - -static guint -_g_strv_length(gconstpointer arr) -{ - return arr ? g_strv_length((char **) arr) : 0; -} - -static void -test_nm_ptrarray_len(void) -{ -#define _PTRARRAY_cmp(len, arr) \ - G_STMT_START \ - { \ - g_assert_cmpint(len, ==, NM_PTRARRAY_LEN(arr)); \ - g_assert_cmpint(len, ==, _g_strv_length(arr)); \ - } \ - G_STMT_END -#define _PTRARRAY_LEN0(T) \ - G_STMT_START \ - { \ - T ** vnull = NULL; \ - T *const * vnull1 = NULL; \ - T *const *const vnull2 = NULL; \ - T * v0[] = {NULL}; \ - T *const * v01 = v0; \ - T *const *const v02 = v0; \ - T **const v03 = v0; \ - \ - _PTRARRAY_cmp(0, vnull); \ - _PTRARRAY_cmp(0, vnull1); \ - _PTRARRAY_cmp(0, vnull2); \ - _PTRARRAY_cmp(0, v0); \ - _PTRARRAY_cmp(0, v01); \ - _PTRARRAY_cmp(0, v02); \ - _PTRARRAY_cmp(0, v03); \ - } \ - G_STMT_END - - _PTRARRAY_LEN0(char); - _PTRARRAY_LEN0(const char); - _PTRARRAY_LEN0(int); - _PTRARRAY_LEN0(const int); - _PTRARRAY_LEN0(void *); - _PTRARRAY_LEN0(void); - _PTRARRAY_LEN0(const void); - -#define _PTRARRAY_LENn(T) \ - G_STMT_START \ - { \ - T x[5] = {0}; \ - \ - T * v1[] = {&x[0], NULL}; \ - T *const * v11 = v1; \ - T *const *const v12 = v1; \ - T **const v13 = v1; \ - \ - T * v2[] = {&x[0], &x[1], NULL}; \ - T *const * v21 = v2; \ - T *const *const v22 = v2; \ - T **const v23 = v2; \ - \ - _PTRARRAY_cmp(1, v1); \ - _PTRARRAY_cmp(1, v11); \ - _PTRARRAY_cmp(1, v12); \ - _PTRARRAY_cmp(1, v13); \ - \ - _PTRARRAY_cmp(2, v2); \ - _PTRARRAY_cmp(2, v21); \ - _PTRARRAY_cmp(2, v22); \ - _PTRARRAY_cmp(2, v23); \ - } \ - G_STMT_END - - _PTRARRAY_LENn(char); - _PTRARRAY_LENn(const char); - _PTRARRAY_LENn(int); - _PTRARRAY_LENn(const int); - _PTRARRAY_LENn(void *); -} - -/*****************************************************************************/ - -static void -test_nm_utils_dns_option_validate_do(char * option, - gboolean ipv6, - const NMUtilsDNSOptionDesc *descs, - gboolean exp_result, - char * exp_name, - gboolean exp_value) -{ - char * name; - long value = 0; - gboolean result; - - result = _nm_utils_dns_option_validate(option, &name, &value, ipv6, descs); - - g_assert(result == exp_result); - g_assert_cmpstr(name, ==, exp_name); - g_assert(value == exp_value); - - g_free(name); -} - -static const NMUtilsDNSOptionDesc opt_descs[] = { - /* name num ipv6 */ - {"opt1", FALSE, FALSE}, - {"opt2", TRUE, FALSE}, - {"opt3", FALSE, TRUE}, - {"opt4", TRUE, TRUE}, - {NULL, FALSE, FALSE}}; - -static void -test_nm_utils_dns_option_validate(void) -{ - /* opt ipv6 descs result name value */ - test_nm_utils_dns_option_validate_do("", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do(":", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do(":1", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do(":val", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt", FALSE, NULL, TRUE, "opt", -1); - test_nm_utils_dns_option_validate_do("opt:", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt:12", FALSE, NULL, TRUE, "opt", 12); - test_nm_utils_dns_option_validate_do("opt:12 ", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt:val", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt:2val", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt:2:3", FALSE, NULL, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt-6", FALSE, NULL, TRUE, "opt-6", -1); - - test_nm_utils_dns_option_validate_do("opt1", FALSE, opt_descs, TRUE, "opt1", -1); - test_nm_utils_dns_option_validate_do("opt1", TRUE, opt_descs, TRUE, "opt1", -1); - test_nm_utils_dns_option_validate_do("opt1:3", FALSE, opt_descs, FALSE, NULL, -1); - - test_nm_utils_dns_option_validate_do("opt2", FALSE, opt_descs, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt2:5", FALSE, opt_descs, TRUE, "opt2", 5); - - test_nm_utils_dns_option_validate_do("opt3", FALSE, opt_descs, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt3", TRUE, opt_descs, TRUE, "opt3", -1); - - test_nm_utils_dns_option_validate_do("opt4", FALSE, opt_descs, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt4", TRUE, opt_descs, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt4:40", FALSE, opt_descs, FALSE, NULL, -1); - test_nm_utils_dns_option_validate_do("opt4:40", TRUE, opt_descs, TRUE, "opt4", 40); -} - -static void -test_nm_utils_dns_option_find_idx(void) -{ - GPtrArray *options; - - options = g_ptr_array_new(); - - g_ptr_array_add(options, "debug"); - g_ptr_array_add(options, "timeout:5"); - g_ptr_array_add(options, "edns0"); - - g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "debug"), ==, 0); - g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "debug:1"), ==, 0); - g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout"), ==, 1); - g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout:5"), ==, 1); - g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout:2"), ==, 1); - g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "edns0"), ==, 2); - g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "rotate"), ==, -1); - g_assert_cmpint(_nm_utils_dns_option_find_idx(options, ""), ==, -1); - - g_ptr_array_free(options, TRUE); -} - -/*****************************************************************************/ - -static void -_json_config_check_valid(const char *conf, gboolean expected) -{ - gs_free_error GError *error = NULL; - gboolean res; - - res = nm_utils_is_json_object(conf, &error); - g_assert_cmpint(res, ==, expected); - g_assert(res || error); -} - -static void -test_nm_utils_check_valid_json(void) -{ - _json_config_check_valid(NULL, FALSE); - _json_config_check_valid("", FALSE); - - /* Without JSON library everything except empty string is considered valid */ - nmtst_json_vt_reset(FALSE); - _json_config_check_valid("{ }", TRUE); - _json_config_check_valid("{'%!-a1} ", TRUE); - _json_config_check_valid(" {'%!-a1}", TRUE); - _json_config_check_valid("{'%!-a1", FALSE); - - if (nmtst_json_vt_reset(TRUE)) { - _json_config_check_valid("{ }", TRUE); - _json_config_check_valid("{ \"a\" : 1 }", TRUE); - _json_config_check_valid("{ \"a\" : }", FALSE); - } -} - -static void -_team_config_equal_check(const char *conf1, - const char *conf2, - gboolean port_config, - gboolean expected) -{ - nm_auto_free_team_setting NMTeamSetting *team_a = NULL; - nm_auto_free_team_setting NMTeamSetting *team_b = NULL; - gboolean is_same; - - if (nmtst_get_rand_bool()) - NM_SWAP(&conf1, &conf2); - - if (!nm_streq0(conf1, conf2)) { - _team_config_equal_check(conf1, conf1, port_config, TRUE); - _team_config_equal_check(conf2, conf2, port_config, TRUE); - } - - team_a = nm_team_setting_new(port_config, conf1); - team_b = nm_team_setting_new(port_config, conf2); - - is_same = (nm_team_setting_cmp(team_a, team_b, TRUE) == 0); - g_assert_cmpint(is_same, ==, expected); - - if (nm_streq0(conf1, conf2)) { - g_assert_cmpint(nm_team_setting_cmp(team_a, team_b, FALSE), ==, 0); - g_assert(expected); - } else - g_assert_cmpint(nm_team_setting_cmp(team_a, team_b, FALSE), !=, 0); -} - -static void -test_nm_utils_team_config_equal(void) -{ - int with_json_vt; - - for (with_json_vt = 0; with_json_vt < 2; with_json_vt++) { - const NMJsonVt *vt; - - vt = nmtst_json_vt_reset(!!with_json_vt); - - _team_config_equal_check("", "", TRUE, TRUE); - _team_config_equal_check("", " ", TRUE, TRUE); - _team_config_equal_check("{}", "{ }", TRUE, TRUE); - _team_config_equal_check("{}", "{", TRUE, TRUE); - _team_config_equal_check("{ \"a\": 1 }", "{ \"a\": 1 }", TRUE, TRUE); - _team_config_equal_check("{ \"a\": 1 }", "{ \"a\": 1 }", TRUE, TRUE); - - /* team config */ - _team_config_equal_check("{ }", "{ \"runner\" : { \"name\" : \"random\"} }", FALSE, !vt); - _team_config_equal_check("{ \"runner\" : { \"name\" : \"roundrobin\"} }", - "{ \"runner\" : { \"name\" : \"random\"} }", - FALSE, - !vt); - _team_config_equal_check("{ \"runner\" : { \"name\" : \"random\"} }", - "{ \"runner\" : { \"name\" : \"random\"} }", - FALSE, - TRUE); - _team_config_equal_check("{ \"runner\" : { \"name\" : \"loadbalance\"} }", - "{ \"runner\" : { \"name\" : \"loadbalance\"} }", - FALSE, - TRUE); - _team_config_equal_check( - "{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth0\" : {} } }", - "{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth1\" : {} } }", - FALSE, - TRUE); - _team_config_equal_check("{ \"runner\" : { \"name\" : \"lacp\"} }", - "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\", " - "\"ipv4\", \"ipv6\" ] } }", - FALSE, - !vt); - _team_config_equal_check("{ \"runner\" : { \"name\" : \"roundrobin\"} }", - "{ \"runner\" : { \"name\" : \"roundrobin\", \"tx_hash\" : [ " - "\"eth\", \"ipv4\", \"ipv6\" ] } }", - FALSE, - !vt); - _team_config_equal_check( - "{ \"runner\" : { \"name\" : \"lacp\"} }", - "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\" ] } }", - FALSE, - !vt); - - /* team port config */ - _team_config_equal_check("{ }", - "{ \"link_watch\" : { \"name\" : \"ethtool\"} }", - TRUE, - !vt); - _team_config_equal_check("{ }", - "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", - TRUE, - TRUE); - _team_config_equal_check("{ \"link_watch\" : { \"name\" : \"ethtool\"} }", - "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", - TRUE, - !vt); - _team_config_equal_check("{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", - "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", - TRUE, - TRUE); - _team_config_equal_check( - "{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth0\" : {} } }", - "{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth1\" : {} } }", - TRUE, - TRUE); - } - - nmtst_json_vt_reset(TRUE); -} - -/*****************************************************************************/ - -enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED { - _DUMMY_1 = -1, -}; - -enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED { - _DUMMY_2, -}; - -enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64 { - _DUMMY_3 = (1LL << 40), -}; - -enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64 { - _DUMMY_4a = -1, - _DUMMY_4b = (1LL << 40), -}; - -#define test_nm_utils_is_power_of_two_do(type, x, expect) \ - G_STMT_START \ - { \ - typeof(x) x1 = (x); \ - type x2 = (type) x1; \ - gboolean val; \ - \ - val = nm_utils_is_power_of_two(x1); \ - g_assert_cmpint(expect, ==, val); \ - if (x1 != 0) \ - g_assert_cmpint(val, ==, nm_utils_is_power_of_two_or_zero(x1)); \ - else { \ - g_assert(nm_utils_is_power_of_two_or_zero(x1)); \ - g_assert(!val); \ - } \ - if (((typeof(x1)) x2) == x1 && ((typeof(x2)) x1) == x2 && x2 > 0) { \ - /* x2 equals @x, and is positive. Compare to @expect */ \ - g_assert_cmpint(expect, ==, nm_utils_is_power_of_two(x2)); \ - } else if (!(x2 > 0)) { \ - /* a non positive value is always FALSE. */ \ - g_assert_cmpint(FALSE, ==, nm_utils_is_power_of_two(x2)); \ - } \ - if (x2) { \ - x2 = -x2; \ - if (!(x2 > 0)) { \ - /* for negative values, we return FALSE. */ \ - g_assert_cmpint(FALSE, ==, nm_utils_is_power_of_two(x2)); \ - } \ - } \ - } \ - G_STMT_END - -static void -test_nm_utils_is_power_of_two(void) -{ - guint64 xyes, xno; - int i, j; - GRand * rand = nmtst_get_rand(); - int numbits; - - g_assert(!nm_utils_is_power_of_two(0)); - g_assert(nm_utils_is_power_of_two_or_zero(0)); - - for (i = -1; i < 64; i++) { - /* find a (positive) x which is a power of two. */ - if (i == -1) - xyes = 0; - else { - xyes = (((guint64) 1) << i); - g_assert(xyes != 0); - } - - xno = xyes; - if (xyes != 0) { -again: - /* Find another @xno, that is not a power of two. Do that, - * by randomly setting bits. */ - numbits = g_rand_int_range(rand, 1, 65); - while (xno != ~((guint64) 0) && numbits > 0) { - guint64 v = (((guint64) 1) << g_rand_int_range(rand, 0, 64)); - - if ((xno | v) != xno) { - xno |= v; - --numbits; - } - } - if (xno == xyes) - goto again; - } - - for (j = 0; j < 2; j++) { - gboolean expect = j == 0; - guint64 x = expect ? xyes : xno; - - if (expect && xyes == 0) - continue; - - /* check if @x is as @expect, when casted to a certain data type. */ - test_nm_utils_is_power_of_two_do(gint8, x, expect); - test_nm_utils_is_power_of_two_do(guint8, x, expect); - test_nm_utils_is_power_of_two_do(gint16, x, expect); - test_nm_utils_is_power_of_two_do(guint16, x, expect); - test_nm_utils_is_power_of_two_do(gint32, x, expect); - test_nm_utils_is_power_of_two_do(guint32, x, expect); - test_nm_utils_is_power_of_two_do(gint64, x, expect); - test_nm_utils_is_power_of_two_do(guint64, x, expect); - test_nm_utils_is_power_of_two_do(char, x, expect); - test_nm_utils_is_power_of_two_do(unsigned char, x, expect); - test_nm_utils_is_power_of_two_do(signed char, x, expect); - test_nm_utils_is_power_of_two_do(enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED, x, expect); - test_nm_utils_is_power_of_two_do(enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED, x, expect); - test_nm_utils_is_power_of_two_do(enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64, x, expect); - test_nm_utils_is_power_of_two_do(enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64, x, expect); - } - } -} - -/*****************************************************************************/ - -static int -_test_find_binary_search_cmp(gconstpointer a, gconstpointer b, gpointer dummy) -{ - int ia, ib; - - ia = GPOINTER_TO_INT(a); - ib = GPOINTER_TO_INT(b); - - if (ia == ib) - return 0; - if (ia < ib) - return -1; - return 1; -} - -static void -_test_find_binary_search_do(const int *array, gsize len) -{ - gsize i; - gssize idx, idx_first, idx_last; - gs_free gconstpointer *parray = g_new(gconstpointer, len); - const int NEEDLE = 0; - gconstpointer pneedle = GINT_TO_POINTER(NEEDLE); - gssize expected_result; - - for (i = 0; i < len; i++) - parray[i] = GINT_TO_POINTER(array[i]); - - expected_result = _nm_utils_ptrarray_find_first(parray, len, pneedle); - - idx = nm_utils_ptrarray_find_binary_search(parray, - len, - pneedle, - _test_find_binary_search_cmp, - NULL, - &idx_first, - &idx_last); - if (expected_result >= 0) { - g_assert_cmpint(expected_result, ==, idx); - } else { - gssize idx2 = ~idx; - g_assert_cmpint(idx, <, 0); - - g_assert(idx2 >= 0); - g_assert(idx2 <= len); - g_assert(idx2 - 1 < 0 || _test_find_binary_search_cmp(parray[idx2 - 1], pneedle, NULL) < 0); - g_assert(idx2 >= len || _test_find_binary_search_cmp(parray[idx2], pneedle, NULL) > 0); - } - g_assert_cmpint(idx, ==, idx_first); - g_assert_cmpint(idx, ==, idx_last); - for (i = 0; i < len; i++) { - int cmp; - - cmp = _test_find_binary_search_cmp(parray[i], pneedle, NULL); - if (cmp == 0) { - g_assert(pneedle == parray[i]); - g_assert(idx >= 0); - g_assert(i == idx); - } else { - g_assert(pneedle != parray[i]); - if (cmp < 0) { - if (idx < 0) - g_assert(i < ~idx); - else - g_assert(i < idx); - } else { - if (idx < 0) - g_assert(i >= ~idx); - else - g_assert(i >= idx); - } - } - } -} - -static void -_test_find_binary_search_do_uint32(const int *int_array, gsize len) -{ - gssize idx; - const int OFFSET = 100; - const int NEEDLE = 0 + OFFSET; - gssize expected_result = -1; - guint32 array[30]; - - g_assert(len <= G_N_ELEMENTS(array)); - - /* the test data has negative values. Shift them... */ - for (idx = 0; idx < len; idx++) { - int v = int_array[idx]; - - g_assert(v > -OFFSET); - g_assert(v < OFFSET); - g_assert(idx == 0 || v > int_array[idx - 1]); - array[idx] = (guint32)(int_array[idx] + OFFSET); - if (array[idx] == NEEDLE) - expected_result = idx; - } - - idx = nm_utils_array_find_binary_search(array, - sizeof(guint32), - len, - &NEEDLE, - nm_cmp_uint32_p_with_data, - NULL); - if (expected_result >= 0) - g_assert_cmpint(expected_result, ==, idx); - else { - gssize idx2 = ~idx; - g_assert_cmpint(idx, <, 0); - - g_assert(idx2 >= 0); - g_assert(idx2 <= len); - g_assert(idx2 - 1 < 0 || array[idx2 - 1] < NEEDLE); - g_assert(idx2 >= len || array[idx2] > NEEDLE); - } -} -#define test_find_binary_search_do(...) \ - G_STMT_START \ - { \ - const int _array[] = {__VA_ARGS__}; \ - _test_find_binary_search_do(_array, G_N_ELEMENTS(_array)); \ - _test_find_binary_search_do_uint32(_array, G_N_ELEMENTS(_array)); \ - } \ - G_STMT_END - -static void -test_nm_utils_ptrarray_find_binary_search(void) -{ - test_find_binary_search_do(0); - test_find_binary_search_do(-1, 0); - test_find_binary_search_do(-2, -1, 0); - test_find_binary_search_do(-3, -2, -1, 0); - test_find_binary_search_do(0, 1); - test_find_binary_search_do(0, 1, 2); - test_find_binary_search_do(-1, 0, 1, 2); - test_find_binary_search_do(-2, -1, 0, 1, 2); - test_find_binary_search_do(-3, -2, -1, 0, 1, 2); - test_find_binary_search_do(-3, -2, -1, 0, 1, 2); - test_find_binary_search_do(-3, -2, -1, 0, 1, 2, 3); - test_find_binary_search_do(-3, -2, -1, 0, 1, 2, 3, 4); - - test_find_binary_search_do(-1); - test_find_binary_search_do(-2, -1); - test_find_binary_search_do(-3, -2, -1); - test_find_binary_search_do(1); - test_find_binary_search_do(1, 2); - test_find_binary_search_do(-1, 1, 2); - test_find_binary_search_do(-2, -1, 1, 2); - test_find_binary_search_do(-3, -2, -1, 1, 2); - test_find_binary_search_do(-3, -2, -1, 1, 2); - test_find_binary_search_do(-3, -2, -1, 1, 2, 3); - test_find_binary_search_do(-3, -2, -1, 1, 2, 3, 4); -} - -/*****************************************************************************/ - -#define BIN_SEARCH_W_DUPS_LEN 100 -#define BIN_SEARCH_W_DUPS_JITTER 10 - -static int -_test_bin_search2_cmp(gconstpointer pa, gconstpointer pb, gpointer user_data) -{ - int a = GPOINTER_TO_INT(pa); - int b = GPOINTER_TO_INT(pb); - - g_assert(a >= 0 && a <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER); - g_assert(b >= 0 && b <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER); - NM_CMP_DIRECT(a, b); - return 0; -} - -static int -_test_bin_search2_cmp_p(gconstpointer pa, gconstpointer pb, gpointer user_data) -{ - return _test_bin_search2_cmp(*((gpointer *) pa), *((gpointer *) pb), NULL); -} - -static void -test_nm_utils_ptrarray_find_binary_search_with_duplicates(void) -{ - gssize idx, idx2, idx_first2, idx_first, idx_last; - int i_test, i_len, i; - gssize j; - gconstpointer arr[BIN_SEARCH_W_DUPS_LEN]; - const int N_TEST = 10; - - for (i_test = 0; i_test < N_TEST; i_test++) { - for (i_len = 0; i_len < BIN_SEARCH_W_DUPS_LEN; i_len++) { - /* fill with random numbers... surely there are some duplicates - * there... or maybe even there are none... */ - for (i = 0; i < i_len; i++) - arr[i] = - GINT_TO_POINTER(nmtst_get_rand_uint32() % (i_len + BIN_SEARCH_W_DUPS_JITTER)); - g_qsort_with_data(arr, i_len, sizeof(gpointer), _test_bin_search2_cmp_p, NULL); - for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) { - gconstpointer p = GINT_TO_POINTER(i); - - idx = nm_utils_ptrarray_find_binary_search(arr, - i_len, - p, - _test_bin_search2_cmp, - NULL, - &idx_first, - &idx_last); - - idx_first2 = _nm_utils_ptrarray_find_first(arr, i_len, p); - - idx2 = nm_utils_array_find_binary_search(arr, - sizeof(gpointer), - i_len, - &p, - _test_bin_search2_cmp_p, - NULL); - g_assert_cmpint(idx, ==, idx2); - - if (idx_first2 < 0) { - g_assert_cmpint(idx, <, 0); - g_assert_cmpint(idx, ==, idx_first); - g_assert_cmpint(idx, ==, idx_last); - idx = ~idx; - g_assert_cmpint(idx, >=, 0); - g_assert_cmpint(idx, <=, i_len); - if (i_len == 0) - g_assert_cmpint(idx, ==, 0); - else { - g_assert(idx == i_len || GPOINTER_TO_INT(arr[idx]) > i); - g_assert(idx == 0 || GPOINTER_TO_INT(arr[idx - 1]) < i); - } - } else { - g_assert_cmpint(idx_first, ==, idx_first2); - g_assert_cmpint(idx_first, >=, 0); - g_assert_cmpint(idx_last, <, i_len); - g_assert_cmpint(idx_first, <=, idx_last); - g_assert_cmpint(idx, >=, idx_first); - g_assert_cmpint(idx, <=, idx_last); - for (j = idx_first; j < idx_last; j++) - g_assert(GPOINTER_TO_INT(arr[j]) == i); - g_assert(idx_first == 0 || GPOINTER_TO_INT(arr[idx_first - 1]) < i); - g_assert(idx_last == i_len - 1 || GPOINTER_TO_INT(arr[idx_last + 1]) > i); - } - } - } - } -} - -/*****************************************************************************/ - -static void -_test_nm_utils_enum_to_str_do_full(GType type, - int flags, - const char * exp_str, - const NMUtilsEnumValueInfo *value_infos) -{ - gs_free char *str = NULL; - int flags2; - gs_free char *err_token = NULL; - gboolean result; - - g_assert(exp_str); - - str = _nm_utils_enum_to_str_full(type, flags, ", ", value_infos); - g_assert_cmpstr(str, ==, exp_str); - - if (!value_infos) { - gs_free char *str2 = NULL; - - str2 = nm_utils_enum_to_str(type, flags); - g_assert_cmpstr(str2, ==, exp_str); - } - - result = _nm_utils_enum_from_str_full(type, str, &flags2, &err_token, value_infos); - g_assert(result == TRUE); - g_assert_cmpint(flags2, ==, flags); - g_assert_cmpstr(err_token, ==, NULL); -} - -#define _test_nm_utils_enum_to_str_do(...) _test_nm_utils_enum_to_str_do_full(__VA_ARGS__, NULL) - -static void -_test_nm_utils_enum_from_str_do_full(GType type, - const char * str, - gboolean exp_result, - int exp_flags, - const char * exp_err_token, - const NMUtilsEnumValueInfo *value_infos) -{ - int flags; - gs_free char *err_token = NULL; - gboolean result; - - result = _nm_utils_enum_from_str_full(type, str, &flags, &err_token, value_infos); - - g_assert(result == exp_result); - g_assert_cmpint(flags, ==, exp_flags); - g_assert_cmpstr(err_token, ==, exp_err_token); - - if (!value_infos) { - int flags2; - gs_free char *err_token2 = NULL; - gboolean result2; - - result2 = nm_utils_enum_from_str(type, str, &flags2, &err_token2); - g_assert(result2 == exp_result); - g_assert_cmpint(flags2, ==, exp_flags); - g_assert_cmpstr(err_token2, ==, exp_err_token); - } - - if (result) { - int flags2; - gs_free char *str2 = NULL; - gs_free char *err_token2 = NULL; - - str2 = _nm_utils_enum_to_str_full(type, flags, ", ", value_infos); - g_assert(str2); - - result = _nm_utils_enum_from_str_full(type, str2, &flags2, &err_token2, value_infos); - g_assert(result == TRUE); - g_assert_cmpint(flags2, ==, flags); - g_assert_cmpstr(err_token, ==, NULL); - } -} - -#define _test_nm_utils_enum_from_str_do(...) _test_nm_utils_enum_from_str_do_full(__VA_ARGS__, NULL) - -static void -_test_nm_utils_enum_get_values_do(GType type, int from, int to, const char *exp_str) -{ - gs_free const char **strv = NULL; - gs_free char * str = NULL; - - g_assert(exp_str); - - strv = nm_utils_enum_get_values(type, from, to); - g_assert(strv); - str = g_strjoinv(",", (char **) strv); - g_assert_cmpstr(str, ==, exp_str); -} - -static void -test_nm_utils_enum(void) -{ - GType bool_enum = nm_test_general_bool_enum_get_type(); - GType meta_flags = nm_test_general_meta_flags_get_type(); - GType color_flags = nm_test_general_color_flags_get_type(); - static const NMUtilsEnumValueInfo color_value_infos[] = { - { - .nick = "nick-4d", - .value = 0x4D, - }, - { - .nick = "nick-5", - .value = 5, - }, - { - .nick = "nick-red", - .value = NM_TEST_GENERAL_COLOR_FLAGS_RED, - }, - {0}, - }; - - _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes"); - _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown"); - _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, "4"); - _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_67, "67"); - _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_46, "64"); - - _test_nm_utils_enum_to_str_do(meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "none"); - _test_nm_utils_enum_to_str_do(meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz"); - _test_nm_utils_enum_to_str_do(meta_flags, - NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAR - | NM_TEST_GENERAL_META_FLAGS_BAZ, - "foo, bar, baz"); - _test_nm_utils_enum_to_str_do(meta_flags, 0xFF, "foo, bar, baz, 0xf8"); - _test_nm_utils_enum_to_str_do(meta_flags, NM_TEST_GENERAL_META_FLAGS_0x8, "0x8"); - _test_nm_utils_enum_to_str_do(meta_flags, NM_TEST_GENERAL_META_FLAGS_0x4, "0x10"); - - _test_nm_utils_enum_to_str_do(color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red"); - _test_nm_utils_enum_to_str_do(color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "0x1"); - _test_nm_utils_enum_to_str_do(color_flags, - NM_TEST_GENERAL_COLOR_FLAGS_RED - | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, - "red, green"); - - _test_nm_utils_enum_to_str_do_full(color_flags, - NM_TEST_GENERAL_COLOR_FLAGS_RED - | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, - "nick-red, green", - color_value_infos); - - _test_nm_utils_enum_to_str_do_full(color_flags, - 0x4D | NM_TEST_GENERAL_COLOR_FLAGS_RED - | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, - "nick-4d", - color_value_infos); - - _test_nm_utils_enum_to_str_do_full(color_flags, - 5 | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, - "nick-5, green", - color_value_infos); - - _test_nm_utils_enum_from_str_do(bool_enum, "", FALSE, 0, NULL); - _test_nm_utils_enum_from_str_do(bool_enum, " ", FALSE, 0, NULL); - _test_nm_utils_enum_from_str_do(bool_enum, "invalid", FALSE, 0, "invalid"); - _test_nm_utils_enum_from_str_do(bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL); - _test_nm_utils_enum_from_str_do(bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL); - _test_nm_utils_enum_from_str_do(bool_enum, "yes,no", FALSE, 0, "yes,no"); - - _test_nm_utils_enum_from_str_do(meta_flags, "", TRUE, 0, NULL); - _test_nm_utils_enum_from_str_do(meta_flags, " ", TRUE, 0, NULL); - _test_nm_utils_enum_from_str_do(meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL); - _test_nm_utils_enum_from_str_do(meta_flags, - "foo,baz", - TRUE, - NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAZ, - NULL); - _test_nm_utils_enum_from_str_do(meta_flags, - "foo, baz", - TRUE, - NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAZ, - NULL); - _test_nm_utils_enum_from_str_do(meta_flags, - "foo,,bar", - TRUE, - NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAR, - NULL); - _test_nm_utils_enum_from_str_do(meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux"); - _test_nm_utils_enum_from_str_do(meta_flags, - "foo,0x6", - TRUE, - NM_TEST_GENERAL_META_FLAGS_FOO | 0x6, - NULL); - _test_nm_utils_enum_from_str_do(meta_flags, "0x30,0x08,foo", TRUE, 0x39, NULL); - - _test_nm_utils_enum_from_str_do(color_flags, - "green", - TRUE, - NM_TEST_GENERAL_COLOR_FLAGS_GREEN, - NULL); - _test_nm_utils_enum_from_str_do(color_flags, - "blue,red", - TRUE, - NM_TEST_GENERAL_COLOR_FLAGS_BLUE - | NM_TEST_GENERAL_COLOR_FLAGS_RED, - NULL); - _test_nm_utils_enum_from_str_do(color_flags, "blue,white", FALSE, 0, "white"); - - _test_nm_utils_enum_from_str_do_full(color_flags, - "nick-red", - TRUE, - NM_TEST_GENERAL_COLOR_FLAGS_RED, - NULL, - color_value_infos); - - _test_nm_utils_enum_from_str_do_full(color_flags, "0x4D", TRUE, 0x4D, NULL, color_value_infos); - - _test_nm_utils_enum_from_str_do_full(color_flags, - "green,nick-4d", - TRUE, - 0x4D | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, - NULL, - color_value_infos); - - _test_nm_utils_enum_from_str_do_full(color_flags, - "nick-4d,nick-red,nick-5,green,nick-red", - TRUE, - 0x4D | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, - NULL, - color_value_infos); - - _test_nm_utils_enum_from_str_do_full(NM_TYPE_SETTING_CONNECTION_LLMNR, - "-1", - TRUE, - -1, - NULL, - NULL); - - _test_nm_utils_enum_from_str_do_full(NM_TYPE_SETTING_CONNECTION_LLMNR, - "-0x1", - TRUE, - -1, - NULL, - NULL); - - _test_nm_utils_enum_get_values_do(bool_enum, 0, G_MAXINT, "no,yes,maybe,unknown,67,64"); - _test_nm_utils_enum_get_values_do(bool_enum, - NM_TEST_GENERAL_BOOL_ENUM_YES, - NM_TEST_GENERAL_BOOL_ENUM_MAYBE, - "yes,maybe"); - _test_nm_utils_enum_get_values_do(meta_flags, 0, G_MAXINT, "none,foo,bar,baz,0x8,0x10"); - _test_nm_utils_enum_get_values_do(color_flags, 0, G_MAXINT, "blue,red,green"); -} - -/*****************************************************************************/ - -static void -_do_test_utils_str_utf8safe_unescape(const char *str, const char *expected, gsize expected_len) -{ - gsize l; - const char * s; - gs_free gpointer buf_free_1 = NULL; - gs_free char * str_free_1 = NULL; - - s = nm_utils_buf_utf8safe_unescape(str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &l, &buf_free_1); - g_assert_cmpint(expected_len, ==, l); - g_assert_cmpstr(s, ==, expected); - - if (str == NULL) { - g_assert(!s); - g_assert(!buf_free_1); - g_assert_cmpint(l, ==, 0); - } else { - g_assert(s); - if (!strchr(str, '\\')) { - g_assert(!buf_free_1); - g_assert(s == str); - g_assert_cmpint(l, ==, strlen(str)); - } else { - g_assert(buf_free_1); - g_assert(s == buf_free_1); - g_assert(memcmp(s, expected, expected_len) == 0); - } - } - - if (expected && l == strlen(expected)) { - /* there are no embedded NULs. Check that nm_utils_str_utf8safe_unescape() yields the same result. */ - s = nm_utils_str_utf8safe_unescape(str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_1); - g_assert_cmpstr(s, ==, expected); - if (strchr(str, '\\')) { - g_assert(str_free_1 != str); - g_assert(s == str_free_1); - } else - g_assert(s == str); - } -} - -#define do_test_utils_str_utf8safe_unescape(str, expected) \ - _do_test_utils_str_utf8safe_unescape("" str "", expected, NM_STRLEN(expected)) - -static void -_do_test_utils_str_utf8safe(const char * str, - gsize str_len, - const char * expected, - NMUtilsStrUtf8SafeFlags flags) -{ - const char * str_safe; - const char * buf_safe; - const char * s; - gs_free char *str_free_1 = NULL; - gs_free char *str_free_2 = NULL; - gs_free char *str_free_3 = NULL; - gs_free char *str_free_4 = NULL; - gs_free char *str_free_5 = NULL; - gs_free char *str_free_6 = NULL; - gs_free char *str_free_7 = NULL; - gs_free char *str_free_8 = NULL; - gboolean str_has_nul = FALSE; -#define RND_FLAG \ - ((nmtst_get_rand_bool()) ? NM_UTILS_STR_UTF8_SAFE_FLAG_NONE \ - : NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET) - - buf_safe = nm_utils_buf_utf8safe_escape(str, str_len, flags | RND_FLAG, &str_free_1); - - str_safe = nm_utils_str_utf8safe_escape(str, flags | RND_FLAG, &str_free_2); - - if (str_len == 0) { - g_assert(buf_safe == NULL); - g_assert(str_free_1 == NULL); - g_assert(str_safe == str); - g_assert(str == NULL || str[0] == '\0'); - g_assert(str_free_2 == NULL); - } else if (str_len == strlen(str)) { - g_assert(buf_safe); - g_assert_cmpstr(buf_safe, ==, str_safe); - - /* nm_utils_buf_utf8safe_escape() can only return a pointer equal to the input string, - * if and only if str_len is negative. Otherwise, the input str won't be NUL terminated - * and cannot be returned. */ - g_assert(buf_safe != str); - g_assert(buf_safe == str_free_1); - } else - str_has_nul = TRUE; - - str_free_3 = nm_utils_str_utf8safe_escape_cp(str, flags | RND_FLAG); - g_assert_cmpstr(str_free_3, ==, str_safe); - g_assert((!str && !str_free_3) || (str != str_free_3)); - - if (str_len > 0) - _do_test_utils_str_utf8safe_unescape(buf_safe, str, str_len); - - if (expected == NULL) { - g_assert(!str_has_nul); - - g_assert(str_safe == str); - g_assert(!str_free_2); - if (str) { - g_assert(!strchr(str, '\\')); - g_assert(g_utf8_validate(str, -1, NULL)); - } - - g_assert(str - == nm_utils_str_utf8safe_unescape(str_safe, - NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, - &str_free_4)); - g_assert(!str_free_4); - - str_free_5 = nm_utils_str_utf8safe_unescape_cp(str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - if (str) { - g_assert(str_free_5 != str); - g_assert_cmpstr(str_free_5, ==, str); - } else - g_assert(!str_free_5); - return; - } - - if (!str_has_nul) { - g_assert(str); - g_assert(str_safe != str); - g_assert(str_safe == str_free_2); - g_assert(strchr(str, '\\') || !g_utf8_validate(str, -1, NULL) - || (NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) - && NM_STRCHAR_ANY(str, ch, (guchar) ch >= 127)) - || (NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) - && NM_STRCHAR_ANY(str, ch, (guchar) ch < ' '))); - g_assert(g_utf8_validate(str_safe, -1, NULL)); - - str_free_6 = g_strcompress(str_safe); - g_assert_cmpstr(str, ==, str_free_6); - - str_free_7 = nm_utils_str_utf8safe_unescape_cp(str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - g_assert(str_free_7 != str); - g_assert_cmpstr(str_free_7, ==, str); - - s = nm_utils_str_utf8safe_unescape(str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_8); - g_assert(str_free_8 != str); - g_assert(s == str_free_8); - g_assert_cmpstr(str_free_8, ==, str); - - g_assert_cmpstr(str_safe, ==, expected); - - return; - } - - g_assert_cmpstr(buf_safe, ==, expected); -} -#define do_test_utils_str_utf8safe(str, expected, flags) \ - _do_test_utils_str_utf8safe("" str "", NM_STRLEN(str), expected, flags) - -static void -test_utils_str_utf8safe(void) -{ - _do_test_utils_str_utf8safe(NULL, 0, NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - - do_test_utils_str_utf8safe("", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\\", "\\\\", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\\a", "\\\\a", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\314", "\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\314\315x\315\315x", - "\\314\\315x\\315\\315x", - NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\314\315xx", "\\314\\315xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\314xx", "\\314xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\xa0", "\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\xe2\x91\xa0", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\xe2\xe2\x91\xa0", - "\\342\xe2\x91\xa0", - NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\xe2\xe2\x91\xa0\xa0", - "\\342\xe2\x91\xa0\\240", - NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("a", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("ab", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("ab\314", "ab\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("ab\314adsf", "ab\\314adsf", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("abadsf", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("abäb", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("x\xa0", "x\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("Ä\304ab\\äb", "Ä\\304ab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("Äab\\äb", "Äab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("ÄÄab\\äb", "ÄÄab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("㈞abä㈞b", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("abäb", - "ab\\303\\244b", - NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII); - do_test_utils_str_utf8safe("ab\ab", "ab\\007b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL); - - do_test_utils_str_utf8safe("\0", "\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\0a\0", "\\000a\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\\\0", "\\\\\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\n\0", "\n\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); - do_test_utils_str_utf8safe("\n\0", "\\012\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL); - - do_test_utils_str_utf8safe_unescape("\n\\0", "\n\0"); - do_test_utils_str_utf8safe_unescape("\n\\01", "\n\01"); - do_test_utils_str_utf8safe_unescape("\n\\012", "\n\012"); - do_test_utils_str_utf8safe_unescape("\n\\.", "\n."); - do_test_utils_str_utf8safe_unescape("\\n\\.3\\r", "\n.3\r"); -} - -/*****************************************************************************/ - -static int -_test_nm_in_set_get(int *call_counter, gboolean allow_called, int value) -{ - g_assert(call_counter); - *call_counter += 1; - if (!allow_called) - g_assert_not_reached(); - return value; -} - -static void -_test_nm_in_set_assert(int *call_counter, int expected) -{ - g_assert(call_counter); - g_assert_cmpint(expected, ==, *call_counter); - *call_counter = 0; -} - -static void -test_nm_in_set(void) -{ - int call_counter = 0; - -#define G(x) _test_nm_in_set_get(&call_counter, TRUE, x) -#define N(x) _test_nm_in_set_get(&call_counter, FALSE, x) -#define _ASSERT(expected, expr) \ - G_STMT_START \ - { \ - _test_nm_in_set_assert(&call_counter, 0); \ - g_assert(expr); \ - _test_nm_in_set_assert(&call_counter, (expected)); \ - } \ - G_STMT_END - _ASSERT(1, !NM_IN_SET(-1, G(1))); - _ASSERT(1, NM_IN_SET(-1, G(-1))); - - _ASSERT(2, !NM_IN_SET(-1, G(1), G(2))); - _ASSERT(1, NM_IN_SET(-1, G(-1), N(2))); - _ASSERT(2, NM_IN_SET(-1, G(1), G(-1))); - _ASSERT(1, NM_IN_SET(-1, G(-1), N(-1))); - - _ASSERT(3, !NM_IN_SET(-1, G(1), G(2), G(3))); - _ASSERT(1, NM_IN_SET(-1, G(-1), N(2), N(3))); - _ASSERT(2, NM_IN_SET(-1, G(1), G(-1), N(3))); - _ASSERT(3, NM_IN_SET(-1, G(1), G(2), G(-1))); - _ASSERT(2, NM_IN_SET(-1, G(1), G(-1), N(-1))); - _ASSERT(1, NM_IN_SET(-1, G(-1), N(2), N(-1))); - _ASSERT(1, NM_IN_SET(-1, G(-1), N(-1), N(3))); - _ASSERT(1, NM_IN_SET(-1, G(-1), N(-1), N(-1))); - - _ASSERT(4, !NM_IN_SET(-1, G(1), G(2), G(3), G(4))); - _ASSERT(1, NM_IN_SET(-1, G(-1), N(2), N(3), N(4))); - _ASSERT(2, NM_IN_SET(-1, G(1), G(-1), N(3), N(4))); - _ASSERT(3, NM_IN_SET(-1, G(1), G(2), G(-1), N(4))); - _ASSERT(4, NM_IN_SET(-1, G(1), G(2), G(3), G(-1))); - - _ASSERT(4, NM_IN_SET(-1, G(1), G(2), G(3), G(-1), G(5))); - _ASSERT(5, NM_IN_SET(-1, G(1), G(2), G(3), G(4), G(-1))); - _ASSERT(6, NM_IN_SET(-1, G(1), G(2), G(3), G(4), G(5), G(-1))); - - _ASSERT(1, !NM_IN_SET_SE(-1, G(1))); - _ASSERT(1, NM_IN_SET_SE(-1, G(-1))); - - _ASSERT(2, !NM_IN_SET_SE(-1, G(1), G(2))); - _ASSERT(2, NM_IN_SET_SE(-1, G(-1), G(2))); - _ASSERT(2, NM_IN_SET_SE(-1, G(1), G(-1))); - _ASSERT(2, NM_IN_SET_SE(-1, G(-1), G(-1))); - - _ASSERT(3, !NM_IN_SET_SE(-1, G(1), G(2), G(3))); - _ASSERT(3, NM_IN_SET_SE(-1, G(-1), G(2), G(3))); - _ASSERT(3, NM_IN_SET_SE(-1, G(1), G(-1), G(3))); - _ASSERT(3, NM_IN_SET_SE(-1, G(1), G(2), G(-1))); - _ASSERT(3, NM_IN_SET_SE(-1, G(1), G(-1), G(-1))); - _ASSERT(3, NM_IN_SET_SE(-1, G(-1), G(2), G(-1))); - _ASSERT(3, NM_IN_SET_SE(-1, G(-1), G(-1), G(3))); - _ASSERT(3, NM_IN_SET_SE(-1, G(-1), G(-1), G(-1))); - - _ASSERT(4, !NM_IN_SET_SE(-1, G(1), G(2), G(3), G(4))); - _ASSERT(4, NM_IN_SET_SE(-1, G(-1), G(2), G(3), G(4))); - _ASSERT(4, NM_IN_SET_SE(-1, G(1), G(-1), G(3), G(4))); - _ASSERT(4, NM_IN_SET_SE(-1, G(1), G(2), G(-1), G(4))); - _ASSERT(4, NM_IN_SET_SE(-1, G(1), G(2), G(3), G(-1))); - - _ASSERT(5, NM_IN_SET_SE(-1, G(1), G(2), G(3), G(-1), G(5))); - _ASSERT(6, NM_IN_SET_SE(-1, G(1), G(2), G(3), G(4), G(5), G(-1))); - - g_assert(!NM_IN_SET(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)); -#undef G -#undef N -#undef _ASSERT -} - -/*****************************************************************************/ - -static const char * -_test_nm_in_set_getstr(int *call_counter, gboolean allow_called, const char *value) -{ - g_assert(call_counter); - *call_counter += 1; - if (!allow_called) - g_assert_not_reached(); - return value; -} - -static void -test_nm_in_strset(void) -{ - int call_counter = 0; - -#define G(x) _test_nm_in_set_getstr(&call_counter, TRUE, x) -#define N(x) _test_nm_in_set_getstr(&call_counter, FALSE, x) -#define _ASSERT(expected, expr) \ - G_STMT_START \ - { \ - _test_nm_in_set_assert(&call_counter, 0); \ - g_assert(expr); \ - _test_nm_in_set_assert(&call_counter, (expected)); \ - } \ - G_STMT_END - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL))); - _ASSERT(1, !NM_IN_STRSET("a", G(NULL))); - _ASSERT(1, !NM_IN_STRSET(NULL, G("a"))); - - _ASSERT(1, NM_IN_STRSET_SE(NULL, G(NULL))); - _ASSERT(1, !NM_IN_STRSET_SE("a", G(NULL))); - _ASSERT(1, !NM_IN_STRSET_SE(NULL, G("a"))); - - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N(NULL))); - _ASSERT(2, !NM_IN_STRSET("a", G(NULL), G(NULL))); - _ASSERT(2, NM_IN_STRSET(NULL, G("a"), G(NULL))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("a"))); - _ASSERT(2, NM_IN_STRSET("a", G(NULL), G("a"))); - _ASSERT(2, !NM_IN_STRSET(NULL, G("a"), G("a"))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("b"))); - _ASSERT(2, !NM_IN_STRSET("a", G(NULL), G("b"))); - _ASSERT(2, !NM_IN_STRSET(NULL, G("a"), G("b"))); - - _ASSERT(2, NM_IN_STRSET_SE(NULL, G(NULL), G(NULL))); - _ASSERT(2, !NM_IN_STRSET_SE("a", G(NULL), G(NULL))); - _ASSERT(2, NM_IN_STRSET_SE(NULL, G("a"), G(NULL))); - _ASSERT(2, NM_IN_STRSET_SE(NULL, G(NULL), G("a"))); - _ASSERT(2, NM_IN_STRSET_SE("a", G(NULL), G("a"))); - _ASSERT(2, !NM_IN_STRSET_SE(NULL, G("a"), G("a"))); - _ASSERT(2, NM_IN_STRSET_SE(NULL, G(NULL), G("b"))); - _ASSERT(2, !NM_IN_STRSET_SE("a", G(NULL), G("b"))); - _ASSERT(2, !NM_IN_STRSET_SE(NULL, G("a"), G("b"))); - - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N(NULL), N(NULL))); - _ASSERT(3, !NM_IN_STRSET("a", G(NULL), G(NULL), G(NULL))); - _ASSERT(2, NM_IN_STRSET(NULL, G("a"), G(NULL), N(NULL))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("a"), N(NULL))); - _ASSERT(2, NM_IN_STRSET("a", G(NULL), G("a"), N(NULL))); - _ASSERT(3, NM_IN_STRSET(NULL, G("a"), G("a"), G(NULL))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("b"), N(NULL))); - _ASSERT(3, !NM_IN_STRSET("a", G(NULL), G("b"), G(NULL))); - _ASSERT(3, NM_IN_STRSET(NULL, G("a"), G("b"), G(NULL))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N(NULL), N("a"))); - _ASSERT(3, NM_IN_STRSET("a", G(NULL), G(NULL), G("a"))); - _ASSERT(2, NM_IN_STRSET(NULL, G("a"), G(NULL), N("a"))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("a"), N("a"))); - _ASSERT(2, NM_IN_STRSET("a", G(NULL), G("a"), N("a"))); - _ASSERT(3, !NM_IN_STRSET(NULL, G("a"), G("a"), G("a"))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("b"), N("a"))); - _ASSERT(3, NM_IN_STRSET("a", G(NULL), G("b"), G("a"))); - _ASSERT(3, !NM_IN_STRSET(NULL, G("a"), G("b"), G("a"))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N(NULL), N("b"))); - _ASSERT(3, !NM_IN_STRSET("a", G(NULL), G(NULL), G("b"))); - _ASSERT(2, NM_IN_STRSET(NULL, G("a"), G(NULL), N("b"))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("a"), N("b"))); - _ASSERT(2, NM_IN_STRSET("a", G(NULL), G("a"), N("b"))); - _ASSERT(3, !NM_IN_STRSET(NULL, G("a"), G("a"), G("b"))); - _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("b"), N("b"))); - _ASSERT(3, !NM_IN_STRSET("a", G(NULL), G("b"), G("b"))); - _ASSERT(3, !NM_IN_STRSET(NULL, G("a"), G("b"), G("b"))); - - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G(NULL), G(NULL))); - _ASSERT(3, !NM_IN_STRSET_SE("a", G(NULL), G(NULL), G(NULL))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G(NULL), G(NULL))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("a"), G(NULL))); - _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G("a"), G(NULL))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G("a"), G(NULL))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("b"), G(NULL))); - _ASSERT(3, !NM_IN_STRSET_SE("a", G(NULL), G("b"), G(NULL))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G("b"), G(NULL))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G(NULL), G("a"))); - _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G(NULL), G("a"))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G(NULL), G("a"))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("a"), G("a"))); - _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G("a"), G("a"))); - _ASSERT(3, !NM_IN_STRSET_SE(NULL, G("a"), G("a"), G("a"))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("b"), G("a"))); - _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G("b"), G("a"))); - _ASSERT(3, !NM_IN_STRSET_SE(NULL, G("a"), G("b"), G("a"))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G(NULL), G("b"))); - _ASSERT(3, !NM_IN_STRSET_SE("a", G(NULL), G(NULL), G("b"))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G(NULL), G("b"))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("a"), G("b"))); - _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G("a"), G("b"))); - _ASSERT(3, !NM_IN_STRSET_SE(NULL, G("a"), G("a"), G("b"))); - _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("b"), G("b"))); - _ASSERT(3, !NM_IN_STRSET_SE("a", G(NULL), G("b"), G("b"))); - _ASSERT(3, !NM_IN_STRSET_SE(NULL, G("a"), G("b"), G("b"))); - - _ASSERT(3, NM_IN_STRSET("a", G(NULL), G("b"), G("a"), N("a"))); - _ASSERT(4, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("a"))); - _ASSERT(4, !NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"))); - - _ASSERT(4, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("a"), N("a"))); - _ASSERT(5, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("a"))); - _ASSERT(5, !NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("e"))); - - _ASSERT(5, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("a"), N("a"))); - _ASSERT(6, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("e"), G("a"))); - _ASSERT(6, !NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("e"), G("f"))); - - g_assert(!NM_IN_STRSET(NULL, - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", - "15", - "16")); - g_assert(!NM_IN_STRSET("_", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", - "15", - "16")); - g_assert(NM_IN_STRSET("10", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", - "15", - "16")); -#undef G -#undef N -#undef _ASSERT -} - -static void -test_route_attributes_parse(void) -{ - GHashTable *ht; - GError * error = NULL; - GVariant * variant; - - ht = nm_utils_parse_variant_attributes("mtu=1400 src=1.2.3.4 cwnd=14", - ' ', - '=', - FALSE, - nm_ip_route_get_variant_attribute_spec(), - &error); - g_assert_no_error(error); - g_assert(ht); - g_hash_table_unref(ht); - - ht = nm_utils_parse_variant_attributes("mtu=1400 src=1.2.3.4 cwnd=14 \\", - ' ', - '=', - FALSE, - nm_ip_route_get_variant_attribute_spec(), - &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED); - g_assert(!ht); - g_clear_error(&error); - - ht = nm_utils_parse_variant_attributes("mtu.1400 src.1\\.2\\.3\\.4 ", - ' ', - '.', - FALSE, - nm_ip_route_get_variant_attribute_spec(), - &error); - g_assert(ht); - g_assert_no_error(error); - variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_MTU); - g_assert(variant); - g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); - g_assert_cmpuint(g_variant_get_uint32(variant), ==, 1400); - - variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_SRC); - g_assert(variant); - g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr(g_variant_get_string(variant, NULL), ==, "1.2.3.4"); - g_hash_table_unref(ht); - - ht = nm_utils_parse_variant_attributes("from:fd01\\:\\:42\\/64/initrwnd:21", - '/', - ':', - FALSE, - nm_ip_route_get_variant_attribute_spec(), - &error); - g_assert(ht); - g_assert_no_error(error); - variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_INITRWND); - g_assert(variant); - g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); - g_assert_cmpuint(g_variant_get_uint32(variant), ==, 21); - - variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_FROM); - g_assert(variant); - g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr(g_variant_get_string(variant, NULL), ==, "fd01::42/64"); - g_hash_table_unref(ht); -} - -static void -test_route_attributes_format(void) -{ - gs_unref_hashtable GHashTable *ht = NULL; - char * str; - - ht = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref); - - str = nm_utils_format_variant_attributes(NULL, ' ', '='); - g_assert_cmpstr(str, ==, NULL); - - str = nm_utils_format_variant_attributes(ht, ' ', '='); - g_assert_cmpstr(str, ==, NULL); - - g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32(5000)); - g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_INITRWND, g_variant_new_uint32(20)); - g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, g_variant_new_boolean(TRUE)); - g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_SRC, g_variant_new_string("aaaa:bbbb::1")); - str = nm_utils_format_variant_attributes(ht, ' ', '='); - g_assert_cmpstr(str, ==, "initrwnd=20 lock-mtu=true mtu=5000 src=aaaa:bbbb::1"); - g_hash_table_remove_all(ht); - g_free(str); - - g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32(30000)); - g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_INITCWND, g_variant_new_uint32(21)); - g_hash_table_insert(ht, - NM_IP_ROUTE_ATTRIBUTE_FROM, - g_variant_new_string("aaaa:bbbb:cccc:dddd::/64")); - str = nm_utils_format_variant_attributes(ht, '/', ':'); - g_assert_cmpstr(str, ==, "from:aaaa\\:bbbb\\:cccc\\:dddd\\:\\:\\/64/initcwnd:21/window:30000"); - g_hash_table_remove_all(ht); - g_free(str); -} - -/*****************************************************************************/ - -static void -test_variant_attribute_spec(void) -{ - const NMVariantAttributeSpec *const *const specs_list[] = { - nm_ip_route_get_variant_attribute_spec(), - }; - int i_specs; - - for (i_specs = 0; i_specs < G_N_ELEMENTS(specs_list); i_specs++) { - const NMVariantAttributeSpec *const *const specs = specs_list[i_specs]; - gsize len; - gsize i; - - g_assert(specs); - - len = NM_PTRARRAY_LEN(specs); - g_assert_cmpint(len, >, 0u); - - _nmtst_variant_attribute_spec_assert_sorted(specs, len); - for (i = 0; i < len; i++) - g_assert(specs[i] - == _nm_variant_attribute_spec_find_binary_search(specs, len, specs[i]->name)); - g_assert(!_nm_variant_attribute_spec_find_binary_search(specs, len, "bogus")); - } -} - -/*****************************************************************************/ - -static gboolean -do_test_nm_set_out_called(int *call_count) -{ - (*call_count)++; - return TRUE; -} - -static void -test_nm_set_out(void) -{ - gboolean val; - gboolean *p_val; - int call_count; - - /* NM_SET_OUT() has an unexpected non-function like behavior - * wrt. side-effects of the value argument. Test it */ - - p_val = &val; - call_count = 0; - NM_SET_OUT(p_val, do_test_nm_set_out_called(&call_count)); - g_assert_cmpint(call_count, ==, 1); - - p_val = NULL; - call_count = 0; - NM_SET_OUT(p_val, do_test_nm_set_out_called(&call_count)); - g_assert_cmpint(call_count, ==, 0); - - /* test that we successfully re-defined _G_BOOLEAN_EXPR() */ -#define _T1(a) \ - ({ \ - g_assert(a > 2); \ - a; \ - }) - g_assert(_T1(3) > 1); -#undef _T1 -} - -/*****************************************************************************/ - -static void -test_get_start_time_for_pid(void) -{ - guint64 x_start_time; - char x_state; - pid_t x_ppid; - - x_start_time = nm_utils_get_start_time_for_pid(getpid(), &x_state, &x_ppid); - - g_assert(x_start_time > 0); - g_assert(x_ppid == getppid()); - g_assert(!NM_IN_SET(x_state, '\0', ' ')); -} - -/*****************************************************************************/ - -static void -test_nm_va_args_macros(void) -{ -#define GET_NARG_1(...) NM_NARG(__VA_ARGS__) - - g_assert_cmpint(0, ==, GET_NARG_1()); - g_assert_cmpint(1, ==, GET_NARG_1(x)); - g_assert_cmpint(2, ==, GET_NARG_1(, )); - g_assert_cmpint(2, ==, GET_NARG_1(, x)); - g_assert_cmpint(2, ==, GET_NARG_1(x, )); - g_assert_cmpint(2, ==, GET_NARG_1(x, x)); - g_assert_cmpint(3, ==, GET_NARG_1(, , )); - g_assert_cmpint(3, ==, GET_NARG_1(, , x)); - g_assert_cmpint(3, ==, GET_NARG_1(, x, )); - g_assert_cmpint(3, ==, GET_NARG_1(, x, x)); - g_assert_cmpint(3, ==, GET_NARG_1(x, , )); - g_assert_cmpint(3, ==, GET_NARG_1(x, , x)); - g_assert_cmpint(3, ==, GET_NARG_1(x, x, )); - g_assert_cmpint(3, ==, GET_NARG_1(x, x, x)); - g_assert_cmpint(4, ==, GET_NARG_1(, , , )); - g_assert_cmpint(4, ==, GET_NARG_1(, , , x)); - g_assert_cmpint(4, ==, GET_NARG_1(, , x, )); - g_assert_cmpint(4, ==, GET_NARG_1(, , x, x)); - g_assert_cmpint(4, ==, GET_NARG_1(, x, , )); - g_assert_cmpint(4, ==, GET_NARG_1(, x, , x)); - g_assert_cmpint(4, ==, GET_NARG_1(, x, x, )); - g_assert_cmpint(4, ==, GET_NARG_1(, x, x, x)); - g_assert_cmpint(4, ==, GET_NARG_1(x, , , )); - g_assert_cmpint(4, ==, GET_NARG_1(x, , , x)); - g_assert_cmpint(4, ==, GET_NARG_1(x, , x, )); - g_assert_cmpint(4, ==, GET_NARG_1(x, , x, x)); - g_assert_cmpint(4, ==, GET_NARG_1(x, x, , )); - g_assert_cmpint(4, ==, GET_NARG_1(x, x, , x)); - g_assert_cmpint(4, ==, GET_NARG_1(x, x, x, )); - g_assert_cmpint(4, ==, GET_NARG_1(x, x, x, x)); - - g_assert_cmpint(5, ==, GET_NARG_1(x, x, x, x, x)); - g_assert_cmpint(6, ==, GET_NARG_1(x, x, x, x, x, x)); - g_assert_cmpint(7, ==, GET_NARG_1(x, x, x, x, x, x, x)); - g_assert_cmpint(8, ==, GET_NARG_1(x, x, x, x, x, x, x, x)); - g_assert_cmpint(9, ==, GET_NARG_1(x, x, x, x, x, x, x, x, x)); - g_assert_cmpint(10, ==, GET_NARG_1(x, x, x, x, x, x, x, x, x, x)); - - G_STATIC_ASSERT_EXPR(0 == GET_NARG_1()); - G_STATIC_ASSERT_EXPR(1 == GET_NARG_1(x)); - G_STATIC_ASSERT_EXPR(2 == GET_NARG_1(x, x)); -} - -/*****************************************************************************/ - -static void -test_ethtool_offload(void) -{ - const NMEthtoolData *d; - - g_assert_cmpint(nm_ethtool_id_get_by_name("invalid"), ==, NM_ETHTOOL_ID_UNKNOWN); - g_assert_cmpint(nm_ethtool_id_get_by_name("feature-rx"), ==, NM_ETHTOOL_ID_FEATURE_RX); - - d = nm_ethtool_data_get_by_optname(NM_ETHTOOL_OPTNAME_FEATURE_RXHASH); - g_assert(d); - g_assert_cmpint(d->id, ==, NM_ETHTOOL_ID_FEATURE_RXHASH); - g_assert_cmpstr(d->optname, ==, NM_ETHTOOL_OPTNAME_FEATURE_RXHASH); - - /* these features are NETIF_F_NEVER_CHANGE: */ - g_assert(!nm_ethtool_data_get_by_optname("feature-netns-local")); - g_assert(!nm_ethtool_data_get_by_optname("feature-tx-lockless")); - g_assert(!nm_ethtool_data_get_by_optname("feature-vlan-challenged")); -} - -/*****************************************************************************/ - -typedef struct { - GMainLoop * loop1; - GMainContext *c2; - GSource * extra_sources[2]; - bool got_signal[5]; - int fd_2; -} IntegData; - -static gboolean -_test_integrate_cb_handle(IntegData *d, int signal) -{ - int i; - - g_assert(d); - g_assert(signal >= 0); - g_assert(signal < G_N_ELEMENTS(d->got_signal)); - - g_assert(!d->got_signal[signal]); - d->got_signal[signal] = TRUE; - - for (i = 0; i < G_N_ELEMENTS(d->got_signal); i++) { - if (!d->got_signal[i]) - break; - } - if (i == G_N_ELEMENTS(d->got_signal)) - g_main_loop_quit(d->loop1); - return G_SOURCE_REMOVE; -} - -static gboolean -_test_integrate_cb_timeout_1(gpointer user_data) -{ - return _test_integrate_cb_handle(user_data, 0); -} - -static gboolean -_test_integrate_cb_fd_2(int fd, GIOCondition condition, gpointer user_data) - -{ - IntegData *d = user_data; - - g_assert(d->got_signal[1]); - g_assert(d->got_signal[2]); - g_assert(d->got_signal[3]); - g_assert(d->extra_sources[0]); - g_assert(d->extra_sources[1]); - - return _test_integrate_cb_handle(d, 4); -} - -static gboolean -_test_integrate_cb_idle_2(gpointer user_data) -{ - IntegData *d = user_data; - GSource * extra_source; - - g_assert(d->got_signal[1]); - g_assert(d->got_signal[2]); - g_assert(d->extra_sources[0]); - g_assert(!d->extra_sources[1]); - - extra_source = nm_g_unix_fd_source_new(d->fd_2, - G_IO_IN, - G_PRIORITY_DEFAULT, - _test_integrate_cb_fd_2, - d, - NULL); - g_source_attach(extra_source, d->c2); - - d->extra_sources[1] = extra_source; - - return _test_integrate_cb_handle(d, 3); -} - -static gboolean -_test_integrate_cb_idle_1(gpointer user_data) -{ - IntegData *d = user_data; - GSource * extra_source; - - g_assert(d->got_signal[2]); - g_assert(!d->extra_sources[0]); - - extra_source = g_idle_source_new(); - g_source_set_callback(extra_source, _test_integrate_cb_idle_2, d, NULL); - g_source_attach(extra_source, d->c2); - - d->extra_sources[0] = extra_source; - - return _test_integrate_cb_handle(d, 1); -} - -static gboolean -_test_integrate_cb_fd_1(int fd, GIOCondition condition, gpointer user_data) - -{ - IntegData *d = user_data; - - g_assert(!d->got_signal[1]); - return _test_integrate_cb_handle(d, 2); -} - -static gboolean -_test_integrate_maincontext_cb_idle1(gpointer user_data) -{ - guint32 *p_count = user_data; - - g_assert(*p_count < 5); - (*p_count)++; - return G_SOURCE_CONTINUE; -} - -static void -test_integrate_maincontext(gconstpointer test_data) -{ - const guint TEST_IDX = GPOINTER_TO_UINT(test_data); - GMainContext * c1 = g_main_context_default(); - nm_auto_unref_gmaincontext GMainContext *c2 = g_main_context_new(); - nm_auto_destroy_and_unref_gsource GSource *integ_source = NULL; - - integ_source = nm_utils_g_main_context_create_integrate_source(c2); - g_source_attach(integ_source, c1); - - if (TEST_IDX == 1) { - nm_auto_destroy_and_unref_gsource GSource *idle_source_1 = NULL; - guint32 count = 0; - - idle_source_1 = g_idle_source_new(); - g_source_set_callback(idle_source_1, _test_integrate_maincontext_cb_idle1, &count, NULL); - g_source_attach(idle_source_1, c2); - - nmtst_main_context_iterate_until_assert(c1, 2000, count == 5); - } - - if (TEST_IDX == 2) { - nm_auto_destroy_and_unref_gsource GSource *main_timeout_source = NULL; - nm_auto_destroy_and_unref_gsource GSource *timeout_source_1 = NULL; - nm_auto_destroy_and_unref_gsource GSource *idle_source_1 = NULL; - nm_auto_destroy_and_unref_gsource GSource *fd_source_1 = NULL; - nm_auto_unref_gmainloop GMainLoop *loop1 = NULL; - nm_auto_close int fd_1 = -1; - nm_auto_close int fd_2 = -1; - IntegData d; - int i; - - main_timeout_source = g_timeout_source_new(3000); - g_source_set_callback(main_timeout_source, nmtst_g_source_assert_not_called, NULL, NULL); - g_source_attach(main_timeout_source, c1); - - loop1 = g_main_loop_new(c1, FALSE); - - d = (IntegData){ - .loop1 = loop1, - .c2 = c2, - }; - - fd_1 = open("/dev/null", O_RDONLY | O_CLOEXEC); - g_assert(fd_1 >= 0); - fd_source_1 = nm_g_unix_fd_source_new(fd_1, - G_IO_IN, - G_PRIORITY_DEFAULT, - _test_integrate_cb_fd_1, - &d, - NULL); - g_source_attach(fd_source_1, c2); - - fd_2 = open("/dev/null", O_RDONLY | O_CLOEXEC); - g_assert(fd_2 >= 0); - d.fd_2 = fd_2; - - idle_source_1 = g_idle_source_new(); - g_source_set_callback(idle_source_1, _test_integrate_cb_idle_1, &d, NULL); - g_source_attach(idle_source_1, c2); - - timeout_source_1 = g_timeout_source_new(5); - g_source_set_callback(timeout_source_1, _test_integrate_cb_timeout_1, &d, NULL); - g_source_attach(timeout_source_1, c2); - - g_main_loop_run(loop1); - - for (i = 0; i < G_N_ELEMENTS(d.extra_sources); i++) { - g_assert(d.extra_sources[i]); - nm_clear_pointer(&d.extra_sources[i], nm_g_source_destroy_and_unref); - } - } -} - -/*****************************************************************************/ - -static void -test_nm_ip_addr_zero(void) -{ - in_addr_t a4 = nmtst_inet4_from_string("0.0.0.0"); - struct in6_addr a6 = *nmtst_inet6_from_string("::"); - char buf[NM_UTILS_INET_ADDRSTRLEN]; - NMIPAddr a = NM_IP_ADDR_INIT; - - g_assert(memcmp(&a, &nm_ip_addr_zero, sizeof(a)) == 0); - - g_assert(IN6_IS_ADDR_UNSPECIFIED(&nm_ip_addr_zero.addr6)); - g_assert(memcmp(&nm_ip_addr_zero.addr6, &in6addr_any, sizeof(in6addr_any)) == 0); - - g_assert(memcmp(&nm_ip_addr_zero, &a4, sizeof(a4)) == 0); - g_assert(memcmp(&nm_ip_addr_zero, &a6, sizeof(a6)) == 0); - - g_assert_cmpstr(_nm_utils_inet4_ntop(nm_ip_addr_zero.addr4, buf), ==, "0.0.0.0"); - g_assert_cmpstr(_nm_utils_inet6_ntop(&nm_ip_addr_zero.addr6, buf), ==, "::"); - - g_assert_cmpstr(nm_utils_inet_ntop(AF_INET, &nm_ip_addr_zero, buf), ==, "0.0.0.0"); - g_assert_cmpstr(nm_utils_inet_ntop(AF_INET6, &nm_ip_addr_zero, buf), ==, "::"); - - G_STATIC_ASSERT_EXPR(sizeof(a) == sizeof(a.array)); -} - -static void -test_connection_ovs_ifname(gconstpointer test_data) -{ - const guint TEST_CASE = GPOINTER_TO_UINT(test_data); - gs_unref_object NMConnection *con = NULL; - NMSettingConnection * s_con = NULL; - NMSettingOvsBridge * s_ovs_bridge = NULL; - NMSettingOvsPort * s_ovs_port = NULL; - NMSettingOvsInterface * s_ovs_iface = NULL; - NMSettingOvsPatch * s_ovs_patch = NULL; - const char * ovs_iface_type = NULL; - - switch (TEST_CASE) { - case 1: - con = nmtst_create_minimal_connection("test_connection_ovs_ifname_bridge", - NULL, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - &s_con); - s_ovs_bridge = nm_connection_get_setting_ovs_bridge(con); - g_assert(s_ovs_bridge); - break; - case 2: - con = nmtst_create_minimal_connection("test_connection_ovs_ifname_port", - NULL, - NM_SETTING_OVS_PORT_SETTING_NAME, - &s_con); - - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NULL); - - s_ovs_port = nm_connection_get_setting_ovs_port(con); - g_assert(s_ovs_port); - break; - case 3: - con = nmtst_create_minimal_connection("test_connection_ovs_ifname_interface_patch", - NULL, - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - &s_con); - s_ovs_iface = nm_connection_get_setting_ovs_interface(con); - g_assert(s_ovs_iface); - - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - - g_object_set(s_ovs_iface, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); - - s_ovs_patch = NM_SETTING_OVS_PATCH(nm_setting_ovs_patch_new()); - g_assert(s_ovs_patch); - - g_object_set(s_ovs_patch, NM_SETTING_OVS_PATCH_PEER, "1.2.3.4", NULL); - - nm_connection_add_setting(con, NM_SETTING(s_ovs_patch)); - s_ovs_patch = nm_connection_get_setting_ovs_patch(con); - g_assert(s_ovs_patch); - ovs_iface_type = "patch"; - break; - case 4: - con = nmtst_create_minimal_connection("test_connection_ovs_ifname_interface_internal", - NULL, - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - &s_con); - s_ovs_iface = nm_connection_get_setting_ovs_interface(con); - g_assert(s_ovs_iface); - - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - - g_object_set(s_ovs_iface, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); - ovs_iface_type = "internal"; - break; - case 5: - con = nmtst_create_minimal_connection("test_connection_ovs_ifname_interface_system", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - &s_con); - - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - - s_ovs_iface = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); - g_assert(s_ovs_iface); - - g_object_set(s_ovs_iface, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); - - nm_connection_add_setting(con, NM_SETTING(s_ovs_iface)); - s_ovs_iface = nm_connection_get_setting_ovs_interface(con); - g_assert(s_ovs_iface); - - ovs_iface_type = "system"; - break; - case 6: - con = nmtst_create_minimal_connection("test_connection_ovs_ifname_interface_dpdk", - NULL, - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - &s_con); - s_ovs_iface = nm_connection_get_setting_ovs_interface(con); - g_assert(s_ovs_iface); - - g_object_set(s_con, - NM_SETTING_CONNECTION_MASTER, - "master0", - NM_SETTING_CONNECTION_SLAVE_TYPE, - NM_SETTING_OVS_PORT_SETTING_NAME, - NULL); - - g_object_set(s_ovs_iface, NM_SETTING_OVS_INTERFACE_TYPE, "dpdk", NULL); - ovs_iface_type = "dpdk"; - break; - } - - if (!nm_streq0(ovs_iface_type, "system")) { - /* wrong: contains backward slash */ - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs\\0", NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - - /* wrong: contains forward slash */ - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs/0", NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - } - - /* wrong: contains space */ - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs 0", NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - - /* good */ - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs0", NULL); - nmtst_assert_connection_verifies(con); - - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs-br0", NULL); - nmtst_assert_connection_verifies(con); - - /* good if bridge, port, or patch interface */ - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs123123123123130123123", NULL); - - if (!ovs_iface_type || nm_streq(ovs_iface_type, "patch")) - nmtst_assert_connection_verifies(con); - else { - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - } -} - -/*****************************************************************************/ - -static gboolean -_strsplit_quoted_char_needs_escaping(char ch) -{ - return NM_IN_SET(ch, '\'', '\"', '\\') || strchr(NM_ASCII_WHITESPACES, ch); -} - -static char * -_strsplit_quoted_create_str_rand(gssize len) -{ - NMStrBuf strbuf = NM_STR_BUF_INIT(nmtst_get_rand_uint32() % 200, nmtst_get_rand_bool()); - - g_assert(len >= -1); - - if (len == -1) - len = nmtst_get_rand_word_length(NULL); - - while (len-- > 0) { - char ch; - - ch = nmtst_rand_select('a', ' ', '\\', '"', '\'', nmtst_get_rand_uint32() % 255 + 1); - g_assert(ch); - nm_str_buf_append_c(&strbuf, ch); - } - - if (!strbuf.allocated) - nm_str_buf_maybe_expand(&strbuf, 1, nmtst_get_rand_bool()); - return nm_str_buf_finalize(&strbuf, NULL); -} - -static char ** -_strsplit_quoted_create_strv_rand(void) -{ - guint len = nmtst_get_rand_word_length(NULL); - char **ptr; - guint i; - - ptr = g_new(char *, len + 1); - for (i = 0; i < len; i++) - ptr[i] = _strsplit_quoted_create_str_rand(-1); - ptr[i] = NULL; - return ptr; -} - -static char * -_strsplit_quoted_join_strv_rand(const char *const *strv) -{ - NMStrBuf strbuf = NM_STR_BUF_INIT(nmtst_get_rand_uint32() % 200, nmtst_get_rand_bool()); - char * result; - gsize l; - gsize l2; - gsize * p_l2 = nmtst_get_rand_bool() ? &l2 : NULL; - gsize i; - - g_assert(strv); - - nm_str_buf_append_c_repeated(&strbuf, ' ', nmtst_get_rand_word_length(NULL) / 4); - for (i = 0; strv[i]; i++) { - const char *s = strv[i]; - gsize j; - char quote; - - nm_str_buf_append_c_repeated(&strbuf, ' ', 1 + nmtst_get_rand_word_length(NULL) / 4); - - j = 0; - quote = '\0'; - while (TRUE) { - char ch = s[j++]; - - /* extract_first_word*/ - if (quote != '\0') { - if (ch == '\0') { - nm_str_buf_append_c(&strbuf, quote); - break; - } - if (ch == quote || ch == '\\' || nmtst_get_rand_uint32() % 5 == 0) - nm_str_buf_append_c(&strbuf, '\\'); - nm_str_buf_append_c(&strbuf, ch); - if (nmtst_get_rand_uint32() % 3 == 0) { - nm_str_buf_append_c(&strbuf, quote); - quote = '\0'; - goto next_maybe_quote; - } - continue; - } - - if (ch == '\0') { - if (s == strv[i]) { - quote = nmtst_rand_select('\'', '"'); - nm_str_buf_append_c_repeated(&strbuf, quote, 2); - } - break; - } - - if (_strsplit_quoted_char_needs_escaping(ch) || nmtst_get_rand_uint32() % 5 == 0) - nm_str_buf_append_c(&strbuf, '\\'); - - nm_str_buf_append_c(&strbuf, ch); - -next_maybe_quote: - if (nmtst_get_rand_uint32() % 5 == 0) { - quote = nmtst_rand_select('\'', '\"'); - nm_str_buf_append_c(&strbuf, quote); - if (nmtst_get_rand_uint32() % 5 == 0) { - nm_str_buf_append_c(&strbuf, quote); - quote = '\0'; - } - } - } - } - nm_str_buf_append_c_repeated(&strbuf, ' ', nmtst_get_rand_word_length(NULL) / 4); - - nm_str_buf_maybe_expand(&strbuf, 1, nmtst_get_rand_bool()); - - l = strbuf.len; - result = nm_str_buf_finalize(&strbuf, p_l2); - g_assert(!p_l2 || l == *p_l2); - g_assert(strlen(result) == l); - return result; -} - -static void -_strsplit_quoted_assert_strv(const char * topic, - const char * str, - const char *const *strv1, - const char *const *strv2) -{ - nm_auto_str_buf NMStrBuf s1 = {}; - nm_auto_str_buf NMStrBuf s2 = {}; - gs_free char * str_escaped = NULL; - int i; - - g_assert(str); - g_assert(strv1); - g_assert(strv2); - - if (nm_utils_strv_equal(strv1, strv2)) - return; - - for (i = 0; strv1[i]; i++) { - gs_free char *s = g_strescape(strv1[i], NULL); - - g_print(">>> [%s] strv1[%d] = \"%s\"\n", topic, i, s); - if (i > 0) - nm_str_buf_append_c(&s1, ' '); - nm_str_buf_append_printf(&s1, "\"%s\"", s); - } - - for (i = 0; strv2[i]; i++) { - gs_free char *s = g_strescape(strv2[i], NULL); - - g_print(">>> [%s] strv2[%d] = \"%s\"\n", topic, i, s); - if (i > 0) - nm_str_buf_append_c(&s2, ' '); - nm_str_buf_append_printf(&s2, "\"%s\"", s); - } - - nm_str_buf_maybe_expand(&s1, 1, FALSE); - nm_str_buf_maybe_expand(&s2, 1, FALSE); - - str_escaped = g_strescape(str, NULL); - g_error("compared words differs: [%s] str=\"%s\"; strv1=%s; strv2=%s", - topic, - str_escaped, - nm_str_buf_get_str(&s1), - nm_str_buf_get_str(&s2)); -} - -static void -_strsplit_quoted_test(const char *str, const char *const *strv_expected) -{ - gs_strfreev char **strv_systemd = NULL; - gs_strfreev char **strv_nm = NULL; - int r; - - g_assert(str); - - r = nmtst_systemd_extract_first_word_all(str, &strv_systemd); - g_assert_cmpint(r, ==, 1); - g_assert(strv_systemd); - - if (!strv_expected) - strv_expected = (const char *const *) strv_systemd; - - _strsplit_quoted_assert_strv("systemd", str, strv_expected, (const char *const *) strv_systemd); - - strv_nm = nm_utils_strsplit_quoted(str); - g_assert(strv_nm); - _strsplit_quoted_assert_strv("nm", str, strv_expected, (const char *const *) strv_nm); -} - -static void -test_strsplit_quoted(void) -{ - int i_run; - - _strsplit_quoted_test("", NM_MAKE_STRV()); - _strsplit_quoted_test(" ", NM_MAKE_STRV()); - _strsplit_quoted_test(" ", NM_MAKE_STRV()); - _strsplit_quoted_test(" \t", NM_MAKE_STRV()); - _strsplit_quoted_test("a b", NM_MAKE_STRV("a", "b")); - _strsplit_quoted_test("a\\ b", NM_MAKE_STRV("a b")); - _strsplit_quoted_test(" a\\ \"b\"", NM_MAKE_STRV("a b")); - _strsplit_quoted_test(" a\\ \"b\" c \n", NM_MAKE_STRV("a b", "c")); - - for (i_run = 0; i_run < 1000; i_run++) { - gs_strfreev char **strv = NULL; - gs_free char * str = NULL; - - /* create random strv array and join them carefully so that splitting - * them will yield the original value. */ - strv = _strsplit_quoted_create_strv_rand(); - str = _strsplit_quoted_join_strv_rand((const char *const *) strv); - _strsplit_quoted_test(str, (const char *const *) strv); - } - - /* Create random words and assert that systemd and our implementation can - * both split them (and in the exact same way). */ - for (i_run = 0; i_run < 1000; i_run++) { - gs_free char *s = _strsplit_quoted_create_str_rand(nmtst_get_rand_uint32() % 150); - - _strsplit_quoted_test(s, NULL); - } -} - -/*****************************************************************************/ - -static void -_do_wifi_ghz_freqs(const guint *freqs, const char *band) -{ - int len; - int j; - int i; - - g_assert(NM_IN_STRSET(band, "a", "bg")); - g_assert(freqs); - g_assert(freqs[0] != 0); - - for (i = 0; freqs[i]; i++) { - for (j = 0; j < i; j++) - g_assert(freqs[i] != freqs[j]); - } - len = i; - - g_assert(nm_utils_wifi_freq_to_channel(0) == 0); - g_assert(nm_utils_wifi_channel_to_freq(0, "bg") == -1); - g_assert(nm_utils_wifi_channel_to_freq(0, "foo") == 0); - g_assert(!nm_utils_wifi_is_channel_valid(0, "bg")); - g_assert(!nm_utils_wifi_is_channel_valid(0, "foo")); - - for (i = 0; i < len; i++) { - guint freq = freqs[i]; - guint32 chan; - guint32 freq2; - - chan = nm_utils_wifi_freq_to_channel(freq); - g_assert(chan != 0); - - freq2 = nm_utils_wifi_channel_to_freq(chan, band); - g_assert(freq2 == freq); - - g_assert(nm_utils_wifi_is_channel_valid(chan, band)); - } - - g_assert(freqs[len] == 0); -} - -static void -test_nm_utils_wifi_ghz_freqs(void) -{ - _do_wifi_ghz_freqs(nm_utils_wifi_2ghz_freqs(), "bg"); - _do_wifi_ghz_freqs(nm_utils_wifi_5ghz_freqs(), "a"); -} - -/*****************************************************************************/ - -static void -test_vpn_connection_state_reason(void) -{ -#define ASSERT(v1, v2) \ - G_STMT_START \ - { \ - G_STATIC_ASSERT((gint64)(v1) == v2); \ - G_STATIC_ASSERT((gint64)(v2) == v1); \ - \ - nm_assert(((NMActiveConnectionStateReason)(int) (v1)) == v2); \ - nm_assert(((NMVpnConnectionStateReason)(int) (v2)) == v1); \ - } \ - G_STMT_END - - ASSERT(NM_VPN_CONNECTION_STATE_REASON_UNKNOWN, NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_NONE, NM_ACTIVE_CONNECTION_STATE_REASON_NONE); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED, - NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED, - NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, - NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT, - NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT, - NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED, - NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED, - NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED); - ASSERT(NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED, - NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED); -} - -/*****************************************************************************/ - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init(&argc, &argv, TRUE); - - g_test_add_func("/core/general/test_nm_ascii_spaces", test_nm_ascii_spaces); - g_test_add_func("/core/general/test_wired_wake_on_lan_enum", test_wired_wake_on_lan_enum); - g_test_add_func("/core/general/test_nm_hash", test_nm_hash); - g_test_add_func("/core/general/test_nm_g_slice_free_fcn", test_nm_g_slice_free_fcn); - g_test_add_func("/core/general/test_c_list_sort", test_c_list_sort); - g_test_add_func("/core/general/test_dedup_multi", test_dedup_multi); - g_test_add_func("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe); - g_test_add_func("/core/general/test_nm_utils_strsplit_set", test_nm_utils_strsplit_set); - g_test_add_func("/core/general/test_nm_utils_escaped_tokens", test_nm_utils_escaped_tokens); - g_test_add_func("/core/general/test_nm_in_set", test_nm_in_set); - g_test_add_func("/core/general/test_nm_in_strset", test_nm_in_strset); - g_test_add_func("/core/general/test_setting_vpn_items", test_setting_vpn_items); - g_test_add_func("/core/general/test_setting_vpn_update_secrets", - test_setting_vpn_update_secrets); - g_test_add_func("/core/general/test_setting_vpn_modify_during_foreach", - test_setting_vpn_modify_during_foreach); - g_test_add_func("/core/general/test_setting_ip4_config_labels", test_setting_ip4_config_labels); - g_test_add_func("/core/general/test_setting_ip4_config_address_data", - test_setting_ip4_config_address_data); - g_test_add_func("/core/general/test_setting_ip_route_attributes", - test_setting_ip_route_attributes); - g_test_add_func("/core/general/test_setting_gsm_apn_spaces", test_setting_gsm_apn_spaces); - g_test_add_func("/core/general/test_setting_gsm_apn_bad_chars", test_setting_gsm_apn_bad_chars); - g_test_add_func("/core/general/test_setting_gsm_apn_underscore", - test_setting_gsm_apn_underscore); - g_test_add_func("/core/general/test_setting_gsm_without_number", - test_setting_gsm_without_number); - g_test_add_func("/core/general/test_setting_gsm_sim_operator_id", - test_setting_gsm_sim_operator_id); - g_test_add_func("/core/general/test_setting_to_dbus_all", test_setting_to_dbus_all); - g_test_add_func("/core/general/test_setting_to_dbus_no_secrets", - test_setting_to_dbus_no_secrets); - g_test_add_func("/core/general/test_setting_to_dbus_only_secrets", - test_setting_to_dbus_only_secrets); - g_test_add_func("/core/general/test_setting_to_dbus_transform", test_setting_to_dbus_transform); - g_test_add_func("/core/general/test_setting_to_dbus_enum", test_setting_to_dbus_enum); - g_test_add_func("/core/general/test_setting_compare_id", test_setting_compare_id); - g_test_add_func("/core/general/test_setting_compare_addresses", test_setting_compare_addresses); - g_test_add_func("/core/general/test_setting_compare_routes", test_setting_compare_routes); - g_test_add_func("/core/general/test_setting_compare_wired_cloned_mac_address", - test_setting_compare_wired_cloned_mac_address); - g_test_add_func("/core/general/test_setting_compare_wirless_cloned_mac_address", - test_setting_compare_wireless_cloned_mac_address); - g_test_add_func("/core/general/test_setting_compare_timestamp", test_setting_compare_timestamp); -#define ADD_FUNC(name, func, secret_flags, comp_flags, remove_secret) \ - g_test_add_data_func_full( \ - "/core/general/" G_STRINGIFY(func) "_" name, \ - test_data_compare_secrets_new(secret_flags, comp_flags, remove_secret), \ - func, \ - g_free) - ADD_FUNC("agent_owned", - test_setting_compare_secrets, - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, - TRUE); - ADD_FUNC("not_saved", - test_setting_compare_secrets, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, - TRUE); - ADD_FUNC("secrets", - test_setting_compare_secrets, - NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, - TRUE); - ADD_FUNC("exact", - test_setting_compare_secrets, - NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_COMPARE_FLAG_EXACT, - FALSE); - ADD_FUNC("agent_owned", - test_setting_compare_vpn_secrets, - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, - TRUE); - ADD_FUNC("not_saved", - test_setting_compare_vpn_secrets, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, - TRUE); - ADD_FUNC("secrets", - test_setting_compare_vpn_secrets, - NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, - TRUE); - ADD_FUNC("exact", - test_setting_compare_vpn_secrets, - NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_COMPARE_FLAG_EXACT, - FALSE); - g_test_add_func("/core/general/test_setting_old_uuid", test_setting_old_uuid); - - g_test_add_func("/core/general/test_connection_to_dbus_setting_name", - test_connection_to_dbus_setting_name); - g_test_add_func("/core/general/test_connection_to_dbus_deprecated_props", - test_connection_to_dbus_deprecated_props); - g_test_add_func("/core/general/test_setting_new_from_dbus", test_setting_new_from_dbus); - g_test_add_func("/core/general/test_setting_new_from_dbus_transform", - test_setting_new_from_dbus_transform); - g_test_add_func("/core/general/test_setting_new_from_dbus_enum", - test_setting_new_from_dbus_enum); - g_test_add_func("/core/general/test_setting_new_from_dbus_bad", test_setting_new_from_dbus_bad); - g_test_add_func("/core/general/test_connection_replace_settings", - test_connection_replace_settings); - g_test_add_func("/core/general/test_connection_replace_settings_from_connection", - test_connection_replace_settings_from_connection); - g_test_add_func("/core/general/test_connection_replace_settings_bad", - test_connection_replace_settings_bad); - g_test_add_func("/core/general/test_connection_new_from_dbus", test_connection_new_from_dbus); - g_test_add_func("/core/general/test_connection_normalize_virtual_iface_name", - test_connection_normalize_virtual_iface_name); - g_test_add_func("/core/general/test_connection_normalize_uuid", test_connection_normalize_uuid); - g_test_add_func("/core/general/test_connection_normalize_type", test_connection_normalize_type); - g_test_add_func("/core/general/test_connection_normalize_slave_type_1", - test_connection_normalize_slave_type_1); - g_test_add_func("/core/general/test_connection_normalize_slave_type_2", - test_connection_normalize_slave_type_2); - g_test_add_func("/core/general/test_connection_normalize_infiniband_mtu", - test_connection_normalize_infiniband_mtu); - g_test_add_func("/core/general/test_connection_normalize_gateway_never_default", - test_connection_normalize_gateway_never_default); - g_test_add_func("/core/general/test_connection_normalize_may_fail", - test_connection_normalize_may_fail); - g_test_add_func("/core/general/test_connection_normalize_shared_addresses", - test_connection_normalize_shared_addresses); - g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/1", - GUINT_TO_POINTER(1), - test_connection_normalize_ovs_interface_type_system); - g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/2", - GUINT_TO_POINTER(2), - test_connection_normalize_ovs_interface_type_system); - g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/3", - GUINT_TO_POINTER(3), - test_connection_normalize_ovs_interface_type_system); - g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/4", - GUINT_TO_POINTER(4), - test_connection_normalize_ovs_interface_type_system); - g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/5", - GUINT_TO_POINTER(5), - test_connection_normalize_ovs_interface_type_system); - g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/6", - GUINT_TO_POINTER(6), - test_connection_normalize_ovs_interface_type_system); - g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/7", - GUINT_TO_POINTER(7), - test_connection_normalize_ovs_interface_type_system); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/1", - GUINT_TO_POINTER(1), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/2", - GUINT_TO_POINTER(2), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/3", - GUINT_TO_POINTER(3), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/4", - GUINT_TO_POINTER(4), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/5", - GUINT_TO_POINTER(5), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/6", - GUINT_TO_POINTER(6), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/7", - GUINT_TO_POINTER(7), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/8", - GUINT_TO_POINTER(8), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/9", - GUINT_TO_POINTER(9), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/10", - GUINT_TO_POINTER(10), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/11", - GUINT_TO_POINTER(11), - test_connection_normalize_ovs_interface_type_ovs_interface); - g_test_add_data_func( - "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/12", - GUINT_TO_POINTER(12), - test_connection_normalize_ovs_interface_type_ovs_interface); - - g_test_add_data_func("/core/general/test_connection_ovs_ifname/1", - GUINT_TO_POINTER(1), - test_connection_ovs_ifname); - g_test_add_data_func("/core/general/test_connection_ovs_ifname/2", - GUINT_TO_POINTER(2), - test_connection_ovs_ifname); - g_test_add_data_func("/core/general/test_connection_ovs_ifname/3", - GUINT_TO_POINTER(3), - test_connection_ovs_ifname); - g_test_add_data_func("/core/general/test_connection_ovs_ifname/4", - GUINT_TO_POINTER(4), - test_connection_ovs_ifname); - g_test_add_data_func("/core/general/test_connection_ovs_ifname/5", - GUINT_TO_POINTER(5), - test_connection_ovs_ifname); - g_test_add_data_func("/core/general/test_connection_ovs_ifname/6", - GUINT_TO_POINTER(6), - test_connection_ovs_ifname); - - g_test_add_func("/core/general/test_setting_connection_permissions_helpers", - test_setting_connection_permissions_helpers); - g_test_add_func("/core/general/test_setting_connection_permissions_property", - test_setting_connection_permissions_property); - - g_test_add_func("/core/general/test_connection_compare_same", test_connection_compare_same); - g_test_add_func("/core/general/test_connection_compare_key_only_in_a", - test_connection_compare_key_only_in_a); - g_test_add_func("/core/general/test_connection_compare_setting_only_in_a", - test_connection_compare_setting_only_in_a); - g_test_add_func("/core/general/test_connection_compare_key_only_in_b", - test_connection_compare_key_only_in_b); - g_test_add_func("/core/general/test_connection_compare_setting_only_in_b", - test_connection_compare_setting_only_in_b); - - g_test_add_func("/core/general/test_connection_diff_a_only", test_connection_diff_a_only); - g_test_add_func("/core/general/test_connection_diff_same", test_connection_diff_same); - g_test_add_func("/core/general/test_connection_diff_different", test_connection_diff_different); - g_test_add_func("/core/general/test_connection_diff_no_secrets", - test_connection_diff_no_secrets); - g_test_add_func("/core/general/test_connection_diff_inferrable", - test_connection_diff_inferrable); - g_test_add_func("/core/general/test_connection_good_base_types", - test_connection_good_base_types); - g_test_add_func("/core/general/test_connection_bad_base_types", test_connection_bad_base_types); - - g_test_add_func("/core/general/test_hwaddr_aton_ether_normal", test_hwaddr_aton_ether_normal); - g_test_add_func("/core/general/test_hwaddr_aton_ib_normal", test_hwaddr_aton_ib_normal); - g_test_add_func("/core/general/test_hwaddr_aton_no_leading_zeros", - test_hwaddr_aton_no_leading_zeros); - g_test_add_func("/core/general/test_hwaddr_aton_malformed", test_hwaddr_aton_malformed); - g_test_add_func("/core/general/test_hwaddr_equal", test_hwaddr_equal); - g_test_add_func("/core/general/test_hwaddr_canonical", test_hwaddr_canonical); - - g_test_add_func("/core/general/test_ip4_prefix_to_netmask", test_ip4_prefix_to_netmask); - g_test_add_func("/core/general/test_ip4_netmask_to_prefix", test_ip4_netmask_to_prefix); - - g_test_add_func("/core/general/test_connection_changed_signal", test_connection_changed_signal); - g_test_add_func("/core/general/test_setting_connection_changed_signal", - test_setting_connection_changed_signal); - g_test_add_func("/core/general/test_setting_bond_changed_signal", - test_setting_bond_changed_signal); - g_test_add_func("/core/general/test_setting_ip4_changed_signal", - test_setting_ip4_changed_signal); - g_test_add_func("/core/general/test_setting_ip6_changed_signal", - test_setting_ip6_changed_signal); - g_test_add_func("/core/general/test_setting_vlan_changed_signal", - test_setting_vlan_changed_signal); - g_test_add_func("/core/general/test_setting_vpn_changed_signal", - test_setting_vpn_changed_signal); - g_test_add_func("/core/general/test_setting_wired_changed_signal", - test_setting_wired_changed_signal); - g_test_add_func("/core/general/test_setting_wireless_changed_signal", - test_setting_wireless_changed_signal); - g_test_add_func("/core/general/test_setting_wireless_security_changed_signal", - test_setting_wireless_security_changed_signal); - g_test_add_func("/core/general/test_setting_802_1x_changed_signal", - test_setting_802_1x_changed_signal); - g_test_add_func("/core/general/test_setting_ip4_gateway", test_setting_ip4_gateway); - g_test_add_func("/core/general/test_setting_ip6_gateway", test_setting_ip6_gateway); - g_test_add_func("/core/general/test_setting_compare_default_strv", - test_setting_compare_default_strv); - g_test_add_func("/core/general/test_setting_user_data", test_setting_user_data); - - g_test_add_func("/core/general/test_sock_addr_endpoint", test_sock_addr_endpoint); - - g_test_add_func("/core/general/hexstr2bin", test_hexstr2bin); - g_test_add_func("/core/general/nm_strquote", test_nm_strquote); - g_test_add_func("/core/general/test_nm_utils_uuid_generate_from_string", - test_nm_utils_uuid_generate_from_string); - g_test_add_func("/core/general/_nm_utils_uuid_generate_from_strings", - test_nm_utils_uuid_generate_from_strings); - - g_test_add_func("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64); - g_test_add_func("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two); - g_test_add_func("/core/general/nm_utils_ptrarray_find_binary_search", - test_nm_utils_ptrarray_find_binary_search); - g_test_add_func("/core/general/nm_utils_ptrarray_find_binary_search_with_duplicates", - test_nm_utils_ptrarray_find_binary_search_with_duplicates); - g_test_add_func("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey); - g_test_add_func("/core/general/nm_ptrarray_len", test_nm_ptrarray_len); - - g_test_add_func("/core/general/_nm_utils_dns_option_validate", - test_nm_utils_dns_option_validate); - g_test_add_func("/core/general/_nm_utils_dns_option_find_idx", - test_nm_utils_dns_option_find_idx); - g_test_add_func("/core/general/_nm_utils_validate_json", test_nm_utils_check_valid_json); - g_test_add_func("/core/general/_nm_utils_team_config_equal", test_nm_utils_team_config_equal); - g_test_add_func("/core/general/test_nm_utils_enum", test_nm_utils_enum); - g_test_add_func("/core/general/nm-set-out", test_nm_set_out); - g_test_add_func("/core/general/route_attributes/parse", test_route_attributes_parse); - g_test_add_func("/core/general/route_attributes/format", test_route_attributes_format); - g_test_add_func("/core/general/test_variant_attribute_spec", test_variant_attribute_spec); - - g_test_add_func("/core/general/get_start_time_for_pid", test_get_start_time_for_pid); - g_test_add_func("/core/general/test_nm_va_args_macros", test_nm_va_args_macros); - g_test_add_func("/core/general/test_ethtool_offload", test_ethtool_offload); - - g_test_add_data_func("/core/general/test_integrate_maincontext/1", - GUINT_TO_POINTER(1), - test_integrate_maincontext); - g_test_add_data_func("/core/general/test_integrate_maincontext/2", - GUINT_TO_POINTER(2), - test_integrate_maincontext); - - g_test_add_func("/core/general/test_nm_ip_addr_zero", test_nm_ip_addr_zero); - g_test_add_func("/core/general/test_nm_utils_wifi_ghz_freqs", test_nm_utils_wifi_ghz_freqs); - - g_test_add_func("/core/general/test_strsplit_quoted", test_strsplit_quoted); - g_test_add_func("/core/general/test_vpn_connection_state_reason", - test_vpn_connection_state_reason); - - return g_test_run(); -} diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c deleted file mode 100644 index b3af6c4e4a..0000000000 --- a/libnm-core/tests/test-keyfile.c +++ /dev/null @@ -1,909 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-glib-aux/nm-json-aux.h" -#include "nm-keyfile-utils.h" -#include "nm-keyfile-internal.h" -#include "nm-simple-connection.h" -#include "nm-setting-connection.h" -#include "nm-setting-wired.h" -#include "nm-setting-8021x.h" -#include "nm-setting-team.h" -#include "nm-setting-user.h" -#include "nm-setting-proxy.h" - -#include "nm-utils/nm-test-utils.h" - -#define TEST_CERT_DIR NM_BUILD_SRCDIR "/libnm-core/tests/certs" -#define TEST_WIRED_TLS_CA_CERT TEST_CERT_DIR "/test-ca-cert.pem" -#define TEST_WIRED_TLS_PRIVKEY TEST_CERT_DIR "/test-key-and-cert.pem" -#define TEST_WIRED_TLS_TPM2KEY TEST_CERT_DIR "/test-tpm2wrapped-key.pem" - -/*****************************************************************************/ - -static void -do_test_encode_key_full(GKeyFile * kf, - const char *name, - const char *key, - const char *key_decode_encode) -{ - gs_free char *to_free1 = NULL; - gs_free char *to_free2 = NULL; - const char * key2; - const char * name2; - - g_assert(key); - - if (name) { - key2 = nm_keyfile_key_encode(name, &to_free1); - g_assert(key2); - g_assert(NM_STRCHAR_ALL(key2, ch, (guchar) ch < 127)); - g_assert_cmpstr(key2, ==, key); - - /* try to add the encoded key to the keyfile. We expect - * no g_critical warning about invalid key. */ - g_key_file_set_value(kf, "group", key, "dummy"); - } - - name2 = nm_keyfile_key_decode(key, &to_free2); - if (name) - g_assert_cmpstr(name2, ==, name); - else { - key2 = nm_keyfile_key_encode(name2, &to_free1); - g_assert(key2); - g_assert(NM_STRCHAR_ALL(key2, ch, (guchar) ch < 127)); - if (key_decode_encode) - g_assert_cmpstr(key2, ==, key_decode_encode); - g_key_file_set_value(kf, "group", key2, "dummy"); - } -} - -#define do_test_encode_key_bijection(kf, name, key) \ - do_test_encode_key_full(kf, "" name, "" key, NULL) -#define do_test_encode_key_identity(kf, name) do_test_encode_key_full(kf, "" name, "" name, NULL) -#define do_test_encode_key_decode_surjection(kf, key, key_decode_encode) \ - do_test_encode_key_full(kf, NULL, "" key, "" key_decode_encode) - -static void -test_encode_key(void) -{ - nm_auto_unref_keyfile GKeyFile *kf = g_key_file_new(); - - do_test_encode_key_identity(kf, "a"); - do_test_encode_key_bijection(kf, "", "\\00"); - do_test_encode_key_bijection(kf, " ", "\\20"); - do_test_encode_key_bijection(kf, "\\ ", "\\\\20"); - do_test_encode_key_identity(kf, "\\0"); - do_test_encode_key_identity(kf, "\\a"); - do_test_encode_key_identity(kf, "\\0g"); - do_test_encode_key_bijection(kf, "\\0f", "\\5C0f"); - do_test_encode_key_bijection(kf, "\\0f ", "\\5C0f\\20"); - do_test_encode_key_bijection(kf, " \\0f ", "\\20\\5C0f\\20"); - do_test_encode_key_bijection(kf, "\xF5", "\\F5"); - do_test_encode_key_bijection(kf, "\x7F", "\\7F"); - do_test_encode_key_bijection(kf, "\x1f", "\\1F"); - do_test_encode_key_bijection(kf, " ", "\\20\\20"); - do_test_encode_key_bijection(kf, " ", "\\20 \\20"); - do_test_encode_key_decode_surjection(kf, "f\\20c", "f c"); - do_test_encode_key_decode_surjection(kf, "\\20\\20\\20", "\\20 \\20"); - - do_test_encode_key_bijection(kf, "\t", "\\09"); - do_test_encode_key_bijection(kf, "\t=x", "\\09\\3Dx"); - do_test_encode_key_bijection( - kf, - "(nm-openvpn-auth-dialog:10283): GdkPixbuf-DEBUG: \tCopy pixels == false", - "(nm-openvpn-auth-dialog:10283): GdkPixbuf-DEBUG: \\09Copy pixels \\3D\\3D false"); -} - -/*****************************************************************************/ - -#define CLEAR(con, keyfile) \ - G_STMT_START \ - { \ - NMConnection **_con = (con); \ - GKeyFile ** _keyfile = (keyfile); \ - \ - g_clear_object(_con); \ - nm_clear_pointer(_keyfile, g_key_file_unref); \ - } \ - G_STMT_END - -static void -_assert_gbytes(GBytes *bytes, gconstpointer data, gssize len) -{ - g_assert((data && len > 0) || !len || (data && len == -1)); - - if (len == -1) - len = strlen(data); - - if (!len) - g_assert(!bytes); - - g_assert(nm_utils_gbytes_equal_mem(bytes, data, len)); -} - -static GKeyFile * -_keyfile_load_from_data(const char *str) -{ - GError * error = NULL; - gboolean success; - GKeyFile *keyfile; - - g_assert(str); - - keyfile = g_key_file_new(); - success = g_key_file_load_from_data(keyfile, str, strlen(str), G_KEY_FILE_NONE, &error); - g_assert_no_error(error); - g_assert(success); - - return keyfile; -} - -static GKeyFile * -_nm_keyfile_write(NMConnection *connection, NMKeyfileWriteHandler handler, void *user_data) -{ - GError * error = NULL; - GKeyFile *kf; - - g_assert(NM_IS_CONNECTION(connection)); - - kf = nm_keyfile_write(connection, NM_KEYFILE_HANDLER_FLAGS_NONE, handler, user_data, &error); - g_assert_no_error(error); - g_assert(kf); - return kf; -} - -static NMConnection * -_nm_keyfile_read(GKeyFile * keyfile, - const char * keyfile_name, - NMKeyfileReadHandler read_handler, - void * read_data, - gboolean needs_normalization) -{ - GError * error = NULL; - NMConnection *con; - gs_free char *filename = NULL; - gs_free char *base_dir = NULL; - - g_assert(keyfile); - g_assert(!keyfile_name || (keyfile_name[0] == '/')); - - base_dir = g_path_get_dirname(keyfile_name); - filename = g_path_get_basename(keyfile_name); - - con = nm_keyfile_read(keyfile, - base_dir, - NM_KEYFILE_HANDLER_FLAGS_NONE, - read_handler, - read_data, - &error); - g_assert_no_error(error); - g_assert(NM_IS_CONNECTION(con)); - - nm_keyfile_read_ensure_id(con, filename); - nm_keyfile_read_ensure_uuid(con, keyfile_name); - - if (needs_normalization) { - nmtst_assert_connection_verifies_after_normalization(con, 0, 0); - nmtst_connection_normalize(con); - } else { - { - NMSettingConnection *s_con; - - /* a non-slave connection must have a proxy setting, but - * keyfile reader does not add that (unless a [proxy] section - * is present. */ - s_con = nm_connection_get_setting_connection(con); - if (s_con && !nm_setting_connection_get_master(s_con) - && !nm_connection_get_setting_proxy(con)) - nm_connection_add_setting(con, nm_setting_proxy_new()); - } - nmtst_assert_connection_verifies_without_normalization(con); - } - return con; -} - -static void -_keyfile_convert(NMConnection ** con, - GKeyFile ** keyfile, - const char * keyfile_name, - NMKeyfileReadHandler read_handler, - void * read_data, - NMKeyfileWriteHandler write_handler, - void * write_data, - gboolean needs_normalization) -{ - NMConnection * c0; - GKeyFile * k0; - gs_unref_object NMConnection *c0_k1_c2 = NULL, *k0_c1 = NULL, *k0_c1_k2_c3 = NULL; - nm_auto_unref_keyfile GKeyFile *k0_c1_k2 = NULL, *c0_k1 = NULL, *c0_k1_c2_k3 = NULL; - - /* convert from @con to @keyfile and check that we can make - * full round trips and obtaining the same result. */ - - g_assert(con); - g_assert(keyfile); - g_assert(*con || *keyfile); - - c0 = *con; - k0 = *keyfile; - - if (c0) { - c0_k1 = _nm_keyfile_write(c0, write_handler, write_data); - c0_k1_c2 = _nm_keyfile_read(c0_k1, keyfile_name, read_handler, read_data, FALSE); - c0_k1_c2_k3 = _nm_keyfile_write(c0_k1_c2, write_handler, write_data); - - g_assert(_nm_keyfile_equals(c0_k1, c0_k1_c2_k3, TRUE)); - } - if (k0) { - NMSetting8021x *s1, *s2; - - k0_c1 = _nm_keyfile_read(k0, keyfile_name, read_handler, read_data, needs_normalization); - k0_c1_k2 = _nm_keyfile_write(k0_c1, write_handler, write_data); - k0_c1_k2_c3 = _nm_keyfile_read(k0_c1_k2, keyfile_name, read_handler, read_data, FALSE); - - /* It is a expected behavior, that if @k0 contains a relative path ca-cert, @k0_c1 will - * contain that path as relative. But @k0_c1_k2 and @k0_c1_k2_c3 will have absolute paths. - * In this case, hack up @k0_c1_k2_c3 to contain the same relative path. */ - s1 = nm_connection_get_setting_802_1x(k0_c1); - s2 = nm_connection_get_setting_802_1x(k0_c1_k2_c3); - if (s1 || s2) { - g_assert_cmpint(nm_setting_802_1x_get_ca_cert_scheme(s1), - ==, - nm_setting_802_1x_get_ca_cert_scheme(s2)); - switch (nm_setting_802_1x_get_ca_cert_scheme(s1)) { - case NM_SETTING_802_1X_CK_SCHEME_PATH: - { - const char *p1 = nm_setting_802_1x_get_ca_cert_path(s1); - const char *p2 = nm_setting_802_1x_get_ca_cert_path(s2); - - nmtst_assert_resolve_relative_path_equals(p1, p2); - if (strcmp(p1, p2) != 0) { - gs_free char * puri = NULL; - gs_unref_bytes GBytes *pfile = NULL; - - g_assert(p1[0] != '/' && p2[0] == '/'); - - /* one of the paths is a relative path and the other is absolute. This is an - * expected difference. - * Make the paths of s2 identical to s1... */ - puri = g_strconcat(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, p1, NULL); - pfile = g_bytes_new(puri, strlen(puri) + 1); - g_object_set(s2, NM_SETTING_802_1X_CA_CERT, pfile, NULL); - } - } break; - case NM_SETTING_802_1X_CK_SCHEME_BLOB: - { - GBytes *b1, *b2; - - b1 = nm_setting_802_1x_get_ca_cert_blob(s1); - b2 = nm_setting_802_1x_get_ca_cert_blob(s2); - g_assert(b1); - g_assert(b2); - g_assert(g_bytes_equal(b1, b2)); - break; - } - default: - break; - } - } - - nmtst_assert_connection_equals(k0_c1, FALSE, k0_c1_k2_c3, FALSE); - } - - if (!k0) - *keyfile = g_key_file_ref(c0_k1); - else if (!c0) - *con = g_object_ref(k0_c1); - else { - /* finally, if both a keyfile and a connection are given, assert that they are equal - * after a round of conversion. */ - g_assert(_nm_keyfile_equals(c0_k1, k0_c1_k2, TRUE)); - nmtst_assert_connection_equals(k0_c1, FALSE, c0_k1_c2, FALSE); - } -} - -/*****************************************************************************/ - -static void -_test_8021x_cert_check(NMConnection * con, - NMSetting8021xCKScheme expected_scheme, - const void * value, - gssize val_len) -{ - GKeyFile * keyfile = NULL; - NMSetting8021x *s_8021x; - gs_free char * kval = NULL; - - _keyfile_convert(&con, &keyfile, "/_test_8021x_cert_check/foo", NULL, NULL, NULL, NULL, FALSE); - - s_8021x = nm_connection_get_setting_802_1x(con); - - g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == expected_scheme); - - if (expected_scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { - const char *path = nm_setting_802_1x_get_ca_cert_path(s_8021x); - - g_assert_cmpstr(path, ==, value); - g_assert(val_len == -1 || strlen(path) == val_len); - - kval = g_key_file_get_string(keyfile, "802-1x", "ca-cert", NULL); - g_assert(kval); - g_assert_cmpstr(kval, ==, value); - } else if (expected_scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - GBytes * blob = nm_setting_802_1x_get_ca_cert_blob(s_8021x); - gs_free char *file_blob = NULL; - - if (val_len == -1) { - gsize l; - gboolean success; - - success = g_file_get_contents(value, &file_blob, &l, NULL); - g_assert(success); - - value = file_blob; - val_len = l; - } - - g_assert(blob); - g_assert(nm_utils_gbytes_equal_mem(blob, value, val_len)); - - kval = g_key_file_get_string(keyfile, "802-1x", "ca-cert", NULL); - g_assert(kval); - g_assert(g_str_has_prefix(kval, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)); - } - - g_key_file_unref(keyfile); -} - -static void -_test_8021x_cert_check_blob_full(NMConnection *con, const void *data, gsize len) -{ - GBytes * bytes; - NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x(con); - - bytes = g_bytes_new(data, len); - g_object_set(s_8021x, NM_SETTING_802_1X_CA_CERT, bytes, NULL); - _test_8021x_cert_check(con, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - g_bytes_get_data(bytes, NULL), - g_bytes_get_size(bytes)); - g_bytes_unref(bytes); -} -#define _test_8021x_cert_check_blob(con, data) \ - _test_8021x_cert_check_blob_full(con, data, NM_STRLEN(data)) - -static void -_test_8021x_cert_from_files(const char *cert, const char *key) -{ - NMSetting8021x *s_8021x; - gs_unref_object NMConnection *con = - nmtst_create_minimal_connection("test-cert", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - GError * error = NULL; - gboolean success; - NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; - gs_free char *full_TEST_WIRED_TLS_CA_CERT = nmtst_file_resolve_relative_path(cert, NULL); - gs_free char *full_TEST_WIRED_TLS_PRIVKEY = nmtst_file_resolve_relative_path(key, NULL); - - /* test writing/reading of certificates of NMSetting8021x */ - - /* create a valid connection with NMSetting8021x */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_setting_802_1x_add_eap_method(s_8021x, "tls"); - g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); - success = - nm_setting_802_1x_set_ca_cert(s_8021x, full_TEST_WIRED_TLS_CA_CERT, scheme, NULL, &error); - g_assert_no_error(error); - g_assert(success); - success = nm_setting_802_1x_set_client_cert(s_8021x, - full_TEST_WIRED_TLS_CA_CERT, - scheme, - NULL, - &error); - g_assert_no_error(error); - g_assert(success); - success = nm_setting_802_1x_set_private_key(s_8021x, - full_TEST_WIRED_TLS_PRIVKEY, - "test1", - scheme, - NULL, - &error); - g_assert_no_error(error); - g_assert(success); - - /* test resetting ca-cert to different values and see whether we can write/read. */ - - nm_connection_add_setting(con, NM_SETTING(s_8021x)); - nmtst_assert_connection_verifies_and_normalizable(con); - nmtst_connection_normalize(con); - - _test_8021x_cert_check(con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1); - - scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB; - success = - nm_setting_802_1x_set_ca_cert(s_8021x, full_TEST_WIRED_TLS_CA_CERT, scheme, NULL, &error); - g_assert_no_error(error); - g_assert(success); - _test_8021x_cert_check(con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1); - - _test_8021x_cert_check_blob(con, "a"); - _test_8021x_cert_check_blob(con, "\0"); - _test_8021x_cert_check_blob(con, "10"); - _test_8021x_cert_check_blob(con, "data:;base64,a"); - _test_8021x_cert_check_blob_full(con, "data:;base64,a", NM_STRLEN("data:;base64,a") + 1); - _test_8021x_cert_check_blob(con, "data:;base64,file://a"); - _test_8021x_cert_check_blob(con, "123"); -} - -static void -test_8021x_cert(void) -{ - _test_8021x_cert_from_files(TEST_WIRED_TLS_CA_CERT, TEST_WIRED_TLS_PRIVKEY); -} - -static void -test_8021x_cert_tpm2key(void) -{ - _test_8021x_cert_from_files(TEST_WIRED_TLS_CA_CERT, TEST_WIRED_TLS_TPM2KEY); -} - -/*****************************************************************************/ - -static void -test_8021x_cert_read(void) -{ - GKeyFile * keyfile = NULL; - gs_unref_object NMConnection *con = NULL; - NMSetting8021x * s_8021x; - - con = nmtst_create_connection_from_keyfile("[connection]\n" - "type=ethernet", - "/test_8021x_cert_read/test0"); - CLEAR(&con, &keyfile); - - keyfile = _keyfile_load_from_data("[connection]\n" - "type=ethernet"); - _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test1", NULL, NULL, NULL, NULL, TRUE); - CLEAR(&con, &keyfile); - - keyfile = _keyfile_load_from_data( - "[connection]\n" - "type=802-3-ethernet\n" - - "[802-1x]\n" - "eap=tls;\n" - "identity=Bill Smith\n" - "ca-cert=48;130;2;52;48;130;1;161;2;16;2;173;102;126;78;69;254;94;87;111;60;152;25;94;221;" - "192;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;" - "48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;" - "73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;" - "114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;" - "121;48;30;23;13;57;52;49;49;48;57;48;48;48;48;48;48;90;23;13;49;48;48;49;48;55;50;51;53;" - "57;53;57;90;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;" - "32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;" - "11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;" - "97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;129;155;48;13;6;9;42;134;72;" - "134;247;13;1;1;1;5;0;3;129;137;0;48;129;133;2;126;0;146;206;122;193;174;131;62;90;170;137;" - "131;87;172;37;1;118;12;173;174;142;44;55;206;235;53;120;100;84;3;229;132;64;81;201;191;" - "143;8;226;138;130;8;210;22;134;55;85;233;177;33;2;173;118;104;129;154;5;162;75;201;75;37;" - "102;34;86;108;136;7;143;247;129;89;109;132;7;101;112;19;113;118;62;155;119;76;227;80;137;" - "86;152;72;185;29;167;41;26;19;46;74;17;89;156;30;21;213;73;84;44;115;58;105;130;177;151;" - "57;156;109;112;103;72;229;221;45;214;200;30;123;2;3;1;0;1;48;13;6;9;42;134;72;134;247;13;" - "1;1;2;5;0;3;126;0;101;221;126;225;178;236;176;226;58;224;236;113;70;154;25;17;184;211;199;" - "160;180;3;64;38;2;62;9;156;225;18;179;209;90;246;55;165;183;97;3;182;91;22;105;59;198;68;" - "8;12;136;83;12;107;151;73;199;62;53;220;108;185;187;170;223;92;187;58;47;147;96;182;169;" - "75;77;242;32;247;205;95;127;100;123;142;220;0;92;215;250;119;202;57;22;89;111;14;234;211;" - "181;131;127;77;77;66;86;118;180;201;95;4;248;56;248;235;210;95;117;95;205;123;252;229;142;" - "128;124;252;80;\n" - "client-cert=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;" - "107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;" - "109;0;\n" - "private-key=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;" - "107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;" - "109;0;\n" - "private-key-password=12345testing\n"); - _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); - CLEAR(&con, &keyfile); - - keyfile = - _keyfile_load_from_data("[connection]\n" - "type=802-3-ethernet\n" - - "[802-1x]\n" - "eap=tls;\n" - "identity=Bill Smith\n" - /* unqualified strings are only recognized as path up to 500 chars*/ - "ca-cert=" - "/11111111111111111111111111111111111111111111111111111111111111111" - "1111111111111111111111111111111111" - "/11111111111111111111111111111111111111111111111111111111111111111" - "1111111111111111111111111111111111" - "/11111111111111111111111111111111111111111111111111111111111111111" - "1111111111111111111111111111111111" - "/11111111111111111111111111111111111111111111111111111111111111111" - "1111111111111111111111111111111111" - "/11111111111111111111111111111111111111111111111111111111111111111" - "111111111111111111111111111111111\n" - "client-cert=/" - "222222222222222222222222222222222222222222222222222222222222222222" - "222222222222222222222222222222221" - "/22222222222222222222222222222222222222222222222222222222222222222" - "2222222222222222222222222222222221" - "/22222222222222222222222222222222222222222222222222222222222222222" - "2222222222222222222222222222222221" - "/22222222222222222222222222222222222222222222222222222222222222222" - "2222222222222222222222222222222221" - "/22222222222222222222222222222222222222222222222222222222222222222" - "2222222222222222222222222222222222\n" - "private-key=file://" - "/33333333333333333333333333333333333333333333333333333333333333333" - "3333333333333333333333333333333331" - "/33333333333333333333333333333333333333333333333333333333333333333" - "3333333333333333333333333333333331" - "/33333333333333333333333333333333333333333333333333333333333333333" - "3333333333333333333333333333333331" - "/33333333333333333333333333333333333333333333333333333333333333333" - "3333333333333333333333333333333331" - "/33333333333333333333333333333333333333333333333333333333333333333" - "333333333333333333333333333333333111111\n" - "private-key-password=12345testing\n"); - _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); - s_8021x = nm_connection_get_setting_802_1x(con); - - g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); - g_assert(g_str_has_prefix(nm_setting_802_1x_get_ca_cert_path(s_8021x), "/111111111111")); - g_assert_cmpint(strlen(nm_setting_802_1x_get_ca_cert_path(s_8021x)), ==, 499); - - g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); - g_assert( - g_str_has_prefix(g_bytes_get_data(nm_setting_802_1x_get_client_cert_blob(s_8021x), NULL), - "/2222222222")); - g_assert_cmpint(g_bytes_get_size(nm_setting_802_1x_get_client_cert_blob(s_8021x)), - ==, - 500 + 1 /* keyfile reader adds a trailing NUL */); - - g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); - g_assert(g_str_has_prefix(nm_setting_802_1x_get_private_key_path(s_8021x), "/333333333")); - g_assert_cmpint(strlen(nm_setting_802_1x_get_private_key_path(s_8021x)), ==, 505); - CLEAR(&con, &keyfile); - - keyfile = _keyfile_load_from_data("[connection]\n" - "type=802-3-ethernet\n" - - "[802-1x]\n" - "eap=tls;\n" - "identity=Bill Smith\n" - "ca-cert=/\n" - "client-cert=a.pem\n" - "private-key=data:;base64,aGFsbG8=\n" // hallo - "private-key-password=12345testing\n"); - _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); - s_8021x = nm_connection_get_setting_802_1x(con); - - g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); - g_assert_cmpstr(nm_setting_802_1x_get_ca_cert_path(s_8021x), ==, "/"); - - g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); - g_assert_cmpstr(nm_setting_802_1x_get_client_cert_path(s_8021x), - ==, - "/test_8021x_cert_read/a.pem"); - - g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); - _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "hallo", -1); - CLEAR(&con, &keyfile); - - keyfile = _keyfile_load_from_data("[connection]\n" - "type=802-3-ethernet\n" - - "[802-1x]\n" - "eap=tls;\n" - "identity=Bill Smith\n" - "ca-cert=file://data:;base64,x\n" - "client-cert=abc.der\n" - "private-key=abc.deR\n" - "private-key-password=12345testing\n"); - _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); - s_8021x = nm_connection_get_setting_802_1x(con); - - g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); - g_assert_cmpstr(nm_setting_802_1x_get_ca_cert_path(s_8021x), ==, "data:;base64,x"); - - g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); - g_assert_cmpstr(nm_setting_802_1x_get_client_cert_path(s_8021x), - ==, - "/test_8021x_cert_read/abc.der"); - - g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); - _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "abc.deR\0", 8); - CLEAR(&con, &keyfile); - - keyfile = - _keyfile_load_from_data("[connection]\n" - "type=802-3-ethernet\n" - - "[802-1x]\n" - "eap=tls;\n" - "identity=Bill Smith\n" - "ca-cert=104;97;108;108;111;\n" /* "hallo" without trailing NUL */ - "client-cert=104;097;108;108;111;0;\n" - "private-key=hallo\n" - "private-key-password=12345testing\n"); - _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); - s_8021x = nm_connection_get_setting_802_1x(con); - - g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); - _assert_gbytes(nm_setting_802_1x_get_ca_cert_blob(s_8021x), "hallo", 5); - - g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); - _assert_gbytes(nm_setting_802_1x_get_client_cert_blob(s_8021x), "hallo\0", 6); - - g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); - _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "hallo\0", 6); - CLEAR(&con, &keyfile); -} - -static void -test_team_conf_read_valid(void) -{ - GKeyFile * keyfile = NULL; - gs_unref_object NMConnection *con = NULL; - NMSettingTeam * s_team; - - con = nmtst_create_connection_from_keyfile("[connection]\n" - "type=team\n" - "interface-name=nm-team1\n" - "[team]\n" - "config={\"foo\":\"bar\"}", - "/test_team_conf_read/valid"); - - g_assert(con); - s_team = nm_connection_get_setting_team(con); - g_assert(s_team); - g_assert_cmpstr(nm_setting_team_get_config(s_team), ==, "{\"foo\":\"bar\"}"); - - CLEAR(&con, &keyfile); -} - -static void -test_team_conf_read_invalid(void) -{ - GKeyFile * keyfile = NULL; - gs_unref_object NMConnection *con = NULL; - NMSettingTeam * s_team; - - if (!nm_json_vt()) { - g_test_skip("team test requires JSON validation"); - return; - } - - con = nmtst_create_connection_from_keyfile("[connection]\n" - "type=team\n" - "interface-name=nm-team1\n" - "[team]\n" - "config={foobar}", - "/test_team_conf_read/invalid"); - - g_assert(con); - s_team = nm_connection_get_setting_team(con); - g_assert(s_team); - g_assert(nm_setting_team_get_config(s_team) == NULL); - - CLEAR(&con, &keyfile); -} - -/*****************************************************************************/ - -static void -test_user_1(void) -{ - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - gs_unref_object NMConnection *con = NULL; - NMSettingUser * s_user; - - con = nmtst_create_connection_from_keyfile("[connection]\n" - "id=t\n" - "type=ethernet\n" - "\n" - "[user]\n" - "my-value.x=value1\n" - "", - "/test_user_1/invalid"); - g_assert(con); - s_user = NM_SETTING_USER(nm_connection_get_setting(con, NM_TYPE_SETTING_USER)); - g_assert(s_user); - g_assert_cmpstr(nm_setting_user_get_data(s_user, "my-value.x"), ==, "value1"); - - CLEAR(&con, &keyfile); - - con = nmtst_create_minimal_connection("user-2", - "8b85fb8d-3070-48ba-93d9-53eee231d9a2", - NM_SETTING_WIRED_SETTING_NAME, - NULL); - s_user = NM_SETTING_USER(nm_setting_user_new()); - -#define _USER_SET_DATA(s_user, key, val) \ - G_STMT_START \ - { \ - GError * _error = NULL; \ - gboolean _success; \ - \ - _success = nm_setting_user_set_data((s_user), (key), (val), &_error); \ - nmtst_assert_success(_success, _error); \ - } \ - G_STMT_END - -#define _USER_SET_DATA_X(s_user, key) _USER_SET_DATA(s_user, key, "val=" key "") - - _USER_SET_DATA(s_user, "my.val1", ""); - _USER_SET_DATA_X(s_user, "my.val2"); - _USER_SET_DATA_X(s_user, "my.v__al3"); - _USER_SET_DATA_X(s_user, "my._v"); - _USER_SET_DATA_X(s_user, "my.v+"); - _USER_SET_DATA_X(s_user, "my.Av"); - _USER_SET_DATA_X(s_user, "MY.AV"); - _USER_SET_DATA_X(s_user, "MY.8V"); - _USER_SET_DATA_X(s_user, "MY.8-V"); - _USER_SET_DATA_X(s_user, "MY.8_V"); - _USER_SET_DATA_X(s_user, "MY.8+V"); - _USER_SET_DATA_X(s_user, "MY.8/V"); - _USER_SET_DATA_X(s_user, "MY.8=V"); - _USER_SET_DATA_X(s_user, "MY.-"); - _USER_SET_DATA_X(s_user, "MY._"); - _USER_SET_DATA_X(s_user, "MY.+"); - _USER_SET_DATA_X(s_user, "MY./"); - _USER_SET_DATA_X(s_user, "MY.="); - _USER_SET_DATA_X(s_user, "my.keys.1"); - _USER_SET_DATA_X(s_user, "my.other.KEY.42"); - - nm_connection_add_setting(con, NM_SETTING(s_user)); - nmtst_connection_normalize(con); - - _keyfile_convert(&con, &keyfile, "/test_user_1/foo", NULL, NULL, NULL, NULL, FALSE); -} - -/*****************************************************************************/ - -static void -test_vpn_1(void) -{ - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - gs_unref_object NMConnection *con = NULL; - NMSettingVpn * s_vpn; - - con = nmtst_create_connection_from_keyfile("[connection]\n" - "id=t\n" - "type=vpn\n" - "\n" - "[vpn]\n" - "service-type=a.b.c\n" - "vpn-key-1=value1\n" - "", - "/test_vpn_1/invalid"); - g_assert(con); - s_vpn = NM_SETTING_VPN(nm_connection_get_setting(con, NM_TYPE_SETTING_VPN)); - g_assert(s_vpn); - g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, "vpn-key-1"), ==, "value1"); - - CLEAR(&con, &keyfile); -} - -/*****************************************************************************/ - -static void -test_bridge_vlans(void) -{ - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - gs_unref_object NMConnection *con = NULL; - NMSettingBridge * s_bridge; - NMBridgeVlan * vlan; - guint16 vid, vid_end; - - con = nmtst_create_connection_from_keyfile("[connection]\n" - "id=t\n" - "type=bridge\n" - "interface-name=br4\n" - "\n" - "[bridge]\n" - "vlans=900 , 1 pvid untagged, 100-123 untagged\n" - "", - "/test_bridge_port/vlans"); - s_bridge = NM_SETTING_BRIDGE(nm_connection_get_setting(con, NM_TYPE_SETTING_BRIDGE)); - g_assert(s_bridge); - g_assert_cmpuint(nm_setting_bridge_get_num_vlans(s_bridge), ==, 3); - - vlan = nm_setting_bridge_get_vlan(s_bridge, 0); - g_assert(vlan); - nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); - g_assert_cmpuint(vid, ==, 1); - g_assert_cmpuint(vid_end, ==, 1); - g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, TRUE); - g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); - - vlan = nm_setting_bridge_get_vlan(s_bridge, 1); - g_assert(vlan); - nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); - g_assert_cmpuint(vid, ==, 100); - g_assert_cmpuint(vid_end, ==, 123); - g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); - g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); - - vlan = nm_setting_bridge_get_vlan(s_bridge, 2); - g_assert(vlan); - nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); - g_assert_cmpuint(vid, ==, 900); - g_assert_cmpuint(vid_end, ==, 900); - g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); - g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, FALSE); - - CLEAR(&con, &keyfile); -} - -static void -test_bridge_port_vlans(void) -{ - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - gs_unref_object NMConnection *con = NULL; - NMSettingBridgePort * s_port; - NMBridgeVlan * vlan; - guint16 vid_start, vid_end; - - con = nmtst_create_connection_from_keyfile("[connection]\n" - "id=t\n" - "type=dummy\n" - "interface-name=dummy1\n" - "master=br0\n" - "slave-type=bridge\n" - "\n" - "[bridge-port]\n" - "vlans=4094 pvid , 10-20 untagged\n" - "", - "/test_bridge_port/vlans"); - s_port = NM_SETTING_BRIDGE_PORT(nm_connection_get_setting(con, NM_TYPE_SETTING_BRIDGE_PORT)); - g_assert(s_port); - g_assert_cmpuint(nm_setting_bridge_port_get_num_vlans(s_port), ==, 2); - - vlan = nm_setting_bridge_port_get_vlan(s_port, 0); - g_assert(vlan); - nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); - g_assert_cmpuint(vid_start, ==, 10); - g_assert_cmpuint(vid_end, ==, 20); - g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); - g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); - - vlan = nm_setting_bridge_port_get_vlan(s_port, 1); - g_assert(vlan); - nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); - g_assert_cmpuint(vid_start, ==, 4094); - g_assert_cmpuint(vid_end, ==, 4094); - g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, TRUE); - g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, FALSE); - - CLEAR(&con, &keyfile); -} - -/*****************************************************************************/ - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init(&argc, &argv, TRUE); - - g_test_add_func("/core/keyfile/encode_key", test_encode_key); - g_test_add_func("/core/keyfile/test_8021x_cert", test_8021x_cert); - g_test_add_func("/core/keyfile/test_8021x_cert_tpm2key", test_8021x_cert_tpm2key); - g_test_add_func("/core/keyfile/test_8021x_cert_read", test_8021x_cert_read); - g_test_add_func("/core/keyfile/test_team_conf_read/valid", test_team_conf_read_valid); - g_test_add_func("/core/keyfile/test_team_conf_read/invalid", test_team_conf_read_invalid); - g_test_add_func("/core/keyfile/test_user/1", test_user_1); - g_test_add_func("/core/keyfile/test_vpn/1", test_vpn_1); - g_test_add_func("/core/keyfile/bridge/vlans", test_bridge_vlans); - g_test_add_func("/core/keyfile/bridge-port/vlans", test_bridge_port_vlans); - - return g_test_run(); -} diff --git a/libnm-core/tests/test-secrets.c b/libnm-core/tests/test-secrets.c deleted file mode 100644 index 42f1fd0a32..0000000000 --- a/libnm-core/tests/test-secrets.c +++ /dev/null @@ -1,681 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2008 - 2011 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-8021x.h" -#include "nm-setting-cdma.h" -#include "nm-setting-connection.h" -#include "nm-setting-gsm.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ppp.h" -#include "nm-setting-pppoe.h" -#include "nm-setting-vpn.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireless-security.h" -#include "nm-setting-wireless.h" -#include "nm-simple-connection.h" -#include "nm-utils.h" -#include "nm-core-internal.h" - -#include "nm-utils/nm-test-utils.h" - -#define TEST_CERT_DIR NM_BUILD_SRCDIR "/libnm-core/tests/certs" -#define TEST_NEED_SECRETS_EAP_TLS_CA_CERT TEST_CERT_DIR "/test_ca_cert.pem" -#define TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT TEST_CERT_DIR "/test_key_and_cert.pem" -#define TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY TEST_CERT_DIR "/test_key_and_cert.pem" - -static void -_assert_hints_has(GPtrArray *hints, const char *item) -{ - guint i; - guint found = 0; - - g_assert(hints); - g_assert(item); - for (i = 0; i < hints->len; i++) { - g_assert(hints->pdata[i]); - if (strcmp(hints->pdata[i], item) == 0) - found++; - } - g_assert_cmpint(found, ==, 1); -} - -static NMConnection * -make_tls_connection(const char *detail, NMSetting8021xCKScheme scheme) -{ - NMConnection * connection; - NMSettingConnection *s_con; - NMSetting8021x * s_8021x; - NMSettingWired * s_wired; - NMSettingIP4Config * s_ip4; - char * uuid; - gboolean success; - GError * error = NULL; - - connection = nm_simple_connection_new(); - - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - - uuid = nm_utils_uuid_generate(); - g_object_set(s_con, - NM_SETTING_CONNECTION_ID, - "Test Need TLS Secrets", - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_AUTOCONNECT, - TRUE, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRED_SETTING_NAME, - NULL); - g_free(uuid); - - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* Wireless security setting */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); - - g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); - - nm_setting_802_1x_add_eap_method(s_8021x, "tls"); - - success = nm_setting_802_1x_set_ca_cert(s_8021x, - TEST_NEED_SECRETS_EAP_TLS_CA_CERT, - scheme, - NULL, - &error); - nmtst_assert_success(success, error); - - success = nm_setting_802_1x_set_client_cert(s_8021x, - TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, - scheme, - NULL, - &error); - nmtst_assert_success(success, error); - - success = nm_setting_802_1x_set_private_key(s_8021x, - TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, - "test", - scheme, - NULL, - &error); - nmtst_assert_success(success, error); - - success = nm_setting_set_secret_flags(NM_SETTING(s_8021x), - NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - &error); - nmtst_assert_success(success, error); - - /* IP4 setting */ - s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - - nmtst_assert_connection_verifies_and_normalizable(connection); - - return connection; -} - -static void -test_need_tls_secrets_path(void) -{ - NMConnection *connection; - const char * setting_name; - GPtrArray * hints = NULL; - - connection = make_tls_connection("need-tls-secrets-path-key", NM_SETTING_802_1X_CK_SCHEME_PATH); - - /* Ensure we don't need any secrets since we just set up the connection */ - setting_name = nm_connection_need_secrets(connection, &hints); - g_assert(!setting_name); - g_assert(!hints); - - /* Connection is good; clear secrets and ensure private key password is then required */ - nm_connection_clear_secrets(connection); - - hints = NULL; - setting_name = nm_connection_need_secrets(connection, &hints); - g_assert_cmpstr(setting_name, ==, NM_SETTING_802_1X_SETTING_NAME); - _assert_hints_has(hints, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); - - g_ptr_array_free(hints, TRUE); - g_object_unref(connection); -} - -static void -test_need_tls_secrets_blob(void) -{ - NMConnection *connection; - const char * setting_name; - GPtrArray * hints = NULL; - - connection = make_tls_connection("need-tls-secrets-blob-key", NM_SETTING_802_1X_CK_SCHEME_BLOB); - - /* Ensure we don't need any secrets since we just set up the connection */ - setting_name = nm_connection_need_secrets(connection, &hints); - g_assert(!setting_name); - g_assert(!hints); - - /* Clear secrets and ensure password is again required */ - nm_connection_clear_secrets(connection); - - hints = NULL; - setting_name = nm_connection_need_secrets(connection, &hints); - g_assert_cmpstr(setting_name, ==, NM_SETTING_802_1X_SETTING_NAME); - _assert_hints_has(hints, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); - - g_ptr_array_free(hints, TRUE); - g_object_unref(connection); -} - -static NMConnection * -make_tls_phase2_connection(const char *detail, NMSetting8021xCKScheme scheme) -{ - NMConnection * connection; - NMSettingConnection *s_con; - NMSetting8021x * s_8021x; - NMSettingWired * s_wired; - NMSettingIP4Config * s_ip4; - char * uuid; - gboolean success; - GError * error = NULL; - - connection = nm_simple_connection_new(); - - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - - uuid = nm_utils_uuid_generate(); - g_object_set(s_con, - NM_SETTING_CONNECTION_ID, - "Test Need TLS Secrets", - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_AUTOCONNECT, - TRUE, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRED_SETTING_NAME, - NULL); - g_free(uuid); - - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* Wireless security setting */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); - - g_object_set(s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "blahblah", NULL); - g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); - - nm_setting_802_1x_add_eap_method(s_8021x, "ttls"); - g_object_set(s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "tls", NULL); - - success = nm_setting_802_1x_set_phase2_ca_cert(s_8021x, - TEST_NEED_SECRETS_EAP_TLS_CA_CERT, - scheme, - NULL, - &error); - nmtst_assert_success(success, error); - - success = nm_setting_802_1x_set_phase2_client_cert(s_8021x, - TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, - scheme, - NULL, - &error); - nmtst_assert_success(success, error); - - success = nm_setting_802_1x_set_phase2_private_key(s_8021x, - TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, - "test", - scheme, - NULL, - &error); - nmtst_assert_success(success, error); - - success = nm_setting_set_secret_flags(NM_SETTING(s_8021x), - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - &error); - nmtst_assert_success(success, error); - - /* IP4 setting */ - s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - - nmtst_assert_connection_verifies_and_normalizable(connection); - return connection; -} - -static void -test_need_tls_phase2_secrets_path(void) -{ - NMConnection *connection; - const char * setting_name; - GPtrArray * hints = NULL; - - connection = make_tls_phase2_connection("need-tls-phase2-secrets-path-key", - NM_SETTING_802_1X_CK_SCHEME_PATH); - - /* Ensure we don't need any secrets since we just set up the connection */ - setting_name = nm_connection_need_secrets(connection, &hints); - g_assert(!setting_name); - g_assert(!hints); - - /* Connection is good; clear secrets and ensure private key password is then required */ - nm_connection_clear_secrets(connection); - - hints = NULL; - setting_name = nm_connection_need_secrets(connection, &hints); - g_assert_cmpstr(setting_name, ==, NM_SETTING_802_1X_SETTING_NAME); - _assert_hints_has(hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); - - g_ptr_array_free(hints, TRUE); - g_object_unref(connection); -} - -static void -test_need_tls_phase2_secrets_blob(void) -{ - NMConnection *connection; - const char * setting_name; - GPtrArray * hints = NULL; - - connection = make_tls_phase2_connection("need-tls-phase2-secrets-blob-key", - NM_SETTING_802_1X_CK_SCHEME_BLOB); - - /* Ensure we don't need any secrets since we just set up the connection */ - setting_name = nm_connection_need_secrets(connection, &hints); - g_assert(!setting_name); - g_assert(!hints); - - /* Connection is good; clear secrets and ensure private key password is then required */ - nm_connection_clear_secrets(connection); - - hints = NULL; - setting_name = nm_connection_need_secrets(connection, &hints); - g_assert_cmpstr(setting_name, ==, NM_SETTING_802_1X_SETTING_NAME); - _assert_hints_has(hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); - - g_ptr_array_free(hints, TRUE); - g_object_unref(connection); -} - -static NMConnection * -wifi_connection_new(void) -{ - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wifi; - NMSettingWirelessSecurity *s_wsec; - unsigned char tmpssid[] = {0x31, 0x33, 0x33, 0x37}; - char * uuid; - GBytes * ssid; - - connection = nm_simple_connection_new(); - g_assert(connection); - - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - g_assert(s_con); - - uuid = nm_utils_uuid_generate(); - g_object_set(s_con, - NM_SETTING_CONNECTION_ID, - "Test Wireless", - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_AUTOCONNECT, - FALSE, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRELESS_SETTING_NAME, - NULL); - g_free(uuid); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - - /* Wireless setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - g_assert(s_wifi); - - ssid = g_bytes_new(tmpssid, sizeof(tmpssid)); - g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL); - g_bytes_unref(ssid); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - /* Wifi security */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - g_assert(s_wsec); - - g_object_set(G_OBJECT(s_wsec), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NULL); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - - return connection; -} - -static GVariant * -build_wep_secrets(const char *wepkey) -{ - GVariantBuilder builder; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&builder, - "{sv}", - NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, - g_variant_new_string(wepkey)); - g_variant_builder_add(&builder, - "{sv}", - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, - g_variant_new_uint32(NM_WEP_KEY_TYPE_KEY)); - - return g_variant_builder_end(&builder); -} - -static void -test_update_secrets_wifi_single_setting(void) -{ - NMConnection * connection; - NMSettingWirelessSecurity *s_wsec; - GVariant * secrets; - GError * error = NULL; - gboolean success; - const char * wepkey = "11111111111111111111111111"; - const char * tmp; - - /* Test update with a hashed setting of 802-11-wireless secrets */ - - connection = wifi_connection_new(); - - secrets = build_wep_secrets(wepkey); - success = nm_connection_update_secrets(connection, - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - secrets, - &error); - g_assert_no_error(error); - g_assert(success); - - g_variant_unref(secrets); - - /* Make sure the secret is now in the connection */ - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); - tmp = nm_setting_wireless_security_get_wep_key(s_wsec, 0); - g_assert_cmpstr(tmp, ==, wepkey); - - g_object_unref(connection); -} - -static void -test_update_secrets_wifi_full_hash(void) -{ - NMConnection * connection; - NMSettingWirelessSecurity *s_wsec; - GVariantBuilder builder; - GVariant * all; - GError * error = NULL; - gboolean success; - const char * wepkey = "11111111111111111111111111"; - const char * tmp; - - /* Test update with a hashed connection containing only 802-11-wireless - * setting and secrets. - */ - - connection = wifi_connection_new(); - - g_variant_builder_init(&builder, NM_VARIANT_TYPE_CONNECTION); - g_variant_builder_add(&builder, - "{s@a{sv}}", - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - build_wep_secrets(wepkey)); - all = g_variant_builder_end(&builder); - - success = nm_connection_update_secrets(connection, - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - all, - &error); - g_assert_no_error(error); - g_assert(success); - - g_variant_unref(all); - - /* Make sure the secret is now in the connection */ - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); - tmp = nm_setting_wireless_security_get_wep_key(s_wsec, 0); - g_assert_cmpstr(tmp, ==, wepkey); - - g_object_unref(connection); -} - -static void -test_update_secrets_wifi_bad_setting_name(void) -{ - NMConnection *connection; - GVariant * secrets; - GError * error = NULL; - gboolean success; - const char * wepkey = "11111111111111111111111111"; - - /* Test that passing an invalid setting name to - * nm_connection_update_secrets() fails with the correct error. - */ - - connection = wifi_connection_new(); - - secrets = build_wep_secrets(wepkey); - - success = nm_connection_update_secrets(connection, "asdfasdfasdfasf", secrets, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND); - g_assert(success == FALSE); - - g_clear_error(&error); - g_variant_unref(secrets); - g_object_unref(connection); -} - -static void -test_update_secrets_whole_connection(void) -{ - NMConnection * connection; - NMSettingWirelessSecurity *s_wsec; - GVariant * secrets; - GError * error = NULL; - gboolean success; - const char * wepkey = "11111111111111111111111111"; - - /* Test calling nm_connection_update_secrets() with an entire hashed - * connection including non-secrets. - */ - - connection = wifi_connection_new(); - - /* Build up the secrets dictionary */ - secrets = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); - NMTST_VARIANT_EDITOR(secrets, - NMTST_VARIANT_ADD_PROPERTY(NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, - "s", - wepkey);); - - success = nm_connection_update_secrets(connection, NULL, secrets, &error); - g_assert_no_error(error); - g_assert(success == TRUE); - - g_variant_unref(secrets); - - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); - g_assert_cmpstr(nm_setting_wireless_security_get_wep_key(s_wsec, 0), ==, wepkey); - - g_object_unref(connection); -} - -static void -test_update_secrets_whole_connection_empty_hash(void) -{ - NMConnection *connection; - GVariant * secrets; - GError * error = NULL; - gboolean success; - - /* Test that updating secrets with an empty connection hash returns success */ - - connection = wifi_connection_new(); - secrets = g_variant_new_array(G_VARIANT_TYPE("{sa{sv}}"), NULL, 0); - success = nm_connection_update_secrets(connection, NULL, secrets, &error); - g_assert_no_error(error); - g_assert(success == TRUE); - g_variant_unref(secrets); - g_object_unref(connection); -} - -static void -test_update_secrets_whole_connection_bad_setting(void) -{ - NMConnection * connection; - NMSettingWirelessSecurity *s_wsec; - GVariant * secrets, *copy, *setting_hash; - const char * setting_name; - GVariantBuilder conn_builder; - GVariantIter conn_iter; - GError * error = NULL; - gboolean success; - const char * wepkey = "11111111111111111111111111"; - - /* Test that sending a hashed connection containing an invalid setting - * name fails with the right error. - */ - - connection = wifi_connection_new(); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec != NULL); - g_object_set(G_OBJECT(s_wsec), NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, wepkey, NULL); - - /* Build up the secrets hash */ - secrets = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); - - /* Copy the dict, renaming the wireless-security setting in the process - * (so we ensure libnm is returning the right error when it finds an entry - * in the connection hash that doesn't match any setting in the connection). - */ - g_variant_builder_init(&conn_builder, NM_VARIANT_TYPE_CONNECTION); - g_variant_iter_init(&conn_iter, secrets); - while (g_variant_iter_next(&conn_iter, "{&s@a{sv}}", &setting_name, &setting_hash)) { - if (strcmp(setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0) - setting_name = "asdfasdfasdfasdf"; - - g_variant_builder_add(&conn_builder, "{s@a{sv}}", setting_name, setting_hash); - g_variant_unref(setting_hash); - } - copy = g_variant_builder_end(&conn_builder); - g_variant_unref(secrets); - - success = nm_connection_update_secrets(connection, NULL, copy, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND); - g_assert(success == FALSE); - - g_clear_error(&error); - g_variant_unref(copy); - g_object_unref(connection); -} - -static void -test_update_secrets_whole_connection_empty_base_setting(void) -{ - NMConnection *connection; - GVariant * secrets, *setting; - GError * error = NULL; - gboolean success; - - /* Test that a hashed connection which does not have any hashed secrets - * for the requested setting returns success. - */ - - connection = wifi_connection_new(); - secrets = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ONLY_SECRETS); - g_assert_cmpint(g_variant_n_children(secrets), ==, 3); - - setting = g_variant_lookup_value(secrets, NM_SETTING_WIRELESS_SETTING_NAME, NULL); - g_assert(setting != NULL); - g_variant_unref(setting); - - success = nm_connection_update_secrets(connection, - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - secrets, - &error); - g_assert_no_error(error); - g_assert(success); - - g_variant_unref(secrets); - g_object_unref(connection); -} - -static void -test_update_secrets_null_setting_name_with_setting_hash(void) -{ - NMConnection *connection; - GVariant * secrets; - GError * error = NULL; - gboolean success; - const char * wepkey = "11111111111111111111111111"; - - /* Ensure that a NULL setting name and only a hashed setting fails */ - - connection = wifi_connection_new(); - - secrets = build_wep_secrets(wepkey); - - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(setting_name || full_connection)); - success = nm_connection_update_secrets(connection, NULL, secrets, &error); - g_test_assert_expected_messages(); - g_assert_no_error(error); - g_assert(!success); - - g_variant_unref(secrets); - g_object_unref(connection); -} - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init(&argc, &argv, TRUE); - - /* The tests */ - g_test_add_func("/libnm/need_tls_secrets_path", test_need_tls_secrets_path); - g_test_add_func("/libnm/need_tls_secrets_blob", test_need_tls_secrets_blob); - g_test_add_func("/libnm/need_tls_phase2_secrets_path", test_need_tls_phase2_secrets_path); - g_test_add_func("/libnm/need_tls_phase2_secrets_blob", test_need_tls_phase2_secrets_blob); - - g_test_add_func("/libnm/update_secrets_wifi_single_setting", - test_update_secrets_wifi_single_setting); - g_test_add_func("/libnm/update_secrets_wifi_full_hash", test_update_secrets_wifi_full_hash); - g_test_add_func("/libnm/update_secrets_wifi_bad_setting_name", - test_update_secrets_wifi_bad_setting_name); - - g_test_add_func("/libnm/update_secrets_whole_connection", test_update_secrets_whole_connection); - g_test_add_func("/libnm/update_secrets_whole_connection_empty_hash", - test_update_secrets_whole_connection_empty_hash); - g_test_add_func("/libnm/update_secrets_whole_connection_bad_setting", - test_update_secrets_whole_connection_bad_setting); - g_test_add_func("/libnm/update_secrets_whole_connection_empty_base_setting", - test_update_secrets_whole_connection_empty_base_setting); - g_test_add_func("/libnm/update_secrets_null_setting_name_with_setting_hash", - test_update_secrets_null_setting_name_with_setting_hash); - - return g_test_run(); -} diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c deleted file mode 100644 index 01cdb41cb2..0000000000 --- a/libnm-core/tests/test-setting.c +++ /dev/null @@ -1,4356 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2008 - 2017 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include -#include - -#include "nm-glib-aux/nm-json-aux.h" -#include "nm-base/nm-ethtool-utils-base.h" -#include "nm-core-internal.h" -#include "nm-utils.h" -#include "nm-utils-private.h" -#include "nm-core-internal.h" -#include "nm-setting-8021x.h" -#include "nm-setting-bond.h" -#include "nm-setting-dcb.h" -#include "nm-setting-ethtool.h" -#include "nm-setting-team.h" -#include "nm-setting-team-port.h" -#include "nm-setting-tc-config.h" -#include "nm-setting-dummy.h" -#include "nm-connection.h" -#include "nm-simple-connection.h" -#include "nm-setting-connection.h" -#include "nm-errors.h" -#include "nm-keyfile-internal.h" - -#include "nm-utils/nm-test-utils.h" - -#define TEST_CERT_DIR NM_BUILD_SRCDIR "/libnm-core/tests/certs" - -/*****************************************************************************/ - -/* converts @dict to a connection. In this case, @dict must be good, without warnings, so that - * NM_SETTING_PARSE_FLAGS_STRICT and NM_SETTING_PARSE_FLAGS_BEST_EFFORT yield the exact same results. */ -static NMConnection * -_connection_new_from_dbus_strict(GVariant *dict, gboolean normalize) -{ - gs_unref_object NMConnection *con_x_0 = NULL; - gs_unref_object NMConnection *con_x_s = NULL; - gs_unref_object NMConnection *con_x_e = NULL; - gs_unref_object NMConnection *con_n_0 = NULL; - gs_unref_object NMConnection *con_n_s = NULL; - gs_unref_object NMConnection *con_n_e = NULL; - gs_free_error GError *error = NULL; - guint i; - - g_assert(g_variant_is_of_type(dict, NM_VARIANT_TYPE_CONNECTION)); - - con_x_0 = _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_NONE, &error); - nmtst_assert_success(NM_IS_CONNECTION(con_x_0), error); - - con_x_s = _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_STRICT, &error); - nmtst_assert_success(NM_IS_CONNECTION(con_x_s), error); - - con_x_e = _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); - nmtst_assert_success(NM_IS_CONNECTION(con_x_e), error); - - con_n_0 = _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, &error); - nmtst_assert_success(NM_IS_CONNECTION(con_n_0), error); - - con_n_s = _nm_simple_connection_new_from_dbus(dict, - NM_SETTING_PARSE_FLAGS_STRICT - | NM_SETTING_PARSE_FLAGS_NORMALIZE, - &error); - nmtst_assert_success(NM_IS_CONNECTION(con_n_s), error); - - con_n_e = _nm_simple_connection_new_from_dbus(dict, - NM_SETTING_PARSE_FLAGS_BEST_EFFORT - | NM_SETTING_PARSE_FLAGS_NORMALIZE, - &error); - nmtst_assert_success(NM_IS_CONNECTION(con_n_e), error); - - nmtst_assert_connection_verifies(con_x_0); - nmtst_assert_connection_verifies(con_x_e); - nmtst_assert_connection_verifies(con_x_s); - - nmtst_assert_connection_verifies_without_normalization(con_n_0); - nmtst_assert_connection_verifies_without_normalization(con_n_e); - nmtst_assert_connection_verifies_without_normalization(con_n_s); - - /* randomly compare some pairs that we created. They must all be equal, - * after accounting for normalization. */ - for (i = 0; i < 10; i++) { - NMConnection *cons[] = {con_x_0, con_x_s, con_x_e, con_n_0, con_n_s, con_n_e}; - guint idx_a = (nmtst_get_rand_uint32() % G_N_ELEMENTS(cons)); - guint idx_b = (nmtst_get_rand_uint32() % G_N_ELEMENTS(cons)); - gboolean normalize_a, normalize_b; - - if (idx_a <= 2 && idx_b <= 2) { - normalize_a = nmtst_get_rand_bool(); - normalize_b = normalize_a; - } else if (idx_a > 2 && idx_b > 2) { - normalize_a = nmtst_get_rand_bool(); - normalize_b = nmtst_get_rand_bool(); - } else { - normalize_a = (idx_a <= 2) ? TRUE : nmtst_get_rand_bool(); - normalize_b = (idx_b <= 2) ? TRUE : nmtst_get_rand_bool(); - } - nmtst_assert_connection_equals(cons[idx_a], normalize_a, cons[idx_b], normalize_b); - } - - return (normalize) ? g_steal_pointer(&con_x_0) : g_steal_pointer(&con_n_0); -} - -/*****************************************************************************/ - -static char * -_create_random_ipaddr(int addr_family, gboolean as_service) -{ - char delimiter = as_service ? ':' : '/'; - int num; - - if (addr_family == AF_UNSPEC) - addr_family = nmtst_rand_select(AF_INET, AF_INET6); - - g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - - if (as_service) - num = (nmtst_get_rand_uint32() % 1000) + 30000; - else - num = addr_family == AF_INET ? 32 : 128; - - if (addr_family == AF_INET) - return g_strdup_printf("192.168.%u.%u%c%d", - nmtst_get_rand_uint32() % 256, - nmtst_get_rand_uint32() % 256, - delimiter, - num); - else - return g_strdup_printf("a:b:c::%02x:%02x%c%d", - nmtst_get_rand_uint32() % 256, - nmtst_get_rand_uint32() % 256, - delimiter, - num); -} - -/*****************************************************************************/ - -static void -compare_blob_data(const char *test, const char *key_path, GBytes *key) -{ - gs_free char *contents = NULL; - gsize len = 0; - GError * error = NULL; - gboolean success; - - g_assert(key && g_bytes_get_size(key) > 0); - - success = g_file_get_contents(key_path, &contents, &len, &error); - nmtst_assert_success(success, error); - - g_assert_cmpmem(contents, len, g_bytes_get_data(key, NULL), g_bytes_get_size(key)); -} - -static void -check_scheme_path(GBytes *value, const char *path) -{ - const guint8 *p; - gsize l; - - g_assert(value); - - p = g_bytes_get_data(value, &l); - g_assert_cmpint(l, ==, strlen(path) + NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + 1); - g_assert(memcmp(p, - NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, - strlen(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) - == 0); - p += strlen(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); - g_assert(memcmp(p, path, strlen(path)) == 0); - p += strlen(path); - g_assert(*p == '\0'); -} - -static void -test_private_key_import(const char *path, const char *password, NMSetting8021xCKScheme scheme) -{ - NMSetting8021x * s_8021x; - gboolean success; - NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - NMSetting8021xCKFormat tmp_fmt; - GError * error = NULL; - GBytes * tmp_key = NULL, *client_cert = NULL; - const char * pw; - - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - g_assert(s_8021x); - - success = nm_setting_802_1x_set_private_key(s_8021x, path, password, scheme, &format, &error); - nmtst_assert_success(success, error); - g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - tmp_fmt = nm_setting_802_1x_get_private_key_format(s_8021x); - g_assert(tmp_fmt == format); - - /* Make sure the password is what we expect */ - pw = nm_setting_802_1x_get_private_key_password(s_8021x); - g_assert(pw != NULL); - g_assert_cmpstr(pw, ==, password); - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - tmp_key = nm_setting_802_1x_get_private_key_blob(s_8021x); - compare_blob_data("private-key-import", path, tmp_key); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { - g_object_get(s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL); - check_scheme_path(tmp_key, path); - g_bytes_unref(tmp_key); - } else - g_assert_not_reached(); - - /* If it's PKCS#12 ensure the client cert is the same value */ - if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { - g_object_get(s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL); - g_assert(tmp_key); - - g_object_get(s_8021x, NM_SETTING_802_1X_CLIENT_CERT, &client_cert, NULL); - g_assert(client_cert); - - /* make sure they are the same */ - g_assert(g_bytes_equal(tmp_key, client_cert)); - - g_bytes_unref(tmp_key); - g_bytes_unref(client_cert); - } - - g_object_unref(s_8021x); -} - -static void -test_phase2_private_key_import(const char * path, - const char * password, - NMSetting8021xCKScheme scheme) -{ - NMSetting8021x * s_8021x; - gboolean success; - NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - NMSetting8021xCKFormat tmp_fmt; - GError * error = NULL; - GBytes * tmp_key = NULL, *client_cert = NULL; - const char * pw; - - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - g_assert(s_8021x); - - success = - nm_setting_802_1x_set_phase2_private_key(s_8021x, path, password, scheme, &format, &error); - nmtst_assert_success(success, error); - g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - tmp_fmt = nm_setting_802_1x_get_phase2_private_key_format(s_8021x); - g_assert(tmp_fmt == format); - - /* Make sure the password is what we expect */ - pw = nm_setting_802_1x_get_phase2_private_key_password(s_8021x); - g_assert(pw); - g_assert_cmpstr(pw, ==, password); - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - tmp_key = nm_setting_802_1x_get_phase2_private_key_blob(s_8021x); - compare_blob_data("phase2-private-key-import", path, tmp_key); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { - g_object_get(s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL); - check_scheme_path(tmp_key, path); - g_bytes_unref(tmp_key); - } else - g_assert_not_reached(); - - /* If it's PKCS#12 ensure the client cert is the same value */ - if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { - g_object_get(s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL); - g_assert(tmp_key); - - g_object_get(s_8021x, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &client_cert, NULL); - g_assert(client_cert); - - /* make sure they are the same */ - g_assert(g_bytes_equal(tmp_key, client_cert)); - - g_bytes_unref(tmp_key); - g_bytes_unref(client_cert); - } - - g_object_unref(s_8021x); -} - -static void -test_wrong_password_keeps_data(const char *path, const char *password) -{ - NMSetting8021x * s_8021x; - gboolean success; - NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - GError * error = NULL; - const char * pw; - - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - g_assert(s_8021x); - - success = nm_setting_802_1x_set_private_key(s_8021x, - path, - password, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - &format, - &error); - nmtst_assert_success(success, error); - g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - - /* Now try to set it to something that's not a certificate */ - format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - success = nm_setting_802_1x_set_private_key(s_8021x, - "Makefile.am", - password, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - &format, - &error); - nmtst_assert_no_success(success, error); - g_assert(format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - g_clear_error(&error); - - /* Make sure the password hasn't changed */ - pw = nm_setting_802_1x_get_private_key_password(s_8021x); - g_assert(pw); - g_assert_cmpstr(pw, ==, password); - - g_object_unref(s_8021x); -} - -static void -test_clear_private_key(const char *path, const char *password) -{ - NMSetting8021x * s_8021x; - gboolean success; - NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - GError * error = NULL; - const char * pw; - - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - g_assert(s_8021x); - - success = nm_setting_802_1x_set_private_key(s_8021x, - path, - password, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - &format, - &error); - nmtst_assert_success(success, error); - g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - - /* Make sure the password is what we expect */ - pw = nm_setting_802_1x_get_private_key_password(s_8021x); - g_assert(pw); - g_assert_cmpstr(pw, ==, password); - - /* Now clear it */ - success = nm_setting_802_1x_set_private_key(s_8021x, - NULL, - NULL, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - NULL, - &error); - nmtst_assert_success(success, error); - - /* Ensure the password is also now clear */ - g_assert(!nm_setting_802_1x_get_private_key_password(s_8021x)); - - g_object_unref(s_8021x); -} - -static void -test_wrong_phase2_password_keeps_data(const char *path, const char *password) -{ - NMSetting8021x * s_8021x; - gboolean success; - NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - GError * error = NULL; - const char * pw; - - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - g_assert(s_8021x); - - success = nm_setting_802_1x_set_phase2_private_key(s_8021x, - path, - password, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - &format, - &error); - nmtst_assert_success(success, error); - g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - - /* Now try to set it to something that's not a certificate */ - format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - success = nm_setting_802_1x_set_phase2_private_key(s_8021x, - "Makefile.am", - password, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - &format, - &error); - nmtst_assert_no_success(success, error); - g_assert(format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - g_clear_error(&error); - - /* Make sure the password hasn't changed */ - pw = nm_setting_802_1x_get_phase2_private_key_password(s_8021x); - g_assert(pw); - g_assert_cmpstr(pw, ==, password); - - g_object_unref(s_8021x); -} - -static void -test_clear_phase2_private_key(const char *path, const char *password) -{ - NMSetting8021x * s_8021x; - gboolean success; - NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - GError * error = NULL; - const char * pw; - - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - g_assert(s_8021x); - - success = nm_setting_802_1x_set_phase2_private_key(s_8021x, - path, - password, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - &format, - &error); - nmtst_assert_success(success, error); - g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - - /* Make sure the password is what we expect */ - pw = nm_setting_802_1x_get_phase2_private_key_password(s_8021x); - g_assert(pw); - g_assert_cmpstr(pw, ==, password); - - /* Now clear it */ - success = nm_setting_802_1x_set_phase2_private_key(s_8021x, - NULL, - NULL, - NM_SETTING_802_1X_CK_SCHEME_BLOB, - NULL, - &error); - nmtst_assert_success(success, error); - - /* Ensure the password is also now clear */ - g_assert(!nm_setting_802_1x_get_phase2_private_key_password(s_8021x)); - - g_object_unref(s_8021x); -} - -static void -test_8021x(gconstpointer test_data) -{ - char **parts, *path, *password; - - parts = g_strsplit((const char *) test_data, ", ", -1); - g_assert_cmpint(g_strv_length(parts), ==, 2); - - path = g_build_filename(TEST_CERT_DIR, parts[0], NULL); - password = parts[1]; - - /* Test phase1 and phase2 path scheme */ - test_private_key_import(path, password, NM_SETTING_802_1X_CK_SCHEME_PATH); - test_phase2_private_key_import(path, password, NM_SETTING_802_1X_CK_SCHEME_PATH); - - /* Test phase1 and phase2 blob scheme */ - test_private_key_import(path, password, NM_SETTING_802_1X_CK_SCHEME_BLOB); - test_phase2_private_key_import(path, password, NM_SETTING_802_1X_CK_SCHEME_BLOB); - - /* Test that using a wrong password does not change existing data */ - test_wrong_password_keeps_data(path, password); - test_wrong_phase2_password_keeps_data(path, password); - - /* Test clearing the private key */ - test_clear_private_key(path, password); - test_clear_phase2_private_key(path, password); - - g_free(path); - g_strfreev(parts); -} - -/*****************************************************************************/ - -static void -create_bond_connection(NMConnection **con, NMSettingBond **s_bond) -{ - NMSettingConnection *s_con; - - g_assert(con); - g_assert(s_bond); - - *con = nmtst_create_minimal_connection("bond", NULL, NM_SETTING_BOND_SETTING_NAME, &s_con); - - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bond0", NULL); - - *s_bond = (NMSettingBond *) nm_setting_bond_new(); - g_assert(*s_bond); - - nm_connection_add_setting(*con, NM_SETTING(*s_bond)); -} - -#define test_verify_options(exp, ...) _test_verify_options(exp, NM_MAKE_STRV(__VA_ARGS__)) - -static void -_test_verify_options(gboolean expected_result, const char *const *options) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingBond * s_bond; - const char *const * option; - - g_assert(NM_PTRARRAY_LEN(options) % 2 == 0); - - create_bond_connection(&con, &s_bond); - - for (option = options; option[0]; option += 2) - g_assert(nm_setting_bond_add_option(s_bond, option[0], option[1])); - - if (expected_result) { - nmtst_assert_connection_verifies_and_normalizable(con); - } else { - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - } -} - -static void -test_bond_verify(void) -{ - test_verify_options(TRUE, "mode", "3", "arp_interval", "0"); - test_verify_options(FALSE, - /* arp_interval not supported in balance-alb mode */ - "mode", - "balance-alb", - "arp_interval", - "1", - "arp_ip_target", - "1.2.3.4"); - test_verify_options(FALSE, - /* arp_ip_target requires arp_interval */ - "mode", - "balance-rr", - "arp_ip_target", - "1.2.3.4"); - test_verify_options(TRUE, - "mode", - "balance-rr", - "arp_interval", - "1", - "arp_ip_target", - "1.2.3.4"); - test_verify_options(FALSE, - /* num_grat_arp, num_unsol_na cannot be different */ - "mode", - "balance-rr", - "num_grat_arp", - "3", - "num_unsol_na", - "4"); - test_verify_options(TRUE, "mode", "balance-rr", "num_grat_arp", "5", "num_unsol_na", "5"); - test_verify_options(TRUE, "mode", "active-backup", "primary", "eth0"); - test_verify_options(FALSE, - /* primary requires mode=active-backup */ - "mode", - "802.3ad", - "primary", - "eth0"); - test_verify_options(TRUE, "mode", "802.3ad", "lacp_rate", "fast"); - test_verify_options(FALSE, - /* lacp_rate=fast requires mode=802.3ad */ - "mode", - "balance-rr", - "lacp_rate", - "fast"); - test_verify_options(TRUE, "mode", "802.3ad", "ad_actor_system", "ae:00:11:33:44:55"); - test_verify_options(TRUE, "mode", "0", "miimon", "0", "updelay", "0", "downdelay", "0"); - test_verify_options(TRUE, "mode", "0", "downdelay", "0", "updelay", "0"); - test_verify_options(TRUE, - "mode", - "0", - "miimon", - "100", - "arp_ip_target", - "1.1.1.1", - "arp_interval", - "200"); - test_verify_options(TRUE, - "mode", - "0", - "downdelay", - "100", - "arp_ip_target", - "1.1.1.1", - "arp_interval", - "200"); -} - -static void -test_bond_compare_options(gboolean exp_res, const char **opts1, const char **opts2) -{ - gs_unref_object NMSettingBond *s_bond1 = NULL, *s_bond2 = NULL; - const char ** p; - - s_bond1 = (NMSettingBond *) nm_setting_bond_new(); - g_assert(s_bond1); - s_bond2 = (NMSettingBond *) nm_setting_bond_new(); - g_assert(s_bond2); - - for (p = opts1; p[0] && p[1]; p += 2) - g_assert(nm_setting_bond_add_option(s_bond1, p[0], p[1])); - - for (p = opts2; p[0] && p[1]; p += 2) - g_assert(nm_setting_bond_add_option(s_bond2, p[0], p[1])); - - g_assert_cmpint(nm_setting_compare((NMSetting *) s_bond1, - (NMSetting *) s_bond2, - NM_SETTING_COMPARE_FLAG_EXACT), - ==, - exp_res); -} - -static void -test_bond_compare(void) -{ - test_bond_compare_options(TRUE, - ((const char *[]){"mode", "balance-rr", "miimon", "1", NULL}), - ((const char *[]){"mode", "balance-rr", "miimon", "1", NULL})); - test_bond_compare_options(FALSE, - ((const char *[]){"mode", "balance-rr", "miimon", "1", NULL}), - ((const char *[]){"mode", "balance-rr", "miimon", "2", NULL})); - - test_bond_compare_options(FALSE, - ((const char *[]){"miimon", "1", NULL}), - ((const char *[]){"miimon", "1", "updelay", "0", NULL})); - - test_bond_compare_options(FALSE, - ((const char *[]){"num_grat_arp", "2", NULL}), - ((const char *[]){"num_grat_arp", "1", NULL})); - test_bond_compare_options(FALSE, - ((const char *[]){"num_grat_arp", "3", NULL}), - ((const char *[]){"num_unsol_na", "3", NULL})); - test_bond_compare_options(FALSE, - ((const char *[]){"num_grat_arp", "4", NULL}), - ((const char *[]){"num_unsol_na", "4", "num_grat_arp", "4", NULL})); - - test_bond_compare_options(FALSE, - ((const char *[]){"mode", "balance-rr", "miimon", "100", NULL}), - ((const char *[]){"mode", "balance-rr", NULL})); -} - -static void -test_bond_normalize_options(const char **opts1, const char **opts2) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingBond * s_bond; - GError * error = NULL; - gboolean success; - const char ** p; - int num = 0; - - create_bond_connection(&con, &s_bond); - - for (p = opts1; p[0] && p[1]; p += 2) - g_assert(nm_setting_bond_add_option(s_bond, p[0], p[1])); - - nmtst_assert_connection_verifies_and_normalizable(con); - nmtst_connection_normalize(con); - success = nm_setting_verify((NMSetting *) s_bond, con, &error); - nmtst_assert_success(success, error); - - for (p = opts2; p[0] && p[1]; p += 2) { - g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, p[0]), ==, p[1]); - num++; - } - - g_assert_cmpint(num, ==, nm_setting_bond_get_num_options(s_bond)); -} - -static void -test_bond_normalize(void) -{ - test_bond_normalize_options( - ((const char *[]){"mode", "802.3ad", "ad_actor_system", "00:02:03:04:05:06", NULL}), - ((const char *[]){"mode", "802.3ad", "ad_actor_system", "00:02:03:04:05:06", NULL})); - test_bond_normalize_options(((const char *[]){"mode", "1", "miimon", "1", NULL}), - ((const char *[]){"mode", "active-backup", "miimon", "1", NULL})); - test_bond_normalize_options( - ((const char *[]){"mode", "balance-alb", "tlb_dynamic_lb", "1", NULL}), - ((const char *[]){"mode", "balance-alb", NULL})); - test_bond_normalize_options( - ((const char *[]){"mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL}), - ((const char *[]){"mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL})); - test_bond_normalize_options( - ((const char - *[]){"mode", "balance-rr", "ad_actor_sys_prio", "4", "packets_per_slave", "3", NULL}), - ((const char *[]){"mode", "balance-rr", "packets_per_slave", "3", NULL})); -} - -/*****************************************************************************/ - -#define DCB_FLAGS_ALL \ - (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) - -static void -test_dcb_flags_valid(void) -{ - gs_unref_object NMSettingDcb *s_dcb = NULL; - GError * error = NULL; - gboolean success; - guint i; - - s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); - g_assert(s_dcb); - - g_assert_cmpint(nm_setting_dcb_get_app_fcoe_flags(s_dcb), ==, 0); - g_assert_cmpint(nm_setting_dcb_get_app_iscsi_flags(s_dcb), ==, 0); - g_assert_cmpint(nm_setting_dcb_get_app_fip_flags(s_dcb), ==, 0); - g_assert_cmpint(nm_setting_dcb_get_priority_flow_control_flags(s_dcb), ==, 0); - g_assert_cmpint(nm_setting_dcb_get_priority_group_flags(s_dcb), ==, 0); - - g_object_set(G_OBJECT(s_dcb), - NM_SETTING_DCB_APP_FCOE_FLAGS, - DCB_FLAGS_ALL, - NM_SETTING_DCB_APP_ISCSI_FLAGS, - DCB_FLAGS_ALL, - NM_SETTING_DCB_APP_FIP_FLAGS, - DCB_FLAGS_ALL, - NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, - DCB_FLAGS_ALL, - NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, - DCB_FLAGS_ALL, - NULL); - /* Priority Group Bandwidth must total 100% */ - for (i = 0; i < 7; i++) - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, i, 12); - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 7, 16); - - success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); - g_assert_no_error(error); - g_assert(success); - - g_assert_cmpint(nm_setting_dcb_get_app_fcoe_flags(s_dcb), ==, DCB_FLAGS_ALL); - g_assert_cmpint(nm_setting_dcb_get_app_iscsi_flags(s_dcb), ==, DCB_FLAGS_ALL); - g_assert_cmpint(nm_setting_dcb_get_app_fip_flags(s_dcb), ==, DCB_FLAGS_ALL); - g_assert_cmpint(nm_setting_dcb_get_priority_flow_control_flags(s_dcb), ==, DCB_FLAGS_ALL); - g_assert_cmpint(nm_setting_dcb_get_priority_group_flags(s_dcb), ==, DCB_FLAGS_ALL); -} - -#define TEST_FLAG(p, f, v) \ - { \ - /* GObject property min/max should ensure the property does not get set to \ - * the invalid value, so we ensure the value we just tried to set is 0 and \ - * that verify is successful since the property never got set. \ - */ \ - g_object_set(G_OBJECT(s_dcb), p, v, NULL); \ - g_assert_cmpint(f(s_dcb), ==, 0); \ - success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ - g_assert_no_error(error); \ - g_assert(success); \ - } - -static void -test_dcb_flags_invalid(void) -{ - gs_unref_object NMSettingDcb *s_dcb = NULL; - GError * error = NULL; - gboolean success; - - s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); - g_assert(s_dcb); - - NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); - TEST_FLAG(NM_SETTING_DCB_APP_FCOE_FLAGS, nm_setting_dcb_get_app_fcoe_flags, 0x332523); - g_test_assert_expected_messages(); - - NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); - TEST_FLAG(NM_SETTING_DCB_APP_ISCSI_FLAGS, nm_setting_dcb_get_app_iscsi_flags, 0xFF); - g_test_assert_expected_messages(); - - NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); - TEST_FLAG(NM_SETTING_DCB_APP_FIP_FLAGS, nm_setting_dcb_get_app_fip_flags, 0x1111); - g_test_assert_expected_messages(); - - NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); - TEST_FLAG(NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, - nm_setting_dcb_get_priority_flow_control_flags, - G_MAXUINT32); - g_test_assert_expected_messages(); - - NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); - TEST_FLAG( - NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, - nm_setting_dcb_get_priority_group_flags, - (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) - + 1); - g_test_assert_expected_messages(); -} - -#define TEST_APP_PRIORITY(lcprop, ucprop, v) \ - { \ - g_object_set(G_OBJECT(s_dcb), \ - NM_SETTING_DCB_APP_##ucprop##_FLAGS, \ - NM_SETTING_DCB_FLAG_NONE, \ - NULL); \ - \ - g_object_set(G_OBJECT(s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, v, NULL); \ - g_assert_cmpint(nm_setting_dcb_get_app_##lcprop##_priority(s_dcb), ==, v); \ - \ - /* Assert that the setting is invalid while the app is disabled unless v is default */ \ - success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ - if (v >= 0) { \ - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); \ - g_assert(success == FALSE); \ - } else { \ - g_assert_no_error(error); \ - g_assert(success); \ - } \ - g_clear_error(&error); \ - \ - /* Set the enable flag and re-verify, this time it should be valid */ \ - g_object_set(G_OBJECT(s_dcb), \ - NM_SETTING_DCB_APP_##ucprop##_FLAGS, \ - NM_SETTING_DCB_FLAG_ENABLE, \ - NULL); \ - success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ - g_assert_no_error(error); \ - g_assert(success); \ - \ - g_object_set(G_OBJECT(s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, 0, NULL); \ - } - -static void -test_dcb_app_priorities(void) -{ - gs_unref_object NMSettingDcb *s_dcb = NULL; - GError * error = NULL; - gboolean success; - - s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); - g_assert(s_dcb); - - /* Defaults */ - g_assert_cmpint(nm_setting_dcb_get_app_fcoe_priority(s_dcb), ==, -1); - g_assert_cmpint(nm_setting_dcb_get_app_iscsi_priority(s_dcb), ==, -1); - g_assert_cmpint(nm_setting_dcb_get_app_fip_priority(s_dcb), ==, -1); - - TEST_APP_PRIORITY(fcoe, FCOE, 6); - TEST_APP_PRIORITY(iscsi, ISCSI, 5); - TEST_APP_PRIORITY(fip, FIP, 4); - - TEST_APP_PRIORITY(fcoe, FCOE, -1); - TEST_APP_PRIORITY(iscsi, ISCSI, -1); - TEST_APP_PRIORITY(fip, FIP, -1); -} - -#define TEST_PRIORITY_VALID(fn, id, val, flagsprop, verify) \ - { \ - /* Assert that setting the value gets the same value back out */ \ - nm_setting_dcb_set_priority_##fn(s_dcb, id, val); \ - g_assert_cmpint(nm_setting_dcb_get_priority_##fn(s_dcb, id), ==, val); \ - \ - if (verify) { \ - if (val != 0) { \ - /* Assert that verify fails because the flags do not include 'enabled' \ - * and a value has been set. \ - */ \ - success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); \ - g_assert(success == FALSE); \ - g_clear_error(&error); \ - } \ - \ - /* Assert that adding the 'enabled' flag verifies the setting */ \ - g_object_set(G_OBJECT(s_dcb), \ - NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, \ - NM_SETTING_DCB_FLAG_ENABLE, \ - NULL); \ - success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ - g_assert_no_error(error); \ - g_assert(success); \ - } \ - \ - /* Reset everything */ \ - g_object_set(G_OBJECT(s_dcb), \ - NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, \ - NM_SETTING_DCB_FLAG_NONE, \ - NULL); \ - nm_setting_dcb_set_priority_##fn(s_dcb, id, 0); \ - } - -/* If Priority Groups are enabled, PG bandwidth must equal 100% */ -#define SET_VALID_PRIORITY_GROUP_BANDWIDTH \ - { \ - guint x; \ - for (x = 0; x < 7; x++) \ - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, x, 12); \ - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 7, 16); \ - } - -static void -test_dcb_priorities_valid(void) -{ - gs_unref_object NMSettingDcb *s_dcb = NULL; - GError * error = NULL; - gboolean success; - guint i; - - s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); - g_assert(s_dcb); - - for (i = 0; i < 8; i++) - TEST_PRIORITY_VALID(flow_control, i, TRUE, FLOW_CONTROL, TRUE); - - SET_VALID_PRIORITY_GROUP_BANDWIDTH - for (i = 0; i < 8; i++) { - TEST_PRIORITY_VALID(group_id, i, i, GROUP, TRUE); - TEST_PRIORITY_VALID(group_id, i, 7 - i, GROUP, TRUE); - } - - /* Clear PG bandwidth from earlier tests */ - for (i = 0; i < 8; i++) - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, i, 0); - - /* Priority Group Bandwidth must add up to 100% if enabled, which requires - * some dancing for verifying individual values here. - */ - for (i = 0; i < 8; i++) { - guint other = 7 - (i % 8); - - /* Set another priority group to the remaining bandwidth */ - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, other, 100 - i); - TEST_PRIORITY_VALID(group_bandwidth, i, i, GROUP, TRUE); - - /* Set another priority group to the remaining bandwidth */ - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, other, 100 - (7 - i)); - TEST_PRIORITY_VALID(group_bandwidth, i, 7 - i, GROUP, TRUE); - - /* Clear remaining bandwidth */ - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, other, 0); - } - - SET_VALID_PRIORITY_GROUP_BANDWIDTH - for (i = 0; i < 8; i++) { - TEST_PRIORITY_VALID(bandwidth, i, i, GROUP, TRUE); - TEST_PRIORITY_VALID(bandwidth, i, 7 - i, GROUP, TRUE); - } - - SET_VALID_PRIORITY_GROUP_BANDWIDTH - for (i = 0; i < 8; i++) - TEST_PRIORITY_VALID(strict_bandwidth, i, TRUE, GROUP, TRUE); - - SET_VALID_PRIORITY_GROUP_BANDWIDTH - for (i = 0; i < 8; i++) { - TEST_PRIORITY_VALID(traffic_class, i, i, GROUP, TRUE); - TEST_PRIORITY_VALID(traffic_class, i, 7 - i, GROUP, TRUE); - } -} - -static void -test_dcb_bandwidth_sums(void) -{ - gs_unref_object NMSettingDcb *s_dcb = NULL; - GError * error = NULL; - gboolean success; - - s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); - g_assert(s_dcb); - - /* Assert that setting the value gets the same value back out */ - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 0, 9); - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 1, 10); - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 2, 11); - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 3, 12); - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 4, 13); - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 5, 14); - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 6, 15); - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 7, 16); - - /* Assert verify success when sums total 100% */ - g_object_set(G_OBJECT(s_dcb), - NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, - NM_SETTING_DCB_FLAG_ENABLE, - NULL); - success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); - g_assert_no_error(error); - g_assert(success); - - /* Assert verify fails when sums do not total 100% */ - nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 4, 20); - success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); - g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); - g_assert(success == FALSE); - g_clear_error(&error); -} - -/*****************************************************************************/ - -static void -test_nm_json(void) -{ - g_assert(NM_IN_SET(WITH_JANSSON, 0, 1)); - -#if WITH_JANSSON - g_assert(nm_json_vt()); -#else - g_assert(!nm_json_vt()); -#endif - -#if WITH_JANSSON != defined(JANSSON_SONAME) - #error "WITH_JANSON and JANSSON_SONAME are defined inconsistently." -#endif -} - -/*****************************************************************************/ - -static void -_test_team_config_sync(const char *team_config, - int notify_peer_count, - int notify_peers_interval, - int mcast_rejoin_count, - int mcast_rejoin_interval, - char * runner, - char * runner_hwaddr_policy, /* activebackup */ - GPtrArray * runner_tx_hash, /* lacp, loadbalance */ - char * runner_tx_balancer, /* lacp, loadbalance */ - int runner_tx_balancer_interval, /* lacp, loadbalance */ - gboolean runner_active, /* lacp */ - gboolean runner_fast_rate, /* lacp */ - int runner_sys_prio, /* lacp */ - int runner_min_ports, /* lacp */ - char * runner_agg_select_policy, /* lacp */ - GPtrArray * link_watchers) -{ - gs_unref_object NMSettingTeam *s_team = NULL; - guint i, j; - gboolean found; - - if (!nm_json_vt()) { - g_test_skip("team test requires JSON validation"); - return; - } - - s_team = (NMSettingTeam *) nm_setting_team_new(); - g_assert(s_team); - - g_object_set(s_team, NM_SETTING_TEAM_CONFIG, team_config, NULL); - g_assert_cmpint(nm_setting_team_get_notify_peers_count(s_team), ==, notify_peer_count); - g_assert_cmpint(nm_setting_team_get_notify_peers_interval(s_team), ==, notify_peers_interval); - g_assert_cmpint(nm_setting_team_get_mcast_rejoin_count(s_team), ==, mcast_rejoin_count); - g_assert_cmpint(nm_setting_team_get_mcast_rejoin_interval(s_team), ==, mcast_rejoin_interval); - g_assert_cmpint(nm_setting_team_get_runner_tx_balancer_interval(s_team), - ==, - runner_tx_balancer_interval); - g_assert_cmpint(nm_setting_team_get_runner_active(s_team), ==, runner_active); - g_assert_cmpint(nm_setting_team_get_runner_fast_rate(s_team), ==, runner_fast_rate); - g_assert_cmpint(nm_setting_team_get_runner_sys_prio(s_team), ==, runner_sys_prio); - g_assert_cmpint(nm_setting_team_get_runner_min_ports(s_team), ==, runner_min_ports); - g_assert_cmpstr(nm_setting_team_get_runner(s_team), ==, runner); - g_assert_cmpstr(nm_setting_team_get_runner_hwaddr_policy(s_team), ==, runner_hwaddr_policy); - g_assert_cmpstr(nm_setting_team_get_runner_tx_balancer(s_team), ==, runner_tx_balancer); - g_assert_cmpstr(nm_setting_team_get_runner_agg_select_policy(s_team), - ==, - runner_agg_select_policy); - - if (runner_tx_hash) { - g_assert_cmpint(runner_tx_hash->len, ==, nm_setting_team_get_num_runner_tx_hash(s_team)); - for (i = 0; i < runner_tx_hash->len; i++) { - found = FALSE; - for (j = 0; j < nm_setting_team_get_num_runner_tx_hash(s_team); j++) { - if (nm_streq0(nm_setting_team_get_runner_tx_hash(s_team, j), - runner_tx_hash->pdata[i])) { - found = TRUE; - break; - } - } - g_assert(found); - } - } - - if (link_watchers) { - g_assert_cmpint(link_watchers->len, ==, nm_setting_team_get_num_link_watchers(s_team)); - for (i = 0; i < link_watchers->len; i++) { - found = FALSE; - for (j = 0; j < nm_setting_team_get_num_link_watchers(s_team); j++) { - if (nm_team_link_watcher_equal(link_watchers->pdata[i], - nm_setting_team_get_link_watcher(s_team, j))) { - found = TRUE; - break; - } - } - g_assert(found); - } - } - - g_assert(nm_setting_verify((NMSetting *) s_team, NULL, NULL)); -} - -static void -test_runner_roundrobin_sync_from_config(void) -{ - _test_team_config_sync("", - -1, - -1, - -1, - -1, - NULL, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - NULL); -} - -static void -test_runner_broadcast_sync_from_config(void) -{ - _test_team_config_sync("{\"runner\": {\"name\": \"broadcast\"}}", - -1, - -1, - -1, - -1, - NM_SETTING_TEAM_RUNNER_BROADCAST, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - NULL); -} - -static void -test_runner_random_sync_from_config(void) -{ - _test_team_config_sync("{\"runner\": {\"name\": \"random\"}}", - -1, - -1, - -1, - -1, - NM_SETTING_TEAM_RUNNER_RANDOM, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - NULL); -} - -static void -test_runner_activebackup_sync_from_config(void) -{ - _test_team_config_sync("{\"runner\": {\"name\": \"activebackup\"}}", - -1, - -1, - -1, - -1, - NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - NULL); -} - -static void -test_runner_loadbalance_sync_from_config(void) -{ - gs_unref_ptrarray GPtrArray *tx_hash = NULL; - - tx_hash = g_ptr_array_new_with_free_func(g_free); - g_ptr_array_add(tx_hash, g_strdup("eth")); - g_ptr_array_add(tx_hash, g_strdup("ipv4")); - g_ptr_array_add(tx_hash, g_strdup("ipv6")); - - _test_team_config_sync("{\"runner\": {\"name\": \"loadbalance\"}}", - -1, - -1, - -1, - -1, - NM_SETTING_TEAM_RUNNER_LOADBALANCE, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - NULL); - - _test_team_config_sync("{\"runner\": {\"name\": \"loadbalance\", " - "\"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"]}}", - -1, - -1, - -1, - -1, - NM_SETTING_TEAM_RUNNER_LOADBALANCE, - NULL, - tx_hash, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - NULL); - - _test_team_config_sync( - "{\"runner\": {\"name\": \"loadbalance\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"], " - "\"tx_balancer\": {\"name\": \"basic\", \"balancing_interval\": 30}}}", - -1, - -1, - -1, - -1, - NM_SETTING_TEAM_RUNNER_LOADBALANCE, - NULL, - tx_hash, - "basic", - 30, - TRUE, - FALSE, - -1, - -1, - NULL, - NULL); -} - -static void -test_runner_lacp_sync_from_config(void) -{ - gs_unref_ptrarray GPtrArray *tx_hash = NULL; - - tx_hash = g_ptr_array_new_with_free_func(g_free); - g_ptr_array_add(tx_hash, g_strdup("eth")); - g_ptr_array_add(tx_hash, g_strdup("ipv4")); - g_ptr_array_add(tx_hash, g_strdup("ipv6")); - - _test_team_config_sync( - "{\"runner\": {\"name\": \"lacp\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"]}}", - -1, - -1, - -1, - -1, - NM_SETTING_TEAM_RUNNER_LACP, - NULL, - tx_hash, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - NULL); - - _test_team_config_sync( - "{\"runner\": {\"name\": \"lacp\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"], " - "\"active\": false, \"fast_rate\": true, \"sys_prio\": 10, \"min_ports\": 5, " - "\"agg_select_policy\": \"port_config\"}}", - -1, - -1, - -1, - -1, - NM_SETTING_TEAM_RUNNER_LACP, - NULL, - tx_hash, - NULL, - -1, - FALSE, - TRUE, - 10, - 5, - "port_config", - NULL); -} - -static void -test_watcher_ethtool_sync_from_config(void) -{ - gs_unref_ptrarray GPtrArray *link_watchers = NULL; - - link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); - g_ptr_array_add(link_watchers, nm_team_link_watcher_new_ethtool(0, 0, NULL)); - _test_team_config_sync("{\"link_watch\": {\"name\": \"ethtool\"}}", - -1, - -1, - -1, - -1, - NULL, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - link_watchers); -} - -static void -test_watcher_nsna_ping_sync_from_config(void) -{ - gs_unref_ptrarray GPtrArray *link_watchers = NULL; - - link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); - g_ptr_array_add(link_watchers, - nm_team_link_watcher_new_nsna_ping(0, 0, 3, "target.host", NULL)); - _test_team_config_sync( - "{\"link_watch\": {\"name\": \"nsna_ping\", \"target_host\": \"target.host\"}}", - -1, - -1, - -1, - -1, - NULL, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - link_watchers); -} - -static void -test_watcher_arp_ping_sync_from_config(void) -{ - gs_unref_ptrarray GPtrArray *link_watchers = NULL; - - link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); - g_ptr_array_add( - link_watchers, - nm_team_link_watcher_new_arp_ping(0, 0, 3, "target.host", "source.host", 0, NULL)); - _test_team_config_sync( - "{\"link_watch\": {\"name\": \"arp_ping\", \"target_host\": \"target.host\", " - "\"source_host\": \"source.host\"}}", - -1, - -1, - -1, - -1, - NULL, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - link_watchers); -} - -static void -test_multiple_watchers_sync_from_config(void) -{ - gs_unref_ptrarray GPtrArray *link_watchers = NULL; - - link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); - g_ptr_array_add(link_watchers, nm_team_link_watcher_new_ethtool(2, 4, NULL)); - g_ptr_array_add(link_watchers, - nm_team_link_watcher_new_nsna_ping(3, 6, 9, "target.host", NULL)); - g_ptr_array_add( - link_watchers, - nm_team_link_watcher_new_arp_ping(5, - 10, - 15, - "target.host", - "source.host", - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE - | NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE - | NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS, - NULL)); - _test_team_config_sync( - "{\"link_watch\": [" - "{\"name\": \"ethtool\", \"delay_up\": 2, \"delay_down\": 4}, " - "{\"name\": \"arp_ping\", \"init_wait\": 5, \"interval\": 10, \"missed_max\": 15, " - "\"target_host\": \"target.host\", \"source_host\": \"source.host\", " - "\"validate_active\": true, \"validate_inactive\": true, \"send_always\": true}, " - "{\"name\": \"nsna_ping\", \"init_wait\": 3, \"interval\": 6, \"missed_max\": 9, " - "\"target_host\": \"target.host\"}]}", - -1, - -1, - -1, - -1, - NULL, - NULL, - NULL, - NULL, - -1, - TRUE, - FALSE, - -1, - -1, - NULL, - link_watchers); -} - -/*****************************************************************************/ - -static void -_test_team_port_config_sync(const char *team_port_config, - int queue_id, - int prio, - gboolean sticky, - int lacp_prio, - int lacp_key, - GPtrArray * link_watchers) -{ - gs_unref_object NMSettingTeamPort *s_team_port = NULL; - guint i, j; - gboolean found; - - if (!nm_json_vt()) { - g_test_skip("team test requires JSON validation"); - return; - } - - s_team_port = (NMSettingTeamPort *) nm_setting_team_port_new(); - g_assert(s_team_port); - - g_object_set(s_team_port, NM_SETTING_TEAM_CONFIG, team_port_config, NULL); - g_assert(nm_setting_team_port_get_queue_id(s_team_port) == queue_id); - g_assert(nm_setting_team_port_get_prio(s_team_port) == prio); - g_assert(nm_setting_team_port_get_sticky(s_team_port) == sticky); - g_assert(nm_setting_team_port_get_lacp_prio(s_team_port) == lacp_prio); - g_assert(nm_setting_team_port_get_lacp_key(s_team_port) == lacp_key); - - if (link_watchers) { - g_assert(link_watchers->len == nm_setting_team_port_get_num_link_watchers(s_team_port)); - for (i = 0; i < link_watchers->len; i++) { - found = FALSE; - for (j = 0; j < nm_setting_team_port_get_num_link_watchers(s_team_port); j++) { - if (nm_team_link_watcher_equal( - link_watchers->pdata[i], - nm_setting_team_port_get_link_watcher(s_team_port, j))) { - found = TRUE; - break; - } - } - g_assert(found); - } - } - - g_assert(nm_setting_verify((NMSetting *) s_team_port, NULL, NULL)); -} - -static void -test_team_port_default(void) -{ - _test_team_port_config_sync("", -1, 0, FALSE, -1, -1, NULL); -} - -static void -test_team_port_queue_id(void) -{ - _test_team_port_config_sync("{\"queue_id\": 3}", 3, 0, FALSE, -1, -1, NULL); - _test_team_port_config_sync("{\"queue_id\": 0}", 0, 0, FALSE, -1, -1, NULL); -} - -static void -test_team_port_prio(void) -{ - _test_team_port_config_sync("{\"prio\": 6}", -1, 6, FALSE, -1, -1, NULL); - _test_team_port_config_sync("{\"prio\": 0}", -1, 0, FALSE, -1, -1, NULL); -} - -static void -test_team_port_sticky(void) -{ - _test_team_port_config_sync("{\"sticky\": true}", -1, 0, TRUE, -1, -1, NULL); - _test_team_port_config_sync("{\"sticky\": false}", -1, 0, FALSE, -1, -1, NULL); -} - -static void -test_team_port_lacp_prio(void) -{ - _test_team_port_config_sync("{\"lacp_prio\": 9}", -1, 0, FALSE, 9, -1, NULL); - _test_team_port_config_sync("{\"lacp_prio\": 0}", -1, 0, FALSE, 0, -1, NULL); -} - -static void -test_team_port_lacp_key(void) -{ - _test_team_port_config_sync("{\"lacp_key\": 12}", -1, 0, FALSE, -1, 12, NULL); - _test_team_port_config_sync("{\"lacp_key\": 0}", -1, 0, FALSE, -1, 0, NULL); -} - -static void -test_team_port_full_config(void) -{ - gs_unref_ptrarray GPtrArray *link_watchers = NULL; - - link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); - g_ptr_array_add( - link_watchers, - nm_team_link_watcher_new_arp_ping(0, - 3, - 3, - "1.2.3.2", - "1.2.3.1", - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE, - NULL)); - g_ptr_array_add( - link_watchers, - nm_team_link_watcher_new_arp_ping(1, - 1, - 0, - "1.2.3.4", - "1.2.3.1", - NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS, - NULL)); - - _test_team_port_config_sync( - "{\"queue_id\": 10, \"prio\": 20, \"sticky\": true, \"lacp_prio\": 30, " - "\"lacp_key\": 40, \"link_watch\": [" - "{\"name\": \"arp_ping\", \"interval\": 3, \"target_host\": \"1.2.3.2\", " - "\"source_host\": \"1.2.3.1\", \"validate_inactive\": true}, " - "{\"name\": \"arp_ping\", \"init_wait\": 1, \"interval\": 1, " - "\"target_host\": \"1.2.3.4\", \"source_host\": \"1.2.3.1\", " - "\"send_always\": true}]}", - 10, - 20, - true, - 30, - 40, - NULL); -} - -/*****************************************************************************/ - -static void -_check_team_setting(NMSetting *setting) -{ - gs_unref_object NMSetting *setting2 = NULL; - gs_unref_object NMSetting *setting_clone = NULL; - gboolean is_port = NM_IS_SETTING_TEAM_PORT(setting); - gs_unref_variant GVariant *variant2 = NULL; - gs_unref_variant GVariant *variant3 = NULL; - - g_assert(NM_IS_SETTING_TEAM(setting) || is_port); - - setting2 = g_object_new(G_OBJECT_TYPE(setting), - is_port ? NM_SETTING_TEAM_PORT_CONFIG : NM_SETTING_TEAM_CONFIG, - is_port ? nm_setting_team_port_get_config(NM_SETTING_TEAM_PORT(setting)) - : nm_setting_team_get_config(NM_SETTING_TEAM(setting)), - NULL); - - if (nm_json_vt()) - nmtst_assert_setting_is_equal(setting, setting2, NM_SETTING_COMPARE_FLAG_EXACT); - - g_clear_object(&setting2); - - nmtst_assert_setting_dbus_roundtrip(setting); - - /* OK, now parse the setting only from the D-Bus variant, but removing the JSON config. - * For that, we have to "drop" the JSON and we do that by resetting the property. - * This causes JSON to be regenerated and it's in a normalized form that will compare - * equal. */ - setting_clone = nm_setting_duplicate(setting); - setting = setting_clone; - if (is_port) { - g_object_set(setting, - NM_SETTING_TEAM_PORT_STICKY, - nm_setting_team_port_get_sticky(NM_SETTING_TEAM_PORT(setting)), - NULL); - } else { - g_object_set(setting, - NM_SETTING_TEAM_RUNNER_SYS_PRIO, - nm_setting_team_get_runner_sys_prio(NM_SETTING_TEAM(setting)), - NULL); - } - variant2 = _nm_setting_to_dbus(setting, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); - variant3 = nm_utils_gvariant_vardict_filter_drop_one(variant2, "config"); - setting2 = nmtst_assert_setting_dbus_new(G_OBJECT_TYPE(setting), variant3); - nmtst_assert_setting_is_equal(setting, setting2, NM_SETTING_COMPARE_FLAG_EXACT); -} - -static void -test_team_setting(void) -{ - gs_unref_variant GVariant *variant = nmtst_variant_from_string( - G_VARIANT_TYPE_VARDICT, - "{'config': <'{\"link_watch\": {\"name\": \"ethtool\"}}'>, 'interface-name': <'nm-team'>, " - "'link-watchers': <[{'name': <'ethtool'>}]>}"); - gs_free_error GError *error = NULL; - gs_unref_object NMSetting * setting = NULL; - nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher1 = - nm_team_link_watcher_new_nsna_ping(1, 3, 4, "bbb", NULL); - nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher2 = - nm_team_link_watcher_new_arp_ping2(1, 3, 4, -1, "ccc", "ddd", 0, NULL); - - g_assert(watcher1); - g_assert(watcher2); - - setting = _nm_setting_new_from_dbus(NM_TYPE_SETTING_TEAM, - variant, - NULL, - NM_SETTING_PARSE_FLAGS_STRICT, - &error); - nmtst_assert_success(setting, error); - _check_team_setting(setting); - - g_assert_cmpstr(nm_setting_team_get_config(NM_SETTING_TEAM(setting)), - ==, - "{\"link_watch\": {\"name\": \"ethtool\"}}"); - g_assert_cmpint(nm_setting_team_get_num_link_watchers(NM_SETTING_TEAM(setting)), ==, 1); - - g_object_set(setting, NM_SETTING_TEAM_RUNNER_SYS_PRIO, (int) 10, NULL); - - _check_team_setting(setting); - g_assert_cmpint(nm_setting_team_get_num_link_watchers(NM_SETTING_TEAM(setting)), ==, 1); - g_assert_cmpstr( - nm_setting_team_get_config(NM_SETTING_TEAM(setting)), - ==, - "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"ethtool\" } }"); - - nm_setting_team_remove_link_watcher(NM_SETTING_TEAM(setting), 0); - - _check_team_setting(setting); - g_assert_cmpint(nm_setting_team_get_num_link_watchers(NM_SETTING_TEAM(setting)), ==, 0); - g_assert_cmpstr(nm_setting_team_get_config(NM_SETTING_TEAM(setting)), - ==, - "{ \"runner\": { \"sys_prio\": 10 } }"); - - nm_setting_team_add_link_watcher(NM_SETTING_TEAM(setting), watcher1); - _check_team_setting(setting); - g_assert_cmpstr( - nm_setting_team_get_config(NM_SETTING_TEAM(setting)), - ==, - "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"nsna_ping\", " - "\"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, \"target_host\": \"bbb\" } }"); - - nm_setting_team_add_link_watcher(NM_SETTING_TEAM(setting), watcher2); - _check_team_setting(setting); - g_assert_cmpstr( - nm_setting_team_get_config(NM_SETTING_TEAM(setting)), - ==, - "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": [ { \"name\": \"nsna_ping\", " - "\"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, \"target_host\": \"bbb\" }, { " - "\"name\": \"arp_ping\", \"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, " - "\"source_host\": \"ddd\", \"target_host\": \"ccc\" } ] }"); - - nm_setting_team_remove_link_watcher(NM_SETTING_TEAM(setting), 0); - nm_setting_team_remove_link_watcher(NM_SETTING_TEAM(setting), 0); - g_object_set(setting, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, (int) 5, NULL); - g_assert_cmpstr( - nm_setting_team_get_config(NM_SETTING_TEAM(setting)), - ==, - "{ \"runner\": { \"tx_balancer\": { \"balancing_interval\": 5 }, \"sys_prio\": 10 } }"); - - g_object_set(setting, NM_SETTING_TEAM_RUNNER, NULL, NULL); - _check_team_setting(setting); - g_assert_cmpstr( - nm_setting_team_get_config(NM_SETTING_TEAM(setting)), - ==, - "{ \"runner\": { \"tx_balancer\": { \"balancing_interval\": 5 }, \"sys_prio\": 10 } }"); - - g_object_set(setting, - NM_SETTING_TEAM_CONFIG, - "{ \"runner\": { \"tx_hash\": [ \"eth\", \"l3\" ] } }", - NULL); - _check_team_setting(setting); -} - -/*****************************************************************************/ - -static void -_setting_ethtool_set_feature(NMSettingEthtool *s_ethtool, const char *opt_name, NMTernary value) -{ - g_assert(NM_IS_SETTING_ETHTOOL(s_ethtool)); - - if (nmtst_get_rand_bool()) { - nm_setting_ethtool_set_feature(s_ethtool, opt_name, value); - return; - } - - if (value == NM_TERNARY_DEFAULT) { - nm_setting_option_set(NM_SETTING(s_ethtool), opt_name, NULL); - return; - } - - if (nmtst_get_rand_bool()) - nm_setting_option_set_boolean(NM_SETTING(s_ethtool), opt_name, value); - else - nm_setting_option_set(NM_SETTING(s_ethtool), opt_name, g_variant_new_boolean(value)); -} - -static NMTernary -_setting_ethtool_get_feature(NMSettingEthtool *s_ethtool, const char *opt_name) -{ - GVariant *v; - gboolean b; - - switch (nmtst_get_rand_uint32() % 3) { - case 0: - return nm_setting_ethtool_get_feature(s_ethtool, opt_name); - case 1: - if (!nm_setting_option_get_boolean(NM_SETTING(s_ethtool), opt_name, &b)) - return NM_TERNARY_DEFAULT; - return b; - default: - v = nm_setting_option_get(NM_SETTING(s_ethtool), opt_name); - if (!v || !g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) - return NM_TERNARY_DEFAULT; - return g_variant_get_boolean(v); - } -} - -static void -test_ethtool_features(void) -{ - gs_unref_object NMConnection *con = NULL; - gs_unref_object NMConnection *con2 = NULL; - gs_unref_object NMConnection *con3 = NULL; - gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - NMSettingConnection * s_con; - NMSettingEthtool * s_ethtool; - NMSettingEthtool * s_ethtool2; - NMSettingEthtool * s_ethtool3; - - con = nmtst_create_minimal_connection("ethtool-1", NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con); - s_ethtool = NM_SETTING_ETHTOOL(nm_setting_ethtool_new()); - nm_connection_add_setting(con, NM_SETTING(s_ethtool)); - - _setting_ethtool_set_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX, NM_TERNARY_TRUE); - _setting_ethtool_set_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_LRO, NM_TERNARY_FALSE); - - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX), - ==, - NM_TERNARY_TRUE); - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_LRO), - ==, - NM_TERNARY_FALSE); - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_SG), - ==, - NM_TERNARY_DEFAULT); - - nmtst_connection_normalize(con); - - variant = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); - - con2 = nm_simple_connection_new_from_dbus(variant, &error); - nmtst_assert_success(con2, error); - - s_ethtool2 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con2, NM_TYPE_SETTING_ETHTOOL)); - - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_RX), - ==, - NM_TERNARY_TRUE); - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_LRO), - ==, - NM_TERNARY_FALSE); - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_SG), - ==, - NM_TERNARY_DEFAULT); - - nmtst_assert_connection_verifies_without_normalization(con2); - - nmtst_assert_connection_equals(con, FALSE, con2, FALSE); - - keyfile = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); - nmtst_assert_success(keyfile, error); - - con3 = nm_keyfile_read(keyfile, - "/ignored/current/working/directory/for/loading/relative/paths", - NM_KEYFILE_HANDLER_FLAGS_NONE, - NULL, - NULL, - &error); - nmtst_assert_success(con3, error); - - nm_keyfile_read_ensure_id(con3, "unused-because-already-has-id"); - nm_keyfile_read_ensure_uuid(con3, "unused-because-already-has-uuid"); - - nmtst_connection_normalize(con3); - - nmtst_assert_connection_equals(con, FALSE, con3, FALSE); - - s_ethtool3 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con3, NM_TYPE_SETTING_ETHTOOL)); - - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_RX), - ==, - NM_TERNARY_TRUE); - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_LRO), - ==, - NM_TERNARY_FALSE); - g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_SG), - ==, - NM_TERNARY_DEFAULT); -} - -static void -test_ethtool_coalesce(void) -{ - gs_unref_object NMConnection *con = NULL; - gs_unref_object NMConnection *con2 = NULL; - gs_unref_object NMConnection *con3 = NULL; - gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - NMSettingConnection * s_con; - NMSettingEthtool * s_ethtool; - NMSettingEthtool * s_ethtool2; - NMSettingEthtool * s_ethtool3; - guint32 u32; - - con = nmtst_create_minimal_connection("ethtool-coalesce", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - &s_con); - s_ethtool = NM_SETTING_ETHTOOL(nm_setting_ethtool_new()); - nm_connection_add_setting(con, NM_SETTING(s_ethtool)); - - nm_setting_option_set_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, 4); - - g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, - &u32)); - g_assert_cmpuint(u32, ==, 4); - - nmtst_connection_normalize(con); - - variant = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); - - con2 = nm_simple_connection_new_from_dbus(variant, &error); - nmtst_assert_success(con2, error); - - s_ethtool2 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con2, NM_TYPE_SETTING_ETHTOOL)); - - g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool2), - NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, - &u32)); - g_assert_cmpuint(u32, ==, 4); - - nmtst_assert_connection_verifies_without_normalization(con2); - - nmtst_assert_connection_equals(con, FALSE, con2, FALSE); - - keyfile = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); - nmtst_assert_success(keyfile, error); - - con3 = nm_keyfile_read(keyfile, - "/ignored/current/working/directory/for/loading/relative/paths", - NM_KEYFILE_HANDLER_FLAGS_NONE, - NULL, - NULL, - &error); - nmtst_assert_success(con3, error); - - nm_keyfile_read_ensure_id(con3, "unused-because-already-has-id"); - nm_keyfile_read_ensure_uuid(con3, "unused-because-already-has-uuid"); - - nmtst_connection_normalize(con3); - - nmtst_assert_connection_equals(con, FALSE, con3, FALSE); - - s_ethtool3 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con3, NM_TYPE_SETTING_ETHTOOL)); - - g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool3), - NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, - &u32)); - g_assert_cmpuint(u32, ==, 4); - - nm_setting_option_set(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, NULL); - g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, - NULL)); - - nm_setting_option_set_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES, 8); - - g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES, - &u32)); - g_assert_cmpuint(u32, ==, 8); - - nm_setting_option_clear_by_name(NM_SETTING(s_ethtool), nm_ethtool_optname_is_coalesce); - g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, - NULL)); - g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES, - NULL)); - g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS, - NULL)); -} - -static void -test_ethtool_ring(void) -{ - gs_unref_object NMConnection *con = NULL; - gs_unref_object NMConnection *con2 = NULL; - gs_unref_object NMConnection *con3 = NULL; - gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - NMSettingConnection * s_con; - NMSettingEthtool * s_ethtool; - NMSettingEthtool * s_ethtool2; - NMSettingEthtool * s_ethtool3; - guint32 out_value; - - con = nmtst_create_minimal_connection("ethtool-ring", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - &s_con); - s_ethtool = NM_SETTING_ETHTOOL(nm_setting_ethtool_new()); - nm_connection_add_setting(con, NM_SETTING(s_ethtool)); - - nm_setting_option_set_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, 4); - - g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, - &out_value)); - g_assert_cmpuint(out_value, ==, 4); - - nmtst_connection_normalize(con); - - variant = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); - - con2 = nm_simple_connection_new_from_dbus(variant, &error); - nmtst_assert_success(con2, error); - - s_ethtool2 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con2, NM_TYPE_SETTING_ETHTOOL)); - - g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool2), - NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, - &out_value)); - g_assert_cmpuint(out_value, ==, 4); - - nmtst_assert_connection_verifies_without_normalization(con2); - - nmtst_assert_connection_equals(con, FALSE, con2, FALSE); - - keyfile = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); - nmtst_assert_success(keyfile, error); - - con3 = nm_keyfile_read(keyfile, - "/ignored/current/working/directory/for/loading/relative/paths", - NM_KEYFILE_HANDLER_FLAGS_NONE, - NULL, - NULL, - &error); - nmtst_assert_success(con3, error); - - nm_keyfile_read_ensure_id(con3, "unused-because-already-has-id"); - nm_keyfile_read_ensure_uuid(con3, "unused-because-already-has-uuid"); - - nmtst_connection_normalize(con3); - - nmtst_assert_connection_equals(con, FALSE, con3, FALSE); - - s_ethtool3 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con3, NM_TYPE_SETTING_ETHTOOL)); - - g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool3), - NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, - &out_value)); - g_assert_cmpuint(out_value, ==, 4); - - nm_setting_option_set(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, NULL); - g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, - NULL)); - - nm_setting_option_set_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, 8); - - g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, - &out_value)); - g_assert_cmpuint(out_value, ==, 8); - - nm_setting_option_clear_by_name(NM_SETTING(s_ethtool), nm_ethtool_optname_is_ring); - g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), - NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, - NULL)); - g_assert_false( - nm_setting_option_get_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_RX, NULL)); - g_assert_false( - nm_setting_option_get_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_TX, NULL)); -} - -/*****************************************************************************/ - -static void -test_sriov_vf(void) -{ - NMSriovVF *vf1, *vf2; - GError * error = NULL; - char * str; - - vf1 = nm_sriov_vf_new(1); - nm_sriov_vf_set_attribute(vf1, - NM_SRIOV_VF_ATTRIBUTE_MAC, - g_variant_new_string("00:11:22:33:44:55")); - nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean(TRUE)); - nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean(FALSE)); - nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32(100)); - nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32(500)); - - str = nm_utils_sriov_vf_to_str(vf1, FALSE, &error); - g_assert_no_error(error); - g_assert_cmpstr( - str, - ==, - "1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100 spoof-check=true trust=false"); - g_free(str); - - vf2 = nm_utils_sriov_vf_from_str(" 1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100", - &error); - nmtst_assert_success(vf2, error); - nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean(FALSE)); - nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean(TRUE)); - nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean(TRUE)); - nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, NULL); - nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean(FALSE)); - - g_assert(nm_sriov_vf_equal(vf1, vf2)); - - nm_sriov_vf_unref(vf1); - nm_sriov_vf_unref(vf2); -} - -static void -test_sriov_vf_dup(void) -{ - NMSriovVF *vf1, *vf2; - - vf1 = nm_sriov_vf_new(1); - nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string("foobar")); - nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean(FALSE)); - nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32(10)); - nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32(1000)); - nm_sriov_vf_add_vlan(vf1, 80); - nm_sriov_vf_set_vlan_qos(vf1, 80, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); - - vf2 = nm_sriov_vf_dup(vf1); - g_assert(nm_sriov_vf_equal(vf1, vf2)); - - nm_sriov_vf_unref(vf1); - nm_sriov_vf_unref(vf2); -} - -static void -test_sriov_vf_vlan(void) -{ - NMSriovVF * vf; - const guint * vlan_ids; - guint num; - GError * error = NULL; - gs_free char *str = NULL; - - vf = nm_sriov_vf_new(19); - nm_sriov_vf_set_attribute(vf, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string("00:11:22")); - g_assert(nm_sriov_vf_add_vlan(vf, 80)); - g_assert(!nm_sriov_vf_add_vlan(vf, 80)); - g_assert(nm_sriov_vf_add_vlan(vf, 82)); - g_assert(nm_sriov_vf_add_vlan(vf, 83)); - g_assert(nm_sriov_vf_add_vlan(vf, 81)); - g_assert(!nm_sriov_vf_remove_vlan(vf, 100)); - g_assert(nm_sriov_vf_remove_vlan(vf, 82)); - nm_sriov_vf_set_vlan_qos(vf, 81, 0xabba); - nm_sriov_vf_set_vlan_protocol(vf, 81, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); - - vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num); - g_assert(vlan_ids); - g_assert_cmpint(num, ==, 3); - g_assert_cmpint(vlan_ids[0], ==, 80); - g_assert_cmpint(vlan_ids[1], ==, 81); - g_assert_cmpint(vlan_ids[2], ==, 83); - g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 80), ==, 0x0); - g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 80), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 81), ==, 0xabba); - g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); - - nm_sriov_vf_unref(vf); - - vf = nm_utils_sriov_vf_from_str("20 spoof-check=false vlans=85.0.q;4000.0x20.ad;81.10;83", - &error); - nmtst_assert_success(vf, error); - vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num); - g_assert(vlan_ids); - g_assert_cmpint(num, ==, 4); - g_assert_cmpint(vlan_ids[0], ==, 81); - g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 81), ==, 10); - g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - g_assert_cmpint(vlan_ids[1], ==, 83); - g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 83), ==, 0); - g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 83), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - g_assert_cmpint(vlan_ids[2], ==, 85); - g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 85), ==, 0); - g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 85), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - g_assert_cmpint(vlan_ids[3], ==, 4000); - g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 4000), ==, 0x20); - g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 4000), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); - - str = nm_utils_sriov_vf_to_str(vf, FALSE, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "20 spoof-check=false vlans=81.10;83;85;4000.32.ad"); - - nm_sriov_vf_unref(vf); -} - -static void -test_sriov_setting(void) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingConnection * s_con; - NMSettingSriov * s_sriov = NULL; - NMSriovVF * vf1, *vf2, *vf3; - GError * error = NULL; - gboolean success; - - con = nm_simple_connection_new(); - - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(con, NM_SETTING(s_con)); - - g_object_set(s_con, - NM_SETTING_CONNECTION_ID, - "Test SR-IOV connection", - NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), - NM_SETTING_CONNECTION_AUTOCONNECT, - TRUE, - NM_SETTING_CONNECTION_INTERFACE_NAME, - "eth0", - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRED_SETTING_NAME, - NULL); - - nm_connection_add_setting(con, nm_setting_wired_new()); - - s_sriov = (NMSettingSriov *) nm_setting_sriov_new(); - nm_connection_add_setting(con, NM_SETTING(s_sriov)); - - g_object_set(s_sriov, NM_SETTING_SRIOV_TOTAL_VFS, 16, NULL); - nm_setting_sriov_add_vf(s_sriov, (vf1 = nm_sriov_vf_new(0))); - nm_setting_sriov_add_vf(s_sriov, (vf2 = nm_sriov_vf_new(4))); - nm_setting_sriov_add_vf(s_sriov, (vf3 = nm_sriov_vf_new(10))); - g_assert(nm_setting_sriov_remove_vf_by_index(s_sriov, 4)); - nm_sriov_vf_unref(vf2); - nm_setting_sriov_add_vf(s_sriov, (vf2 = nm_sriov_vf_new(2))); - - nmtst_assert_connection_verifies_and_normalizable(con); - nmtst_connection_normalize(con); - success = nm_setting_verify((NMSetting *) s_sriov, con, &error); - nmtst_assert_success(success, error); - - g_assert_cmpint(nm_setting_sriov_get_num_vfs(s_sriov), ==, 3); - g_assert_cmpint(nm_sriov_vf_get_index(nm_setting_sriov_get_vf(s_sriov, 0)), ==, 0); - g_assert_cmpint(nm_sriov_vf_get_index(nm_setting_sriov_get_vf(s_sriov, 1)), ==, 2); - g_assert_cmpint(nm_sriov_vf_get_index(nm_setting_sriov_get_vf(s_sriov, 2)), ==, 10); - - nm_sriov_vf_unref(vf1); - nm_sriov_vf_unref(vf2); - nm_sriov_vf_unref(vf3); -} - -typedef struct { - guint id; - guint qos; - bool proto_ad; -} VlanData; - -static void -_test_sriov_parse_vlan_one(const char *string, gboolean exp_res, VlanData *data, guint data_length) -{ - NMSriovVF * vf; - gboolean res; - guint i, num_vlans; - const guint *vlan_ids; - - vf = nm_sriov_vf_new(1); - g_assert(vf); - - res = _nm_sriov_vf_parse_vlans(vf, string, NULL); - g_assert_cmpint(res, ==, exp_res); - - if (exp_res) { - vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num_vlans); - g_assert_cmpint(num_vlans, ==, data_length); - for (i = 0; i < num_vlans; i++) { - g_assert_cmpint(vlan_ids[i], ==, data[i].id); - g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, vlan_ids[i]), ==, data[i].qos); - g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, vlan_ids[i]), - ==, - data[i].proto_ad ? NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD - : NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - } - } - - nm_sriov_vf_unref(vf); -} - -#define test_sriov_parse_vlan_one(string, result, ...) \ - { \ - VlanData _data[] = {__VA_ARGS__}; \ - guint _length = G_N_ELEMENTS(_data); \ - \ - _test_sriov_parse_vlan_one(string, result, _data, _length); \ - } - -static void -test_sriov_parse_vlans(void) -{ - test_sriov_parse_vlan_one("", FALSE, {}); - test_sriov_parse_vlan_one("1", TRUE, {1, 0, 0}); - test_sriov_parse_vlan_one("1;2", TRUE, {1, 0, 0}, {2, 0, 0}); - test_sriov_parse_vlan_one("4095;;2", TRUE, {2, 0, 0}, {4095, 0, 0}); - test_sriov_parse_vlan_one("1 2", FALSE, {}); - test_sriov_parse_vlan_one("4096", FALSE, {}); - test_sriov_parse_vlan_one("1.10", TRUE, {1, 10, 0}); - test_sriov_parse_vlan_one("1.20.ad", TRUE, {1, 20, 1}); - test_sriov_parse_vlan_one("1.21.q", TRUE, {1, 21, 0}); - test_sriov_parse_vlan_one("9.20.foo", FALSE, {}); - test_sriov_parse_vlan_one("1.20.ad.12", FALSE, {}); - test_sriov_parse_vlan_one("1;1.10", FALSE, {}); - test_sriov_parse_vlan_one("1..1;2", FALSE, {}); - test_sriov_parse_vlan_one("1..ad;2", FALSE, {}); - test_sriov_parse_vlan_one("1.2.ad;2.0.q;5;3", TRUE, {1, 2, 1}, {2, 0, 0}, {3, 0, 0}, {5, 0, 0}); -} - -static void -test_bridge_vlans(void) -{ - NMBridgeVlan *v1, *v2; - GError * error = NULL; - guint16 vid_start, vid_end; - char * str; - - v1 = nm_bridge_vlan_from_str("1 foobar", &error); - nmtst_assert_no_success(v1, error); - g_clear_error(&error); - - v1 = nm_bridge_vlan_from_str("4095", &error); - nmtst_assert_no_success(v1, error); - g_clear_error(&error); - - /* test ranges */ - v1 = nm_bridge_vlan_from_str("2-1000 untagged", &error); - nmtst_assert_success(v1, error); - g_assert_cmpint(nm_bridge_vlan_get_vid_range(v1, &vid_start, &vid_end), ==, TRUE); - g_assert_cmpuint(vid_start, ==, 2); - g_assert_cmpuint(vid_end, ==, 1000); - g_assert_cmpint(nm_bridge_vlan_is_pvid(v1), ==, FALSE); - g_assert_cmpint(nm_bridge_vlan_is_untagged(v1), ==, TRUE); - nm_bridge_vlan_unref(v1); - - /* test comparison (1) */ - v1 = nm_bridge_vlan_from_str("10 untagged", &error); - nmtst_assert_success(v1, error); - - g_assert_cmpint(nm_bridge_vlan_get_vid_range(v1, &vid_start, &vid_end), ==, FALSE); - g_assert_cmpuint(vid_start, ==, 10); - g_assert_cmpuint(vid_end, ==, 10); - g_assert_cmpint(nm_bridge_vlan_is_sealed(v1), ==, FALSE); - g_assert_cmpint(nm_bridge_vlan_is_pvid(v1), ==, FALSE); - g_assert_cmpint(nm_bridge_vlan_is_untagged(v1), ==, TRUE); - - nm_bridge_vlan_set_pvid(v1, TRUE); - nm_bridge_vlan_set_untagged(v1, FALSE); - nm_bridge_vlan_seal(v1); - - g_assert_cmpint(nm_bridge_vlan_is_sealed(v1), ==, TRUE); - g_assert_cmpint(nm_bridge_vlan_is_pvid(v1), ==, TRUE); - g_assert_cmpint(nm_bridge_vlan_is_untagged(v1), ==, FALSE); - - str = nm_bridge_vlan_to_str(v1, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "10 pvid"); - nm_clear_g_free(&str); - - v2 = nm_bridge_vlan_from_str(" 10 pvid ", &error); - nmtst_assert_success(v2, error); - - g_assert_cmpint(nm_bridge_vlan_cmp(v1, v2), ==, 0); - - nm_bridge_vlan_unref(v1); - nm_bridge_vlan_unref(v2); - - /* test comparison (2) */ - v1 = nm_bridge_vlan_from_str("10", &error); - nmtst_assert_success(v1, error); - v2 = nm_bridge_vlan_from_str("20", &error); - nmtst_assert_success(v2, error); - - g_assert_cmpint(nm_bridge_vlan_cmp(v1, v2), <, 0); - - nm_bridge_vlan_unref(v1); - nm_bridge_vlan_unref(v2); -} - -static void -create_bridge_connection(NMConnection **con, NMSettingBridge **s_bridge) -{ - NMSettingConnection *s_con; - - g_assert(con); - g_assert(s_bridge); - - *con = nmtst_create_minimal_connection("bridge", NULL, NM_SETTING_BOND_SETTING_NAME, &s_con); - - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bridge0", NULL); - - *s_bridge = (NMSettingBridge *) nm_setting_bridge_new(); - g_assert(*s_bridge); - - nm_connection_add_setting(*con, NM_SETTING(*s_bridge)); -} - -#define test_verify_options_bridge(exp, ...) \ - _test_verify_options_bridge(exp, NM_MAKE_STRV(__VA_ARGS__)) - -static void -_test_verify_options_bridge(gboolean expected_result, const char *const *options) -{ - gs_unref_object NMConnection *con = NULL; - NMSettingBridge * s_bridge; - const char *const * option; - - g_assert(NM_PTRARRAY_LEN(options) % 2 == 0); - - create_bridge_connection(&con, &s_bridge); - - for (option = options; option[0]; option += 2) { - const char *option_key = option[0]; - const char *option_val = option[1]; - GParamSpec *pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(s_bridge), option_key); - - g_assert(pspec); - g_assert(option_val); - - switch (G_PARAM_SPEC_VALUE_TYPE(pspec)) { - case G_TYPE_UINT: - { - guint uvalue; - - uvalue = _nm_utils_ascii_str_to_uint64(option_val, 10, 0, G_MAXUINT, -1); - g_assert(errno == 0); - g_object_set(s_bridge, option_key, uvalue, NULL); - } break; - case G_TYPE_BOOLEAN: - { - int bvalue; - - bvalue = _nm_utils_ascii_str_to_bool(option_val, -1); - g_assert(bvalue != -1); - g_object_set(s_bridge, option_key, bvalue, NULL); - } break; - case G_TYPE_STRING: - g_object_set(s_bridge, option_key, option_val, NULL); - break; - default: - g_assert_not_reached(); - break; - } - } - - if (expected_result) - nmtst_assert_connection_verifies_and_normalizable(con); - else { - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - } -} - -static void -test_bridge_verify(void) -{ - /* group-address */ - test_verify_options_bridge(FALSE, "group-address", "nonsense"); - test_verify_options_bridge(FALSE, "group-address", "FF:FF:FF:FF:FF:FF"); - test_verify_options_bridge(FALSE, "group-address", "01:02:03:04:05:06"); - test_verify_options_bridge(TRUE, "group-address", "01:80:C2:00:00:00"); - test_verify_options_bridge(FALSE, "group-address", "01:80:C2:00:00:02"); - test_verify_options_bridge(FALSE, "group-address", "01:80:C2:00:00:03"); - test_verify_options_bridge(TRUE, "group-address", "01:80:C2:00:00:00"); - test_verify_options_bridge(TRUE, "group-address", "01:80:C2:00:00:0A"); - /* vlan-protocol */ - test_verify_options_bridge(FALSE, "vlan-protocol", "nonsense124"); - test_verify_options_bridge(FALSE, "vlan-protocol", "802.11"); - test_verify_options_bridge(FALSE, "vlan-protocol", "802.1Q1"); - test_verify_options_bridge(TRUE, "vlan-protocol", "802.1Q"); - test_verify_options_bridge(TRUE, "vlan-protocol", "802.1ad"); - /* multicast-router */ - test_verify_options_bridge(FALSE, "multicast-router", "nonsense"); - test_verify_options_bridge(TRUE, "multicast-snooping", "no", "multicast-router", "auto"); - test_verify_options_bridge(TRUE, "multicast-snooping", "no", "multicast-router", "enabled"); - test_verify_options_bridge(TRUE, "multicast-snooping", "no", "multicast-router", "disabled"); - test_verify_options_bridge(TRUE, "multicast-snooping", "yes", "multicast-router", "enabled"); - test_verify_options_bridge(TRUE, "multicast-snooping", "yes", "multicast-router", "auto"); - test_verify_options_bridge(TRUE, "multicast-snooping", "yes", "multicast-router", "disabled"); - /* multicast-hash-max */ - test_verify_options_bridge(TRUE, "multicast-hash-max", "1024"); - test_verify_options_bridge(TRUE, "multicast-hash-max", "8192"); - test_verify_options_bridge(FALSE, "multicast-hash-max", "3"); -} - -/*****************************************************************************/ - -static void -test_tc_config_qdisc(void) -{ - NMTCQdisc *qdisc1, *qdisc2; - char * str; - GError * error = NULL; - GVariant * variant; - - qdisc1 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error); - nmtst_assert_success(qdisc1, error); - - qdisc2 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error); - nmtst_assert_success(qdisc2, error); - - g_assert(nm_tc_qdisc_equal(qdisc1, qdisc2)); - - nm_tc_qdisc_unref(qdisc2); - qdisc2 = nm_tc_qdisc_dup(qdisc1); - - g_assert(nm_tc_qdisc_equal(qdisc1, qdisc2)); - - g_assert_cmpstr(nm_tc_qdisc_get_kind(qdisc1), ==, "fq_codel"); - g_assert(nm_tc_qdisc_get_handle(qdisc1) == TC_H_UNSPEC); - g_assert(nm_tc_qdisc_get_parent(qdisc1) == TC_H_ROOT); - - str = nm_utils_tc_qdisc_to_str(qdisc1, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "root fq_codel"); - g_free(str); - - nm_tc_qdisc_unref(qdisc1); - qdisc1 = nm_tc_qdisc_new("ingress", TC_H_INGRESS, &error); - nmtst_assert_success(qdisc1, error); - - g_assert(!nm_tc_qdisc_equal(qdisc1, qdisc2)); - - str = nm_utils_tc_qdisc_to_str(qdisc1, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "ingress"); - g_free(str); - - nm_tc_qdisc_unref(qdisc1); - qdisc1 = nm_utils_tc_qdisc_from_str("narodil sa kristus pan", &error); - nmtst_assert_no_success(qdisc1, error); - g_clear_error(&error); - - qdisc1 = nm_utils_tc_qdisc_from_str("handle 1234 parent fff1:1 pfifo_fast", &error); - nmtst_assert_success(qdisc1, error); - - g_assert_cmpstr(nm_tc_qdisc_get_kind(qdisc1), ==, "pfifo_fast"); - g_assert(nm_tc_qdisc_get_handle(qdisc1) == TC_H_MAKE(0x1234u << 16, 0x0000u)); - g_assert(nm_tc_qdisc_get_parent(qdisc1) == TC_H_MAKE(0xfff1u << 16, 0x0001u)); - - str = nm_utils_tc_qdisc_to_str(qdisc1, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "parent fff1:1 handle 1234: pfifo_fast"); - g_free(str); - - nm_tc_qdisc_unref(qdisc2); - str = nm_utils_tc_qdisc_to_str(qdisc1, &error); - nmtst_assert_success(str, error); - qdisc2 = nm_utils_tc_qdisc_from_str(str, &error); - nmtst_assert_success(qdisc2, error); - g_free(str); - - g_assert(nm_tc_qdisc_equal(qdisc1, qdisc2)); - - nm_tc_qdisc_unref(qdisc1); - nm_tc_qdisc_unref(qdisc2); - - qdisc1 = nm_utils_tc_qdisc_from_str("clsact", &error); - nmtst_assert_success(qdisc1, error); - str = nm_utils_tc_qdisc_to_str(qdisc1, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "clsact"); - nm_tc_qdisc_unref(qdisc1); - g_free(str); - -#define CHECK_ATTRIBUTE(qdisc, name, vtype, type, value) \ - variant = nm_tc_qdisc_get_attribute(qdisc, name); \ - g_assert(variant); \ - g_assert(g_variant_is_of_type(variant, vtype)); \ - g_assert_cmpint(g_variant_get_##type(variant), ==, value); - - qdisc1 = nm_utils_tc_qdisc_from_str("handle 1235 root sfq perturb 10 quantum 1480 " - "limit 9000 flows 1024 divisor 500 depth 12", - &error); - nmtst_assert_success(qdisc1, error); - - g_assert_cmpstr(nm_tc_qdisc_get_kind(qdisc1), ==, "sfq"); - g_assert(nm_tc_qdisc_get_handle(qdisc1) == TC_H_MAKE(0x1235u << 16, 0x0000u)); - g_assert(nm_tc_qdisc_get_parent(qdisc1) == TC_H_ROOT); - CHECK_ATTRIBUTE(qdisc1, "perturb", G_VARIANT_TYPE_INT32, int32, 10); - CHECK_ATTRIBUTE(qdisc1, "quantum", G_VARIANT_TYPE_UINT32, uint32, 1480); - CHECK_ATTRIBUTE(qdisc1, "limit", G_VARIANT_TYPE_UINT32, uint32, 9000); - CHECK_ATTRIBUTE(qdisc1, "flows", G_VARIANT_TYPE_UINT32, uint32, 1024); - CHECK_ATTRIBUTE(qdisc1, "divisor", G_VARIANT_TYPE_UINT32, uint32, 500); - CHECK_ATTRIBUTE(qdisc1, "depth", G_VARIANT_TYPE_UINT32, uint32, 12); - nm_tc_qdisc_unref(qdisc1); - - qdisc1 = nm_utils_tc_qdisc_from_str("handle 1235 root tbf rate 1000000 burst 5000 limit 10000", - &error); - nmtst_assert_success(qdisc1, error); - - g_assert_cmpstr(nm_tc_qdisc_get_kind(qdisc1), ==, "tbf"); - g_assert(nm_tc_qdisc_get_handle(qdisc1) == TC_H_MAKE(0x1235u << 16, 0x0000u)); - g_assert(nm_tc_qdisc_get_parent(qdisc1) == TC_H_ROOT); - CHECK_ATTRIBUTE(qdisc1, "rate", G_VARIANT_TYPE_UINT64, uint64, 1000000); - CHECK_ATTRIBUTE(qdisc1, "burst", G_VARIANT_TYPE_UINT32, uint32, 5000); - CHECK_ATTRIBUTE(qdisc1, "limit", G_VARIANT_TYPE_UINT32, uint32, 10000); - nm_tc_qdisc_unref(qdisc1); - -#undef CHECK_ATTRIBUTE -} - -static void -test_tc_config_action(void) -{ - NMTCAction *action1, *action2; - char * str; - GError * error = NULL; - - action1 = nm_tc_action_new("drop", &error); - nmtst_assert_success(action1, error); - action2 = nm_tc_action_new("drop", &error); - nmtst_assert_success(action2, error); - - g_assert(nm_tc_action_equal(action1, action2)); - g_assert_cmpstr(nm_tc_action_get_kind(action1), ==, "drop"); - - nm_tc_action_unref(action1); - action1 = nm_tc_action_new("simple", &error); - nmtst_assert_success(action1, error); - nm_tc_action_set_attribute(action1, "sdata", g_variant_new_bytestring("Hello")); - - g_assert(!nm_tc_action_equal(action1, action2)); - - str = nm_utils_tc_action_to_str(action1, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "simple sdata Hello"); - g_free(str); - - str = nm_utils_tc_action_to_str(action2, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "drop"); - g_free(str); - - nm_tc_action_unref(action2); - action2 = nm_tc_action_dup(action1); - - g_assert(nm_tc_action_equal(action1, action2)); - - nm_tc_action_unref(action1); - action1 = nm_utils_tc_action_from_str("narodil sa kristus pan", &error); - nmtst_assert_no_success(action1, error); - g_clear_error(&error); - - action1 = nm_utils_tc_action_from_str("simple sdata Hello", &error); - nmtst_assert_success(action1, error); - - g_assert_cmpstr(nm_tc_action_get_kind(action1), ==, "simple"); - g_assert_cmpstr(g_variant_get_bytestring(nm_tc_action_get_attribute(action1, "sdata")), - ==, - "Hello"); - - nm_tc_action_unref(action1); - nm_tc_action_unref(action2); -} - -static void -test_tc_config_tfilter_matchall_sdata(void) -{ - NMTCAction * action1; - NMTCTfilter *tfilter1, *tfilter2; - char * str; - GError * error = NULL; - - tfilter1 = nm_tc_tfilter_new("matchall", TC_H_MAKE(0x1234u << 16, 0x0000u), &error); - nmtst_assert_success(tfilter1, error); - - tfilter2 = nm_tc_tfilter_new("matchall", TC_H_MAKE(0x1234u << 16, 0x0000u), &error); - nmtst_assert_success(tfilter2, error); - - g_assert(nm_tc_tfilter_equal(tfilter1, tfilter2)); - - action1 = nm_tc_action_new("simple", &error); - nmtst_assert_success(action1, error); - nm_tc_action_set_attribute(action1, "sdata", g_variant_new_bytestring("Hello")); - nm_tc_tfilter_set_action(tfilter1, action1); - nm_tc_action_unref(action1); - - g_assert(!nm_tc_tfilter_equal(tfilter1, tfilter2)); - - str = nm_utils_tc_tfilter_to_str(tfilter1, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "parent 1234: matchall action simple sdata Hello"); - g_free(str); - - nm_tc_tfilter_unref(tfilter2); - tfilter2 = nm_tc_tfilter_dup(tfilter1); - - g_assert(nm_tc_tfilter_equal(tfilter1, tfilter2)); - - nm_tc_tfilter_unref(tfilter1); - tfilter1 = nm_utils_tc_tfilter_from_str("narodil sa kristus pan", &error); - nmtst_assert_no_success(tfilter1, error); - g_clear_error(&error); - - str = nm_utils_tc_tfilter_to_str(tfilter2, &error); - nmtst_assert_success(str, error); - tfilter1 = nm_utils_tc_tfilter_from_str(str, &error); - nmtst_assert_success(tfilter1, error); - g_free(str); - - g_assert(nm_tc_tfilter_equal(tfilter1, tfilter2)); - - nm_tc_tfilter_unref(tfilter1); - nm_tc_tfilter_unref(tfilter2); -} - -static void -test_tc_config_tfilter_matchall_mirred(void) -{ - NMTCAction * action; - NMTCTfilter * tfilter1; - GError * error = NULL; - gs_strfreev char **attr_names = NULL; - gs_free char * str; - GVariant * variant; - - tfilter1 = - nm_utils_tc_tfilter_from_str("parent ffff: matchall action mirred ingress mirror dev eth0", - &error); - nmtst_assert_success(tfilter1, error); - g_assert_cmpint(nm_tc_tfilter_get_parent(tfilter1), ==, TC_H_MAKE(0xffff << 16, 0)); - g_assert_cmpstr(nm_tc_tfilter_get_kind(tfilter1), ==, "matchall"); - - action = nm_tc_tfilter_get_action(tfilter1); - nm_assert(action); - g_assert_cmpstr(nm_tc_action_get_kind(action), ==, "mirred"); - attr_names = nm_tc_action_get_attribute_names(action); - g_assert(attr_names); - g_assert_cmpint(g_strv_length(attr_names), ==, 3); - - variant = nm_tc_action_get_attribute(action, "ingress"); - g_assert(variant); - g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); - g_assert(g_variant_get_boolean(variant)); - - variant = nm_tc_action_get_attribute(action, "mirror"); - g_assert(variant); - g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); - g_assert(g_variant_get_boolean(variant)); - - variant = nm_tc_action_get_attribute(action, "dev"); - g_assert(variant); - g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr(g_variant_get_string(variant, NULL), ==, "eth0"); - - str = nm_utils_tc_tfilter_to_str(tfilter1, &error); - nmtst_assert_success(str, error); - g_assert_cmpstr(str, ==, "parent ffff: matchall action mirred dev eth0 ingress mirror"); - - nm_tc_tfilter_unref(tfilter1); -} - -static void -test_tc_config_setting_valid(void) -{ - gs_unref_object NMSettingTCConfig *s_tc = NULL; - NMTCQdisc * qdisc1, *qdisc2; - GError * error = NULL; - - s_tc = (NMSettingTCConfig *) nm_setting_tc_config_new(); - - qdisc1 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error); - nmtst_assert_success(qdisc1, error); - - qdisc2 = nm_tc_qdisc_new("pfifo_fast", TC_H_MAKE(0xfff1u << 16, 0x0001u), &error); - nmtst_assert_success(qdisc2, error); - nm_tc_qdisc_set_handle(qdisc2, TC_H_MAKE(0x1234u << 16, 0x0000u)); - - g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 0); - g_assert(nm_setting_tc_config_add_qdisc(s_tc, qdisc1) == TRUE); - g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 1); - g_assert(nm_setting_tc_config_get_qdisc(s_tc, 0) != NULL); - g_assert(nm_setting_tc_config_remove_qdisc_by_value(s_tc, qdisc2) == FALSE); - g_assert(nm_setting_tc_config_add_qdisc(s_tc, qdisc2) == TRUE); - g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 2); - g_assert(nm_setting_tc_config_remove_qdisc_by_value(s_tc, qdisc1) == TRUE); - g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 1); - nm_setting_tc_config_clear_qdiscs(s_tc); - g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 0); - - nm_tc_qdisc_unref(qdisc1); - nm_tc_qdisc_unref(qdisc2); -} - -static void -test_tc_config_setting_duplicates(void) -{ - gs_unref_ptrarray GPtrArray *qdiscs = NULL; - gs_unref_ptrarray GPtrArray *tfilters = NULL; - NMSettingConnection * s_con; - NMConnection * con; - NMSetting * s_tc; - NMTCQdisc * qdisc; - NMTCTfilter * tfilter; - GError * error = NULL; - - con = nmtst_create_minimal_connection("dummy", NULL, NM_SETTING_DUMMY_SETTING_NAME, &s_con); - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "dummy1", NULL); - - s_tc = nm_setting_tc_config_new(); - nm_connection_add_setting(con, s_tc); - qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref); - tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref); - - /* 1. add duplicate qdiscs */ - qdisc = nm_utils_tc_qdisc_from_str("handle 1234 parent fff1:1 pfifo_fast", &error); - nmtst_assert_success(qdisc, error); - g_ptr_array_add(qdiscs, qdisc); - - qdisc = nm_utils_tc_qdisc_from_str("handle 1234 parent fff1:1 pfifo_fast", &error); - nmtst_assert_success(qdisc, error); - g_ptr_array_add(qdiscs, qdisc); - - g_object_set(s_tc, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - - /* 2. make qdiscs unique */ - g_ptr_array_remove_index(qdiscs, 0); - g_object_set(s_tc, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL); - nmtst_assert_connection_verifies_and_normalizable(con); - - /* 3. add duplicate filters */ - tfilter = - nm_utils_tc_tfilter_from_str("parent 1234: matchall action simple sdata Hello", &error); - nmtst_assert_success(tfilter, error); - g_ptr_array_add(tfilters, tfilter); - - tfilter = - nm_utils_tc_tfilter_from_str("parent 1234: matchall action simple sdata Hello", &error); - nmtst_assert_success(tfilter, error); - g_ptr_array_add(tfilters, tfilter); - - g_object_set(s_tc, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL); - nmtst_assert_connection_unnormalizable(con, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY); - - /* 4. make filters unique */ - g_ptr_array_remove_index(tfilters, 0); - g_object_set(s_tc, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL); - nmtst_assert_connection_verifies_and_normalizable(con); -} - -static void -test_tc_config_dbus(void) -{ - NMConnection *connection1, *connection2; - NMSetting * s_tc; - NMTCQdisc * qdisc1, *qdisc2; - NMTCTfilter * tfilter1, *tfilter2; - NMTCAction * action; - GVariant * dbus, *tc_dbus, *var1, *var2; - GError * error = NULL; - gboolean success; - - connection1 = - nmtst_create_minimal_connection("dummy", NULL, NM_SETTING_DUMMY_SETTING_NAME, NULL); - - s_tc = nm_setting_tc_config_new(); - - qdisc1 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error); - nmtst_assert_success(qdisc1, error); - nm_tc_qdisc_set_handle(qdisc1, TC_H_MAKE(0x1234u << 16, 0x0000u)); - nm_setting_tc_config_add_qdisc(NM_SETTING_TC_CONFIG(s_tc), qdisc1); - - qdisc2 = nm_tc_qdisc_new("ingress", TC_H_INGRESS, &error); - nmtst_assert_success(qdisc2, error); - nm_tc_qdisc_set_handle(qdisc2, TC_H_MAKE(TC_H_INGRESS, 0u)); - nm_setting_tc_config_add_qdisc(NM_SETTING_TC_CONFIG(s_tc), qdisc2); - - tfilter1 = nm_tc_tfilter_new("matchall", TC_H_MAKE(0x1234u << 16, 0x0000u), &error); - nmtst_assert_success(tfilter1, error); - action = nm_tc_action_new("drop", &error); - nmtst_assert_success(action, error); - nm_tc_tfilter_set_action(tfilter1, action); - nm_tc_action_unref(action); - nm_setting_tc_config_add_tfilter(NM_SETTING_TC_CONFIG(s_tc), tfilter1); - nm_tc_tfilter_unref(tfilter1); - - tfilter2 = nm_tc_tfilter_new("matchall", TC_H_MAKE(TC_H_INGRESS, 0u), &error); - nmtst_assert_success(tfilter2, error); - action = nm_tc_action_new("simple", &error); - nmtst_assert_success(action, error); - nm_tc_action_set_attribute(action, "sdata", g_variant_new_bytestring("Hello")); - nm_tc_tfilter_set_action(tfilter2, action); - nm_tc_action_unref(action); - nm_setting_tc_config_add_tfilter(NM_SETTING_TC_CONFIG(s_tc), tfilter2); - nm_tc_tfilter_unref(tfilter2); - - nm_connection_add_setting(connection1, s_tc); - - dbus = nm_connection_to_dbus(connection1, NM_CONNECTION_SERIALIZE_ALL); - - tc_dbus = g_variant_lookup_value(dbus, "tc", G_VARIANT_TYPE_VARDICT); - g_assert(tc_dbus); - - var1 = g_variant_lookup_value(tc_dbus, "qdiscs", G_VARIANT_TYPE("aa{sv}")); - var2 = g_variant_new_parsed("[{'kind': <'fq_codel'>," - " 'handle': ," - " 'parent': }," - " {'kind': <'ingress'>," - " 'handle': ," - " 'parent': }]"); - g_assert(g_variant_equal(var1, var2)); - g_variant_unref(var1); - g_variant_unref(var2); - - var1 = g_variant_lookup_value(tc_dbus, "tfilters", G_VARIANT_TYPE("aa{sv}")); - var2 = g_variant_new_parsed("[{'kind': <'matchall'>," - " 'handle': ," - " 'parent': ," - " 'action': <{'kind': <'drop'>}>}," - " {'kind': <'matchall'>," - " 'handle': ," - " 'parent': ," - " 'action': <{'kind': <'simple'>," - " 'sdata': }>}]"); - g_variant_unref(var1); - g_variant_unref(var2); - - g_variant_unref(tc_dbus); - - connection2 = nm_simple_connection_new(); - success = nm_connection_replace_settings(connection2, dbus, &error); - nmtst_assert_success(success, error); - - g_assert(nm_connection_diff(connection1, connection2, NM_SETTING_COMPARE_FLAG_EXACT, NULL)); - - g_variant_unref(dbus); - - nm_tc_qdisc_unref(qdisc1); - nm_tc_qdisc_unref(qdisc2); - - g_object_unref(connection1); - g_object_unref(connection2); -} - -/*****************************************************************************/ - -static void -_rndt_wired_add_s390_options(NMSettingWired *s_wired, char **out_keyfile_entries) -{ - gsize n_opts; - gsize i, j; - const char *const * option_names; - gs_free const char **opt_keys = NULL; - gs_strfreev char ** opt_vals = NULL; - gs_free bool * opt_found = NULL; - GString * keyfile_entries; - nm_auto_free_gstring GString *str_tmp = NULL; - - option_names = nm_setting_wired_get_valid_s390_options(nmtst_get_rand_bool() ? NULL : s_wired); - - n_opts = NM_PTRARRAY_LEN(option_names); - opt_keys = g_new(const char *, (n_opts + 1)); - nmtst_rand_perm(NULL, opt_keys, option_names, sizeof(const char *), n_opts); - n_opts = nmtst_get_rand_uint32() % (n_opts + 1); - opt_keys[n_opts] = NULL; - - opt_vals = g_new0(char *, n_opts + 1); - opt_found = g_new0(bool, n_opts + 1); - for (i = 0; i < n_opts; i++) { - guint p = nmtst_get_rand_uint32() % 1000; - - if (p < 200) - opt_vals[i] = nm_strdup_int(i); - else { - opt_vals[i] = g_strdup_printf("%s%s%s%s-%zu", - ((p % 5) % 2) ? "\n" : "", - ((p % 7) % 2) ? "\t" : "", - ((p % 11) % 2) ? "x" : "", - ((p % 13) % 2) ? "=" : "", - i); - } - } - - if (nmtst_get_rand_bool()) { - gs_unref_hashtable GHashTable *hash = NULL; - - hash = g_hash_table_new(nm_str_hash, g_str_equal); - for (i = 0; i < n_opts; i++) - g_hash_table_insert(hash, (char *) opt_keys[i], opt_vals[i]); - g_object_set(s_wired, NM_SETTING_WIRED_S390_OPTIONS, hash, NULL); - } else { - _nm_setting_wired_clear_s390_options(s_wired); - for (i = 0; i < n_opts; i++) { - if (!nm_setting_wired_add_s390_option(s_wired, opt_keys[i], opt_vals[i])) - g_assert_not_reached(); - } - } - - g_assert_cmpint(nm_setting_wired_get_num_s390_options(s_wired), ==, n_opts); - - keyfile_entries = g_string_new(NULL); - str_tmp = g_string_new(NULL); - if (n_opts > 0) - g_string_append_printf(keyfile_entries, "[ethernet-s390-options]\n"); - for (i = 0; i < n_opts; i++) { - gssize idx; - const char *k, *v; - - nm_setting_wired_get_s390_option(s_wired, i, &k, &v); - g_assert(k); - g_assert(v); - - idx = nm_utils_strv_find_first((char **) opt_keys, n_opts, k); - g_assert(idx >= 0); - g_assert(!opt_found[idx]); - opt_found[idx] = TRUE; - g_assert_cmpstr(opt_keys[idx], ==, k); - g_assert_cmpstr(opt_vals[idx], ==, v); - - g_string_truncate(str_tmp, 0); - for (j = 0; v[j] != '\0'; j++) { - if (v[j] == '\n') - g_string_append(str_tmp, "\\n"); - else if (v[j] == '\t') - g_string_append(str_tmp, "\\t"); - else - g_string_append_c(str_tmp, v[j]); - } - - g_string_append_printf(keyfile_entries, "%s=%s\n", k, str_tmp->str); - } - for (i = 0; i < n_opts; i++) - g_assert(opt_found[i]); - if (n_opts > 0) - g_string_append_printf(keyfile_entries, "\n"); - *out_keyfile_entries = g_string_free(keyfile_entries, FALSE); -} - -static GPtrArray * -_rndt_wg_peers_create(void) -{ - GPtrArray *wg_peers; - guint i, n; - - wg_peers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_wireguard_peer_unref); - - n = nmtst_get_rand_uint32() % 10; - for (i = 0; i < n; i++) { - NMWireGuardPeer *peer; - guint8 public_key_buf[NM_WIREGUARD_PUBLIC_KEY_LEN]; - guint8 preshared_key_buf[NM_WIREGUARD_SYMMETRIC_KEY_LEN]; - gs_free char * public_key = NULL; - gs_free char * preshared_key = NULL; - gs_free char * s_endpoint = NULL; - guint i_aip, n_aip; - - /* we don't bother to create a valid curve25519 public key. Of course, libnm cannot - * check whether the public key is bogus or not. Hence, for our purpose a random - * bogus key is good enough. */ - public_key = g_base64_encode(nmtst_rand_buf(NULL, public_key_buf, sizeof(public_key_buf)), - sizeof(public_key_buf)); - - preshared_key = - g_base64_encode(nmtst_rand_buf(NULL, preshared_key_buf, sizeof(preshared_key_buf)), - sizeof(preshared_key_buf)); - - s_endpoint = _create_random_ipaddr(AF_UNSPEC, TRUE); - - peer = nm_wireguard_peer_new(); - if (!nm_wireguard_peer_set_public_key(peer, public_key, TRUE)) - g_assert_not_reached(); - - if (!nm_wireguard_peer_set_preshared_key(peer, - nmtst_rand_select(NULL, preshared_key), - TRUE)) - g_assert_not_reached(); - - nm_wireguard_peer_set_preshared_key_flags( - peer, - nmtst_rand_select(NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NM_SETTING_SECRET_FLAG_AGENT_OWNED)); - - nm_wireguard_peer_set_persistent_keepalive( - peer, - nmtst_rand_select((guint32) 0, nmtst_get_rand_uint32())); - - if (!nm_wireguard_peer_set_endpoint(peer, nmtst_rand_select(s_endpoint, NULL), TRUE)) - g_assert_not_reached(); - - n_aip = nmtst_rand_select(0, nmtst_get_rand_uint32() % 10); - for (i_aip = 0; i_aip < n_aip; i_aip++) { - gs_free char *aip = NULL; - - aip = _create_random_ipaddr(AF_UNSPEC, FALSE); - if (!nm_wireguard_peer_append_allowed_ip(peer, aip, FALSE)) - g_assert_not_reached(); - } - - g_assert(nm_wireguard_peer_is_valid(peer, TRUE, TRUE, NULL)); - - nm_wireguard_peer_seal(peer); - g_ptr_array_add(wg_peers, peer); - } - - return wg_peers; -} - -static const char * -_rndt_wg_peers_to_keyfile(GPtrArray *wg_peers, gboolean strict, char **out_str) -{ - nm_auto_free_gstring GString *gstr = NULL; - nm_auto_free_gstring GString *gstr_aip = NULL; - guint i, j; - - g_assert(wg_peers); - g_assert(out_str && !*out_str); - - nm_gstring_prepare(&gstr); - for (i = 0; i < wg_peers->len; i++) { - const NMWireGuardPeer *peer = wg_peers->pdata[i]; - gs_free char * s_endpoint = NULL; - gs_free char * s_preshared_key = NULL; - gs_free char * s_preshared_key_flags = NULL; - gs_free char * s_persistent_keepalive = NULL; - gs_free char * s_allowed_ips = NULL; - - if (nm_wireguard_peer_get_endpoint(peer)) - s_endpoint = g_strdup_printf("endpoint=%s\n", nm_wireguard_peer_get_endpoint(peer)); - else if (!strict) - s_endpoint = g_strdup_printf("endpoint=\n"); - - if (nm_wireguard_peer_get_preshared_key(peer) || !strict) { - if (nm_wireguard_peer_get_preshared_key_flags(peer) == NM_SETTING_SECRET_FLAG_NONE) - s_preshared_key = g_strdup_printf("preshared-key=%s\n", - nm_wireguard_peer_get_preshared_key(peer) ?: ""); - } - - if (nm_wireguard_peer_get_preshared_key_flags(peer) != NM_SETTING_SECRET_FLAG_NOT_REQUIRED - || !strict) - s_preshared_key_flags = - g_strdup_printf("preshared-key-flags=%d\n", - (int) nm_wireguard_peer_get_preshared_key_flags(peer)); - - if (nm_wireguard_peer_get_persistent_keepalive(peer) != 0 || !strict) - s_persistent_keepalive = - g_strdup_printf("persistent-keepalive=%u\n", - nm_wireguard_peer_get_persistent_keepalive(peer)); - - if (nm_wireguard_peer_get_allowed_ips_len(peer) > 0 || !strict) { - nm_gstring_prepare(&gstr_aip); - for (j = 0; j < nm_wireguard_peer_get_allowed_ips_len(peer); j++) - g_string_append_printf(gstr_aip, - "%s;", - nm_wireguard_peer_get_allowed_ip(peer, j, NULL)); - s_allowed_ips = g_strdup_printf("allowed-ips=%s\n", gstr_aip->str); - } - - if (!s_endpoint && !s_preshared_key && !s_preshared_key_flags && !s_persistent_keepalive - && !s_allowed_ips) - s_endpoint = g_strdup_printf("endpoint=\n"); - - g_string_append_printf(gstr, - "\n" - "[wireguard-peer.%s]\n" - "%s" /* endpoint */ - "%s" /* preshared-key */ - "%s" /* preshared-key-flags */ - "%s" /* persistent-keepalive */ - "%s" /* allowed-ips */ - "", - nm_wireguard_peer_get_public_key(peer), - s_endpoint ?: "", - s_preshared_key ?: "", - s_preshared_key_flags ?: "", - s_persistent_keepalive ?: "", - s_allowed_ips ?: ""); - } - - return (*out_str = g_string_free(g_steal_pointer(&gstr), FALSE)); -} - -static void -_rndt_wg_peers_assert_equal(NMSettingWireGuard *s_wg, - GPtrArray * peers, - gboolean consider_persistent_secrets, - gboolean consider_all_secrets, - gboolean expect_no_secrets) -{ - guint i; - - g_assert(NM_IS_SETTING_WIREGUARD(s_wg)); - g_assert(peers); - - g_assert_cmpint(peers->len, ==, nm_setting_wireguard_get_peers_len(s_wg)); - - for (i = 0; i < peers->len; i++) { - const NMWireGuardPeer *a = peers->pdata[i]; - const NMWireGuardPeer *b = nm_setting_wireguard_get_peer(s_wg, i); - gboolean consider_secrets; - - g_assert(a); - g_assert(b); - - g_assert_cmpint(nm_wireguard_peer_cmp(a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS), ==, 0); - - if (consider_all_secrets || !nm_wireguard_peer_get_preshared_key(a)) - consider_secrets = TRUE; - else if (nm_wireguard_peer_get_preshared_key(b)) - consider_secrets = TRUE; - else if (consider_persistent_secrets - && nm_wireguard_peer_get_preshared_key_flags(b) == NM_SETTING_SECRET_FLAG_NONE) - consider_secrets = TRUE; - else - consider_secrets = FALSE; - - if (consider_secrets) { - g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(a), - ==, - nm_wireguard_peer_get_preshared_key(b)); - g_assert_cmpint(nm_wireguard_peer_cmp(a, b, NM_SETTING_COMPARE_FLAG_EXACT), ==, 0); - } - - if (expect_no_secrets) - g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(b), ==, NULL); - } -} - -static void -_rndt_wg_peers_fix_secrets(NMSettingWireGuard *s_wg, GPtrArray *peers) -{ - guint i; - - g_assert(NM_IS_SETTING_WIREGUARD(s_wg)); - g_assert(peers); - - g_assert_cmpint(peers->len, ==, nm_setting_wireguard_get_peers_len(s_wg)); - - for (i = 0; i < peers->len; i++) { - const NMWireGuardPeer *a = peers->pdata[i]; - const NMWireGuardPeer *b = nm_setting_wireguard_get_peer(s_wg, i); - nm_auto_unref_wgpeer NMWireGuardPeer *b_clone = NULL; - - g_assert(a); - g_assert(b); - - g_assert_cmpint(nm_wireguard_peer_get_preshared_key_flags(a), - ==, - nm_wireguard_peer_get_preshared_key_flags(b)); - g_assert_cmpint(nm_wireguard_peer_cmp(a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS), ==, 0); - - if (!nm_streq0(nm_wireguard_peer_get_preshared_key(a), - nm_wireguard_peer_get_preshared_key(b))) { - g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(a), !=, NULL); - g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(b), ==, NULL); - g_assert(NM_IN_SET(nm_wireguard_peer_get_preshared_key_flags(a), - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - NM_SETTING_SECRET_FLAG_NOT_SAVED)); - b_clone = nm_wireguard_peer_new_clone(b, TRUE); - if (!nm_wireguard_peer_set_preshared_key(b_clone, - nm_wireguard_peer_get_preshared_key(a), - TRUE)) - g_assert_not_reached(); - nm_setting_wireguard_set_peer(s_wg, b_clone, i); - b = nm_setting_wireguard_get_peer(s_wg, i); - g_assert(b == b_clone); - } else { - if (nm_wireguard_peer_get_preshared_key(a)) { - g_assert(NM_IN_SET(nm_wireguard_peer_get_preshared_key_flags(a), - NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_SECRET_FLAG_NOT_REQUIRED)); - } else { - g_assert(NM_IN_SET(nm_wireguard_peer_get_preshared_key_flags(a), - NM_SETTING_SECRET_FLAG_AGENT_OWNED, - NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NM_SETTING_SECRET_FLAG_NOT_REQUIRED)); - } - } - - g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(a), - ==, - nm_wireguard_peer_get_preshared_key(b)); - g_assert_cmpint(nm_wireguard_peer_cmp(a, b, NM_SETTING_COMPARE_FLAG_EXACT), ==, 0); - } -} - -static void -test_roundtrip_conversion(gconstpointer test_data) -{ - const int MODE = GPOINTER_TO_INT(test_data); - const char *ID = nm_sprintf_bufa(100, "roundtrip-conversion-%d", MODE); - const char *UUID = "63376701-b61e-4318-bf7e-664a1c1eeaab"; - const char *INTERFACE_NAME = nm_sprintf_bufa(100, "ifname%d", MODE); - guint32 ETH_MTU = nmtst_rand_select((guint32) 0u, nmtst_get_rand_uint32()); - const char *WG_PRIVATE_KEY = - nmtst_get_rand_bool() ? "yGXGK+5bVnxSJUejH4vbpXbq+ZtaG4NB8IHRK/aVtE0=" : NULL; - const NMSettingSecretFlags WG_PRIVATE_KEY_FLAGS = - nmtst_rand_select(NM_SETTING_SECRET_FLAG_NONE, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NM_SETTING_SECRET_FLAG_AGENT_OWNED); - const guint WG_LISTEN_PORT = nmtst_rand_select(0u, nmtst_get_rand_uint32() % 0x10000); - const guint WG_FWMARK = nmtst_rand_select(0u, nmtst_get_rand_uint32()); - gs_unref_ptrarray GPtrArray *kf_data_arr = g_ptr_array_new_with_free_func(g_free); - gs_unref_ptrarray GPtrArray * wg_peers = NULL; - const NMConnectionSerializationFlags dbus_serialization_flags[] = { - NM_CONNECTION_SERIALIZE_ALL, - NM_CONNECTION_SERIALIZE_NO_SECRETS, - NM_CONNECTION_SERIALIZE_ONLY_SECRETS, - }; - guint dbus_serialization_flags_idx; - gs_unref_object NMConnection *con = NULL; - gs_free_error GError *error = NULL; - gs_free char * tmp_str = NULL; - guint kf_data_idx; - NMSettingConnection * s_con = NULL; - NMSettingWired * s_eth = NULL; - NMSettingWireGuard * s_wg = NULL; - union { - struct { - NMSettingIPConfig *s_6; - NMSettingIPConfig *s_4; - }; - NMSettingIPConfig *s_x[2]; - } s_ip; - int is_ipv4; - guint i; - gboolean success; - gs_free char *s390_keyfile_entries = NULL; - - switch (MODE) { - case 0: - con = nmtst_create_minimal_connection(ID, UUID, NM_SETTING_WIRED_SETTING_NAME, &s_con); - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, INTERFACE_NAME, NULL); - nmtst_connection_normalize(con); - - s_eth = NM_SETTING_WIRED(nm_connection_get_setting(con, NM_TYPE_SETTING_WIRED)); - g_assert(NM_IS_SETTING_WIRED(s_eth)); - - g_object_set(s_eth, NM_SETTING_WIRED_MTU, ETH_MTU, NULL); - - _rndt_wired_add_s390_options(s_eth, &s390_keyfile_entries); - - g_ptr_array_add( - kf_data_arr, - g_strdup_printf("[connection]\n" - "id=%s\n" - "uuid=%s\n" - "type=ethernet\n" - "interface-name=%s\n" - "permissions=\n" - "\n" - "[ethernet]\n" - "mac-address-blacklist=\n" - "%s" /* mtu */ - "\n" - "%s" /* [ethernet-s390-options] */ - "[ipv4]\n" - "dns-search=\n" - "method=auto\n" - "\n" - "[ipv6]\n" - "addr-gen-mode=stable-privacy\n" - "dns-search=\n" - "method=auto\n" - "\n" - "[proxy]\n" - "", - ID, - UUID, - INTERFACE_NAME, - (ETH_MTU != 0) ? nm_sprintf_bufa(100, "mtu=%u\n", ETH_MTU) : "", - s390_keyfile_entries)); - - g_ptr_array_add( - kf_data_arr, - g_strdup_printf("[connection]\n" - "id=%s\n" - "uuid=%s\n" - "type=ethernet\n" - "interface-name=%s\n" - "permissions=\n" - "\n" - "[ethernet]\n" - "mac-address-blacklist=\n" - "%s" /* mtu */ - "\n" - "%s" /* [ethernet-s390-options] */ - "[ipv4]\n" - "dns-search=\n" - "method=auto\n" - "\n" - "[ipv6]\n" - "addr-gen-mode=stable-privacy\n" - "dns-search=\n" - "method=auto\n" - "", - ID, - UUID, - INTERFACE_NAME, - (ETH_MTU != 0) ? nm_sprintf_bufa(100, "mtu=%d\n", (int) ETH_MTU) : "", - s390_keyfile_entries)); - - break; - - case 1: - con = nmtst_create_minimal_connection(ID, UUID, "wireguard", &s_con); - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, INTERFACE_NAME, NULL); - nmtst_connection_normalize(con); - - s_wg = NM_SETTING_WIREGUARD(nm_connection_get_setting(con, NM_TYPE_SETTING_WIREGUARD)); - - g_ptr_array_add(kf_data_arr, - g_strdup_printf("[connection]\n" - "id=%s\n" - "uuid=%s\n" - "type=wireguard\n" - "interface-name=%s\n" - "permissions=\n" - "\n" - "[wireguard]\n" - "\n" - "[ipv4]\n" - "dns-search=\n" - "method=disabled\n" - "\n" - "[ipv6]\n" - "addr-gen-mode=stable-privacy\n" - "dns-search=\n" - "method=ignore\n" - "\n" - "[proxy]\n" - "", - ID, - UUID, - INTERFACE_NAME)); - break; - - case 2: - con = nmtst_create_minimal_connection(ID, UUID, "wireguard", &s_con); - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, INTERFACE_NAME, NULL); - nmtst_connection_normalize(con); - - s_wg = NM_SETTING_WIREGUARD(nm_connection_get_setting(con, NM_TYPE_SETTING_WIREGUARD)); - g_object_set(s_wg, - NM_SETTING_WIREGUARD_PRIVATE_KEY, - WG_PRIVATE_KEY, - NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, - WG_PRIVATE_KEY_FLAGS, - NM_SETTING_WIREGUARD_LISTEN_PORT, - WG_LISTEN_PORT, - NM_SETTING_WIREGUARD_FWMARK, - WG_FWMARK, - NULL); - - wg_peers = _rndt_wg_peers_create(); - - for (i = 0; i < wg_peers->len; i++) - nm_setting_wireguard_append_peer(s_wg, wg_peers->pdata[i]); - - nm_clear_g_free(&tmp_str); - - g_ptr_array_add( - kf_data_arr, - g_strdup_printf( - "[connection]\n" - "id=%s\n" - "uuid=%s\n" - "type=wireguard\n" - "interface-name=%s\n" - "permissions=\n" - "\n" - "[wireguard]\n" - "%s" /* fwmark */ - "%s" /* listen-port */ - "%s" /* private-key-flags */ - "%s" /* private-key */ - "%s" /* [wireguard-peers*] */ - "\n" - "[ipv4]\n" - "dns-search=\n" - "method=disabled\n" - "\n" - "[ipv6]\n" - "addr-gen-mode=stable-privacy\n" - "dns-search=\n" - "method=ignore\n" - "\n" - "[proxy]\n" - "", - ID, - UUID, - INTERFACE_NAME, - ((WG_FWMARK != 0) ? nm_sprintf_bufa(100, "fwmark=%u\n", WG_FWMARK) : ""), - ((WG_LISTEN_PORT != 0) ? nm_sprintf_bufa(100, "listen-port=%u\n", WG_LISTEN_PORT) - : ""), - ((WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) - ? nm_sprintf_bufa(100, "private-key-flags=%u\n", (guint) WG_PRIVATE_KEY_FLAGS) - : ""), - ((WG_PRIVATE_KEY && WG_PRIVATE_KEY_FLAGS == NM_SETTING_SECRET_FLAG_NONE) - ? nm_sprintf_bufa(100, "private-key=%s\n", WG_PRIVATE_KEY) - : ""), - _rndt_wg_peers_to_keyfile(wg_peers, TRUE, &tmp_str))); - - _rndt_wg_peers_assert_equal(s_wg, wg_peers, TRUE, TRUE, FALSE); - break; - - case 3: - con = nmtst_create_minimal_connection(ID, UUID, NM_SETTING_WIRED_SETTING_NAME, &s_con); - g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, INTERFACE_NAME, NULL); - nmtst_connection_normalize(con); - - s_eth = NM_SETTING_WIRED(nm_connection_get_setting(con, NM_TYPE_SETTING_WIRED)); - g_assert(NM_IS_SETTING_WIRED(s_eth)); - - g_object_set(s_eth, NM_SETTING_WIRED_MTU, ETH_MTU, NULL); - - s_ip.s_4 = NM_SETTING_IP_CONFIG(nm_connection_get_setting(con, NM_TYPE_SETTING_IP4_CONFIG)); - g_assert(NM_IS_SETTING_IP4_CONFIG(s_ip.s_4)); - - s_ip.s_6 = NM_SETTING_IP_CONFIG(nm_connection_get_setting(con, NM_TYPE_SETTING_IP6_CONFIG)); - g_assert(NM_IS_SETTING_IP6_CONFIG(s_ip.s_6)); - - for (is_ipv4 = 0; is_ipv4 < 2; is_ipv4++) { - g_assert(NM_IS_SETTING_IP_CONFIG(s_ip.s_x[is_ipv4])); - for (i = 0; i < 3; i++) { - char addrstr[NM_UTILS_INET_ADDRSTRLEN]; - - nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr = NULL; - - rr = nm_ip_routing_rule_new(is_ipv4 ? AF_INET : AF_INET6); - nm_ip_routing_rule_set_priority(rr, i + 1); - if (i > 0) { - if (is_ipv4) - nm_sprintf_buf(addrstr, "192.168.%u.0", i); - else - nm_sprintf_buf(addrstr, "1:2:3:%x::", 10 + i); - nm_ip_routing_rule_set_from(rr, addrstr, is_ipv4 ? 24 + i : 64 + i); - } - nm_ip_routing_rule_set_table(rr, 1000 + i); - - success = nm_ip_routing_rule_validate(rr, &error); - nmtst_assert_success(success, error); - - nm_setting_ip_config_add_routing_rule(s_ip.s_x[is_ipv4], rr); - } - } - - g_ptr_array_add( - kf_data_arr, - g_strdup_printf("[connection]\n" - "id=%s\n" - "uuid=%s\n" - "type=ethernet\n" - "interface-name=%s\n" - "permissions=\n" - "\n" - "[ethernet]\n" - "mac-address-blacklist=\n" - "%s" /* mtu */ - "\n" - "[ipv4]\n" - "dns-search=\n" - "method=auto\n" - "routing-rule1=priority 1 from 0.0.0.0/0 table 1000\n" - "routing-rule2=priority 2 from 192.168.1.0/25 table 1001\n" - "routing-rule3=priority 3 from 192.168.2.0/26 table 1002\n" - "\n" - "[ipv6]\n" - "addr-gen-mode=stable-privacy\n" - "dns-search=\n" - "method=auto\n" - "routing-rule1=priority 1 from ::/0 table 1000\n" - "routing-rule2=priority 2 from 1:2:3:b::/65 table 1001\n" - "routing-rule3=priority 3 from 1:2:3:c::/66 table 1002\n" - "\n" - "[proxy]\n" - "", - ID, - UUID, - INTERFACE_NAME, - (ETH_MTU != 0) ? nm_sprintf_bufa(100, "mtu=%u\n", ETH_MTU) : "")); - - break; - - default: - g_assert_not_reached(); - } - - /* the first kf_data_arr entry is special: it is the exact result of what we expect - * when converting @con to keyfile. Write @con to keyfile and compare the expected result - * literally. */ - { - nm_auto_unref_keyfile GKeyFile *kf = NULL; - - kf = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); - nmtst_assert_success(kf, error); - - /* the first kf_data_arr entry is special: it must be what the writer would - * produce again. */ - nmtst_keyfile_assert_data(kf, kf_data_arr->pdata[0], -1); - } - - /* check that reading any of kf_data_arr yields the same result that we expect. */ - for (kf_data_idx = 0; kf_data_idx < kf_data_arr->len; kf_data_idx++) { - gs_unref_object NMConnection *con2 = NULL; - NMSettingWireGuard * s_wg2 = NULL; - NMSettingWired * s_eth2 = NULL; - - con2 = nmtst_create_connection_from_keyfile(kf_data_arr->pdata[kf_data_idx], - "/no/where/file.nmconnection"); - - switch (MODE) { - case 0: - s_eth2 = NM_SETTING_WIRED(nm_connection_get_setting(con2, NM_TYPE_SETTING_WIRED)); - g_assert(NM_IS_SETTING_WIRED(s_eth2)); - - if (ETH_MTU > (guint32) G_MAXINT && kf_data_idx == 1) { - /* older versions wrote values > 2^21 as signed integers, but the reader would - * always reject such negative values for G_TYPE_UINT. - * - * The test case kf_data_idx #1 still writes the values in the old style. - * The behavior was fixed, but such values are still rejected as invalid. - * - * Patch the setting so that the comparison below succeeds are usual. */ - g_assert_cmpint(nm_setting_wired_get_mtu(s_eth2), ==, 0); - g_object_set(s_eth2, NM_SETTING_WIRED_MTU, ETH_MTU, NULL); - } - - g_assert_cmpint(nm_setting_wired_get_mtu(s_eth), ==, ETH_MTU); - g_assert_cmpint(nm_setting_wired_get_mtu(s_eth2), ==, ETH_MTU); - - g_assert_cmpint(nm_setting_wired_get_num_s390_options(s_eth2), - ==, - nm_setting_wired_get_num_s390_options(s_eth)); - - break; - - case 1: - s_wg2 = - NM_SETTING_WIREGUARD(nm_connection_get_setting(con2, NM_TYPE_SETTING_WIREGUARD)); - g_assert(NM_IS_SETTING_WIREGUARD(s_wg2)); - - g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg), ==, NULL); - g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg2), ==, NULL); - break; - - case 2: - s_wg2 = - NM_SETTING_WIREGUARD(nm_connection_get_setting(con2, NM_TYPE_SETTING_WIREGUARD)); - g_assert(NM_IS_SETTING_WIREGUARD(s_wg2)); - - /* the private key was lost due to the secret-flags. Patch it. */ - if (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) { - g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg2), ==, NULL); - g_object_set(s_wg2, NM_SETTING_WIREGUARD_PRIVATE_KEY, WG_PRIVATE_KEY, NULL); - } - - g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg), ==, WG_PRIVATE_KEY); - g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg2), ==, WG_PRIVATE_KEY); - - _rndt_wg_peers_assert_equal(s_wg2, wg_peers, TRUE, FALSE, FALSE); - _rndt_wg_peers_fix_secrets(s_wg2, wg_peers); - _rndt_wg_peers_assert_equal(s_wg2, wg_peers, TRUE, TRUE, FALSE); - break; - } - - nmtst_assert_connection_equals(con, nmtst_get_rand_bool(), con2, nmtst_get_rand_bool()); - } - - for (dbus_serialization_flags_idx = 0; - dbus_serialization_flags_idx < G_N_ELEMENTS(dbus_serialization_flags); - dbus_serialization_flags_idx++) { - NMConnectionSerializationFlags flag = - dbus_serialization_flags[dbus_serialization_flags_idx]; - gs_unref_variant GVariant *con_var = NULL; - gs_unref_object NMConnection *con2 = NULL; - NMSettingWireGuard * s_wg2 = NULL; - - con_var = nm_connection_to_dbus(con, flag); - g_assert(g_variant_is_of_type(con_var, NM_VARIANT_TYPE_CONNECTION)); - g_assert(g_variant_is_floating(con_var)); - g_variant_ref_sink(con_var); - - if (flag == NM_CONNECTION_SERIALIZE_ALL) { - con2 = _connection_new_from_dbus_strict(con_var, TRUE); - nmtst_assert_connection_equals(con, nmtst_get_rand_bool(), con2, nmtst_get_rand_bool()); - - { - nm_auto_unref_keyfile GKeyFile *kf = NULL; - - kf = nm_keyfile_write(con2, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); - nmtst_assert_success(kf, error); - nmtst_keyfile_assert_data(kf, kf_data_arr->pdata[0], -1); - } - } - - switch (MODE) { - case 2: - if (flag == NM_CONNECTION_SERIALIZE_ALL) { - s_wg2 = NM_SETTING_WIREGUARD( - nm_connection_get_setting(con2, NM_TYPE_SETTING_WIREGUARD)); - - if (flag == NM_CONNECTION_SERIALIZE_ALL) - _rndt_wg_peers_assert_equal(s_wg2, wg_peers, TRUE, TRUE, FALSE); - else if (flag == NM_CONNECTION_SERIALIZE_NO_SECRETS) - _rndt_wg_peers_assert_equal(s_wg2, wg_peers, FALSE, FALSE, TRUE); - else - g_assert_not_reached(); - } - break; - } - } -} - -/*****************************************************************************/ - -static NMIPRoutingRule * -_rr_from_str_get_impl(const char *str, const char *const *aliases) -{ - nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr = NULL; - gs_free_error GError * error = NULL; - gboolean vbool; - int addr_family; - int i; - NMIPRoutingRuleAsStringFlags to_string_flags; - - rr = nm_ip_routing_rule_from_string(str, - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE, - NULL, - &error); - nmtst_assert_success(rr, error); - - addr_family = nm_ip_routing_rule_get_addr_family(rr); - g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - - if (addr_family == AF_INET) - to_string_flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET; - else - to_string_flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6; - - for (i = 0; TRUE; i++) { - nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr2 = NULL; - gs_free char * str1 = NULL; - gs_unref_variant GVariant *variant1 = NULL; - const char * cstr1; - - switch (i) { - case 0: - rr2 = nm_ip_routing_rule_ref(rr); - break; - - case 1: - rr2 = nm_ip_routing_rule_from_string( - str, - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE - | (nmtst_get_rand_bool() ? to_string_flags - : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE), - NULL, - &error); - nmtst_assert_success(rr, error); - break; - - case 2: - str1 = nm_ip_routing_rule_to_string( - rr, - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE - | (nmtst_get_rand_bool() ? to_string_flags - : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE), - NULL, - &error); - nmtst_assert_success(str1 && str1[0], error); - - g_assert_cmpstr(str, ==, str1); - - rr2 = nm_ip_routing_rule_from_string( - str1, - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE - | (nmtst_get_rand_bool() ? to_string_flags - : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE), - NULL, - &error); - nmtst_assert_success(rr, error); - break; - - case 3: - variant1 = nm_ip_routing_rule_to_dbus(rr); - g_assert(variant1); - g_assert(g_variant_is_floating(variant1)); - g_assert(g_variant_is_of_type(variant1, G_VARIANT_TYPE_VARDICT)); - - rr2 = nm_ip_routing_rule_from_dbus(variant1, TRUE, &error); - nmtst_assert_success(rr, error); - break; - - default: - if (!aliases || !aliases[0]) - goto done; - cstr1 = (aliases++)[0]; - rr2 = nm_ip_routing_rule_from_string( - cstr1, - NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE - | (nmtst_get_rand_bool() ? to_string_flags - : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE), - NULL, - &error); - nmtst_assert_success(rr, error); - break; - } - - g_assert(rr2); - vbool = nm_ip_routing_rule_validate(rr, &error); - nmtst_assert_success(vbool, error); - vbool = nm_ip_routing_rule_validate(rr2, &error); - nmtst_assert_success(vbool, error); - - g_assert_cmpint(nm_ip_routing_rule_cmp(rr, rr2), ==, 0); - g_assert_cmpint(nm_ip_routing_rule_cmp(rr2, rr), ==, 0); - } - -done: - return g_steal_pointer(&rr); -} -#define _rr_from_str_get(a, ...) _rr_from_str_get_impl(a, &(NM_MAKE_STRV(NULL, ##__VA_ARGS__))[1]) - -#define _rr_from_str(...) \ - G_STMT_START \ - { \ - nm_auto_unref_ip_routing_rule NMIPRoutingRule *_rr = NULL; \ - \ - _rr = _rr_from_str_get(__VA_ARGS__); \ - g_assert(_rr); \ - } \ - G_STMT_END - -static void -test_routing_rule(gconstpointer test_data) -{ - nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr1 = NULL; - gboolean success; - char ifname_buf[16]; - - _rr_from_str("priority 5 from 0.0.0.0 table 1", " from 0.0.0.0 priority 5 lookup 1 "); - _rr_from_str("priority 5 from 0.0.0.0/0 table 4"); - _rr_from_str("priority 5 to 0.0.0.0 table 6"); - _rr_from_str("priority 5 to 0.0.0.0 table 254", "priority 5 to 0.0.0.0/32"); - _rr_from_str("priority 5 from 1.2.3.4 table 15", - "priority 5 from 1.2.3.4/32 table 0xF ", - "priority 5 from 1.2.3.4/32 to 0.0.0.0/0 lookup 15 "); - _rr_from_str("priority 5 from 1.2.3.4 to 0.0.0.0 table 8"); - _rr_from_str("priority 5 to a:b:c:: tos 0x16 table 25", - "priority 5 to a:b:c::/128 table 0x19 tos 16", - "priority 5 to a:b:c::/128 lookup 0x19 dsfield 16", - "priority 5 to a:b:c::/128 lookup 0x19 dsfield 16 fwmark 0/0x00", - "priority 5 to a:b:c:: from all lookup 0x19 dsfield 16 fwmark 0x0/0"); - _rr_from_str("priority 5 from :: fwmark 0 table 25", - "priority 5 from ::/128 to all table 0x19 fwmark 0/0xFFFFFFFF", - "priority 5 from :: to ::/0 table 0x19 fwmark 0x00/4294967295"); - _rr_from_str("priority 5 from :: iif aab table 25"); - _rr_from_str("priority 5 from :: iif aab oif er table 25", - "priority 5 from :: table 0x19 dev aab oif er"); - _rr_from_str("priority 5 from :: iif a\\\\303b table 25"); - _rr_from_str("priority 5 to 0.0.0.0 sport 10 table 6", - "priority 5 to 0.0.0.0 sport 10-10 table 6"); - _rr_from_str("priority 5 not to 0.0.0.0 dport 10-133 table 6", - "not priority 5 to 0.0.0.0 dport 10-133 table 6", - "not priority 5 not to 0.0.0.0 dport 10-133 table 6", - "priority 5 to 0.0.0.0 not dport 10-133 not table 6", - "priority 5 to 0.0.0.0 not dport 10-\\ 133 not table 6"); - _rr_from_str("priority 5 to 0.0.0.0 ipproto 10 sport 10 table 6"); - - rr1 = _rr_from_str_get("priority 5 from :: iif aab table 25"); - g_assert_cmpstr(nm_ip_routing_rule_get_iifname(rr1), ==, "aab"); - success = nm_ip_routing_rule_get_xifname_bin(rr1, FALSE, ifname_buf); - g_assert(!success); - success = nm_ip_routing_rule_get_xifname_bin(rr1, TRUE, ifname_buf); - g_assert_cmpstr(ifname_buf, ==, "aab"); - g_assert(success); - nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); - - rr1 = _rr_from_str_get("priority 5 from :: iif a\\\\303\\\\261xb table 254"); - g_assert_cmpstr(nm_ip_routing_rule_get_iifname(rr1), ==, "a\\303\\261xb"); - success = nm_ip_routing_rule_get_xifname_bin(rr1, FALSE, ifname_buf); - g_assert(!success); - success = nm_ip_routing_rule_get_xifname_bin(rr1, TRUE, ifname_buf); - g_assert_cmpstr(ifname_buf, ==, "a\303\261xb"); - g_assert(success); - nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); - - rr1 = _rr_from_str_get("priority 5 from :: oif \\\\101=\\\\303\\\\261xb table 7"); - g_assert_cmpstr(nm_ip_routing_rule_get_oifname(rr1), ==, "\\101=\\303\\261xb"); - success = nm_ip_routing_rule_get_xifname_bin(rr1, FALSE, ifname_buf); - g_assert_cmpstr(ifname_buf, ==, "A=\303\261xb"); - g_assert(success); - success = nm_ip_routing_rule_get_xifname_bin(rr1, TRUE, ifname_buf); - g_assert(!success); - nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); - - rr1 = _rr_from_str_get("priority 5 to 0.0.0.0 tos 0x10 table 7"); - g_assert_cmpstr(NULL, ==, nm_ip_routing_rule_get_from(rr1)); - g_assert(!nm_ip_routing_rule_get_from_bin(rr1)); - g_assert_cmpint(0, ==, nm_ip_routing_rule_get_from_len(rr1)); - g_assert_cmpstr("0.0.0.0", ==, nm_ip_routing_rule_get_to(rr1)); - g_assert(nm_ip_addr_is_null(AF_INET, nm_ip_routing_rule_get_to_bin(rr1))); - g_assert_cmpint(32, ==, nm_ip_routing_rule_get_to_len(rr1)); - g_assert_cmpint(7, ==, nm_ip_routing_rule_get_table(rr1)); - g_assert_cmpint(0x10, ==, nm_ip_routing_rule_get_tos(rr1)); - nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); - - rr1 = _rr_from_str_get("priority 5 from :: iif a\\\\303\\\\261,x;b table 254", - "priority 5 from :: iif a\\\\303\\\\261,x;b table 254"); - g_assert_cmpstr(nm_ip_routing_rule_get_iifname(rr1), ==, "a\\303\\261,x;b"); - success = nm_ip_routing_rule_get_xifname_bin(rr1, FALSE, ifname_buf); - g_assert(!success); - success = nm_ip_routing_rule_get_xifname_bin(rr1, TRUE, ifname_buf); - g_assert_cmpstr(ifname_buf, ==, "a\303\261,x;b"); - g_assert(success); - nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); -} - -/*****************************************************************************/ - -static void -test_parse_tc_handle(void) -{ -#define _parse_tc_handle(str, exp) \ - G_STMT_START \ - { \ - gs_free_error GError *_error = NULL; \ - GError ** _perror = nmtst_get_rand_bool() ? &_error : NULL; \ - guint32 _v; \ - const guint32 _v_exp = (exp); \ - \ - _v = _nm_utils_parse_tc_handle("" str "", _perror); \ - \ - if (_v != _v_exp) \ - g_error("%s:%d: \"%s\" gave %08x but %08x expected.", \ - __FILE__, \ - __LINE__, \ - "" str "", \ - _v, \ - _v_exp); \ - \ - if (_v == TC_H_UNSPEC) \ - g_assert(!_perror || *_perror); \ - else \ - g_assert(!_perror || !*_perror); \ - } \ - G_STMT_END - -#define _parse_tc_handle_inval(str) _parse_tc_handle(str, TC_H_UNSPEC) -#define _parse_tc_handle_valid(str, maj, min) \ - _parse_tc_handle(str, TC_H_MAKE(((guint32)(maj)) << 16, ((guint16)(min)))) - - _parse_tc_handle_inval(""); - _parse_tc_handle_inval(" "); - _parse_tc_handle_inval(" \n"); - _parse_tc_handle_valid("1", 1, 0); - _parse_tc_handle_valid(" 1 ", 1, 0); - _parse_tc_handle_valid("1:", 1, 0); - _parse_tc_handle_valid("1: ", 1, 0); - _parse_tc_handle_valid("1:0", 1, 0); - _parse_tc_handle_valid("1 :0", 1, 0); - _parse_tc_handle_valid("1 \t\n\f\r:0", 1, 0); - _parse_tc_handle_inval("1 \t\n\f\r\v:0"); - _parse_tc_handle_valid(" 1 : 0 ", 1, 0); - _parse_tc_handle_inval(" \t\v\n1: 0"); - _parse_tc_handle_valid("1:2", 1, 2); - _parse_tc_handle_valid("01:02", 1, 2); - _parse_tc_handle_inval("0x01:0x02"); - _parse_tc_handle_valid(" 01: 02", 1, 2); - _parse_tc_handle_valid("019: 020", 0x19, 0x20); - _parse_tc_handle_valid("FFFF: 020", 0xFFFF, 0x20); - _parse_tc_handle_valid("FfFF: ffff", 0xFFFF, 0xFFFF); - _parse_tc_handle_valid("FFFF", 0xFFFF, 0); - _parse_tc_handle_inval("0xFFFF"); - _parse_tc_handle_inval("10000"); - _parse_tc_handle_valid("\t\n\f\r FFFF", 0xFFFF, 0); - _parse_tc_handle_inval("\t\n\f\r \vFFFF"); -} - -/*****************************************************************************/ - -static void -test_empty_setting(void) -{ - gs_unref_object NMConnection *con = NULL; - gs_unref_object NMConnection *con2 = NULL; - NMSettingBluetooth * s_bt; - NMSettingGsm * s_gsm; - nm_auto_unref_keyfile GKeyFile *kf = NULL; - gs_free_error GError *error = NULL; - - con = nmtst_create_minimal_connection("bt-empty-gsm", - "dca3192a-f2dc-48eb-b806-d0ff788f122c", - NM_SETTING_BLUETOOTH_SETTING_NAME, - NULL); - - s_bt = _nm_connection_get_setting(con, NM_TYPE_SETTING_BLUETOOTH); - g_object_set(s_bt, - NM_SETTING_BLUETOOTH_TYPE, - "dun", - NM_SETTING_BLUETOOTH_BDADDR, - "aa:bb:cc:dd:ee:ff", - NULL); - - s_gsm = NM_SETTING_GSM(nm_setting_gsm_new()); - nm_connection_add_setting(con, NM_SETTING(s_gsm)); - - nmtst_connection_normalize(con); - - nmtst_assert_connection_verifies_without_normalization(con); - - kf = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); - nmtst_assert_success(kf, error); - - g_assert(g_key_file_has_group(kf, "gsm")); - g_assert_cmpint(nmtst_keyfile_get_num_keys(kf, "gsm"), ==, 0); - - con2 = nm_keyfile_read(kf, - "/ignored/current/working/directory/for/loading/relative/paths", - NM_KEYFILE_HANDLER_FLAGS_NONE, - NULL, - NULL, - &error); - nmtst_assert_success(con2, error); - - g_assert(nm_connection_get_setting(con2, NM_TYPE_SETTING_GSM)); - - nmtst_assert_connection_verifies_without_normalization(con2); -} - -/*****************************************************************************/ - -static guint -_PROP_IDX_PACK(NMMetaSettingType meta_type, guint idx) -{ - return (((guint) meta_type) & 0xFFu) | (idx << 8); -} - -static const char * -_PROP_IDX_OWNER(GHashTable *h_property_types, const NMSettInfoPropertType *property_type) -{ - const NMSettInfoSetting *sett_info_settings = nmtst_sett_info_settings(); - const NMSettInfoSetting *sis; - const NMMetaSettingInfo *msi; - GArray * arr; - guint idx; - NMMetaSettingType meta_type; - guint prop_idx; - char sbuf[300]; - - g_assert(h_property_types); - g_assert(property_type); - - arr = g_hash_table_lookup(h_property_types, property_type); - - g_assert(arr); - g_assert(arr->len > 0); - - idx = g_array_index(arr, guint, 0); - - meta_type = (idx & 0xFFu); - prop_idx = idx >> 8; - - g_assert(meta_type < _NM_META_SETTING_TYPE_NUM); - - sis = &sett_info_settings[meta_type]; - msi = &nm_meta_setting_infos[meta_type]; - - g_assert(prop_idx < sis->property_infos_len); - - nm_sprintf_buf(sbuf, "%s.%s", msi->setting_name, sis->property_infos[prop_idx].name); - - return g_intern_string(sbuf); -} - -static void -test_setting_metadata(void) -{ - const NMSettInfoSetting *sett_info_settings = nmtst_sett_info_settings(); - NMMetaSettingType meta_type; - gs_unref_hashtable GHashTable *h_property_types = NULL; - - G_STATIC_ASSERT(_NM_META_SETTING_TYPE_NUM == NM_META_SETTING_TYPE_UNKNOWN); - - h_property_types = - g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) g_array_unref); - - for (meta_type = 0; meta_type < _NM_META_SETTING_TYPE_NUM; meta_type++) { - const NMMetaSettingInfo *msi = &nm_meta_setting_infos[meta_type]; - nm_auto_unref_gtypeclass NMSettingClass *klass = NULL; - GType gtype; - - g_assert(msi->setting_name); - g_assert(msi->get_setting_gtype); - g_assert(msi->meta_type == meta_type); - g_assert(msi->setting_priority >= NM_SETTING_PRIORITY_CONNECTION); - g_assert(msi->setting_priority <= NM_SETTING_PRIORITY_USER); - - if (meta_type > 0) - g_assert_cmpint( - strcmp(nm_meta_setting_infos[meta_type - 1].setting_name, msi->setting_name), - <, - 0); - - gtype = msi->get_setting_gtype(); - - g_assert(g_type_is_a(gtype, NM_TYPE_SETTING)); - g_assert(gtype != NM_TYPE_SETTING); - - klass = g_type_class_ref(gtype); - g_assert(klass); - g_assert(NM_IS_SETTING_CLASS(klass)); - - g_assert(msi == klass->setting_info); - } - - g_assert(sett_info_settings); - - for (meta_type = 0; meta_type < _NM_META_SETTING_TYPE_NUM; meta_type++) { - const NMSettInfoSetting *sis = &sett_info_settings[meta_type]; - const NMMetaSettingInfo *msi = &nm_meta_setting_infos[meta_type]; - gs_unref_hashtable GHashTable *h_properties = NULL; - GType gtype; - gs_unref_object NMSetting *setting = NULL; - guint prop_idx; - gs_free GParamSpec **property_specs = NULL; - guint n_property_specs; - - g_assert(sis); - - g_assert(NM_IS_SETTING_CLASS(sis->setting_class)); - - gtype = msi->get_setting_gtype(); - - g_assert(G_TYPE_FROM_CLASS(sis->setting_class) == gtype); - - setting = g_object_new(gtype, NULL); - - g_assert(NM_IS_SETTING(setting)); - - g_assert_cmpint(sis->property_infos_len, >, 0); - g_assert(sis->property_infos); - - h_properties = g_hash_table_new(nm_str_hash, g_str_equal); - - for (prop_idx = 0; prop_idx < sis->property_infos_len; prop_idx++) { - const NMSettInfoProperty *sip = &sis->property_infos[prop_idx]; - GArray * property_types_data; - guint prop_idx_val; - - g_assert(sip->name); - - if (prop_idx > 0) - g_assert_cmpint(strcmp(sis->property_infos[prop_idx - 1].name, sip->name), <, 0); - - g_assert(sip->property_type); - g_assert(sip->property_type->dbus_type); - g_assert(g_variant_type_string_is_valid((const char *) sip->property_type->dbus_type)); - - g_assert(!sip->property_type->to_dbus_fcn || !sip->property_type->gprop_to_dbus_fcn); - g_assert(!sip->property_type->from_dbus_fcn - || !sip->property_type->gprop_from_dbus_fcn); - - if (!g_hash_table_insert(h_properties, (char *) sip->name, sip->param_spec)) - g_assert_not_reached(); - - property_types_data = g_hash_table_lookup(h_property_types, sip->property_type); - if (!property_types_data) { - property_types_data = g_array_new(FALSE, FALSE, sizeof(guint)); - if (!g_hash_table_insert(h_property_types, - (gpointer) sip->property_type, - property_types_data)) - g_assert_not_reached(); - } - prop_idx_val = _PROP_IDX_PACK(meta_type, prop_idx); - g_array_append_val(property_types_data, prop_idx_val); - - if (sip->param_spec) { - nm_auto_unset_gvalue GValue val = G_VALUE_INIT; - - g_assert_cmpstr(sip->name, ==, sip->param_spec->name); - - g_value_init(&val, sip->param_spec->value_type); - g_object_get_property(G_OBJECT(setting), sip->name, &val); - - if (sip->param_spec->value_type == G_TYPE_STRING) { - const char *default_value; - - default_value = ((const GParamSpecString *) sip->param_spec)->default_value; - if (default_value) { - /* having a string property with a default != NULL is really ugly. They - * should be best avoided... */ - if (meta_type == NM_META_SETTING_TYPE_DCB - && nm_streq(sip->name, NM_SETTING_DCB_APP_FCOE_MODE)) { - /* Whitelist the properties that have a non-NULL default value. */ - g_assert_cmpstr(default_value, ==, NM_SETTING_DCB_FCOE_MODE_FABRIC); - } else - g_assert_not_reached(); - } - - if (nm_streq(sip->name, NM_SETTING_NAME)) - g_assert_cmpstr(g_value_get_string(&val), ==, msi->setting_name); - else - g_assert_cmpstr(g_value_get_string(&val), ==, default_value); - } - - if (NM_FLAGS_HAS(sip->param_spec->flags, NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS)) - g_assert(sip->property_type->to_dbus_fcn); - } - } - - /* check that all GObject based properties are tracked by the settings. */ - property_specs = - g_object_class_list_properties(G_OBJECT_CLASS(sis->setting_class), &n_property_specs); - g_assert(property_specs); - g_assert_cmpint(n_property_specs, >, 0); - for (prop_idx = 0; prop_idx < n_property_specs; prop_idx++) { - const GParamSpec *pip = property_specs[prop_idx]; - - g_assert(g_hash_table_lookup(h_properties, pip->name) == pip); - } - - /* check that property_infos_sorted is as expected. */ - if (sis->property_infos_sorted) { - gs_unref_hashtable GHashTable *h = g_hash_table_new(nm_direct_hash, NULL); - - /* property_infos_sorted is only implemented for [connection] type */ - g_assert_cmpint(meta_type, ==, NM_META_SETTING_TYPE_CONNECTION); - - /* ensure that there are no duplicates, and that all properties are also - * tracked by sis->property_infos. */ - for (prop_idx = 0; prop_idx < sis->property_infos_len; prop_idx++) { - const NMSettInfoProperty *sip = sis->property_infos_sorted[prop_idx]; - - if (!g_hash_table_add(h, (gpointer) sip)) - g_assert_not_reached(); - } - for (prop_idx = 0; prop_idx < sis->property_infos_len; prop_idx++) { - const NMSettInfoProperty *sip = &sis->property_infos[prop_idx]; - - g_assert(g_hash_table_contains(h, sip)); - } - } else - g_assert_cmpint(meta_type, !=, NM_META_SETTING_TYPE_CONNECTION); - - /* consistency check for gendata-info. */ - if (sis->detail.gendata_info) { - g_assert_cmpint(meta_type, ==, NM_META_SETTING_TYPE_ETHTOOL); - g_assert(sis->detail.gendata_info->get_variant_type); - - /* the gendata info based setting has only one regular property: the "name". */ - g_assert_cmpint(sis->property_infos_len, ==, 1); - g_assert_cmpstr(sis->property_infos[0].name, ==, NM_SETTING_NAME); - } else - g_assert_cmpint(meta_type, !=, NM_META_SETTING_TYPE_ETHTOOL); - } - - { - gs_free NMSettInfoPropertType **a_property_types = NULL; - guint a_property_types_len; - guint prop_idx; - guint prop_idx_2; - - a_property_types = - (NMSettInfoPropertType **) g_hash_table_get_keys_as_array(h_property_types, - &a_property_types_len); - - for (prop_idx = 0; prop_idx < a_property_types_len; prop_idx++) { - const NMSettInfoPropertType *pt = a_property_types[prop_idx]; - - for (prop_idx_2 = prop_idx + 1; prop_idx_2 < a_property_types_len; prop_idx_2++) { - const NMSettInfoPropertType *pt_2 = a_property_types[prop_idx_2]; - - if (!g_variant_type_equal(pt->dbus_type, pt_2->dbus_type) - || pt->to_dbus_fcn != pt_2->to_dbus_fcn - || pt->from_dbus_fcn != pt_2->from_dbus_fcn - || pt->missing_from_dbus_fcn != pt_2->missing_from_dbus_fcn - || pt->gprop_to_dbus_fcn != pt_2->gprop_to_dbus_fcn - || pt->gprop_from_dbus_fcn != pt_2->gprop_from_dbus_fcn) - continue; - - if ((pt == &nm_sett_info_propert_type_plain_i - && pt_2 == &nm_sett_info_propert_type_deprecated_ignore_i) - || (pt_2 == &nm_sett_info_propert_type_plain_i - && pt == &nm_sett_info_propert_type_deprecated_ignore_i) - || (pt == &nm_sett_info_propert_type_plain_u - && pt_2 == &nm_sett_info_propert_type_deprecated_ignore_u) - || (pt_2 == &nm_sett_info_propert_type_plain_u - && pt == &nm_sett_info_propert_type_deprecated_ignore_u)) { - /* These are known to be duplicated. This is the case for - * "gsm.network-type" and plain properties like "802-11-wireless-security.fils" ("i" D-Bus type) - * "gsm.allowed-bands" and plain properties like "802-11-olpc-mesh.channel" ("u" D-Bus type) - * While the content/behaviour of the property types are identical, their purpose - * is different. So allow them. - */ - continue; - } - - /* the property-types with same content should all be shared. Here we have two that - * are the same content, but different instances. Bug. */ - g_error("The identical property type for D-Bus type \"%s\" is used by: %s and %s", - (const char *) pt->dbus_type, - _PROP_IDX_OWNER(h_property_types, pt), - _PROP_IDX_OWNER(h_property_types, pt_2)); - } - } - } -} - -/*****************************************************************************/ - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init(&argc, &argv, TRUE); - - g_test_add_data_func("/libnm/setting-8021x/key-and-cert", - "test_key_and_cert.pem, test", - test_8021x); - g_test_add_data_func("/libnm/setting-8021x/key-only", "test-key-only.pem, test", test_8021x); - g_test_add_data_func("/libnm/setting-8021x/pkcs8-enc-key", - "pkcs8-enc-key.pem, 1234567890", - test_8021x); - g_test_add_data_func("/libnm/setting-8021x/pkcs12", "test-cert.p12, test", test_8021x); - - g_test_add_func("/libnm/settings/bond/verify", test_bond_verify); - g_test_add_func("/libnm/settings/bond/compare", test_bond_compare); - g_test_add_func("/libnm/settings/bond/normalize", test_bond_normalize); - - g_test_add_func("/libnm/settings/dcb/flags-valid", test_dcb_flags_valid); - g_test_add_func("/libnm/settings/dcb/flags-invalid", test_dcb_flags_invalid); - g_test_add_func("/libnm/settings/dcb/app-priorities", test_dcb_app_priorities); - g_test_add_func("/libnm/settings/dcb/priorities", test_dcb_priorities_valid); - g_test_add_func("/libnm/settings/dcb/bandwidth-sums", test_dcb_bandwidth_sums); - - g_test_add_func("/libnm/settings/ethtool/features", test_ethtool_features); - g_test_add_func("/libnm/settings/ethtool/coalesce", test_ethtool_coalesce); - g_test_add_func("/libnm/settings/ethtool/ring", test_ethtool_ring); - - g_test_add_func("/libnm/settings/sriov/vf", test_sriov_vf); - g_test_add_func("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup); - g_test_add_func("/libnm/settings/sriov/vf-vlan", test_sriov_vf_vlan); - g_test_add_func("/libnm/settings/sriov/setting", test_sriov_setting); - g_test_add_func("/libnm/settings/sriov/vlans", test_sriov_parse_vlans); - - g_test_add_func("/libnm/settings/tc_config/qdisc", test_tc_config_qdisc); - g_test_add_func("/libnm/settings/tc_config/action", test_tc_config_action); - g_test_add_func("/libnm/settings/tc_config/tfilter/matchall_sdata", - test_tc_config_tfilter_matchall_sdata); - g_test_add_func("/libnm/settings/tc_config/tfilter/matchall_mirred", - test_tc_config_tfilter_matchall_mirred); - g_test_add_func("/libnm/settings/tc_config/setting/valid", test_tc_config_setting_valid); - g_test_add_func("/libnm/settings/tc_config/setting/duplicates", - test_tc_config_setting_duplicates); - g_test_add_func("/libnm/settings/tc_config/dbus", test_tc_config_dbus); - - g_test_add_func("/libnm/settings/bridge/vlans", test_bridge_vlans); - g_test_add_func("/libnm/settings/bridge/verify", test_bridge_verify); - - g_test_add_func("/libnm/test_nm_json", test_nm_json); - g_test_add_func("/libnm/settings/team/sync_runner_from_config_roundrobin", - test_runner_roundrobin_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_runner_from_config_broadcast", - test_runner_broadcast_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_runner_from_config_random", - test_runner_random_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_runner_from_config_activebackup", - test_runner_activebackup_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_runner_from_config_loadbalance", - test_runner_loadbalance_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_runner_from_config_lacp", - test_runner_lacp_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_watcher_from_config_ethtool", - test_watcher_ethtool_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_watcher_from_config_nsna_ping", - test_watcher_nsna_ping_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_watcher_from_config_arp_ping", - test_watcher_arp_ping_sync_from_config); - g_test_add_func("/libnm/settings/team/sync_watcher_from_config_all", - test_multiple_watchers_sync_from_config); - - g_test_add_func("/libnm/settings/team-port/sync_from_config_defaults", test_team_port_default); - g_test_add_func("/libnm/settings/team-port/sync_from_config_queue_id", test_team_port_queue_id); - g_test_add_func("/libnm/settings/team-port/sync_from_config_prio", test_team_port_prio); - g_test_add_func("/libnm/settings/team-port/sync_from_config_sticky", test_team_port_sticky); - g_test_add_func("/libnm/settings/team-port/sync_from_config_lacp_prio", - test_team_port_lacp_prio); - g_test_add_func("/libnm/settings/team-port/sync_from_config_lacp_key", test_team_port_lacp_key); - g_test_add_func("/libnm/settings/team-port/sycn_from_config_full", test_team_port_full_config); - - g_test_add_data_func("/libnm/settings/roundtrip-conversion/general/0", - GINT_TO_POINTER(0), - test_roundtrip_conversion); - g_test_add_data_func("/libnm/settings/roundtrip-conversion/wireguard/1", - GINT_TO_POINTER(1), - test_roundtrip_conversion); - g_test_add_data_func("/libnm/settings/roundtrip-conversion/wireguard/2", - GINT_TO_POINTER(2), - test_roundtrip_conversion); - g_test_add_data_func("/libnm/settings/roundtrip-conversion/general/3", - GINT_TO_POINTER(3), - test_roundtrip_conversion); - - g_test_add_data_func("/libnm/settings/routing-rule/1", GINT_TO_POINTER(0), test_routing_rule); - - g_test_add_func("/libnm/parse-tc-handle", test_parse_tc_handle); - - g_test_add_func("/libnm/test_team_setting", test_team_setting); - - g_test_add_func("/libnm/test_empty_setting", test_empty_setting); - - g_test_add_func("/libnm/test_setting_metadata", test_setting_metadata); - - return g_test_run(); -} diff --git a/libnm-core/tests/test-settings-defaults.c b/libnm-core/tests/test-settings-defaults.c deleted file mode 100644 index 1e6acd3c5f..0000000000 --- a/libnm-core/tests/test-settings-defaults.c +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2008 - 2011 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-utils.h" -#include "nm-setting-8021x.h" -#include "nm-setting-cdma.h" -#include "nm-setting-connection.h" -#include "nm-setting-gsm.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-setting-ppp.h" -#include "nm-setting-pppoe.h" -#include "nm-setting-serial.h" -#include "nm-setting-vpn.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireless.h" -#include "nm-setting-wireless-security.h" - -#include "nm-utils/nm-test-utils.h" - -static void -test_defaults(GType type, const char *name) -{ - GParamSpec **property_specs; - guint n_property_specs; - GObject * setting; - int i; - - setting = g_object_new(type, NULL); - - property_specs = g_object_class_list_properties(G_OBJECT_GET_CLASS(setting), &n_property_specs); - g_assert(property_specs); - - for (i = 0; i < n_property_specs; i++) { - GParamSpec *prop_spec = property_specs[i]; - GValue value = G_VALUE_INIT; - GValue defvalue = G_VALUE_INIT; - char * actual, *expected; - gboolean ok = FALSE; - - /* Ignore non-fundamental types since they won't really have - * defaults. - */ - if (!G_TYPE_IS_FUNDAMENTAL(prop_spec->value_type)) - continue; - - g_value_init(&value, prop_spec->value_type); - g_object_get_property(G_OBJECT(setting), prop_spec->name, &value); - - g_value_init(&defvalue, prop_spec->value_type); - g_param_value_set_default(prop_spec, &defvalue); - - actual = g_strdup_value_contents(&value); - expected = g_strdup_value_contents(&defvalue); - - if (!strcmp(prop_spec->name, NM_SETTING_NAME)) { - /* 'name' is always the setting name, not the default value */ - ok = !strcmp(nm_setting_get_name(NM_SETTING(setting)), name); - g_free(expected); - expected = g_strdup(name); - } else - ok = g_param_value_defaults(prop_spec, &value); - - g_assert(ok); - - g_free(actual); - g_free(expected); - g_value_unset(&value); - g_value_unset(&defvalue); - } - - g_free(property_specs); - g_object_unref(setting); -} - -static void -defaults(void) -{ - /* The tests */ - test_defaults(NM_TYPE_SETTING_CONNECTION, NM_SETTING_CONNECTION_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_802_1X, NM_SETTING_802_1X_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_CDMA, NM_SETTING_CDMA_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_GSM, NM_SETTING_GSM_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_IP4_CONFIG, NM_SETTING_IP4_CONFIG_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_IP6_CONFIG, NM_SETTING_IP6_CONFIG_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_PPP, NM_SETTING_PPP_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_PPPOE, NM_SETTING_PPPOE_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_SERIAL, NM_SETTING_SERIAL_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_VPN, NM_SETTING_VPN_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_WIRED, NM_SETTING_WIRED_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_WIRELESS, NM_SETTING_WIRELESS_SETTING_NAME); - test_defaults(NM_TYPE_SETTING_WIRELESS_SECURITY, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); -} - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init(&argc, &argv, TRUE); - - g_test_add_func("/libnm/defaults", defaults); - - return g_test_run(); -} diff --git a/libnm/meson.build b/libnm/meson.build index d0846419c5..8462d4bc50 100644 --- a/libnm/meson.build +++ b/libnm/meson.build @@ -3,9 +3,16 @@ libnm_inc = include_directories('.') libnm_nm_default_dep = declare_dependency( - sources: libnm_core_enum_sources[1], - include_directories: libnm_inc, - dependencies: libnm_core_nm_default_dep, + include_directories: [ + libnm_inc, + libnm_core_public_inc, + top_inc, + shared_inc, + src_inc, + ], + dependencies: [ + libnm_core_public_dep, + ], ) libnm_headers = files( @@ -135,7 +142,7 @@ libnm_static = static_library( sources: libnm_sources + libnm_enum_sources, dependencies: [ libnmdbus_dep, - libnm_libnm_core_intern_dep, + libnm_core_aux_intern_dep, libnm_nm_default_dep, libnm_udev_aux_dep, libudev_dep, @@ -154,10 +161,11 @@ libnm = shared_library( dependencies: libnm_nm_default_dep, link_whole: [ libnm_static, - libnm_core, + libnm_core_impl, libnmdbus, libnm_systemd_logging_stub, libnm_glib_aux, + libnm_base, ], link_args: '-Wl,--version-script,@0@'.format(linker_script), link_depends: linker_script, @@ -194,8 +202,11 @@ if enable_introspection libnm_gir = gnome.generate_gir( libnm, - sources: libnm_core_sources + libnm_core_headers + libnm_core_enum_sources + libnm_sources + libnm_headers + libnm_enum_sources + [nm_version_macro_header], + sources: libnm_core_settings_sources + libnm_core_impl_sources + libnm_core_public_enum_sources + libnm_core_headers + libnm_sources + libnm_headers + libnm_enum_sources + [nm_version_macro_header], includes: 'Gio-2.0', + include_directories: [ + libnm_core_public_inc, + ], nsversion: nm_gir_version, namespace: 'NM', identifier_prefix: nm_id_prefix, @@ -300,8 +311,7 @@ libnm_libnm_aux = static_library( '-DG_LOG_DOMAIN="libnmc"', ], dependencies: [ - libnm_core_nm_default_dep, - libnm_libnm_core_intern_dep, + libnm_core_aux_intern_dep, libnm_dep, ], ) diff --git a/libnm/nm-active-connection.c b/libnm/nm-active-connection.c index 80fb25115b..60c68f3478 100644 --- a/libnm/nm-active-connection.c +++ b/libnm/nm-active-connection.c @@ -10,7 +10,7 @@ #include "nm-dbus-interface.h" #include "nm-object-private.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-device.h" #include "nm-connection.h" #include "nm-vpn-connection.h" diff --git a/libnm/nm-checkpoint.c b/libnm/nm-checkpoint.c index 5fd55bc1d7..951e66229f 100644 --- a/libnm/nm-checkpoint.c +++ b/libnm/nm-checkpoint.c @@ -7,7 +7,7 @@ #include "nm-checkpoint.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-interface.h" #include "nm-device.h" #include "nm-object-private.h" diff --git a/libnm/nm-client.c b/libnm/nm-client.c index f1b259700f..a2d953cee0 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -13,12 +13,12 @@ #include "nm-std-aux/c-list-util.h" #include "nm-glib-aux/nm-c-list.h" #include "nm-glib-aux/nm-dbus-aux.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-access-point.h" #include "nm-active-connection.h" #include "nm-checkpoint.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-helpers.h" #include "nm-device-6lowpan.h" #include "nm-device-adsl.h" diff --git a/libnm/nm-device-bond.c b/libnm/nm-device-bond.c index 1214964161..caf9cdcaef 100644 --- a/libnm/nm-device-bond.c +++ b/libnm/nm-device-bond.c @@ -11,7 +11,7 @@ #include "nm-utils.h" #include "nm-device-bond.h" #include "nm-object-private.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/libnm/nm-device-bridge.c b/libnm/nm-device-bridge.c index 732c5a2ceb..2a7226e92b 100644 --- a/libnm/nm-device-bridge.c +++ b/libnm/nm-device-bridge.c @@ -11,7 +11,7 @@ #include "nm-utils.h" #include "nm-device-bridge.h" #include "nm-object-private.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/libnm/nm-device-ip-tunnel.c b/libnm/nm-device-ip-tunnel.c index a6d2ef4a4c..c370f79e20 100644 --- a/libnm/nm-device-ip-tunnel.c +++ b/libnm/nm-device-ip-tunnel.c @@ -11,7 +11,7 @@ #include "nm-setting-ip-tunnel.h" #include "nm-utils.h" #include "nm-object-private.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/libnm/nm-device-ovs-bridge.c b/libnm/nm-device-ovs-bridge.c index 9c17554899..c95355161e 100644 --- a/libnm/nm-device-ovs-bridge.c +++ b/libnm/nm-device-ovs-bridge.c @@ -11,7 +11,7 @@ #include "nm-setting-ovs-bridge.h" #include "nm-setting-ovs-port.h" #include "nm-setting-connection.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/libnm/nm-device-ovs-port.c b/libnm/nm-device-ovs-port.c index 1b3faa53f1..b52fdf9b21 100644 --- a/libnm/nm-device-ovs-port.c +++ b/libnm/nm-device-ovs-port.c @@ -11,7 +11,7 @@ #include "nm-setting-ovs-port.h" #include "nm-setting-ovs-port.h" #include "nm-setting-connection.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/libnm/nm-device-team.c b/libnm/nm-device-team.c index d76dd5c1c1..4af9f8e60a 100644 --- a/libnm/nm-device-team.c +++ b/libnm/nm-device-team.c @@ -11,7 +11,7 @@ #include "nm-setting-team.h" #include "nm-utils.h" #include "nm-object-private.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/libnm/nm-device-wifi-p2p.c b/libnm/nm-device-wifi-p2p.c index 019bf1cf6a..d946977383 100644 --- a/libnm/nm-device-wifi-p2p.c +++ b/libnm/nm-device-wifi-p2p.c @@ -13,7 +13,7 @@ #include "nm-utils.h" #include "nm-wifi-p2p-peer.h" #include "nm-object-private.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-helpers.h" /*****************************************************************************/ diff --git a/libnm/nm-device-wifi.c b/libnm/nm-device-wifi.c index 90e4a302f2..76a6e824ab 100644 --- a/libnm/nm-device-wifi.c +++ b/libnm/nm-device-wifi.c @@ -17,7 +17,7 @@ #include "nm-utils.h" #include "nm-access-point.h" #include "nm-object-private.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-helpers.h" /*****************************************************************************/ diff --git a/libnm/nm-device.c b/libnm/nm-device.c index 9cb88dae8e..b1ace53bed 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -20,7 +20,7 @@ #include "nm-ip6-config.h" #include "nm-object-private.h" #include "nm-remote-connection.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-utils.h" #include "nm-dbus-helpers.h" #include "nm-device-tun.h" diff --git a/libnm/nm-dns-manager.c b/libnm/nm-dns-manager.c index 6261c71ac6..9c5f0cf0f7 100644 --- a/libnm/nm-dns-manager.c +++ b/libnm/nm-dns-manager.c @@ -12,7 +12,7 @@ #include "nm-client.h" #include "nm-object-private.h" #include "nm-dbus-helpers.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /***************************************************************************** * NMDnsEntry diff --git a/libnm/nm-ip-config.c b/libnm/nm-ip-config.c index 1663c62257..4c336213c9 100644 --- a/libnm/nm-ip-config.c +++ b/libnm/nm-ip-config.c @@ -14,7 +14,7 @@ #include "nm-dbus-interface.h" #include "nm-object-private.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c index 1000e04d1a..02abd560c6 100644 --- a/libnm/nm-libnm-utils.c +++ b/libnm/nm-libnm-utils.c @@ -9,7 +9,7 @@ #include "nm-libnm-utils.h" #include "nm-glib-aux/nm-time-utils.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-object.h" /*****************************************************************************/ diff --git a/libnm/nm-object.c b/libnm/nm-object.c index 00e520d7e5..eaf178e7db 100644 --- a/libnm/nm-object.c +++ b/libnm/nm-object.c @@ -16,7 +16,7 @@ #include "nm-object-private.h" #include "nm-dbus-helpers.h" #include "nm-client.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "c-list/src/c-list.h" /*****************************************************************************/ diff --git a/libnm/nm-remote-connection.c b/libnm/nm-remote-connection.c index b5b12bf020..8ad1e51c72 100644 --- a/libnm/nm-remote-connection.c +++ b/libnm/nm-remote-connection.c @@ -12,7 +12,7 @@ #include "nm-dbus-interface.h" #include "nm-utils.h" #include "nm-setting-connection.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-remote-connection-private.h" #include "nm-object-private.h" #include "nm-dbus-helpers.h" diff --git a/libnm/nm-secret-agent-old.c b/libnm/nm-secret-agent-old.c index 8f826ed86b..771706610d 100644 --- a/libnm/nm-secret-agent-old.c +++ b/libnm/nm-secret-agent-old.c @@ -8,7 +8,7 @@ #include "nm-secret-agent-old.h" #include "c-list/src/c-list.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-helpers.h" #include "nm-dbus-interface.h" #include "nm-enum-types.h" diff --git a/libnm/nm-vpn-plugin-old.c b/libnm/nm-vpn-plugin-old.c index f45d0c09e9..2ff83efa3c 100644 --- a/libnm/nm-vpn-plugin-old.c +++ b/libnm/nm-vpn-plugin-old.c @@ -15,7 +15,7 @@ #include "nm-utils.h" #include "nm-connection.h" #include "nm-dbus-helpers.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-simple-connection.h" #include "nm-vpn-service-plugin.h" diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c index 34de21b875..f89ea4ce7f 100644 --- a/libnm/nm-vpn-service-plugin.c +++ b/libnm/nm-vpn-service-plugin.c @@ -17,7 +17,7 @@ #include "nm-utils.h" #include "nm-connection.h" #include "nm-dbus-helpers.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-simple-connection.h" #include "introspection/org.freedesktop.NetworkManager.VPN.Plugin.h" diff --git a/libnm/tests/meson.build b/libnm/tests/meson.build index 08eecfbdee..efc86a71b3 100644 --- a/libnm/tests/meson.build +++ b/libnm/tests/meson.build @@ -16,13 +16,16 @@ foreach test_unit: test_units libnm_enum_sources[1], ], dependencies: [ - libnm_core_dep, + libnm_core_impl_dep_link, libnm_nm_default_dep, ], c_args: [ '-DG_LOG_DOMAIN="test"', ], - link_with: libnm_static, + link_with: [ + libnm_static, + libnm_base, + ], ) test( diff --git a/libnm/tests/test-libnm.c b/libnm/tests/test-libnm.c index a90acd9b10..f97cd62c20 100644 --- a/libnm/tests/test-libnm.c +++ b/libnm/tests/test-libnm.c @@ -22,7 +22,7 @@ #include "nm-libnm-utils.h" #include "nm-object.h" #include "nm-vpn-service-plugin.h" -#include "nm-libnm-core-intern/nm-libnm-core-utils.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nm-utils/nm-test-utils.h" diff --git a/meson.build b/meson.build index 4adcf0fec7..8a42183594 100644 --- a/meson.build +++ b/meson.build @@ -917,8 +917,7 @@ content_files = [] subdir('introspection') subdir('shared') -subdir('libnm-core') -subdir('src/core') +subdir('src') subdir('libnm') subdir('dispatcher') subdir('clients') diff --git a/po/POTFILES.in b/po/POTFILES.in index 21507eecee..db73203878 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -33,9 +33,9 @@ clients/tui/nmt-page-bridge.c clients/tui/nmt-page-dsl.c clients/tui/nmt-page-ethernet.c clients/tui/nmt-page-infiniband.c +clients/tui/nmt-page-ip-tunnel.c clients/tui/nmt-page-ip4.c clients/tui/nmt-page-ip6.c -clients/tui/nmt-page-ip-tunnel.c clients/tui/nmt-page-ppp.c clients/tui/nmt-page-team-port.c clients/tui/nmt-page-team.c @@ -51,67 +51,7 @@ clients/tui/nmtui-connect.c clients/tui/nmtui-edit.c clients/tui/nmtui-hostname.c clients/tui/nmtui.c -libnm-core/nm-crypto.c -libnm-core/nm-crypto-gnutls.c -libnm-core/nm-crypto-nss.c -libnm-core/nm-connection.c -libnm-core/nm-dbus-utils.c -libnm-core/nm-keyfile-utils.c -libnm-core/nm-keyfile.c -libnm-core/nm-libnm-core-aux/nm-libnm-core-aux.c -libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c -libnm-core/nm-setting-6lowpan.c -libnm-core/nm-setting-8021x.c -libnm-core/nm-setting-adsl.c -libnm-core/nm-setting-bluetooth.c -libnm-core/nm-setting-bond.c -libnm-core/nm-setting-bridge-port.c -libnm-core/nm-setting-bridge.c -libnm-core/nm-setting-cdma.c -libnm-core/nm-setting-connection.c -libnm-core/nm-setting-dcb.c -libnm-core/nm-setting-ethtool.c -libnm-core/nm-setting-gsm.c -libnm-core/nm-setting-infiniband.c -libnm-core/nm-setting-ip-config.c -libnm-core/nm-setting-ip-tunnel.c -libnm-core/nm-setting-ip4-config.c -libnm-core/nm-setting-ip6-config.c -libnm-core/nm-setting-macsec.c -libnm-core/nm-setting-macvlan.c -libnm-core/nm-setting-match.c -libnm-core/nm-setting-olpc-mesh.c -libnm-core/nm-setting-ovs-bridge.c -libnm-core/nm-setting-ovs-external-ids.c -libnm-core/nm-setting-ovs-interface.c -libnm-core/nm-setting-ovs-patch.c -libnm-core/nm-setting-ovs-port.c -libnm-core/nm-setting-ppp.c -libnm-core/nm-setting-pppoe.c -libnm-core/nm-setting-proxy.c -libnm-core/nm-setting-sriov.c -libnm-core/nm-setting-tc-config.c -libnm-core/nm-setting-team-port.c -libnm-core/nm-setting-team.c -libnm-core/nm-setting-tun.c -libnm-core/nm-setting-user.c -libnm-core/nm-setting-veth.c -libnm-core/nm-setting-vlan.c -libnm-core/nm-setting-vrf.c -libnm-core/nm-setting-vpn.c -libnm-core/nm-setting-vxlan.c -libnm-core/nm-setting-wifi-p2p.c -libnm-core/nm-setting-wimax.c -libnm-core/nm-setting-wired.c -libnm-core/nm-setting-wireguard.c -libnm-core/nm-setting-wireless-security.c -libnm-core/nm-setting-wireless.c -libnm-core/nm-setting-wpan.c -libnm-core/nm-setting.c -libnm-core/nm-team-utils.c -libnm-core/nm-utils.c -libnm-core/nm-vpn-editor-plugin.c -libnm-core/nm-vpn-plugin-info.c +data/org.freedesktop.NetworkManager.policy.in.in libnm/nm-client.c libnm/nm-device-6lowpan.c libnm/nm-device-adsl.c @@ -145,16 +85,9 @@ libnm/nm-remote-connection.c libnm/nm-secret-agent-old.c libnm/nm-vpn-plugin-old.c libnm/nm-vpn-service-plugin.c -data/org.freedesktop.NetworkManager.policy.in.in shared/nm-glib-aux/nm-shared-utils.c shared/nm-log-core/nm-logging.c src/core/NetworkManagerUtils.c -src/core/main.c -src/core/main-utils.c -src/core/dhcp/nm-dhcp-dhclient.c -src/core/dhcp/nm-dhcp-dhclient-utils.c -src/core/dhcp/nm-dhcp-manager.c -src/core/dns/nm-dns-manager.c src/core/devices/adsl/nm-device-adsl.c src/core/devices/bluetooth/nm-bluez-manager.c src/core/devices/bluetooth/nm-device-bt.c @@ -162,8 +95,8 @@ src/core/devices/nm-device-6lowpan.c src/core/devices/nm-device-bond.c src/core/devices/nm-device-bridge.c src/core/devices/nm-device-dummy.c -src/core/devices/nm-device-ethernet.c src/core/devices/nm-device-ethernet-utils.c +src/core/devices/nm-device-ethernet.c src/core/devices/nm-device-infiniband.c src/core/devices/nm-device-ip-tunnel.c src/core/devices/nm-device-macvlan.c @@ -178,8 +111,75 @@ src/core/devices/wifi/nm-device-olpc-mesh.c src/core/devices/wifi/nm-device-wifi.c src/core/devices/wifi/nm-wifi-utils.c src/core/devices/wwan/nm-modem-broadband.c +src/core/dhcp/nm-dhcp-dhclient-utils.c +src/core/dhcp/nm-dhcp-dhclient.c +src/core/dhcp/nm-dhcp-manager.c +src/core/dns/nm-dns-manager.c +src/core/main-utils.c +src/core/main.c src/core/nm-config.c src/core/nm-iface-helper.c src/core/nm-manager.c src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +src/libnm-core-aux-extern/nm-libnm-core-aux.c +src/libnm-core-aux-intern/nm-libnm-core-utils.c +src/libnm-core-impl/nm-connection.c +src/libnm-core-impl/nm-crypto-gnutls.c +src/libnm-core-impl/nm-crypto-nss.c +src/libnm-core-impl/nm-crypto.c +src/libnm-core-impl/nm-dbus-utils.c +src/libnm-core-impl/nm-keyfile-utils.c +src/libnm-core-impl/nm-keyfile.c +src/libnm-core-impl/nm-setting-6lowpan.c +src/libnm-core-impl/nm-setting-8021x.c +src/libnm-core-impl/nm-setting-adsl.c +src/libnm-core-impl/nm-setting-bluetooth.c +src/libnm-core-impl/nm-setting-bond.c +src/libnm-core-impl/nm-setting-bridge-port.c +src/libnm-core-impl/nm-setting-bridge.c +src/libnm-core-impl/nm-setting-cdma.c +src/libnm-core-impl/nm-setting-connection.c +src/libnm-core-impl/nm-setting-dcb.c +src/libnm-core-impl/nm-setting-ethtool.c +src/libnm-core-impl/nm-setting-gsm.c +src/libnm-core-impl/nm-setting-infiniband.c +src/libnm-core-impl/nm-setting-ip-config.c +src/libnm-core-impl/nm-setting-ip-tunnel.c +src/libnm-core-impl/nm-setting-ip4-config.c +src/libnm-core-impl/nm-setting-ip6-config.c +src/libnm-core-impl/nm-setting-macsec.c +src/libnm-core-impl/nm-setting-macvlan.c +src/libnm-core-impl/nm-setting-match.c +src/libnm-core-impl/nm-setting-olpc-mesh.c +src/libnm-core-impl/nm-setting-ovs-bridge.c +src/libnm-core-impl/nm-setting-ovs-external-ids.c +src/libnm-core-impl/nm-setting-ovs-interface.c +src/libnm-core-impl/nm-setting-ovs-patch.c +src/libnm-core-impl/nm-setting-ovs-port.c +src/libnm-core-impl/nm-setting-ppp.c +src/libnm-core-impl/nm-setting-pppoe.c +src/libnm-core-impl/nm-setting-proxy.c +src/libnm-core-impl/nm-setting-sriov.c +src/libnm-core-impl/nm-setting-tc-config.c +src/libnm-core-impl/nm-setting-team-port.c +src/libnm-core-impl/nm-setting-team.c +src/libnm-core-impl/nm-setting-tun.c +src/libnm-core-impl/nm-setting-user.c +src/libnm-core-impl/nm-setting-veth.c +src/libnm-core-impl/nm-setting-vlan.c +src/libnm-core-impl/nm-setting-vpn.c +src/libnm-core-impl/nm-setting-vrf.c +src/libnm-core-impl/nm-setting-vxlan.c +src/libnm-core-impl/nm-setting-wifi-p2p.c +src/libnm-core-impl/nm-setting-wimax.c +src/libnm-core-impl/nm-setting-wired.c +src/libnm-core-impl/nm-setting-wireguard.c +src/libnm-core-impl/nm-setting-wireless-security.c +src/libnm-core-impl/nm-setting-wireless.c +src/libnm-core-impl/nm-setting-wpan.c +src/libnm-core-impl/nm-setting.c +src/libnm-core-impl/nm-team-utils.c +src/libnm-core-impl/nm-utils.c +src/libnm-core-impl/nm-vpn-editor-plugin.c +src/libnm-core-impl/nm-vpn-plugin-info.c diff --git a/shared/meson.build b/shared/meson.build index 52eb6b9b10..a51497000e 100644 --- a/shared/meson.build +++ b/shared/meson.build @@ -4,8 +4,8 @@ shared_inc = include_directories('.') glib_nm_default_dep = declare_dependency( include_directories: [ - top_inc, shared_inc, + top_inc, ], dependencies: [ glib_dep, @@ -139,7 +139,17 @@ libnm_glib_aux = static_library( ) libnm_glib_aux_dep = declare_dependency( - dependencies: glib_nm_default_dep, + include_directories: [ + shared_inc, + top_inc, + ], + dependencies: [ + glib_nm_default_dep, + ], +) + +libnm_glib_aux_dep_link = declare_dependency( + dependencies: libnm_glib_aux_dep, link_with: libnm_glib_aux, ) @@ -165,7 +175,7 @@ libnm_base = static_library( sources: files( 'nm-base/nm-ethtool-base.c', ), - dependencies: libnm_glib_aux_dep, + dependencies: libnm_glib_aux_dep_link, c_args: [ '-DG_LOG_DOMAIN="libnm"', ], @@ -174,6 +184,10 @@ libnm_base = static_library( libnm_base_dep = declare_dependency( include_directories: shared_inc, dependencies: libnm_glib_aux_dep, +) + +libnm_base_dep_link = declare_dependency( + dependencies: libnm_glib_aux_dep_link, link_with: libnm_base, ) @@ -192,7 +206,7 @@ libnm_log_core = static_library( libnm_log_core_dep = declare_dependency( include_directories: shared_inc, dependencies: [ - libnm_glib_aux_dep, + libnm_glib_aux_dep_link, ], link_with: libnm_log_core, ) @@ -215,7 +229,7 @@ libnm_platform = static_library( libnm_platform_dep = declare_dependency( include_directories: shared_inc, dependencies: [ - libnm_glib_aux_dep, + libnm_glib_aux_dep_link, ], link_with: libnm_platform, ) diff --git a/shared/nm-glib-aux/tests/meson.build b/shared/nm-glib-aux/tests/meson.build index 464f4e7c86..a28d3b0802 100644 --- a/shared/nm-glib-aux/tests/meson.build +++ b/shared/nm-glib-aux/tests/meson.build @@ -6,7 +6,7 @@ exe = executable( c_args: [ '-DG_LOG_DOMAIN="test"', ], - dependencies: libnm_glib_aux_dep, + dependencies: libnm_glib_aux_dep_link, link_with: libnm_systemd_logging_stub, ) @@ -25,7 +25,7 @@ if jansson_dep.found() '-DG_LOG_DOMAIN="test"', ], dependencies: [ - libnm_glib_aux_dep, + libnm_glib_aux_dep_link, jansson_dep, dl_dep, ], diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index 5407221097..08402729f9 100644 --- a/src/core/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -14,12 +14,12 @@ #include "nm-glib-aux/nm-c-list.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-utils.h" #include "nm-setting-connection.h" #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "platform/nmp-object.h" #include "platform/nm-platform.h" diff --git a/src/core/devices/bluetooth/meson.build b/src/core/devices/bluetooth/meson.build index d5f260686f..086b0dee80 100644 --- a/src/core/devices/bluetooth/meson.build +++ b/src/core/devices/bluetooth/meson.build @@ -7,7 +7,12 @@ libnm_device_plugin_bluetooth_static = static_library( 'nm-bt-error.c', 'nm-device-bt.c', ) + (enable_bluez5_dun ? files('nm-bluez5-dun.c') : files()), + c_args: [ + '-DG_LOG_DOMAIN="NetworkManager"', + ], dependencies: [ + libnm_core_public_dep, + libnm_core_intern_dep, core_default_dep, libnm_wwan_dep, bluez5_dep, diff --git a/src/core/devices/bluetooth/nm-bluez-manager.c b/src/core/devices/bluetooth/nm-bluez-manager.c index dd998d29b0..fe0350c7f9 100644 --- a/src/core/devices/bluetooth/nm-bluez-manager.c +++ b/src/core/devices/bluetooth/nm-bluez-manager.c @@ -23,7 +23,7 @@ #include "nm-device-bt.h" #include "nm-manager.h" #include "nm-bluez5-dun.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "platform/nm-platform.h" #include "nm-std-aux/nm-dbus-compat.h" diff --git a/src/core/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c index c07be2d3b9..2c336587ed 100644 --- a/src/core/devices/bluetooth/nm-device-bt.c +++ b/src/core/devices/bluetooth/nm-device-bt.c @@ -10,7 +10,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-bluez-common.h" #include "nm-bluez-manager.h" #include "devices/nm-device-private.h" diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index f68c080b18..b650e04753 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -14,7 +14,7 @@ #include "nm-device-private.h" #include "platform/nm-platform.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-ip4-config.h" #define _NMLOG_DEVICE_TYPE NMDeviceBond diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index c919d85dfb..8ace4a4d54 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -14,7 +14,7 @@ #include "nm-device-private.h" #include "platform/nm-platform.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceBridge #include "nm-device-logging.h" diff --git a/src/core/devices/nm-device-dummy.c b/src/core/devices/nm-device-dummy.c index 13cfd3b0a3..b553299ada 100644 --- a/src/core/devices/nm-device-dummy.c +++ b/src/core/devices/nm-device-dummy.c @@ -16,7 +16,7 @@ #include "platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-dummy.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceDummy #include "nm-device-logging.h" diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 44428869cd..92d70aa8f9 100644 --- a/src/core/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -32,7 +32,7 @@ #include "nm-device-ethernet-utils.h" #include "settings/nm-settings.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-udev-aux/nm-udev-utils.h" #include "nm-device-veth.h" diff --git a/src/core/devices/nm-device-factory.c b/src/core/devices/nm-device-factory.c index 81124a8dc3..8dbc985ceb 100644 --- a/src/core/devices/nm-device-factory.c +++ b/src/core/devices/nm-device-factory.c @@ -13,7 +13,7 @@ #include "platform/nm-platform.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-setting-bluetooth.h" #define PLUGIN_PREFIX "libnm-device-plugin-" diff --git a/src/core/devices/nm-device-generic.c b/src/core/devices/nm-device-generic.c index a319666a9c..497a5f94b7 100644 --- a/src/core/devices/nm-device-generic.c +++ b/src/core/devices/nm-device-generic.c @@ -9,7 +9,7 @@ #include "nm-device-private.h" #include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/src/core/devices/nm-device-infiniband.c b/src/core/devices/nm-device-infiniband.c index f54ffcf038..feee1583aa 100644 --- a/src/core/devices/nm-device-infiniband.c +++ b/src/core/devices/nm-device-infiniband.c @@ -16,7 +16,7 @@ #include "nm-ip4-config.h" #include "platform/nm-platform.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define NM_DEVICE_INFINIBAND_IS_PARTITION "is-partition" diff --git a/src/core/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c index da6afb3b50..75cc222e92 100644 --- a/src/core/devices/nm-device-ip-tunnel.c +++ b/src/core/devices/nm-device-ip-tunnel.c @@ -18,7 +18,7 @@ #include "nm-manager.h" #include "platform/nm-platform.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/nm-settings.h" #include "nm-act-request.h" #include "nm-ip4-config.h" diff --git a/src/core/devices/nm-device-macsec.c b/src/core/devices/nm-device-macsec.c index 51b820a165..839a3f094c 100644 --- a/src/core/devices/nm-device-macsec.c +++ b/src/core/devices/nm-device-macsec.c @@ -15,7 +15,7 @@ #include "nm-device-factory.h" #include "nm-manager.h" #include "nm-setting-macsec.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "supplicant/nm-supplicant-manager.h" #include "supplicant/nm-supplicant-interface.h" #include "supplicant/nm-supplicant-config.h" diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index edca69e9fa..d3050b8c89 100644 --- a/src/core/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -17,7 +17,7 @@ #include "platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-tun.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceTun #include "nm-device-logging.h" diff --git a/src/core/devices/nm-device-veth.c b/src/core/devices/nm-device-veth.c index e0ba843df7..03e34bd8bc 100644 --- a/src/core/devices/nm-device-veth.c +++ b/src/core/devices/nm-device-veth.c @@ -7,7 +7,7 @@ #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-device-veth.h" #include "nm-device-private.h" #include "nm-manager.h" diff --git a/src/core/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c index bfde60efec..85edff5b0a 100644 --- a/src/core/devices/nm-device-vlan.c +++ b/src/core/devices/nm-device-vlan.c @@ -19,7 +19,7 @@ #include "platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "platform/nmp-object.h" #define _NMLOG_DEVICE_TYPE NMDeviceVlan diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index 4fec59ba5a..ab17197add 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -4,7 +4,7 @@ #include "nm-device-vrf.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-device-factory.h" #include "nm-device-private.h" #include "nm-manager.h" diff --git a/src/core/devices/nm-device-vxlan.c b/src/core/devices/nm-device-vxlan.c index f16a52c4b1..c0a11cd042 100644 --- a/src/core/devices/nm-device-vxlan.c +++ b/src/core/devices/nm-device-vxlan.c @@ -17,7 +17,7 @@ #include "settings/nm-settings.h" #include "nm-act-request.h" #include "nm-ip4-config.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceVxlan #include "nm-device-logging.h" diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c index 5bee09e6f1..f9bd8ad8f8 100644 --- a/src/core/devices/nm-device-wireguard.c +++ b/src/core/devices/nm-device-wireguard.c @@ -11,7 +11,7 @@ #include #include "nm-setting-wireguard.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-glib-aux/nm-secret-utils.h" #include "nm-device-private.h" #include "platform/nm-platform.h" diff --git a/src/core/devices/nm-device-wpan.c b/src/core/devices/nm-device-wpan.c index 2f3b16ff8a..7f1f9e3286 100644 --- a/src/core/devices/nm-device-wpan.c +++ b/src/core/devices/nm-device-wpan.c @@ -18,7 +18,7 @@ #include "platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-wpan.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceWpan #include "nm-device-logging.h" diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 040dd0b4d3..28ba196b60 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -29,7 +29,7 @@ #include "systemd/nm-sd-utils-shared.h" #include "nm-base/nm-ethtool-base.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-device-private.h" #include "nm-l3cfg.h" #include "nm-l3-config-data.h" @@ -65,7 +65,7 @@ #include "c-list/src/c-list.h" #include "dns/nm-dns-manager.h" #include "nm-acd-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "systemd/nm-sd.h" #include "nm-lldp-listener.h" #include "nm-audit-manager.h" diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c index 3ae8a4813c..37feb2f442 100644 --- a/src/core/devices/ovs/nm-device-ovs-bridge.c +++ b/src/core/devices/ovs/nm-device-ovs-bridge.c @@ -16,7 +16,7 @@ #include "nm-setting-connection.h" #include "nm-setting-ovs-bridge.h" #include "nm-setting-ovs-external-ids.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceOvsBridge #include "devices/nm-device-logging.h" diff --git a/src/core/devices/ovs/nm-ovs-factory.c b/src/core/devices/ovs/nm-ovs-factory.c index e7af38d83d..3a9a736448 100644 --- a/src/core/devices/ovs/nm-ovs-factory.c +++ b/src/core/devices/ovs/nm-ovs-factory.c @@ -11,7 +11,7 @@ #include "nm-device-ovs-port.h" #include "nm-device-ovs-bridge.h" #include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/nm-settings.h" #include "devices/nm-device-factory.h" #include "devices/nm-device-private.h" diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index da3a7989a8..0aa613bd75 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -13,7 +13,7 @@ #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 "libnm-core-intern/nm-core-internal.h" #include "devices/nm-device.h" #include "nm-manager.h" #include "nm-setting-ovs-external-ids.h" diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index d2d717298d..e6e230eed1 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -20,7 +20,7 @@ #include "devices/nm-device-private.h" #include "platform/nm-platform.h" #include "nm-config.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "nm-ip4-config.h" #include "nm-std-aux/nm-dbus-compat.h" diff --git a/src/core/devices/team/nm-team-factory.c b/src/core/devices/team/nm-team-factory.c index 57b51bf843..21be23965b 100644 --- a/src/core/devices/team/nm-team-factory.c +++ b/src/core/devices/team/nm-team-factory.c @@ -11,7 +11,7 @@ #include "devices/nm-device-factory.h" #include "nm-device-team.h" #include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index 95ade44b58..dc5bc54a10 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -13,11 +13,11 @@ #include "devices/nm-device.h" #include "nm-act-request.h" #include "nm-config.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "nm-glib-aux/nm-ref-string.h" #include "nm-iwd-manager.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-setting-8021x.h" #include "nm-setting-connection.h" #include "nm-setting-wireless-security.h" diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c index fb9876005f..74eba64c39 100644 --- a/src/core/devices/wifi/nm-device-wifi-p2p.c +++ b/src/core/devices/wifi/nm-device-wifi-p2p.c @@ -15,7 +15,7 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" #include "nm-act-request.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-glib-aux/nm-ref-string.h" #include "nm-ip4-config.h" #include "nm-manager.h" diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index 042d48871a..3f55d9f15f 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -16,7 +16,7 @@ #include "nm-glib-aux/nm-c-list.h" #include "nm-device-wifi-p2p.h" #include "nm-wifi-ap.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "devices/nm-device.h" #include "devices/nm-device-private.h" #include "nm-dbus-manager.h" @@ -39,7 +39,7 @@ #include "settings/nm-settings.h" #include "nm-wifi-utils.h" #include "nm-wifi-common.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-config.h" #define _NMLOG_DEVICE_TYPE NMDeviceWifi diff --git a/src/core/devices/wifi/nm-iwd-manager.c b/src/core/devices/wifi/nm-iwd-manager.c index b4b019d3e5..b0b208ac52 100644 --- a/src/core/devices/wifi/nm-iwd-manager.c +++ b/src/core/devices/wifi/nm-iwd-manager.c @@ -9,7 +9,7 @@ #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-manager.h" #include "nm-device-iwd.h" #include "nm-wifi-utils.h" diff --git a/src/core/devices/wifi/nm-wifi-ap.c b/src/core/devices/wifi/nm-wifi-ap.c index 08fa10ec33..7d39e913d5 100644 --- a/src/core/devices/wifi/nm-wifi-ap.c +++ b/src/core/devices/wifi/nm-wifi-ap.c @@ -13,7 +13,7 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "nm-glib-aux/nm-ref-string.h" #include "nm-setting-wireless.h" diff --git a/src/core/devices/wifi/nm-wifi-p2p-peer.c b/src/core/devices/wifi/nm-wifi-p2p-peer.c index 8488f32dca..40532bb142 100644 --- a/src/core/devices/wifi/nm-wifi-p2p-peer.c +++ b/src/core/devices/wifi/nm-wifi-p2p-peer.c @@ -12,7 +12,7 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "nm-glib-aux/nm-ref-string.h" #include "nm-setting-wireless.h" diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index aed236ccaa..56a324387f 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -10,7 +10,7 @@ #include #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" static gboolean verify_no_wep(NMSettingWirelessSecurity *s_wsec, const char *tag, GError **error) diff --git a/src/core/devices/wifi/tests/test-devices-wifi.c b/src/core/devices/wifi/tests/test-devices-wifi.c index bc0ba126dc..693bc546da 100644 --- a/src/core/devices/wifi/tests/test-devices-wifi.c +++ b/src/core/devices/wifi/tests/test-devices-wifi.c @@ -7,7 +7,7 @@ #include "devices/wifi/nm-wifi-utils.h" #include "devices/wifi/nm-device-wifi.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-test-utils-core.h" diff --git a/src/core/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c index 3ea89d2c69..87d4023817 100644 --- a/src/core/devices/wwan/nm-device-modem.c +++ b/src/core/devices/wwan/nm-device-modem.c @@ -14,7 +14,7 @@ #include "settings/nm-settings-connection.h" #include "nm-modem-broadband.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceModem #include "devices/nm-device-logging.h" diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index ca02880417..c7bfd7cf1f 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -11,7 +11,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" #include "platform/nm-platform.h" diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index 21734cee77..6ca78292f0 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -7,7 +7,7 @@ #include "nm-modem-ofono.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "devices/nm-device-private.h" #include "nm-modem.h" #include "platform/nm-platform.h" diff --git a/src/core/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c index 0d334fa465..68cd8f00b2 100644 --- a/src/core/devices/wwan/nm-modem.c +++ b/src/core/devices/wwan/nm-modem.c @@ -12,7 +12,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "platform/nm-platform.h" #include "nm-setting-connection.h" #include "NetworkManagerUtils.h" diff --git a/src/core/dhcp/nm-dhcp-listener.c b/src/core/dhcp/nm-dhcp-listener.c index 1673bbb7a5..b8bb3c33a0 100644 --- a/src/core/dhcp/nm-dhcp-listener.c +++ b/src/core/dhcp/nm-dhcp-listener.c @@ -16,7 +16,7 @@ #include "nm-dhcp-helper-api.h" #include "nm-dhcp-client.h" #include "nm-dhcp-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "NetworkManagerUtils.h" diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c index 646411e201..9867e4c16e 100644 --- a/src/core/dhcp/nm-dhcp-utils.c +++ b/src/core/dhcp/nm-dhcp-utils.c @@ -19,7 +19,7 @@ #include "NetworkManagerUtils.h" #include "platform/nm-platform.h" #include "nm-dhcp-client-logging.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/src/core/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c index dcff98e913..7ecd785f5f 100644 --- a/src/core/dns/nm-dns-dnsmasq.c +++ b/src/core/dns/nm-dns-dnsmasq.c @@ -16,7 +16,7 @@ #include #include "nm-glib-aux/nm-dbus-aux.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "platform/nm-platform.h" #include "nm-utils.h" #include "nm-ip4-config.h" diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index f318b9b89b..d30c3fa549 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -23,7 +23,7 @@ #endif #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dns-manager.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" diff --git a/src/core/dns/nm-dns-plugin.c b/src/core/dns/nm-dns-plugin.c index 74d4eb2bd9..e5035f061f 100644 --- a/src/core/dns/nm-dns-plugin.c +++ b/src/core/dns/nm-dns-plugin.c @@ -12,7 +12,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" /*****************************************************************************/ diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index f6e116f375..bbf212b135 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -18,7 +18,7 @@ #include "nm-glib-aux/nm-c-list.h" #include "nm-glib-aux/nm-dbus-aux.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "platform/nm-platform.h" #include "nm-utils.h" #include "nm-ip4-config.h" diff --git a/src/core/dnsmasq/nm-dnsmasq-manager.c b/src/core/dnsmasq/nm-dnsmasq-manager.c index 82c002b0d0..e8697e817e 100644 --- a/src/core/dnsmasq/nm-dnsmasq-manager.c +++ b/src/core/dnsmasq/nm-dnsmasq-manager.c @@ -17,7 +17,7 @@ #include "nm-dnsmasq-utils.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define CONFDIR NMCONFDIR "/dnsmasq-shared.d" diff --git a/src/core/initrd/meson.build b/src/core/initrd/meson.build index bd590e8ca5..5fa575c023 100644 --- a/src/core/initrd/meson.build +++ b/src/core/initrd/meson.build @@ -19,6 +19,8 @@ executable( link_with: [ libNetworkManagerBase, libnmi_core, + libnm_core_impl, + libnm_base, ], link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, diff --git a/src/core/initrd/nm-initrd-generator.c b/src/core/initrd/nm-initrd-generator.c index 18c7258a91..f9756df29b 100644 --- a/src/core/initrd/nm-initrd-generator.c +++ b/src/core/initrd/nm-initrd-generator.c @@ -5,8 +5,8 @@ #include "src/core/nm-default-daemon.h" #include "nm-core-utils.h" -#include "nm-core-internal.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "nm-initrd-generator.h" #include "nm-glib-aux/nm-io-utils.h" #include "nm-config.h" diff --git a/src/core/initrd/nmi-cmdline-reader.c b/src/core/initrd/nmi-cmdline-reader.c index 1a95e4f7dd..3bde667888 100644 --- a/src/core/initrd/nmi-cmdline-reader.c +++ b/src/core/initrd/nmi-cmdline-reader.c @@ -8,7 +8,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-initrd-generator.h" #include "systemd/nm-sd-utils-shared.h" diff --git a/src/core/initrd/nmi-dt-reader.c b/src/core/initrd/nmi-dt-reader.c index 63e4524b5a..de549a208a 100644 --- a/src/core/initrd/nmi-dt-reader.c +++ b/src/core/initrd/nmi-dt-reader.c @@ -10,7 +10,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/src/core/initrd/nmi-ibft-reader.c b/src/core/initrd/nmi-ibft-reader.c index 9895cda43f..3a5b5d6634 100644 --- a/src/core/initrd/nmi-ibft-reader.c +++ b/src/core/initrd/nmi-ibft-reader.c @@ -17,7 +17,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" /*****************************************************************************/ diff --git a/src/core/initrd/tests/test-cmdline-reader.c b/src/core/initrd/tests/test-cmdline-reader.c index 33fb22d364..e1f7bd7030 100644 --- a/src/core/initrd/tests/test-cmdline-reader.c +++ b/src/core/initrd/tests/test-cmdline-reader.c @@ -12,7 +12,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "../nm-initrd-generator.h" diff --git a/src/core/initrd/tests/test-dt-reader.c b/src/core/initrd/tests/test-dt-reader.c index 619a4e6fc1..d9424c9a3d 100644 --- a/src/core/initrd/tests/test-dt-reader.c +++ b/src/core/initrd/tests/test-dt-reader.c @@ -12,7 +12,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "../nm-initrd-generator.h" diff --git a/src/core/initrd/tests/test-ibft-reader.c b/src/core/initrd/tests/test-ibft-reader.c index 1d263b9e2e..5c26659db4 100644 --- a/src/core/initrd/tests/test-ibft-reader.c +++ b/src/core/initrd/tests/test-ibft-reader.c @@ -12,7 +12,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "../nm-initrd-generator.h" diff --git a/src/core/main.c b/src/core/main.c index 9b79bcbb7c..88fd8f20d4 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -29,7 +29,7 @@ #include "nm-dispatcher.h" #include "settings/nm-settings.h" #include "nm-auth-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-object.h" #include "nm-connectivity.h" #include "dns/nm-dns-manager.h" diff --git a/src/core/meson.build b/src/core/meson.build index 368a3e8555..0cbe817344 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -1,25 +1,30 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -src_inc = include_directories('.') +src_core_inc = include_directories('.') core_plugin_dep = declare_dependency( - sources: libnm_core_enum_sources[1], include_directories: [ - src_inc, + src_core_inc, top_inc, shared_inc, - libnm_core_inc, + libnm_core_public_inc, ], dependencies: [ + libnm_core_intern_dep, + libnm_core_public_dep, glib_dep, ], ) core_default_dep = declare_dependency( - sources: libnm_core_enum_sources[1], - include_directories: src_inc, + include_directories: [ + src_core_inc, + shared_inc, + top_inc, + ], dependencies: [ - libnm_core_nm_default_dep, + libnm_core_public_dep, + libnm_core_intern_dep, libnm_log_core_dep, libnm_platform_dep, ], @@ -77,7 +82,7 @@ libNetworkManagerBase = static_library( dependencies: [ core_default_dep, libn_dhcp4_dep, - libnm_core_dep, + libnm_core_impl_dep, libnm_systemd_shared_dep, libnm_udev_aux_dep, libsystemd_dep, @@ -87,6 +92,8 @@ libNetworkManagerBase = static_library( ) nm_deps = [ + libnm_core_public_dep, + libnm_core_impl_dep, core_default_dep, dl_dep, libn_acd_dep, @@ -211,12 +218,16 @@ executable( libndp_dep, libudev_dep, libn_acd_dep, + libnm_glib_aux_dep_link, + libnm_core_impl_dep_link, ], c_args: daemon_c_flags, link_with: [ libNetworkManagerBase, libnm_systemd_core, libnm_systemd_shared, + libnm_base, + libnm_glib_aux, ], link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, @@ -244,7 +255,11 @@ if enable_tests libNetworkManagerTest_dep = declare_dependency( dependencies: core_default_dep, - link_with: libNetworkManagerTest, + link_with: [ + libNetworkManagerTest, + libnm_base, + libnm_core_impl, + ], ) subdir('dnsmasq/tests') @@ -280,7 +295,8 @@ NetworkManager_all_sym = executable( link_whole: [ libNetworkManager, libNetworkManagerBase, - libnm_core, + libnm_core_impl, + libnm_base, ], ) @@ -303,7 +319,12 @@ NetworkManager = executable( 'main.c', dependencies: nm_deps, c_args: daemon_c_flags, - link_with: libNetworkManager, + link_with: [ + libNetworkManager, + libNetworkManagerBase, + libnm_core_impl, + libnm_base, + ], link_args: [ '-rdynamic', '-Wl,--version-script,@0@'.format(ver_script.full_path()), diff --git a/src/core/nm-act-request.c b/src/core/nm-act-request.c index defe3e8c93..cb4b0260a5 100644 --- a/src/core/nm-act-request.c +++ b/src/core/nm-act-request.c @@ -19,7 +19,7 @@ #include "devices/nm-device.h" #include "nm-active-connection.h" #include "settings/nm-settings-connection.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" typedef struct { CList call_ids_lst_head; diff --git a/src/core/nm-active-connection.c b/src/core/nm-active-connection.c index 3c8c472e74..b0327fd0a4 100644 --- a/src/core/nm-active-connection.c +++ b/src/core/nm-active-connection.c @@ -7,17 +7,17 @@ #include "nm-active-connection.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-dbus-interface.h" #include "devices/nm-device.h" #include "settings/nm-settings-connection.h" #include "nm-simple-connection.h" #include "nm-auth-utils.h" #include "nm-auth-manager.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-keep-alive.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED ((NMAuthManagerCallId *) GINT_TO_POINTER(1)) diff --git a/src/core/nm-audit-manager.c b/src/core/nm-audit-manager.c index 8f41947264..a1d20fcb62 100644 --- a/src/core/nm-audit-manager.c +++ b/src/core/nm-audit-manager.c @@ -11,7 +11,7 @@ #include #endif -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-config.h" #include "nm-dbus-manager.h" #include "settings/nm-settings-connection.h" diff --git a/src/core/nm-auth-manager.c b/src/core/nm-auth-manager.c index 9470838c8f..4a7542ccfe 100644 --- a/src/core/nm-auth-manager.c +++ b/src/core/nm-auth-manager.c @@ -10,7 +10,7 @@ #include "c-list/src/c-list.h" #include "nm-glib-aux/nm-dbus-aux.h" #include "nm-errors.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "NetworkManagerUtils.h" diff --git a/src/core/nm-auth-manager.h b/src/core/nm-auth-manager.h index 991083c1b8..0586322fea 100644 --- a/src/core/nm-auth-manager.h +++ b/src/core/nm-auth-manager.h @@ -6,7 +6,7 @@ #ifndef NM_AUTH_MANAGER_H #define NM_AUTH_MANAGER_H -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-config-data.h" /*****************************************************************************/ diff --git a/src/core/nm-auth-utils.c b/src/core/nm-auth-utils.c index 12da5749a5..96c48cc336 100644 --- a/src/core/nm-auth-utils.c +++ b/src/core/nm-auth-utils.c @@ -9,7 +9,7 @@ #include "nm-glib-aux/nm-c-list.h" #include "nm-setting-connection.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-auth-manager.h" #include "nm-session-monitor.h" #include "nm-dbus-manager.h" diff --git a/src/core/nm-checkpoint.c b/src/core/nm-checkpoint.c index 2088c24760..3e22239608 100644 --- a/src/core/nm-checkpoint.c +++ b/src/core/nm-checkpoint.c @@ -9,7 +9,7 @@ #include "nm-active-connection.h" #include "nm-act-request.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-core-utils.h" #include "nm-dbus-interface.h" #include "devices/nm-device.h" diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c index c62c677372..6cdca586cc 100644 --- a/src/core/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -10,9 +10,9 @@ #include "nm-config.h" #include "devices/nm-device.h" -#include "nm-core-internal.h" -#include "nm-keyfile-internal.h" -#include "nm-keyfile-utils.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-utils.h" /*****************************************************************************/ diff --git a/src/core/nm-config.c b/src/core/nm-config.c index 55323919af..4d61f1aa22 100644 --- a/src/core/nm-config.c +++ b/src/core/nm-config.c @@ -13,9 +13,9 @@ #include "nm-utils.h" #include "devices/nm-device.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" -#include "nm-keyfile-internal.h" -#include "nm-keyfile-utils.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-utils.h" #define DEFAULT_CONFIG_MAIN_FILE NMCONFDIR "/NetworkManager.conf" #define DEFAULT_CONFIG_DIR NMCONFDIR "/conf.d" diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c index f847c8f4ef..1d37bd5a22 100644 --- a/src/core/nm-connectivity.c +++ b/src/core/nm-connectivity.c @@ -16,7 +16,7 @@ #include #include "c-list/src/c-list.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-config.h" #include "NetworkManagerUtils.h" #include "nm-dbus-manager.h" diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index 9075c30dd0..49dd1af64b 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -28,7 +28,7 @@ #include "nm-glib-aux/nm-secret-utils.h" #include "nm-glib-aux/nm-time-utils.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-setting-connection.h" #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" diff --git a/src/core/nm-dbus-manager.c b/src/core/nm-dbus-manager.c index 4f34ee52af..cae2d71344 100644 --- a/src/core/nm-dbus-manager.c +++ b/src/core/nm-dbus-manager.c @@ -15,11 +15,11 @@ #include "c-list/src/c-list.h" #include "nm-glib-aux/nm-c-list.h" #include "nm-dbus-interface.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-std-aux/nm-dbus-compat.h" #include "nm-dbus-object.h" #include "NetworkManagerUtils.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" /* The base path for our GDBusObjectManagerServers. They do not contain * "NetworkManager" because GDBusObjectManagerServer requires that all diff --git a/src/core/nm-dispatcher.c b/src/core/nm-dispatcher.c index 0ab409f5ed..5d9c51aa81 100644 --- a/src/core/nm-dispatcher.c +++ b/src/core/nm-dispatcher.c @@ -8,7 +8,7 @@ #include "nm-dispatcher.h" -#include "nm-libnm-core-aux/nm-dispatcher-api.h" +#include "libnm-core-aux-extern/nm-dispatcher-api.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-connectivity.h" @@ -21,7 +21,7 @@ #include "nm-manager.h" #include "settings/nm-settings-connection.h" #include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define CALL_TIMEOUT (1000 * 60 * 10) /* 10 minutes for all scripts */ diff --git a/src/core/nm-hostname-manager.c b/src/core/nm-hostname-manager.c index c99c83267c..4f1624262e 100644 --- a/src/core/nm-hostname-manager.c +++ b/src/core/nm-hostname-manager.c @@ -14,11 +14,11 @@ #include #endif -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-dbus-interface.h" #include "nm-connection.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" diff --git a/src/core/nm-iface-helper.c b/src/core/nm-iface-helper.c index b6e9981da9..c125d572d9 100644 --- a/src/core/nm-iface-helper.c +++ b/src/core/nm-iface-helper.c @@ -26,7 +26,7 @@ #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-setting-ip6-config.h" #include "systemd/nm-sd.h" diff --git a/src/core/nm-ip4-config.c b/src/core/nm-ip4-config.c index c49dfb4c34..24ff29895c 100644 --- a/src/core/nm-ip4-config.c +++ b/src/core/nm-ip4-config.c @@ -19,7 +19,7 @@ #include "platform/nm-platform.h" #include "nm-platform/nm-platform-utils.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-object.h" /*****************************************************************************/ diff --git a/src/core/nm-ip6-config.c b/src/core/nm-ip6-config.c index 1f7def3465..0b44064fc5 100644 --- a/src/core/nm-ip6-config.c +++ b/src/core/nm-ip6-config.c @@ -19,7 +19,7 @@ #include "platform/nmp-object.h" #include "platform/nm-platform.h" #include "nm-platform/nm-platform-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-ip4-config.h" #include "ndisc/nm-ndisc.h" diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 5f9af7ac59..61ef98f45c 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -9,7 +9,7 @@ #include #include "nm-glib-aux/nm-enum-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "platform/nm-platform.h" #include "nm-platform/nm-platform-utils.h" #include "platform/nmp-object.h" diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 5a6e05a934..8d2e8a8fe1 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -18,7 +18,7 @@ #include "nm-glib-aux/nm-c-list.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-dbus-manager.h" #include "vpn/nm-vpn-manager.h" #include "devices/nm-device.h" @@ -40,7 +40,7 @@ #include "nm-policy.h" #include "nm-session-monitor.h" #include "nm-act-request.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-config.h" #include "nm-audit-manager.h" #include "nm-std-aux/nm-dbus-compat.h" diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index 88ea09b6ce..51957d7e04 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -11,7 +11,7 @@ #include "nm-glib-aux/nm-c-list.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-l3cfg.h" #include "platform/nm-platform.h" #include "nm-platform/nmp-netns.h" diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index db4983f889..176cc2ebf3 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -24,7 +24,7 @@ #include "nm-firewall-manager.h" #include "nm-dispatcher.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-manager.h" #include "settings/nm-settings.h" #include "settings/nm-settings-connection.h" diff --git a/src/core/nm-proxy-config.c b/src/core/nm-proxy-config.c index f41601c900..49156dfae0 100644 --- a/src/core/nm-proxy-config.c +++ b/src/core/nm-proxy-config.c @@ -9,7 +9,7 @@ #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/src/core/nm-sleep-monitor.c b/src/core/nm-sleep-monitor.c index ffb4db4ea8..e275fd0883 100644 --- a/src/core/nm-sleep-monitor.c +++ b/src/core/nm-sleep-monitor.c @@ -11,7 +11,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #if defined(SUSPEND_RESUME_UPOWER) diff --git a/src/core/nm-test-utils-core.h b/src/core/nm-test-utils-core.h index e655ce22fa..5bde9cdaab 100644 --- a/src/core/nm-test-utils-core.h +++ b/src/core/nm-test-utils-core.h @@ -7,7 +7,7 @@ #define __NM_TEST_UTILS_CORE_H__ #include "NetworkManagerUtils.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #define _NMTST_INSIDE_CORE 1 diff --git a/src/core/platform/nm-linux-platform.c b/src/core/platform/nm-linux-platform.c index 7bd42bbab5..d4f6b0fb90 100644 --- a/src/core/platform/nm-linux-platform.c +++ b/src/core/platform/nm-linux-platform.c @@ -35,7 +35,7 @@ #include "nm-std-aux/unaligned.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-setting-vlan.h" #include "nm-glib-aux/nm-secret-utils.h" diff --git a/src/core/platform/nm-platform.c b/src/core/platform/nm-platform.c index 0e5f8ab548..e3ee9b8f49 100644 --- a/src/core/platform/nm-platform.c +++ b/src/core/platform/nm-platform.c @@ -23,7 +23,7 @@ #include #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-glib-aux/nm-dedup-multi.h" #include "nm-udev-aux/nm-udev-utils.h" #include "nm-glib-aux/nm-secret-utils.h" diff --git a/src/core/platform/nm-platform.h b/src/core/platform/nm-platform.h index d400c5680a..cf1254c40a 100644 --- a/src/core/platform/nm-platform.h +++ b/src/core/platform/nm-platform.h @@ -7,7 +7,7 @@ #define __NETWORKMANAGER_PLATFORM_H__ #include "nm-dbus-interface.h" -#include "nm-core-types-internal.h" +#include "libnm-core-intern/nm-core-types-internal.h" #include "nm-platform/nmp-base.h" #include "nm-base/nm-base.h" diff --git a/src/core/platform/wifi/nm-wifi-utils-wext.c b/src/core/platform/wifi/nm-wifi-utils-wext.c index a44fcf6239..88529647c5 100644 --- a/src/core/platform/wifi/nm-wifi-utils-wext.c +++ b/src/core/platform/wifi/nm-wifi-utils-wext.c @@ -24,7 +24,7 @@ #include "nm-wifi-utils-private.h" #include "nm-utils.h" #include "nm-platform/nm-platform-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-core-utils.h" typedef struct { diff --git a/src/core/ppp/meson.build b/src/core/ppp/meson.build index 607b471874..6ba36a70ef 100644 --- a/src/core/ppp/meson.build +++ b/src/core/ppp/meson.build @@ -4,7 +4,11 @@ nm_pppd_plugin = shared_module( 'nm-pppd-plugin', name_prefix: '', sources: 'nm-pppd-plugin.c', - dependencies: libnm_core_nm_default_dep, + dependencies: [ + libnm_core_impl_dep_link, + libnm_glib_aux_dep_link, + glib_dep, + ], c_args: [ '-DG_LOG_DOMAIN="nm-pppd-plugin"', ], diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c index 396a49aeb5..eebb82311c 100644 --- a/src/core/ppp/nm-ppp-manager.c +++ b/src/core/ppp/nm-ppp-manager.c @@ -29,7 +29,7 @@ #include "NetworkManagerUtils.h" #include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-act-request.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" diff --git a/src/core/settings/nm-agent-manager.c b/src/core/settings/nm-agent-manager.c index 7e61790998..a1c2eb9c76 100644 --- a/src/core/settings/nm-agent-manager.c +++ b/src/core/settings/nm-agent-manager.c @@ -9,7 +9,7 @@ #include -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-dbus-interface.h" #include "nm-secret-agent.h" #include "nm-auth-utils.h" @@ -19,7 +19,7 @@ #include "nm-session-monitor.h" #include "nm-simple-connection.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "c-list/src/c-list.h" /*****************************************************************************/ diff --git a/src/core/settings/nm-secret-agent.c b/src/core/settings/nm-secret-agent.c index 7e7c5d7dfd..b0d71886b4 100644 --- a/src/core/settings/nm-secret-agent.c +++ b/src/core/settings/nm-secret-agent.c @@ -13,8 +13,8 @@ #include "nm-glib-aux/nm-c-list.h" #include "nm-glib-aux/nm-dbus-aux.h" #include "nm-dbus-interface.h" -#include "nm-core-internal.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-simple-connection.h" #include "NetworkManagerUtils.h" #include "c-list/src/c-list.h" diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c index 0ff0718997..0f0beef068 100644 --- a/src/core/settings/nm-settings-connection.c +++ b/src/core/settings/nm-settings-connection.c @@ -11,7 +11,7 @@ #include "c-list/src/c-list.h" #include "nm-glib-aux/nm-keyfile-aux.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-config.h" #include "nm-config-data.h" #include "nm-dbus-interface.h" @@ -20,7 +20,7 @@ #include "nm-auth-utils.h" #include "nm-agent-manager.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-audit-manager.h" #include "nm-settings.h" #include "nm-dbus-manager.h" diff --git a/src/core/settings/nm-settings-plugin.c b/src/core/settings/nm-settings-plugin.c index 9e81caabb5..66cc19b656 100644 --- a/src/core/settings/nm-settings-plugin.c +++ b/src/core/settings/nm-settings-plugin.c @@ -9,7 +9,7 @@ #include "nm-settings-plugin.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-settings-connection.h" diff --git a/src/core/settings/nm-settings.c b/src/core/settings/nm-settings.c index 3d31fb8b7b..858df29883 100644 --- a/src/core/settings/nm-settings.c +++ b/src/core/settings/nm-settings.c @@ -20,9 +20,9 @@ #include #endif -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-glib-aux/nm-keyfile-aux.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "nm-dbus-interface.h" #include "nm-connection.h" #include "nm-setting-8021x.h" @@ -44,7 +44,7 @@ #include "nm-setting-proxy.h" #include "nm-setting-bond.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-std-aux/c-list-util.h" #include "nm-glib-aux/nm-c-list.h" @@ -54,7 +54,7 @@ #include "nm-settings-plugin.h" #include "nm-dbus-manager.h" #include "nm-auth-utils.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-session-monitor.h" #include "plugins/keyfile/nms-keyfile-plugin.h" #include "plugins/keyfile/nms-keyfile-storage.h" diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index d114db0f82..2cc1d373de 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -18,7 +18,7 @@ #include "nm-glib-aux/nm-io-utils.h" #include "nm-std-aux/nm-dbus-compat.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-config.h" #include "nm-dbus-manager.h" #include "settings/nm-settings-plugin.h" diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 209957d9b8..7524e87c57 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -38,7 +38,7 @@ #include "nm-setting-user.h" #include "nm-setting-proxy.h" #include "nm-setting-generic.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-utils.h" #include "nm-base/nm-ethtool-base.h" diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c index 3f674deab3..714357a8be 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c @@ -8,7 +8,7 @@ #include "nms-ifcfg-rh-storage.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-connection.h" #include "nms-ifcfg-rh-plugin.h" diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 8da5de473b..aa5f7297ef 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -9,7 +9,7 @@ #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nms-ifcfg-rh-common.h" diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index a968fce0ba..a86bf4781d 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -32,7 +32,7 @@ #include "nm-setting-team.h" #include "nm-setting-team-port.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-base/nm-ethtool-base.h" diff --git a/src/core/settings/plugins/ifcfg-rh/shvar.c b/src/core/settings/plugins/ifcfg-rh/shvar.c index 386bcac707..dc26da759c 100644 --- a/src/core/settings/plugins/ifcfg-rh/shvar.c +++ b/src/core/settings/plugins/ifcfg-rh/shvar.c @@ -14,7 +14,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-core-utils.h" #include "nm-glib-aux/nm-enum-utils.h" #include "nm-glib-aux/nm-io-utils.h" diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 59127d0103..bad0052013 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -36,7 +36,7 @@ #include "nm-setting-serial.h" #include "nm-setting-vlan.h" #include "nm-setting-dcb.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-base/nm-ethtool-base.h" #include "nm-base/nm-ethtool-utils-base.h" diff --git a/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c index a4974a9600..63c78f93aa 100644 --- a/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c @@ -12,7 +12,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/nm-settings-plugin.h" #include "nms-ifupdown-plugin.h" diff --git a/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 34523f8d5a..80a5638a13 100644 --- a/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -9,7 +9,7 @@ #include "nms-ifupdown-plugin.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-core-utils.h" #include "nm-config.h" #include "settings/nm-settings-plugin.h" diff --git a/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c index 6e3eb0e74b..0e8db733eb 100644 --- a/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -5,7 +5,7 @@ #include "src/core/nm-default-daemon.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/plugins/ifupdown/nms-ifupdown-interface-parser.h" #include "settings/plugins/ifupdown/nms-ifupdown-parser.h" diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c index 789bfc1ad2..6d3e879611 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -22,8 +22,8 @@ #include "nm-setting-connection.h" #include "nm-utils.h" #include "nm-config.h" -#include "nm-core-internal.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "systemd/nm-sd-utils-shared.h" diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-reader.c b/src/core/settings/plugins/keyfile/nms-keyfile-reader.c index 70b047f32f..8b9d982fa5 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-reader.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-reader.c @@ -9,7 +9,7 @@ #include -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "NetworkManagerUtils.h" #include "nms-keyfile-utils.h" diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-storage.c b/src/core/settings/plugins/keyfile/nms-keyfile-storage.c index 89be817a7e..c6b4b81f57 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-storage.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-storage.c @@ -8,7 +8,7 @@ #include "nms-keyfile-storage.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nms-keyfile-plugin.h" /*****************************************************************************/ diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-utils.c b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c index f3dffdae49..4b69dc79aa 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-utils.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c @@ -11,7 +11,7 @@ #include #include "nm-glib-aux/nm-io-utils.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "nm-utils.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-writer.c b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c index 0e2c94b533..0dae91ae76 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c @@ -12,7 +12,7 @@ #include #include -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "nms-keyfile-utils.h" #include "nms-keyfile-reader.h" diff --git a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c index 348b0ed6ad..5c5786b947 100644 --- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -15,7 +15,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/plugins/keyfile/nms-keyfile-reader.h" #include "settings/plugins/keyfile/nms-keyfile-writer.h" diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c index eab494b022..1f27ab80dd 100644 --- a/src/core/supplicant/nm-supplicant-config.c +++ b/src/core/supplicant/nm-supplicant-config.c @@ -11,10 +11,10 @@ #include #include "nm-glib-aux/nm-str-buf.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-supplicant-settings-verify.h" #include "nm-setting.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-setting-ip4-config.h" diff --git a/src/core/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c index 6d9c604f80..176e4d2f61 100644 --- a/src/core/supplicant/nm-supplicant-interface.c +++ b/src/core/supplicant/nm-supplicant-interface.c @@ -12,7 +12,7 @@ #include #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-glib-aux/nm-c-list.h" #include "nm-glib-aux/nm-ref-string.h" #include "nm-std-aux/nm-dbus-compat.h" diff --git a/src/core/supplicant/nm-supplicant-manager.c b/src/core/supplicant/nm-supplicant-manager.c index 325541876c..d4806161e8 100644 --- a/src/core/supplicant/nm-supplicant-manager.c +++ b/src/core/supplicant/nm-supplicant-manager.c @@ -8,7 +8,7 @@ #include "nm-supplicant-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "nm-glib-aux/nm-dbus-aux.h" #include "nm-glib-aux/nm-ref-string.h" diff --git a/src/core/supplicant/tests/test-supplicant-config.c b/src/core/supplicant/tests/test-supplicant-config.c index 99729c18e5..2c2d9478e2 100644 --- a/src/core/supplicant/tests/test-supplicant-config.c +++ b/src/core/supplicant/tests/test-supplicant-config.c @@ -14,7 +14,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "supplicant/nm-supplicant-config.h" #include "supplicant/nm-supplicant-settings-verify.h" diff --git a/src/core/systemd/meson.build b/src/core/systemd/meson.build index 70f6b54295..518b0053c3 100644 --- a/src/core/systemd/meson.build +++ b/src/core/systemd/meson.build @@ -39,10 +39,12 @@ libnm_systemd_core = static_library( include_directories: [ incs, src_inc, + src_core_inc, + shared_inc, ], dependencies: [ glib_nm_default_dep, - libnm_core_dep, + libnm_core_impl_dep, libnm_systemd_shared_dep, ], c_args: [ @@ -52,10 +54,13 @@ libnm_systemd_core = static_library( ) libnm_systemd_core_dep = declare_dependency( - include_directories: incs, + include_directories: [ + incs, + shared_inc, + ], dependencies: [ glib_dep, - libnm_core_dep, + libnm_core_impl_dep, libnm_systemd_shared_dep, ], link_with: libnm_systemd_core, diff --git a/src/core/systemd/nm-sd-utils-core.c b/src/core/systemd/nm-sd-utils-core.c index af68603ec0..b81e36f377 100644 --- a/src/core/systemd/nm-sd-utils-core.c +++ b/src/core/systemd/nm-sd-utils-core.c @@ -7,7 +7,7 @@ #include "nm-sd-utils-core.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-sd-adapt-core.h" diff --git a/src/core/tests/meson.build b/src/core/tests/meson.build index 994563c42c..5997b70d36 100644 --- a/src/core/tests/meson.build +++ b/src/core/tests/meson.build @@ -35,6 +35,7 @@ exe = executable( include_directories: [ top_inc, src_inc, + src_core_inc, ], dependencies: [ libnm_systemd_core_dep, diff --git a/src/core/tests/test-core.c b/src/core/tests/test-core.c index 8698c40607..fc4a217e81 100644 --- a/src/core/tests/test-core.c +++ b/src/core/tests/test-core.c @@ -12,7 +12,7 @@ #include #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-core-utils.h" #include "systemd/nm-sd-utils-core.h" diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c index 02831b0838..3d110b2888 100644 --- a/src/core/vpn/nm-vpn-connection.c +++ b/src/core/vpn/nm-vpn-connection.c @@ -26,7 +26,7 @@ #include "nm-dispatcher.h" #include "nm-netns.h" #include "settings/nm-agent-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-pacrunner-manager.h" #include "nm-firewall-manager.h" #include "nm-config.h" diff --git a/src/core/vpn/nm-vpn-connection.h b/src/core/vpn/nm-vpn-connection.h index 66ec7eec3a..0209ea3d60 100644 --- a/src/core/vpn/nm-vpn-connection.h +++ b/src/core/vpn/nm-vpn-connection.h @@ -9,7 +9,7 @@ #include "nm-vpn-dbus-interface.h" #include "devices/nm-device.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-active-connection.h" #include "nm-vpn-plugin-info.h" diff --git a/src/core/vpn/nm-vpn-manager.c b/src/core/vpn/nm-vpn-manager.c index 53fe58dd36..f30dba79bc 100644 --- a/src/core/vpn/nm-vpn-manager.c +++ b/src/core/vpn/nm-vpn-manager.c @@ -12,7 +12,7 @@ #include "nm-vpn-connection.h" #include "nm-setting-vpn.h" #include "nm-vpn-dbus-interface.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" typedef struct { GSList * plugins; diff --git a/src/libnm-core-aux-extern/README.md b/src/libnm-core-aux-extern/README.md new file mode 100644 index 0000000000..27f2cccad2 --- /dev/null +++ b/src/libnm-core-aux-extern/README.md @@ -0,0 +1,11 @@ +libnm-core-aux-extern +===================== + +libnm-core-aux-extern is a static library that is similar to +[`libnm-core-aux-intern`](../libnm-core-aux-intern). + +The only difference is that `libnm-core-aux-extern` is not used by +[`libnm-core-impl`](../libnm-core-impl) itself. So you must not +use it there. + +Otherwise, it's the same and has the same usage. diff --git a/src/libnm-core-aux-extern/meson.build b/src/libnm-core-aux-extern/meson.build new file mode 100644 index 0000000000..0aaadc5f52 --- /dev/null +++ b/src/libnm-core-aux-extern/meson.build @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnm_core_aux_extern = static_library( + 'nm-core-aux-extern', + sources: files( + 'nm-libnm-core-aux.c', + ), + dependencies: [ + libnm_core_aux_intern_dep, + libnm_core_public_dep, + libnm_glib_aux_dep, + glib_dep, + ], + c_args: [ + '-DG_LOG_DOMAIN="libnm"', + ], +) + +libnm_core_aux_extern_dep = declare_dependency( + include_directories: [ + src_inc, + ], + dependencies: [ + libnm_core_aux_intern_dep, + libnm_core_public_dep, + libnm_glib_aux_dep, + glib_dep, + ], +) + +libnm_core_aux_extern_dep_link = declare_dependency( + dependencies: libnm_core_aux_extern_dep, + link_with: libnm_core_aux_extern, +) diff --git a/src/libnm-core-aux-extern/nm-dispatcher-api.h b/src/libnm-core-aux-extern/nm-dispatcher-api.h new file mode 100644 index 0000000000..7776c84f9a --- /dev/null +++ b/src/libnm-core-aux-extern/nm-dispatcher-api.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2008 - 2012 Red Hat, Inc. + */ + +#ifndef __NM_DISPACHER_API_H__ +#define __NM_DISPACHER_API_H__ + +#define NM_DISPATCHER_DBUS_SERVICE "org.freedesktop.nm_dispatcher" +#define NM_DISPATCHER_DBUS_INTERFACE "org.freedesktop.nm_dispatcher" +#define NM_DISPATCHER_DBUS_PATH "/org/freedesktop/nm_dispatcher" + +#define NMD_CONNECTION_PROPS_PATH "path" +#define NMD_CONNECTION_PROPS_FILENAME "filename" +#define NMD_CONNECTION_PROPS_EXTERNAL "external" + +#define NMD_DEVICE_PROPS_INTERFACE "interface" +#define NMD_DEVICE_PROPS_IP_INTERFACE "ip-interface" +#define NMD_DEVICE_PROPS_TYPE "type" +#define NMD_DEVICE_PROPS_STATE "state" +#define NMD_DEVICE_PROPS_PATH "path" + +/* Actions */ +#define NMD_ACTION_HOSTNAME "hostname" +#define NMD_ACTION_PRE_UP "pre-up" +#define NMD_ACTION_UP "up" +#define NMD_ACTION_PRE_DOWN "pre-down" +#define NMD_ACTION_DOWN "down" +#define NMD_ACTION_VPN_PRE_UP "vpn-pre-up" +#define NMD_ACTION_VPN_UP "vpn-up" +#define NMD_ACTION_VPN_PRE_DOWN "vpn-pre-down" +#define NMD_ACTION_VPN_DOWN "vpn-down" +#define NMD_ACTION_DHCP4_CHANGE "dhcp4-change" +#define NMD_ACTION_DHCP6_CHANGE "dhcp6-change" +#define NMD_ACTION_CONNECTIVITY_CHANGE "connectivity-change" + +typedef enum { + DISPATCH_RESULT_UNKNOWN = 0, + DISPATCH_RESULT_SUCCESS = 1, + DISPATCH_RESULT_EXEC_FAILED = 2, + DISPATCH_RESULT_FAILED = 3, + DISPATCH_RESULT_TIMEOUT = 4, +} DispatchResult; + +#endif /* __NM_DISPACHER_API_H__ */ diff --git a/src/libnm-core-aux-extern/nm-libnm-core-aux.c b/src/libnm-core-aux-extern/nm-libnm-core-aux.c new file mode 100644 index 0000000000..8f3bbef0b9 --- /dev/null +++ b/src/libnm-core-aux-extern/nm-libnm-core-aux.c @@ -0,0 +1,436 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#include "nm-glib-aux/nm-default-glib-i18n-lib.h" + +#include "nm-libnm-core-aux.h" + +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" + +/*****************************************************************************/ + +typedef enum { + KEY_TYPE_STRING, + KEY_TYPE_INT, + KEY_TYPE_BOOL, +} KeyType; + +typedef struct { + const char *str_val; + union { + int vint; + bool vbool; + } typ_val; +} ParseData; + +typedef struct { + const char * name; + NMTeamLinkWatcherType watcher_type; + KeyType key_type; + union { + int (*fint)(const NMTeamLinkWatcher *watcher); + gboolean (*fbool)(const NMTeamLinkWatcher *watcher); + const char *(*fstring)(const NMTeamLinkWatcher *watcher); + } get_fcn; + union { + int vint; + bool vbool; + } def_val; +} TeamLinkWatcherKeyInfo; + +static gboolean +_team_link_watcher_validate_active(const NMTeamLinkWatcher *watcher) +{ + return NM_FLAGS_HAS(nm_team_link_watcher_get_flags(watcher), + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE); +} + +static gboolean +_team_link_watcher_validate_inactive(const NMTeamLinkWatcher *watcher) +{ + return NM_FLAGS_HAS(nm_team_link_watcher_get_flags(watcher), + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE); +} + +static gboolean +_team_link_watcher_send_always(const NMTeamLinkWatcher *watcher) +{ + return NM_FLAGS_HAS(nm_team_link_watcher_get_flags(watcher), + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS); +} + +static const TeamLinkWatcherKeyInfo _team_link_watcher_key_infos[_NM_TEAM_LINK_WATCHER_KEY_NUM] = { + +#define _KEY_INFO(key_id, _name, _watcher_type, _key_type, ...) \ + [key_id] = {.name = ""_name \ + "", \ + .watcher_type = (_watcher_type), \ + .key_type = _key_type, \ + ##__VA_ARGS__} + + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_NAME, + "name", + NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL | NM_TEAM_LINK_WATCHER_TYPE_NSNAPING + | NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_STRING, + .get_fcn.fstring = nm_team_link_watcher_get_name, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_DELAY_UP, + "delay-up", + NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL, + KEY_TYPE_INT, + .get_fcn.fint = nm_team_link_watcher_get_delay_up, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_DELAY_DOWN, + "delay-down", + NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL, + KEY_TYPE_INT, + .get_fcn.fint = nm_team_link_watcher_get_delay_down, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT, + "init-wait", + NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_INT, + .get_fcn.fint = nm_team_link_watcher_get_init_wait, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_INTERVAL, + "interval", + NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_INT, + .get_fcn.fint = nm_team_link_watcher_get_interval, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX, + "missed-max", + NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_INT, + .get_fcn.fint = nm_team_link_watcher_get_missed_max, + .def_val.vint = 3, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST, + "target-host", + NM_TEAM_LINK_WATCHER_TYPE_NSNAPING | NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_STRING, + .get_fcn.fstring = nm_team_link_watcher_get_target_host, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_VLANID, + "vlanid", + NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_INT, + .get_fcn.fint = nm_team_link_watcher_get_vlanid, + .def_val.vint = -1, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_SOURCE_HOST, + "source-host", + NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_STRING, + .get_fcn.fstring = nm_team_link_watcher_get_source_host, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_VALIDATE_ACTIVE, + "validate-active", + NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_BOOL, + .get_fcn.fbool = _team_link_watcher_validate_active, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_VALIDATE_INACTIVE, + "validate-inactive", + NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_BOOL, + .get_fcn.fbool = _team_link_watcher_validate_inactive, ), + _KEY_INFO(NM_TEAM_LINK_WATCHER_KEY_SEND_ALWAYS, + "send-always", + NM_TEAM_LINK_WATCHER_TYPE_ARPING, + KEY_TYPE_BOOL, + .get_fcn.fbool = _team_link_watcher_send_always, ), + +}; + +static NMTeamLinkWatcherType +_team_link_watcher_get_watcher_type_from_name(const char *name) +{ + if (name) { + if (nm_streq(name, NM_TEAM_LINK_WATCHER_ETHTOOL)) + return NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL; + if (nm_streq(name, NM_TEAM_LINK_WATCHER_NSNA_PING)) + return NM_TEAM_LINK_WATCHER_TYPE_NSNAPING; + if (nm_streq(name, NM_TEAM_LINK_WATCHER_ARP_PING)) + return NM_TEAM_LINK_WATCHER_TYPE_ARPING; + } + return NM_TEAM_LINK_WATCHER_TYPE_NONE; +} + +static const char * +_parse_data_get_str(const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM], + NMTeamLinkWatcherKeyId key_id) +{ + nm_assert(_NM_INT_NOT_NEGATIVE(key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM); + nm_assert(_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_STRING); + + return parse_data[key_id].str_val; +} + +static int +_parse_data_get_int(const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM], + NMTeamLinkWatcherKeyId key_id) +{ + nm_assert(_NM_INT_NOT_NEGATIVE(key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM); + nm_assert(_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_INT); + + if (parse_data[key_id].str_val) + return parse_data[key_id].typ_val.vint; + return _team_link_watcher_key_infos[key_id].def_val.vint; +} + +static int +_parse_data_get_bool(const ParseData parse_data[static _NM_TEAM_LINK_WATCHER_KEY_NUM], + NMTeamLinkWatcherKeyId key_id) +{ + nm_assert(_NM_INT_NOT_NEGATIVE(key_id) && key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM); + nm_assert(_team_link_watcher_key_infos[key_id].key_type == KEY_TYPE_BOOL); + + if (parse_data[key_id].str_val) + return parse_data[key_id].typ_val.vbool; + return _team_link_watcher_key_infos[key_id].def_val.vbool; +} + +char * +nm_utils_team_link_watcher_to_string(const NMTeamLinkWatcher *watcher) +{ + nm_auto_free_gstring GString *str = NULL; + const char * name; + NMTeamLinkWatcherType watcher_type; + NMTeamLinkWatcherKeyId key_id; + + if (!watcher) + return NULL; + + str = g_string_new(NULL); + + name = nm_team_link_watcher_get_name(watcher); + g_string_append_printf(str, "name=%s", name ?: ""); + + watcher_type = _team_link_watcher_get_watcher_type_from_name(name); + + for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) { + const TeamLinkWatcherKeyInfo *info = &_team_link_watcher_key_infos[key_id]; + const char * vstr; + int vint; + bool vbool; + + nm_assert( + info->name && info->name + && NM_STRCHAR_ALL(info->name, ch, ((ch >= 'a' && ch <= 'z') || NM_IN_SET(ch, '-')))); + nm_assert(NM_IN_SET(info->key_type, KEY_TYPE_STRING, KEY_TYPE_INT, KEY_TYPE_BOOL)); + + if (key_id == NM_TEAM_LINK_WATCHER_KEY_NAME) + continue; + + if (!NM_FLAGS_ALL(info->watcher_type, watcher_type)) + continue; + + switch (info->key_type) { + case KEY_TYPE_STRING: + vstr = info->get_fcn.fstring(watcher); + if (vstr) { + g_string_append_printf(nm_gstring_add_space_delimiter(str), + "%s=%s", + info->name, + vstr); + } + break; + case KEY_TYPE_INT: + vint = info->get_fcn.fint(watcher); + if (vint != info->def_val.vint) { + g_string_append_printf(nm_gstring_add_space_delimiter(str), + "%s=%d", + info->name, + vint); + } + break; + case KEY_TYPE_BOOL: + vbool = info->get_fcn.fbool(watcher); + if (vbool != info->def_val.vbool) { + g_string_append_printf(nm_gstring_add_space_delimiter(str), + "%s=%s", + info->name, + vbool ? "true" : "false"); + } + break; + } + } + + return g_string_free(g_steal_pointer(&str), FALSE); +} + +NMTeamLinkWatcher * +nm_utils_team_link_watcher_from_string(const char *str, GError **error) +{ + gs_free const char ** tokens = NULL; + ParseData parse_data[_NM_TEAM_LINK_WATCHER_KEY_NUM] = {}; + NMTeamLinkWatcherType watcher_type; + NMTeamLinkWatcherKeyId key_id; + gsize i_token; + NMTeamLinkWatcher * watcher; + int errsv; + + g_return_val_if_fail(str, NULL); + g_return_val_if_fail(!error || !*error, NULL); + + tokens = nm_utils_escaped_tokens_split(str, NM_ASCII_SPACES); + if (!tokens) { + g_set_error(error, 1, 0, "'%s' is not valid", str); + return NULL; + } + + for (i_token = 0; tokens[i_token]; i_token++) { + const TeamLinkWatcherKeyInfo *info; + const char * key = tokens[i_token]; + const char * val; + + val = strchr(key, '='); + if (!val) { + nm_utils_error_set( + error, + NM_UTILS_ERROR_UNKNOWN, + _("'%s' is not valid: properties should be specified as 'key=value'"), + key); + return NULL; + } + ((char *) val)[0] = '\0'; + val++; + + for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) { + info = &_team_link_watcher_key_infos[key_id]; + if (nm_streq(key, info->name)) + break; + } + + if (key_id == _NM_TEAM_LINK_WATCHER_KEY_NUM) { + nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("'%s' is not a valid key"), key); + return NULL; + } + + if (parse_data[key_id].str_val) { + nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("duplicate key '%s'"), key); + return NULL; + } + + parse_data[key_id].str_val = val; + + if (info->key_type == KEY_TYPE_INT) { + gint64 v64; + + v64 = _nm_utils_ascii_str_to_int64(val, 10, G_MININT, G_MAXINT, G_MAXINT64); + if (v64 == G_MAXINT64 && ((errsv = errno) != 0)) { + if (errsv == ERANGE) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + _("number for '%s' is out of range"), + key); + } else { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + _("value for '%s' must be a number"), + key); + } + return NULL; + } + parse_data[key_id].typ_val.vint = v64; + } else if (info->key_type == KEY_TYPE_BOOL) { + int vbool; + + vbool = _nm_utils_ascii_str_to_bool(val, -1); + if (vbool == -1) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + _("value for '%s' must be a boolean"), + key); + return NULL; + } + parse_data[key_id].typ_val.vbool = vbool; + } + } + + if (!parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val) { + nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("missing 'name' attribute")); + return NULL; + } + + watcher_type = _team_link_watcher_get_watcher_type_from_name( + parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val); + if (watcher_type == NM_TEAM_LINK_WATCHER_TYPE_NONE) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + _("invalid 'name' \"%s\""), + parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val); + return NULL; + } + + for (key_id = 0; key_id < _NM_TEAM_LINK_WATCHER_KEY_NUM; key_id++) { + const TeamLinkWatcherKeyInfo *info = &_team_link_watcher_key_infos[key_id]; + + if (!parse_data[key_id].str_val) + continue; + if (!NM_FLAGS_ALL(info->watcher_type, watcher_type)) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + _("attribute '%s' is invalid for \"%s\""), + info->name, + parse_data[NM_TEAM_LINK_WATCHER_KEY_NAME].str_val); + return NULL; + } + } + + switch (watcher_type) { + case NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL: + watcher = nm_team_link_watcher_new_ethtool( + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_DELAY_UP), + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_DELAY_DOWN), + error); + break; + case NM_TEAM_LINK_WATCHER_TYPE_NSNAPING: + watcher = nm_team_link_watcher_new_nsna_ping( + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT), + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_INTERVAL), + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX), + _parse_data_get_str(parse_data, NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST), + error); + break; + default: + nm_assert(watcher_type == NM_TEAM_LINK_WATCHER_TYPE_ARPING); + watcher = nm_team_link_watcher_new_arp_ping2( + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT), + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_INTERVAL), + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX), + _parse_data_get_int(parse_data, NM_TEAM_LINK_WATCHER_KEY_VLANID), + _parse_data_get_str(parse_data, NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST), + _parse_data_get_str(parse_data, NM_TEAM_LINK_WATCHER_KEY_SOURCE_HOST), + (NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE + | (_parse_data_get_bool(parse_data, NM_TEAM_LINK_WATCHER_KEY_VALIDATE_ACTIVE) + ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE + : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE) + | (_parse_data_get_bool(parse_data, NM_TEAM_LINK_WATCHER_KEY_VALIDATE_INACTIVE) + ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE + : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE) + | (_parse_data_get_bool(parse_data, NM_TEAM_LINK_WATCHER_KEY_SEND_ALWAYS) + ? NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS + : NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE)), + error); + break; + } + +#if NM_MORE_ASSERTS > 5 + if (watcher) { + gs_free char * str2 = NULL; + nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher2 = NULL; + static _nm_thread_local int recursive; + + nm_assert(!error || !*error); + if (recursive == 0) { + recursive = 1; + str2 = nm_utils_team_link_watcher_to_string(watcher); + nm_assert(str2); + watcher2 = nm_utils_team_link_watcher_from_string(str2, NULL); + nm_assert(watcher2); + nm_assert(nm_team_link_watcher_equal(watcher, watcher2)); + nm_assert(nm_team_link_watcher_equal(watcher2, watcher)); + nm_assert(recursive == 1); + recursive = 0; + } + } else + nm_assert(!error || *error); +#endif + + return watcher; +} diff --git a/src/libnm-core-aux-extern/nm-libnm-core-aux.h b/src/libnm-core-aux-extern/nm-libnm-core-aux.h new file mode 100644 index 0000000000..905f24331e --- /dev/null +++ b/src/libnm-core-aux-extern/nm-libnm-core-aux.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#ifndef __NM_LIBNM_CORE_AUX_H__ +#define __NM_LIBNM_CORE_AUX_H__ + +#include "nm-setting-team.h" + +typedef enum { + NM_TEAM_LINK_WATCHER_TYPE_NONE = 0, + NM_TEAM_LINK_WATCHER_TYPE_ETHTOOL = (1u << 0), + NM_TEAM_LINK_WATCHER_TYPE_NSNAPING = (1u << 1), + NM_TEAM_LINK_WATCHER_TYPE_ARPING = (1u << 2), +} NMTeamLinkWatcherType; + +typedef enum { + NM_TEAM_LINK_WATCHER_KEY_NAME, + NM_TEAM_LINK_WATCHER_KEY_DELAY_UP, + NM_TEAM_LINK_WATCHER_KEY_DELAY_DOWN, + NM_TEAM_LINK_WATCHER_KEY_INIT_WAIT, + NM_TEAM_LINK_WATCHER_KEY_INTERVAL, + NM_TEAM_LINK_WATCHER_KEY_MISSED_MAX, + NM_TEAM_LINK_WATCHER_KEY_TARGET_HOST, + NM_TEAM_LINK_WATCHER_KEY_VLANID, + NM_TEAM_LINK_WATCHER_KEY_SOURCE_HOST, + NM_TEAM_LINK_WATCHER_KEY_VALIDATE_ACTIVE, + NM_TEAM_LINK_WATCHER_KEY_VALIDATE_INACTIVE, + NM_TEAM_LINK_WATCHER_KEY_SEND_ALWAYS, + _NM_TEAM_LINK_WATCHER_KEY_NUM, +} NMTeamLinkWatcherKeyId; + +char *nm_utils_team_link_watcher_to_string(const NMTeamLinkWatcher *watcher); + +NMTeamLinkWatcher *nm_utils_team_link_watcher_from_string(const char *str, GError **error); + +#endif /* __NM_LIBNM_CORE_AUX_H__ */ diff --git a/src/libnm-core-aux-intern/README.md b/src/libnm-core-aux-intern/README.md new file mode 100644 index 0000000000..37e238f111 --- /dev/null +++ b/src/libnm-core-aux-intern/README.md @@ -0,0 +1,28 @@ +libnm-core-aux-intern +===================== + +`libnm-core-aux-intern` is a static library that: + + - uses parts of [`libnm-core-impl`](../libnm-core-impl), that are public API + of [`libnm`](../../libnm) (i.e. [`libnm-core-public`](../libnm-core-public)). + - that is statically linked into [`libnm-core-impl`](../libnm-core-impl) (and thus + [`libnm`](../libnm) and NetworkManager core. + - that can also be statically linked into other users of [`libnm`](../libnm). + +Basically, it is a static library with utility functions that extends +[`libnm-core-impl`](../libnm-core-impl) (the part that is public API of libnm), +but it is also used by [`libnm-core-impl`](../libnm-core-impl) itself. + +That means: + + - you can use it everywhere where you either statically link + with [`libnm-core-impl`](../libnm-core-impl), or dynamically link with + [`libnm`](../../libnm). + - you can even use it inside of [`libnm-core-impl`](../libnm-core-impl) itself. + This is the difference between `libnm-core-aux-intern` and + [`libnm-core-aux-extern`](..libnm-core-aux-extern). + +Note that `libnm-core-aux-intern` only uses public API of `libnm`. + +This directory should not be added to the include search path. Instead, +users should fully qualify the include like `#include "libnm-core-aux-intern/nm-auth-subject.h"`. diff --git a/src/libnm-core-aux-intern/meson.build b/src/libnm-core-aux-intern/meson.build new file mode 100644 index 0000000000..fbb534c160 --- /dev/null +++ b/src/libnm-core-aux-intern/meson.build @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnm_core_aux_intern = static_library( + 'nm-core-aux-intern', + sources: files( + 'nm-auth-subject.c', + 'nm-libnm-core-utils.c', + ), + dependencies: [ + libnm_core_public_dep, + libnm_glib_aux_dep, + glib_dep, + ], + c_args: [ + '-DG_LOG_DOMAIN="libnm"', + ], +) + +libnm_core_aux_intern_dep = declare_dependency( + include_directories: [ + shared_inc, + src_inc, + top_inc, + ], + dependencies: [ + libnm_core_public_dep, + glib_dep, + ], +) + +libnm_core_aux_intern_dep_link = declare_dependency( + dependencies: libnm_core_aux_intern_dep, + link_with: libnm_core_aux_intern, +) diff --git a/src/libnm-core-aux-intern/nm-auth-subject.c b/src/libnm-core-aux-intern/nm-auth-subject.c new file mode 100644 index 0000000000..2862356052 --- /dev/null +++ b/src/libnm-core-aux-intern/nm-auth-subject.c @@ -0,0 +1,468 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2013 - 2014 Red Hat, Inc. + */ + +/** + * SECTION:nm-auth-subject + * @short_description: Encapsulates authentication information about a requestor + * + * #NMAuthSubject encpasulates identifying information about an entity that + * makes requests, like process identifier and user UID. + */ + +#include "nm-glib-aux/nm-default-glib-i18n-lib.h" + +#include "nm-auth-subject.h" + +#include + +enum { + PROP_0, + PROP_SUBJECT_TYPE, + PROP_UNIX_PROCESS_DBUS_SENDER, + PROP_UNIX_PROCESS_PID, + PROP_UNIX_PROCESS_UID, + PROP_UNIX_SESSION_ID, + + PROP_LAST, +}; + +typedef struct { + NMAuthSubjectType subject_type; + struct { + gulong pid; + gulong uid; + guint64 start_time; + char * dbus_sender; + } unix_process; + + struct { + char *id; + } unix_session; +} NMAuthSubjectPrivate; + +struct _NMAuthSubject { + GObject parent; + NMAuthSubjectPrivate _priv; +}; + +struct _NMAuthSubjectClass { + GObjectClass parent; +}; + +G_DEFINE_TYPE(NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT) + +#define NM_AUTH_SUBJECT_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMAuthSubject, NM_IS_AUTH_SUBJECT) + +/*****************************************************************************/ + +#define CHECK_SUBJECT(self, error_value) \ + NMAuthSubjectPrivate *priv; \ + g_return_val_if_fail(NM_IS_AUTH_SUBJECT(self), error_value); \ + priv = NM_AUTH_SUBJECT_GET_PRIVATE(self); + +#define CHECK_SUBJECT_TYPED(self, expected_subject_type, error_value) \ + CHECK_SUBJECT(self, error_value); \ + g_return_val_if_fail(priv->subject_type == (expected_subject_type), error_value); + +const char * +nm_auth_subject_to_string(NMAuthSubject *self, char *buf, gsize buf_len) +{ + CHECK_SUBJECT(self, NULL); + + switch (priv->subject_type) { + case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS: + g_snprintf(buf, + buf_len, + "unix-process[pid=%lu, uid=%lu, start=%llu]", + (unsigned long) priv->unix_process.pid, + (unsigned long) priv->unix_process.uid, + (unsigned long long) priv->unix_process.start_time); + break; + case NM_AUTH_SUBJECT_TYPE_INTERNAL: + g_strlcpy(buf, "internal", buf_len); + break; + case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION: + g_snprintf(buf, buf_len, "unix-session[id=%s]", priv->unix_session.id); + break; + default: + g_strlcpy(buf, "invalid", buf_len); + break; + } + return buf; +} + +/* returns a floating variant */ +GVariant * +nm_auth_subject_unix_to_polkit_gvariant(NMAuthSubject *self) +{ + GVariantBuilder builder; + CHECK_SUBJECT(self, NULL); + + switch (priv->subject_type) { + case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION: + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&builder, + "{sv}", + "session-id", + g_variant_new_string(priv->unix_session.id)); + return g_variant_new("(sa{sv})", "unix-session", &builder); + + case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS: + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&builder, + "{sv}", + "pid", + g_variant_new_uint32(priv->unix_process.pid)); + g_variant_builder_add(&builder, + "{sv}", + "start-time", + g_variant_new_uint64(priv->unix_process.start_time)); + g_variant_builder_add(&builder, "{sv}", "uid", g_variant_new_int32(priv->unix_process.uid)); + return g_variant_new("(sa{sv})", "unix-process", &builder); + + default: + g_return_val_if_reached(NULL); + } +} + +NMAuthSubjectType +nm_auth_subject_get_subject_type(NMAuthSubject *subject) +{ + CHECK_SUBJECT(subject, NM_AUTH_SUBJECT_TYPE_INVALID); + + return priv->subject_type; +} + +gulong +nm_auth_subject_get_unix_process_pid(NMAuthSubject *subject) +{ + CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, G_MAXULONG); + + return priv->unix_process.pid; +} + +gulong +nm_auth_subject_get_unix_process_uid(NMAuthSubject *subject) +{ + CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, G_MAXULONG); + + return priv->unix_process.uid; +} + +const char * +nm_auth_subject_get_unix_process_dbus_sender(NMAuthSubject *subject) +{ + CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, NULL); + + return priv->unix_process.dbus_sender; +} + +const char * +nm_auth_subject_get_unix_session_id(NMAuthSubject *subject) +{ + CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_SESSION, NULL); + + return priv->unix_session.id; +} + +/*****************************************************************************/ + +/** + * nm_auth_subject_new_internal(): + * + * Creates a new auth subject representing the NetworkManager process itself. + * + * Returns: the new #NMAuthSubject + */ +NMAuthSubject * +nm_auth_subject_new_internal(void) +{ + return g_object_new(NM_TYPE_AUTH_SUBJECT, + NM_AUTH_SUBJECT_SUBJECT_TYPE, + (int) NM_AUTH_SUBJECT_TYPE_INTERNAL, + NULL); +} + +/** + * nm_auth_subject_new_unix_session(): + * + * Creates a new auth subject representing a given unix session. + * + * Returns: the new #NMAuthSubject + */ +NMAuthSubject * +nm_auth_subject_new_unix_session(const char *session_id) +{ + return g_object_new(NM_TYPE_AUTH_SUBJECT, + NM_AUTH_SUBJECT_SUBJECT_TYPE, + (int) NM_AUTH_SUBJECT_TYPE_UNIX_SESSION, + NM_AUTH_SUBJECT_UNIX_SESSION_ID, + session_id, + NULL); +} + +/** + * nm_auth_subject_new_unix_process(): + * + * Creates a new auth subject representing a given unix process. + * + * Returns: the new #NMAuthSubject + */ +NMAuthSubject * +nm_auth_subject_new_unix_process(const char *dbus_sender, gulong pid, gulong uid) +{ + return g_object_new(NM_TYPE_AUTH_SUBJECT, + NM_AUTH_SUBJECT_SUBJECT_TYPE, + (int) NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, + NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER, + dbus_sender, + NM_AUTH_SUBJECT_UNIX_PROCESS_PID, + pid, + NM_AUTH_SUBJECT_UNIX_PROCESS_UID, + uid, + NULL); +} + +/** + * nm_auth_subject_new_unix_process_self(): + * + * Creates a new auth subject representing the current executing process. + * + * Returns: the new #NMAuthSubject + */ +NMAuthSubject * +nm_auth_subject_new_unix_process_self(void) +{ + return nm_auth_subject_new_unix_process(NULL, getpid(), getuid()); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_SUBJECT_TYPE: + g_value_set_int(value, priv->subject_type); + break; + case PROP_UNIX_PROCESS_DBUS_SENDER: + g_value_set_string(value, priv->unix_process.dbus_sender); + break; + case PROP_UNIX_PROCESS_PID: + g_value_set_ulong(value, priv->unix_process.pid); + break; + case PROP_UNIX_PROCESS_UID: + g_value_set_ulong(value, priv->unix_process.uid); + break; + case PROP_UNIX_SESSION_ID: + g_value_set_string(value, priv->unix_session.id); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(object); + NMAuthSubjectType subject_type; + int i; + const char * str; + gulong id; + + switch (prop_id) { + case PROP_SUBJECT_TYPE: + /* construct-only */ + i = g_value_get_int(value); + g_return_if_fail(NM_IN_SET(i, + (int) NM_AUTH_SUBJECT_TYPE_INTERNAL, + (int) NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, + (int) NM_AUTH_SUBJECT_TYPE_UNIX_SESSION)); + subject_type = i; + priv->subject_type |= subject_type; + g_return_if_fail(priv->subject_type == subject_type); + break; + case PROP_UNIX_PROCESS_DBUS_SENDER: + /* construct-only */ + if ((str = g_value_get_string(value))) { + priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS; + g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS); + priv->unix_process.dbus_sender = g_strdup(str); + } + break; + case PROP_UNIX_PROCESS_PID: + /* construct-only */ + if ((id = g_value_get_ulong(value)) != G_MAXULONG) { + priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS; + g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS); + priv->unix_process.pid = id; + } + break; + case PROP_UNIX_PROCESS_UID: + /* construct-only */ + if ((id = g_value_get_ulong(value)) != G_MAXULONG) { + priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS; + g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS); + priv->unix_process.uid = id; + } + break; + case PROP_UNIX_SESSION_ID: + /* construct-only */ + if ((str = g_value_get_string(value))) { + priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_SESSION; + g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_SESSION); + priv->unix_session.id = g_strdup(str); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +_clear_private(NMAuthSubject *self) +{ + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(self); + + priv->subject_type = NM_AUTH_SUBJECT_TYPE_INVALID; + priv->unix_process.pid = G_MAXULONG; + priv->unix_process.uid = G_MAXULONG; + nm_clear_g_free(&priv->unix_process.dbus_sender); + + nm_clear_g_free(&priv->unix_session.id); +} + +static void +nm_auth_subject_init(NMAuthSubject *self) +{ + _clear_private(self); +} + +static void +constructed(GObject *object) +{ + NMAuthSubject * self = NM_AUTH_SUBJECT(object); + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(self); + + /* validate that the created instance. */ + + switch (priv->subject_type) { + case NM_AUTH_SUBJECT_TYPE_INTERNAL: + priv->unix_process.pid = G_MAXULONG; + priv->unix_process.uid = 0; /* internal uses 'root' user */ + return; + case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS: + /* Ensure pid and uid to be representable as int32. + * DBUS treats them as uint32, polkit library as int. */ + if (priv->unix_process.pid > MIN(G_MAXINT, G_MAXINT32)) + break; + if (priv->unix_process.uid > MIN(G_MAXINT, G_MAXINT32)) { + /* for uid==-1, libpolkit-gobject-1 detects the user based on the process id. + * Don't bother and require the user id as parameter. */ + break; + } + + priv->unix_process.start_time = + nm_utils_get_start_time_for_pid(priv->unix_process.pid, NULL, NULL); + + if (!priv->unix_process.start_time) { + /* Is the process already gone? Then fail creation of the auth subject + * by clearing the type. */ + if (kill(priv->unix_process.pid, 0) != 0) + _clear_private(self); + + /* Otherwise, although we didn't detect a start_time, the process is still around. + * That could be due to procfs mounted with hidepid. So just accept the request. + * + * Polkit on the other side, will accept 0 and try to lookup /proc/$PID/stat + * itself (and if it fails to do so, assume a start-time of 0 and proceed). + * The only combination that would fail here, is when NM is able to read the + * start-time, but polkit is not. */ + } + return; + case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION: + return; + default: + break; + } + + _clear_private(self); + g_return_if_reached(); +} + +static void +finalize(GObject *object) +{ + _clear_private((NMAuthSubject *) object); + + G_OBJECT_CLASS(nm_auth_subject_parent_class)->finalize(object); +} + +static void +nm_auth_subject_class_init(NMAuthSubjectClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(config_class); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->constructed = constructed; + object_class->finalize = finalize; + + g_object_class_install_property( + object_class, + PROP_SUBJECT_TYPE, + g_param_spec_int(NM_AUTH_SUBJECT_SUBJECT_TYPE, + "", + "", + NM_AUTH_SUBJECT_TYPE_INVALID, + NM_AUTH_SUBJECT_TYPE_UNIX_SESSION, + NM_AUTH_SUBJECT_TYPE_INVALID, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property( + object_class, + PROP_UNIX_PROCESS_DBUS_SENDER, + g_param_spec_string(NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property( + object_class, + PROP_UNIX_PROCESS_PID, + g_param_spec_ulong(NM_AUTH_SUBJECT_UNIX_PROCESS_PID, + "", + "", + 0, + G_MAXULONG, + G_MAXULONG, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property( + object_class, + PROP_UNIX_PROCESS_UID, + g_param_spec_ulong(NM_AUTH_SUBJECT_UNIX_PROCESS_UID, + "", + "", + 0, + G_MAXULONG, + G_MAXULONG, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property( + object_class, + PROP_UNIX_SESSION_ID, + g_param_spec_string(NM_AUTH_SUBJECT_UNIX_SESSION_ID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); +} diff --git a/src/libnm-core-aux-intern/nm-auth-subject.h b/src/libnm-core-aux-intern/nm-auth-subject.h new file mode 100644 index 0000000000..2c9c4f71a9 --- /dev/null +++ b/src/libnm-core-aux-intern/nm-auth-subject.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2013 Red Hat, Inc. + */ + +#ifndef __NETWORKMANAGER_AUTH_SUBJECT_H__ +#define __NETWORKMANAGER_AUTH_SUBJECT_H__ + +#define NM_TYPE_AUTH_SUBJECT (nm_auth_subject_get_type()) +#define NM_AUTH_SUBJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubject)) +#define NM_AUTH_SUBJECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass)) +#define NM_IS_AUTH_SUBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_AUTH_SUBJECT)) +#define NM_IS_AUTH_SUBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_AUTH_SUBJECT)) +#define NM_AUTH_SUBJECT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass)) + +typedef enum { + NM_AUTH_SUBJECT_TYPE_INVALID = 0, + NM_AUTH_SUBJECT_TYPE_INTERNAL = 1, + NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS = 2, + NM_AUTH_SUBJECT_TYPE_UNIX_SESSION = 4, +} NMAuthSubjectType; + +#define NM_AUTH_SUBJECT_SUBJECT_TYPE "subject-type" +#define NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER "unix-process-dbus-sender" +#define NM_AUTH_SUBJECT_UNIX_PROCESS_PID "unix-process-pid" +#define NM_AUTH_SUBJECT_UNIX_PROCESS_UID "unix-process-uid" +#define NM_AUTH_SUBJECT_UNIX_SESSION_ID "unix-session-id" + +typedef struct _NMAuthSubjectClass NMAuthSubjectClass; +typedef struct _NMAuthSubject NMAuthSubject; + +GType nm_auth_subject_get_type(void); + +NMAuthSubject *nm_auth_subject_new_internal(void); + +NMAuthSubject *nm_auth_subject_new_unix_session(const char *session_id); + +NMAuthSubject *nm_auth_subject_new_unix_process(const char *dbus_sender, gulong pid, gulong uid); + +NMAuthSubject *nm_auth_subject_new_unix_process_self(void); + +NMAuthSubjectType nm_auth_subject_get_subject_type(NMAuthSubject *subject); + +gulong nm_auth_subject_get_unix_process_pid(NMAuthSubject *subject); + +const char *nm_auth_subject_get_unix_process_dbus_sender(NMAuthSubject *subject); + +gulong nm_auth_subject_get_unix_process_uid(NMAuthSubject *subject); + +const char *nm_auth_subject_get_unix_session_id(NMAuthSubject *subject); + +const char *nm_auth_subject_to_string(NMAuthSubject *self, char *buf, gsize buf_len); + +GVariant *nm_auth_subject_unix_to_polkit_gvariant(NMAuthSubject *self); + +#endif /* __NETWORKMANAGER_AUTH_SUBJECT_H__ */ diff --git a/src/libnm-core-aux-intern/nm-common-macros.h b/src/libnm-core-aux-intern/nm-common-macros.h new file mode 100644 index 0000000000..c452b7d3cb --- /dev/null +++ b/src/libnm-core-aux-intern/nm-common-macros.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2016 Red Hat, Inc. + */ + +#ifndef __NM_COMMON_MACROS_H__ +#define __NM_COMMON_MACROS_H__ + +/*****************************************************************************/ + +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK \ + "org.freedesktop.NetworkManager.enable-disable-network" +#define NM_AUTH_PERMISSION_SLEEP_WAKE "org.freedesktop.NetworkManager.sleep-wake" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX \ + "org.freedesktop.NetworkManager.enable-disable-wimax" +#define NM_AUTH_PERMISSION_NETWORK_CONTROL "org.freedesktop.NetworkManager.network-control" +#define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED \ + "org.freedesktop.NetworkManager.wifi.share.protected" +#define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN "org.freedesktop.NetworkManager.wifi.share.open" +#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM \ + "org.freedesktop.NetworkManager.settings.modify.system" +#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own" +#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME \ + "org.freedesktop.NetworkManager.settings.modify.hostname" +#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS \ + "org.freedesktop.NetworkManager.settings.modify.global-dns" +#define NM_AUTH_PERMISSION_RELOAD "org.freedesktop.NetworkManager.reload" +#define NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK "org.freedesktop.NetworkManager.checkpoint-rollback" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS \ + "org.freedesktop.NetworkManager.enable-disable-statistics" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK \ + "org.freedesktop.NetworkManager.enable-disable-connectivity-check" +#define NM_AUTH_PERMISSION_WIFI_SCAN "org.freedesktop.NetworkManager.wifi.scan" + +#define NM_CLONED_MAC_PRESERVE "preserve" +#define NM_CLONED_MAC_PERMANENT "permanent" +#define NM_CLONED_MAC_RANDOM "random" +#define NM_CLONED_MAC_STABLE "stable" + +static inline gboolean +NM_CLONED_MAC_IS_SPECIAL(const char *str) +{ + return NM_IN_STRSET(str, + NM_CLONED_MAC_PRESERVE, + NM_CLONED_MAC_PERMANENT, + NM_CLONED_MAC_RANDOM, + NM_CLONED_MAC_STABLE); +} + +#define NM_IAID_MAC "mac" +#define NM_IAID_PERM_MAC "perm-mac" +#define NM_IAID_IFNAME "ifname" +#define NM_IAID_STABLE "stable" + +#define NM_CONNECTION_MUD_URL_NONE "none" + +static inline gboolean +NM_IAID_IS_SPECIAL(const char *str) +{ + return NM_IN_STRSET(str, NM_IAID_MAC, NM_IAID_PERM_MAC, NM_IAID_IFNAME, NM_IAID_STABLE); +} + +#endif /* __NM_COMMON_MACROS_H__ */ diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.c b/src/libnm-core-aux-intern/nm-libnm-core-utils.c new file mode 100644 index 0000000000..e3d7b7b183 --- /dev/null +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.c @@ -0,0 +1,387 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "nm-glib-aux/nm-default-glib-i18n-lib.h" + +#include "nm-libnm-core-utils.h" + +#include + +#include "nm-common-macros.h" +#include "nm-errors.h" + +/*****************************************************************************/ + +const char ** +nm_utils_bond_option_arp_ip_targets_split(const char *arp_ip_target) +{ + return nm_utils_strsplit_set_full(arp_ip_target, ",", NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP); +} + +void +_nm_setting_bond_remove_options_miimon(NMSettingBond *s_bond) +{ + g_return_if_fail(NM_IS_SETTING_BOND(s_bond)); + + nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_MIIMON); + nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_UPDELAY); + nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY); +} + +void +_nm_setting_bond_remove_options_arp_interval(NMSettingBond *s_bond) +{ + g_return_if_fail(NM_IS_SETTING_BOND(s_bond)); + + nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); + nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); +} + +/*****************************************************************************/ + +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( + _nm_setting_bond_mode_from_string, + NMBondMode, + { + G_STATIC_ASSERT_EXPR(_NM_BOND_MODE_NUM <= 9); + + if (name && name[0] < '0' + _NM_BOND_MODE_NUM && name[0] >= '0' && name[1] == '\0') { + return name[0] - '0'; + } + }, + { return NM_BOND_MODE_UNKNOWN; }, + {"802.3ad", NM_BOND_MODE_8023AD}, + {"active-backup", NM_BOND_MODE_ACTIVEBACKUP}, + {"balance-alb", NM_BOND_MODE_ALB}, + {"balance-rr", NM_BOND_MODE_ROUNDROBIN}, + {"balance-tlb", NM_BOND_MODE_TLB}, + {"balance-xor", NM_BOND_MODE_XOR}, + {"broadcast", NM_BOND_MODE_BROADCAST}, ); + +const char * +_nm_setting_bond_mode_to_string(int mode) +{ + static const char *const modes[] = { + [NM_BOND_MODE_8023AD] = "802.3ad", + [NM_BOND_MODE_ACTIVEBACKUP] = "active-backup", + [NM_BOND_MODE_ALB] = "balance-alb", + [NM_BOND_MODE_BROADCAST] = "broadcast", + [NM_BOND_MODE_ROUNDROBIN] = "balance-rr", + [NM_BOND_MODE_TLB] = "balance-tlb", + [NM_BOND_MODE_XOR] = "balance-xor", + }; + + G_STATIC_ASSERT(G_N_ELEMENTS(modes) == _NM_BOND_MODE_NUM); + + if (NM_MORE_ASSERT_ONCE(5)) { + char sbuf[100]; + int i; + NMBondMode m; + + for (i = 0; i < (int) G_N_ELEMENTS(modes); i++) { + nm_assert(modes[i]); + nm_assert(i == _nm_setting_bond_mode_from_string(modes[i])); + nm_assert(i == _nm_setting_bond_mode_from_string(nm_sprintf_buf(sbuf, "%d", i))); + } + nm_assert(NM_BOND_MODE_UNKNOWN == _nm_setting_bond_mode_from_string(NULL)); + nm_assert(NM_BOND_MODE_UNKNOWN == _nm_setting_bond_mode_from_string("")); + for (i = -2; i < ((int) G_N_ELEMENTS(modes)) + 20; i++) { + if (i < 0 || i >= G_N_ELEMENTS(modes)) + m = NM_BOND_MODE_UNKNOWN; + else + m = i; + nm_assert(m == _nm_setting_bond_mode_from_string(nm_sprintf_buf(sbuf, "%d", i))); + } + } + + if (mode >= 0 && mode < (int) G_N_ELEMENTS(modes)) + return modes[mode]; + return NULL; +} + +/*****************************************************************************/ + +gboolean +nm_utils_vlan_priority_map_parse_str(NMVlanPriorityMap map_type, + const char * str, + gboolean allow_wildcard_to, + guint32 * out_from, + guint32 * out_to, + gboolean * out_has_wildcard_to) +{ + const char *s2; + gint64 v1, v2; + + nm_assert(str); + + s2 = strchr(str, ':'); + + if (!s2) { + if (!allow_wildcard_to) + return FALSE; + v1 = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT32, -1); + v2 = -1; + } else { + gs_free char *s1_free = NULL; + gsize s1_len = (s2 - str); + + s2 = nm_str_skip_leading_spaces(&s2[1]); + if (s2[0] == '\0' || (s2[0] == '*' && NM_STRCHAR_ALL(&s2[1], ch, g_ascii_isspace(ch)))) { + if (!allow_wildcard_to) + return FALSE; + v2 = -1; + } else { + v2 = _nm_utils_ascii_str_to_int64(s2, 10, 0, G_MAXUINT32, -1); + if (v2 < 0 || (guint32) v2 > nm_utils_vlan_priority_map_get_max_prio(map_type, FALSE)) + return FALSE; + } + + v1 = _nm_utils_ascii_str_to_int64(nm_strndup_a(100, str, s1_len, &s1_free), + 10, + 0, + G_MAXUINT32, + -1); + } + + if (v1 < 0 || (guint32) v1 > nm_utils_vlan_priority_map_get_max_prio(map_type, TRUE)) + return FALSE; + + NM_SET_OUT(out_from, v1); + NM_SET_OUT(out_to, v2 < 0 ? 0u : (guint) v2); + NM_SET_OUT(out_has_wildcard_to, v2 < 0); + return TRUE; +} + +/*****************************************************************************/ + +const char *const nm_auth_permission_names_by_idx[NM_CLIENT_PERMISSION_LAST] = { + [NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK - 1] = NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, + [NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK - 1] = + NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, + [NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, + [NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS - 1] = + NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS, + [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, + [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, + [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, + [NM_CLIENT_PERMISSION_NETWORK_CONTROL - 1] = NM_AUTH_PERMISSION_NETWORK_CONTROL, + [NM_CLIENT_PERMISSION_RELOAD - 1] = NM_AUTH_PERMISSION_RELOAD, + [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS - 1] = + NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, + [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME - 1] = + NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, + [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, + [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, + [NM_CLIENT_PERMISSION_SLEEP_WAKE - 1] = NM_AUTH_PERMISSION_SLEEP_WAKE, + [NM_CLIENT_PERMISSION_WIFI_SCAN - 1] = NM_AUTH_PERMISSION_WIFI_SCAN, + [NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN - 1] = NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, + [NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED - 1] = NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, +}; + +const NMClientPermission nm_auth_permission_sorted[NM_CLIENT_PERMISSION_LAST] = { + NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN, + NM_CLIENT_PERMISSION_NETWORK_CONTROL, + NM_CLIENT_PERMISSION_RELOAD, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM, + NM_CLIENT_PERMISSION_SLEEP_WAKE, + NM_CLIENT_PERMISSION_WIFI_SCAN, + NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN, + NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED, +}; + +const char * +nm_auth_permission_to_string(NMClientPermission permission) +{ + if (permission < 1) + return NULL; + if (permission > NM_CLIENT_PERMISSION_LAST) + return NULL; + return nm_auth_permission_names_by_idx[permission - 1]; +} + +#define AUTH_PERMISSION_PREFIX "org.freedesktop.NetworkManager." + +static int +_nm_auth_permission_from_string_cmp(gconstpointer a, gconstpointer b, gpointer user_data) +{ + const NMClientPermission *const p = a; + const char *const needle = b; + const char * ss = nm_auth_permission_names_by_idx[*p - 1]; + + nm_assert(NM_STR_HAS_PREFIX(ss, AUTH_PERMISSION_PREFIX)); + nm_assert(ss[NM_STRLEN(AUTH_PERMISSION_PREFIX)] != '\0'); + + return strcmp(&ss[NM_STRLEN(AUTH_PERMISSION_PREFIX)], needle); +} + +NMClientPermission +nm_auth_permission_from_string(const char *str) +{ + gssize idx; + + if (!str) + return NM_CLIENT_PERMISSION_NONE; + + if (!NM_STR_HAS_PREFIX(str, AUTH_PERMISSION_PREFIX)) + return NM_CLIENT_PERMISSION_NONE; + idx = nm_utils_array_find_binary_search(nm_auth_permission_sorted, + sizeof(nm_auth_permission_sorted[0]), + G_N_ELEMENTS(nm_auth_permission_sorted), + &str[NM_STRLEN(AUTH_PERMISSION_PREFIX)], + _nm_auth_permission_from_string_cmp, + NULL); + if (idx < 0) + return NM_CLIENT_PERMISSION_NONE; + return nm_auth_permission_sorted[idx]; +} + +/*****************************************************************************/ + +NMClientPermissionResult +nm_client_permission_result_from_string(const char *nm) +{ + if (!nm) + return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; + if (nm_streq(nm, "yes")) + return NM_CLIENT_PERMISSION_RESULT_YES; + if (nm_streq(nm, "no")) + return NM_CLIENT_PERMISSION_RESULT_NO; + if (nm_streq(nm, "auth")) + return NM_CLIENT_PERMISSION_RESULT_AUTH; + return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; +} + +const char * +nm_client_permission_result_to_string(NMClientPermissionResult permission) +{ + switch (permission) { + case NM_CLIENT_PERMISSION_RESULT_YES: + return "yes"; + case NM_CLIENT_PERMISSION_RESULT_NO: + return "no"; + case NM_CLIENT_PERMISSION_RESULT_AUTH: + return "auth"; + case NM_CLIENT_PERMISSION_RESULT_UNKNOWN: + return "unknown"; + } + nm_assert_not_reached(); + return NULL; +} + +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( + nm_utils_route_type_by_name, + guint8, + { nm_assert(name); }, + { return RTN_UNSPEC; }, + {"blackhole", RTN_BLACKHOLE}, + {"broadcast", RTN_BROADCAST}, + {"local", RTN_LOCAL}, + {"multicast", RTN_MULTICAST}, + {"nat", RTN_NAT}, + {"prohibit", RTN_PROHIBIT}, + {"throw", RTN_THROW}, + {"unicast", RTN_UNICAST}, + {"unreachable", RTN_UNREACHABLE}, ); + +NM_UTILS_ENUM2STR_DEFINE(nm_utils_route_type2str, + guint8, + NM_UTILS_ENUM2STR(RTN_BLACKHOLE, "blackhole"), + NM_UTILS_ENUM2STR(RTN_BROADCAST, "broadcast"), + NM_UTILS_ENUM2STR(RTN_LOCAL, "local"), + NM_UTILS_ENUM2STR(RTN_MULTICAST, "multicast"), + NM_UTILS_ENUM2STR(RTN_NAT, "nat"), + NM_UTILS_ENUM2STR(RTN_PROHIBIT, "prohibit"), + NM_UTILS_ENUM2STR(RTN_THROW, "throw"), + NM_UTILS_ENUM2STR(RTN_UNICAST, "unicast"), + NM_UTILS_ENUM2STR(RTN_UNREACHABLE, "unreachable"), + NM_UTILS_ENUM2STR(RTN_UNSPEC, "unspecified"), ); + +gboolean +nm_utils_validate_dhcp4_vendor_class_id(const char *vci, GError **error) +{ + const char * bin; + gsize unescaped_len; + gs_free char *to_free = NULL; + + g_return_val_if_fail(!error || !(*error), FALSE); + g_return_val_if_fail(vci, FALSE); + + if (vci[0] == '\0') { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property cannot be an empty string")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER); + return FALSE; + } + + bin = nm_utils_buf_utf8safe_unescape(vci, + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, + &unescaped_len, + (gpointer *) &to_free); + /* a DHCP option cannot be longer than 255 bytes */ + if (unescaped_len > 255) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property cannot be longer than 255 bytes")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER); + return FALSE; + } + if (strlen(bin) != unescaped_len) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property cannot contain any nul bytes")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER); + return FALSE; + } + + return TRUE; +} + +gboolean +nm_settings_connection_validate_permission_user(const char *item, gssize len) +{ + gsize l; + + if (!item) + return FALSE; + + if (len < 0) { + nm_assert(len == -1); + l = strlen(item); + } else + l = (gsize) len; + + if (l == 0) + return FALSE; + + if (!g_utf8_validate(item, l, NULL)) + return FALSE; + + if (l >= 100) + return FALSE; + + if (memchr(item, ':', l)) + return FALSE; + + return TRUE; +} diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.h b/src/libnm-core-aux-intern/nm-libnm-core-utils.h new file mode 100644 index 0000000000..946c7a2c0e --- /dev/null +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#ifndef __NM_LIBNM_SHARED_UTILS_H__ +#define __NM_LIBNM_SHARED_UTILS_H__ + +/****************************************************************************/ + +#include "nm-setting-bond.h" +#include "nm-setting-bridge.h" +#include "nm-setting-connection.h" +#include "nm-setting-ip-config.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-sriov.h" +#include "nm-setting-team.h" +#include "nm-setting-vlan.h" +#include "nm-setting-wireguard.h" + +/****************************************************************************/ + +#define nm_auto_unref_ip_address nm_auto(_nm_ip_address_unref) +NM_AUTO_DEFINE_FCN0(NMIPAddress *, _nm_ip_address_unref, nm_ip_address_unref); + +#define nm_auto_unref_ip_route nm_auto(_nm_auto_unref_ip_route) +NM_AUTO_DEFINE_FCN0(NMIPRoute *, _nm_auto_unref_ip_route, nm_ip_route_unref); + +#define nm_auto_unref_ip_routing_rule nm_auto(_nm_auto_unref_ip_routing_rule) +NM_AUTO_DEFINE_FCN0(NMIPRoutingRule *, _nm_auto_unref_ip_routing_rule, nm_ip_routing_rule_unref); + +#define nm_auto_unref_sriov_vf nm_auto(_nm_auto_unref_sriov_vf) +NM_AUTO_DEFINE_FCN0(NMSriovVF *, _nm_auto_unref_sriov_vf, nm_sriov_vf_unref); + +#define nm_auto_unref_tc_qdisc nm_auto(_nm_auto_unref_tc_qdisc) +NM_AUTO_DEFINE_FCN0(NMTCQdisc *, _nm_auto_unref_tc_qdisc, nm_tc_qdisc_unref); + +#define nm_auto_unref_tc_tfilter nm_auto(_nm_auto_unref_tc_tfilter) +NM_AUTO_DEFINE_FCN0(NMTCTfilter *, _nm_auto_unref_tc_tfilter, nm_tc_tfilter_unref); + +#define nm_auto_unref_bridge_vlan nm_auto(_nm_auto_unref_bridge_vlan) +NM_AUTO_DEFINE_FCN0(NMBridgeVlan *, _nm_auto_unref_bridge_vlan, nm_bridge_vlan_unref); + +#define nm_auto_unref_team_link_watcher nm_auto(_nm_auto_unref_team_link_watcher) +NM_AUTO_DEFINE_FCN0(NMTeamLinkWatcher *, + _nm_auto_unref_team_link_watcher, + nm_team_link_watcher_unref); + +#define nm_auto_unref_wgpeer nm_auto(_nm_auto_unref_wgpeer) +NM_AUTO_DEFINE_FCN0(NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer_unref); + +/****************************************************************************/ + +const char **nm_utils_bond_option_arp_ip_targets_split(const char *arp_ip_target); + +void _nm_setting_bond_remove_options_miimon(NMSettingBond *s_bond); +void _nm_setting_bond_remove_options_arp_interval(NMSettingBond *s_bond); + +typedef enum { + NM_BOND_MODE_UNKNOWN = -1, + + /* The numeric values correspond to kernel's numbering of the modes. */ + NM_BOND_MODE_ROUNDROBIN = 0, + NM_BOND_MODE_ACTIVEBACKUP = 1, + NM_BOND_MODE_XOR = 2, + NM_BOND_MODE_BROADCAST = 3, + NM_BOND_MODE_8023AD = 4, + NM_BOND_MODE_TLB = 5, + NM_BOND_MODE_ALB = 6, + + _NM_BOND_MODE_NUM, +} NMBondMode; + +NMBondMode _nm_setting_bond_mode_from_string(const char *str); + +const char *_nm_setting_bond_mode_to_string(int mode); + +gboolean _nm_setting_bond_validate_option(const char *name, const char *value, GError **error); + +/*****************************************************************************/ + +static inline guint32 +nm_utils_vlan_priority_map_get_max_prio(NMVlanPriorityMap map, gboolean from) +{ + if (map == NM_VLAN_INGRESS_MAP) { + return from ? 7u /* MAX_8021P_PRIO */ + : (guint32) G_MAXUINT32 /* MAX_SKB_PRIO */; + } + nm_assert(map == NM_VLAN_EGRESS_MAP); + return from ? (guint32) G_MAXUINT32 /* MAX_SKB_PRIO */ + : 7u /* MAX_8021P_PRIO */; +} + +gboolean nm_utils_vlan_priority_map_parse_str(NMVlanPriorityMap map_type, + const char * str, + gboolean allow_wildcard_to, + guint32 * out_from, + guint32 * out_to, + gboolean * out_has_wildcard_to); + +/*****************************************************************************/ + +#define NM_OVS_EXTERNAL_ID_NM_PREFIX "NM." +#define NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID "NM.connection.uuid" + +/*****************************************************************************/ + +static inline int +nm_setting_ip_config_get_addr_family(NMSettingIPConfig *s_ip) +{ + if (NM_IS_SETTING_IP4_CONFIG(s_ip)) + return AF_INET; + if (NM_IS_SETTING_IP6_CONFIG(s_ip)) + return AF_INET6; + g_return_val_if_reached(AF_UNSPEC); +} + +/*****************************************************************************/ + +/* The maximum MTU for infiniband. + * + * This is both in transport-mode "datagram" and "connected" + * and they both have the same maximum define. + * + * Note that in the past, MTU in "datagram" mode was restricted + * to 2044 bytes. That is no longer the case and we accept large + * MTUs. + * + * This define is the maxiumum for the MTU in a connection profile (the + * setting). Whether large MTUs can be configured later (at activation time) + * depends on other factors. */ +#define NM_INFINIBAND_MAX_MTU ((guint) 65520) + +/*****************************************************************************/ + +#define _NM_CAPABILITY_MAX NM_CAPABILITY_OVS + +/*****************************************************************************/ + +extern const char *const nm_auth_permission_names_by_idx[NM_CLIENT_PERMISSION_LAST]; +extern const NMClientPermission nm_auth_permission_sorted[NM_CLIENT_PERMISSION_LAST]; + +const char * nm_auth_permission_to_string(NMClientPermission permission); +NMClientPermission nm_auth_permission_from_string(const char *str); + +/*****************************************************************************/ + +NMClientPermissionResult nm_client_permission_result_from_string(const char *nm); +const char * nm_client_permission_result_to_string(NMClientPermissionResult permission); + +guint8 nm_utils_route_type_by_name(const char *name); + +const char *nm_utils_route_type2str(guint8 val, char *buf, gsize len); + +gboolean nm_utils_validate_dhcp4_vendor_class_id(const char *vci, GError **error); + +/*****************************************************************************/ + +#define NM_SETTINGS_CONNECTION_PERMISSION_USER "user" +#define NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX "user:" + +gboolean nm_settings_connection_validate_permission_user(const char *item, gssize len); + +#endif /* __NM_LIBNM_SHARED_UTILS_H__ */ diff --git a/src/libnm-core-impl/README.md b/src/libnm-core-impl/README.md new file mode 100644 index 0000000000..0fce8e1e5c --- /dev/null +++ b/src/libnm-core-impl/README.md @@ -0,0 +1,22 @@ +libnm-core-impl +=============== + +NetworkManager provides a client library [`libnm`](../../libnm). +NetworkManager core does not (dynamically) link against all of libnm. +Instead, it statically links against a part of it. +That part is the static helper library `libnm-core-impl`. + +`libnm-core-impl` implements (and provides) the API from +[`libnm-core-public`](../libnm-core-public), which is part of the public +API of [`libnm`](../../libnm). In this form, `libnm-core-impl` is part +of the implementation of [`libnm`](../../libnm). It also implements (and +provides) an internal API [`libnm-core-intern`](../libnm-core-intern) which +can only be used by those who link statically against `libnm-core-impl`. + +Only NetworkManager core and [`libnm`](../../libnm) are allowed to statically +link with `libnm-core-impl`. Consequently, only those are allowed to include +[`libnm-core-intern`](../libnm-core-intern). + +This directory should not be added to the include search path of other +components as they are only allowed to include [`libnm-core-public`](../libnm-core-public) +and [`libnm-core-intern`](../libnm-core-intern). diff --git a/src/libnm-core-impl/meson.build b/src/libnm-core-impl/meson.build new file mode 100644 index 0000000000..b4a257e9ec --- /dev/null +++ b/src/libnm-core-impl/meson.build @@ -0,0 +1,132 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnm_core_impl_inc = include_directories('.') + +# FIXME: compile both crypto backends. +libnm_crypto = static_library( + 'nm-crypto', + sources: 'nm-crypto-@0@.c'.format(crypto), + dependencies: [ + libnm_core_public_dep, + crypto_dep, + libnm_glib_aux_dep_link, + ], + c_args: [ + '-DG_LOG_DOMAIN="libnm"', + ], +) + +libnm_core_settings_sources = files( + 'nm-setting-6lowpan.c', + 'nm-setting-8021x.c', + 'nm-setting-adsl.c', + 'nm-setting-bluetooth.c', + 'nm-setting-bond.c', + 'nm-setting-bridge-port.c', + 'nm-setting-bridge.c', + 'nm-setting-cdma.c', + 'nm-setting-connection.c', + 'nm-setting-dcb.c', + 'nm-setting-dummy.c', + 'nm-setting-ethtool.c', + 'nm-setting-generic.c', + 'nm-setting-gsm.c', + 'nm-setting-hostname.c', + 'nm-setting-infiniband.c', + 'nm-setting-ip-config.c', + 'nm-setting-ip-tunnel.c', + 'nm-setting-ip4-config.c', + 'nm-setting-ip6-config.c', + 'nm-setting-macsec.c', + 'nm-setting-macvlan.c', + 'nm-setting-match.c', + 'nm-setting-olpc-mesh.c', + 'nm-setting-ovs-bridge.c', + 'nm-setting-ovs-dpdk.c', + 'nm-setting-ovs-external-ids.c', + 'nm-setting-ovs-interface.c', + 'nm-setting-ovs-patch.c', + 'nm-setting-ovs-port.c', + 'nm-setting-ppp.c', + 'nm-setting-pppoe.c', + 'nm-setting-proxy.c', + 'nm-setting-serial.c', + 'nm-setting-sriov.c', + 'nm-setting-tc-config.c', + 'nm-setting-team-port.c', + 'nm-setting-team.c', + 'nm-setting-tun.c', + 'nm-setting-user.c', + 'nm-setting-veth.c', + 'nm-setting-vlan.c', + 'nm-setting-vpn.c', + 'nm-setting-vrf.c', + 'nm-setting-vxlan.c', + 'nm-setting-wifi-p2p.c', + 'nm-setting-wimax.c', + 'nm-setting-wired.c', + 'nm-setting-wireguard.c', + 'nm-setting-wireless-security.c', + 'nm-setting-wireless.c', + 'nm-setting-wpan.c', +) + +libnm_core_impl_sources = files( + 'nm-connection.c', + 'nm-crypto.c', + 'nm-dbus-utils.c', + 'nm-errors.c', + 'nm-keyfile-utils.c', + 'nm-keyfile.c', + 'nm-meta-setting-base-impl.c', + 'nm-property-compare.c', + 'nm-setting.c', + 'nm-simple-connection.c', + 'nm-team-utils.c', + 'nm-utils.c', + 'nm-vpn-editor-plugin.c', + 'nm-vpn-plugin-info.c', +) + +libnm_core_impl = static_library( + 'nm-core-impl', + sources: libnm_core_impl_sources + libnm_core_settings_sources + libnm_core_public_enum_sources + [nm_version_macro_header], + include_directories: [ + top_inc, + src_inc, + libnm_core_intern_inc, + ], + dependencies: [ + dl_dep, + libnm_systemd_shared_dep, + libnm_core_public_dep, + libnm_core_intern_dep, + libnm_glib_aux_dep_link, + uuid_dep, + ], + c_args: [ + '-DG_LOG_DOMAIN="libnm"', + ], + link_with: [ + libnm_crypto, + libnm_core_aux_intern, + ], +) + +libnm_core_impl_dep = declare_dependency( + dependencies: [ + libnm_core_public_dep, + glib_dep, + ], +) + +libnm_core_impl_dep_link = declare_dependency( + dependencies: [ + libnm_core_impl_dep, + ], + link_with: libnm_core_impl, +) + +if enable_tests + subdir('tests') +endif diff --git a/src/libnm-core-impl/nm-connection-private.h b/src/libnm-core-impl/nm-connection-private.h new file mode 100644 index 0000000000..532b17637b --- /dev/null +++ b/src/libnm-core-impl/nm-connection-private.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2014 Red Hat, Inc. + */ + +#ifndef __NM_CONNECTION_PRIVATE_H__ +#define __NM_CONNECTION_PRIVATE_H__ + +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) + #error Cannot use this header. +#endif + +#include "nm-setting.h" +#include "nm-connection.h" + +NMSetting *_nm_connection_find_base_type_setting(NMConnection *connection); + +const char *_nm_connection_detect_slave_type(NMConnection *connection, NMSetting **out_s_port); + +gboolean _nm_connection_detect_slave_type_full(NMSettingConnection *s_con, + NMConnection * connection, + const char ** out_slave_type, + const char ** out_normerr_slave_setting_type, + const char ** out_normerr_missing_slave_type, + const char **out_normerr_missing_slave_type_port, + GError ** error); + +const char *_nm_connection_detect_bluetooth_type(NMConnection *self); + +gboolean _nm_connection_verify_required_interface_name(NMConnection *connection, GError **error); + +int _nm_setting_ovs_interface_verify_interface_type(NMSettingOvsInterface *self, + const char * type, + NMConnection * connection, + gboolean normalize, + gboolean * out_modified, + const char ** out_normalized_type, + GError ** error); + +#endif /* __NM_CONNECTION_PRIVATE_H__ */ diff --git a/src/libnm-core-impl/nm-connection.c b/src/libnm-core-impl/nm-connection.c new file mode 100644 index 0000000000..bc070a9d84 --- /dev/null +++ b/src/libnm-core-impl/nm-connection.c @@ -0,0 +1,3391 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2018 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-connection.h" + +#include + +#include "nm-connection-private.h" +#include "nm-utils.h" +#include "nm-setting-private.h" +#include "libnm-core-intern/nm-core-internal.h" + +/** + * SECTION:nm-connection + * @short_description: Describes a connection to specific network or provider + * + * An #NMConnection describes all the settings and configuration values that + * are necessary to configure network devices for operation on a specific + * network. Connections are the fundamental operating object for + * NetworkManager; no device is connected without a #NMConnection, or + * disconnected without having been connected with a #NMConnection. + * + * Each #NMConnection contains a list of #NMSetting objects usually referenced + * by name (using nm_connection_get_setting_by_name()) or by type (with + * nm_connection_get_setting()). The settings describe the actual parameters + * with which the network devices are configured, including device-specific + * parameters (MTU, SSID, APN, channel, rate, etc) and IP-level parameters + * (addresses, routes, addressing methods, etc). + * + */ + +/*****************************************************************************/ + +enum { SECRETS_UPDATED, SECRETS_CLEARED, CHANGED, LAST_SIGNAL }; + +static guint signals[LAST_SIGNAL] = {0}; + +typedef struct { + NMConnection *self; + + GHashTable *settings; + + /* D-Bus path of the connection, if any */ + char *path; +} NMConnectionPrivate; + +G_DEFINE_INTERFACE(NMConnection, nm_connection, G_TYPE_OBJECT) + +static NMConnectionPrivate *nm_connection_get_private(NMConnection *connection); +#define NM_CONNECTION_GET_PRIVATE(o) (nm_connection_get_private((NMConnection *) o)) + +/*****************************************************************************/ + +static gpointer +_gtype_to_hash_key(GType gtype) +{ +#if NM_MORE_ASSERTS + _nm_unused const gsize *const test_gtype_typedef = >ype; + + nm_assert((GType)(GPOINTER_TO_SIZE(GSIZE_TO_POINTER(gtype))) == gtype); + G_STATIC_ASSERT_EXPR(sizeof(gpointer) >= sizeof(gsize)); + G_STATIC_ASSERT_EXPR(sizeof(gsize) == sizeof(GType)); +#endif + + return GSIZE_TO_POINTER(gtype); +} + +/*****************************************************************************/ + +static void +setting_changed_cb(NMSetting *setting, GParamSpec *pspec, NMConnection *self) +{ + g_signal_emit(self, signals[CHANGED], 0); +} + +static void +_setting_release(NMConnection *connection, NMSetting *setting) +{ + g_signal_handlers_disconnect_by_func(setting, setting_changed_cb, connection); +} + +static gboolean +_setting_release_hfr(gpointer key, gpointer value, gpointer user_data) +{ + _setting_release(user_data, value); + return TRUE; +} + +static void +_nm_connection_add_setting(NMConnection *connection, NMSetting *setting) +{ + NMConnectionPrivate *priv; + GType setting_type; + NMSetting * s_old; + + nm_assert(NM_IS_CONNECTION(connection)); + nm_assert(NM_IS_SETTING(setting)); + + priv = NM_CONNECTION_GET_PRIVATE(connection); + setting_type = G_OBJECT_TYPE(setting); + + if ((s_old = g_hash_table_lookup(priv->settings, _gtype_to_hash_key(setting_type)))) + _setting_release(connection, s_old); + + g_hash_table_insert(priv->settings, _gtype_to_hash_key(setting_type), setting); + + g_signal_connect(setting, "notify", (GCallback) setting_changed_cb, connection); +} + +/** + * nm_connection_add_setting: + * @connection: a #NMConnection + * @setting: (transfer full): the #NMSetting to add to the connection object + * + * Adds a #NMSetting to the connection, replacing any previous #NMSetting of the + * same name which has previously been added to the #NMConnection. The + * connection takes ownership of the #NMSetting object and does not increase + * the setting object's reference count. + **/ +void +nm_connection_add_setting(NMConnection *connection, NMSetting *setting) +{ + g_return_if_fail(NM_IS_CONNECTION(connection)); + g_return_if_fail(NM_IS_SETTING(setting)); + + _nm_connection_add_setting(connection, setting); + g_signal_emit(connection, signals[CHANGED], 0); +} + +gboolean +_nm_connection_remove_setting(NMConnection *connection, GType setting_type) +{ + NMConnectionPrivate *priv; + NMSetting * setting; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + g_return_val_if_fail(g_type_is_a(setting_type, NM_TYPE_SETTING), FALSE); + + priv = NM_CONNECTION_GET_PRIVATE(connection); + setting = g_hash_table_lookup(priv->settings, _gtype_to_hash_key(setting_type)); + if (setting) { + g_signal_handlers_disconnect_by_func(setting, setting_changed_cb, connection); + g_hash_table_remove(priv->settings, _gtype_to_hash_key(setting_type)); + g_signal_emit(connection, signals[CHANGED], 0); + return TRUE; + } + return FALSE; +} + +/** + * nm_connection_remove_setting: + * @connection: a #NMConnection + * @setting_type: the #GType of the setting object to remove + * + * Removes the #NMSetting with the given #GType from the #NMConnection. This + * operation dereferences the #NMSetting object. + **/ +void +nm_connection_remove_setting(NMConnection *connection, GType setting_type) +{ + _nm_connection_remove_setting(connection, setting_type); +} + +static gpointer +_connection_get_setting(NMConnection *connection, GType setting_type) +{ + NMSetting *setting; + + nm_assert(NM_IS_CONNECTION(connection)); + nm_assert(g_type_is_a(setting_type, NM_TYPE_SETTING)); + + setting = g_hash_table_lookup(NM_CONNECTION_GET_PRIVATE(connection)->settings, + _gtype_to_hash_key(setting_type)); + nm_assert(!setting || G_TYPE_CHECK_INSTANCE_TYPE(setting, setting_type)); + return setting; +} + +static gpointer +_connection_get_setting_check(NMConnection *connection, GType setting_type) +{ + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + + return _connection_get_setting(connection, setting_type); +} + +/** + * nm_connection_get_setting: + * @connection: a #NMConnection + * @setting_type: the #GType of the setting object to return + * + * Gets the #NMSetting with the given #GType, if one has been previously added + * to the #NMConnection. + * + * Returns: (transfer none): the #NMSetting, or %NULL if no setting of that type was previously + * added to the #NMConnection + **/ +NMSetting * +nm_connection_get_setting(NMConnection *connection, GType setting_type) +{ + g_return_val_if_fail(g_type_is_a(setting_type, NM_TYPE_SETTING), NULL); + + return _connection_get_setting_check(connection, setting_type); +} + +NMSettingIPConfig * +nm_connection_get_setting_ip_config(NMConnection *connection, int addr_family) +{ + nm_assert_addr_family(addr_family); + + return NM_SETTING_IP_CONFIG(_connection_get_setting( + connection, + (addr_family == AF_INET) ? NM_TYPE_SETTING_IP4_CONFIG : NM_TYPE_SETTING_IP6_CONFIG)); +} + +/** + * nm_connection_get_setting_by_name: + * @connection: a #NMConnection + * @name: a setting name + * + * Gets the #NMSetting with the given name, if one has been previously added + * the #NMConnection. + * + * Returns: (transfer none): the #NMSetting, or %NULL if no setting with that name was previously + * added to the #NMConnection + **/ +NMSetting * +nm_connection_get_setting_by_name(NMConnection *connection, const char *name) +{ + GType type; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + + type = nm_setting_lookup_type(name); + return type ? _connection_get_setting(connection, type) : NULL; +} + +/*****************************************************************************/ + +gpointer /* (NMSetting *) */ +_nm_connection_check_main_setting(NMConnection *connection, + const char * setting_name, + GError ** error) +{ + NMSetting *setting; + + nm_assert(NM_IS_CONNECTION(connection)); + nm_assert(setting_name); + + if (!nm_connection_is_type(connection, setting_name)) { + nm_utils_error_set(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "connection type is not \"%s\"", + setting_name); + return NULL; + } + + setting = nm_connection_get_setting_by_name(connection, setting_name); + if (!setting) { + nm_utils_error_set(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "connection misses \"%s\" settings", + setting_name); + return NULL; + } + + return setting; +} + +/*****************************************************************************/ + +static gboolean +validate_permissions_type(GVariant *variant, GError **error) +{ + GVariant *s_con; + GVariant *permissions; + gboolean valid = TRUE; + + /* Ensure the connection::permissions item (if present) is the correct + * type, otherwise the g_object_set() will throw a warning and ignore the + * error, leaving us with no permissions. + */ + s_con = g_variant_lookup_value(variant, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + if (!s_con) + return TRUE; + + permissions = g_variant_lookup_value(s_con, NM_SETTING_CONNECTION_PERMISSIONS, NULL); + if (permissions) { + if (!g_variant_is_of_type(permissions, G_VARIANT_TYPE_STRING_ARRAY)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("wrong type; should be a list of strings.")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_PERMISSIONS); + valid = FALSE; + } + g_variant_unref(permissions); + } + + g_variant_unref(s_con); + return valid; +} + +/** + * _nm_connection_replace_settings: + * @connection: a #NMConnection + * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings + * @parse_flags: flags. + * @error: location to store error, or %NULL + * + * Replaces @connection's settings with @new_settings (which must be + * syntactically valid, and describe a known type of connection, but does not + * need to result in a connection that passes nm_connection_verify()). + * + * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not + * be deserialized (in which case @connection will be unchanged). + * Only exception is the NM_SETTING_PARSE_FLAGS_NORMALIZE flag: if normalization + * fails, the input @connection is already modified and the original settings + * are lost. + **/ +gboolean +_nm_connection_replace_settings(NMConnection * connection, + GVariant * new_settings, + NMSettingParseFlags parse_flags, + GError ** error) +{ + NMConnectionPrivate *priv; + GVariantIter iter; + const char * setting_name; + GVariant * setting_dict; + GSList * settings = NULL, *s; + gboolean changed, success; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + g_return_val_if_fail(g_variant_is_of_type(new_settings, NM_VARIANT_TYPE_CONNECTION), FALSE); + g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + + nm_assert(!NM_FLAGS_ANY(parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL)); + nm_assert(!NM_FLAGS_ALL(parse_flags, + NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT)); + + priv = NM_CONNECTION_GET_PRIVATE(connection); + + if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT) + && !validate_permissions_type(new_settings, error)) + return FALSE; + + g_variant_iter_init(&iter, new_settings); + while (g_variant_iter_next(&iter, "{&s@a{sv}}", &setting_name, &setting_dict)) { + gs_unref_variant GVariant *setting_dict_free = NULL; + GError * local = NULL; + NMSetting * setting; + GType type; + + setting_dict_free = setting_dict; + + type = nm_setting_lookup_type(setting_name); + if (type == G_TYPE_INVALID) { + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) + continue; + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("unknown setting name")); + g_prefix_error(error, "%s: ", setting_name); + g_slist_free_full(settings, g_object_unref); + return FALSE; + } + + for (s = settings; s; s = s->next) { + if (G_OBJECT_TYPE(s->data) == type) { + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("duplicate setting name")); + g_prefix_error(error, "%s: ", setting_name); + g_slist_free_full(settings, g_object_unref); + return FALSE; + } + /* last wins. */ + g_object_unref(s->data); + settings = g_slist_delete_link(settings, s); + break; + } + } + + setting = _nm_setting_new_from_dbus(type, setting_dict, new_settings, parse_flags, &local); + + if (!setting) { + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) + continue; + g_propagate_error(error, local); + g_slist_free_full(settings, g_object_unref); + return FALSE; + } + + settings = g_slist_prepend(settings, setting); + } + + if (g_hash_table_size(priv->settings) > 0) { + g_hash_table_foreach_remove(priv->settings, _setting_release_hfr, connection); + changed = TRUE; + } else + changed = (settings != NULL); + + /* Note: @settings might be empty in which case the connection + * has no NMSetting instances... which is fine, just something + * to be aware of. */ + for (s = settings; s; s = s->next) + _nm_connection_add_setting(connection, s->data); + + g_slist_free(settings); + + /* If verification/normalization fails, the original connection + * is already lost. From an API point of view, it would be nicer + * not to touch the input argument if we fail at the end. + * However, that would require creating a temporary connection + * to validate it first. As none of the caller cares about the + * state of the @connection when normalization fails, just do it + * this way. */ + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_NORMALIZE)) + success = nm_connection_normalize(connection, NULL, NULL, error); + else + success = TRUE; + + if (changed) + g_signal_emit(connection, signals[CHANGED], 0); + return success; +} + +/** + * nm_connection_replace_settings: + * @connection: a #NMConnection + * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings + * @error: location to store error, or %NULL + * + * Replaces @connection's settings with @new_settings (which must be + * syntactically valid, and describe a known type of connection, but does not + * need to result in a connection that passes nm_connection_verify()). + * + * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not + * be deserialized (in which case @connection will be unchanged). + **/ +gboolean +nm_connection_replace_settings(NMConnection *connection, GVariant *new_settings, GError **error) +{ + return _nm_connection_replace_settings(connection, + new_settings, + NM_SETTING_PARSE_FLAGS_NONE, + error); +} + +/** + * nm_connection_replace_settings_from_connection: + * @connection: a #NMConnection + * @new_connection: a #NMConnection to replace the settings of @connection with + * + * Deep-copies the settings of @new_connection and replaces the settings of @connection + * with the copied settings. + **/ +void +nm_connection_replace_settings_from_connection(NMConnection *connection, + NMConnection *new_connection) +{ + NMConnectionPrivate *priv, *new_priv; + GHashTableIter iter; + NMSetting * setting; + gboolean changed; + + g_return_if_fail(NM_IS_CONNECTION(connection)); + g_return_if_fail(NM_IS_CONNECTION(new_connection)); + + /* When 'connection' and 'new_connection' are the same object simply return + * in order not to destroy 'connection'. + */ + if (connection == new_connection) + return; + + /* No need to validate permissions like nm_connection_replace_settings() + * since we're dealing with an NMConnection which has already done that. + */ + + priv = NM_CONNECTION_GET_PRIVATE(connection); + new_priv = NM_CONNECTION_GET_PRIVATE(new_connection); + + if ((changed = g_hash_table_size(priv->settings) > 0)) + g_hash_table_foreach_remove(priv->settings, _setting_release_hfr, connection); + + if (g_hash_table_size(new_priv->settings)) { + g_hash_table_iter_init(&iter, new_priv->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) + _nm_connection_add_setting(connection, nm_setting_duplicate(setting)); + changed = TRUE; + } + + if (changed) + g_signal_emit(connection, signals[CHANGED], 0); +} + +/** + * nm_connection_clear_settings: + * @connection: a #NMConnection + * + * Deletes all of @connection's settings. + **/ +void +nm_connection_clear_settings(NMConnection *connection) +{ + NMConnectionPrivate *priv; + + g_return_if_fail(NM_IS_CONNECTION(connection)); + + priv = NM_CONNECTION_GET_PRIVATE(connection); + + if (g_hash_table_size(priv->settings) > 0) { + g_hash_table_foreach_remove(priv->settings, _setting_release_hfr, connection); + g_signal_emit(connection, signals[CHANGED], 0); + } +} + +/** + * nm_connection_compare: + * @a: a #NMConnection + * @b: a second #NMConnection to compare with the first + * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT + * + * Compares two #NMConnection objects for similarity, with comparison behavior + * modified by a set of flags. See nm_setting_compare() for a description of + * each flag's behavior. + * + * Returns: %TRUE if the comparison succeeds, %FALSE if it does not + **/ +gboolean +nm_connection_compare(NMConnection *a, NMConnection *b, NMSettingCompareFlags flags) +{ + GHashTableIter iter; + NMSetting * src; + + if (a == b) + return TRUE; + if (!a || !b) + return FALSE; + + /* B / A: ensure settings in B that are not in A make the comparison fail */ + if (g_hash_table_size(NM_CONNECTION_GET_PRIVATE(a)->settings) + != g_hash_table_size(NM_CONNECTION_GET_PRIVATE(b)->settings)) + return FALSE; + + /* A / B: ensure all settings in A match corresponding ones in B */ + g_hash_table_iter_init(&iter, NM_CONNECTION_GET_PRIVATE(a)->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &src)) { + NMSetting *cmp = nm_connection_get_setting(b, G_OBJECT_TYPE(src)); + + if (!cmp || !_nm_setting_compare(a, src, b, cmp, flags)) + return FALSE; + } + + return TRUE; +} + +static gboolean +diff_one_connection(NMConnection * a, + NMConnection * b, + NMSettingCompareFlags flags, + gboolean invert_results, + GHashTable * diffs) +{ + NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE(a); + GHashTableIter iter; + NMSetting * a_setting = NULL; + gboolean diff_found = FALSE; + + g_hash_table_iter_init(&iter, priv->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &a_setting)) { + NMSetting * b_setting = NULL; + const char *setting_name = nm_setting_get_name(a_setting); + GHashTable *results; + gboolean new_results = TRUE; + + if (b) + b_setting = nm_connection_get_setting(b, G_OBJECT_TYPE(a_setting)); + + results = g_hash_table_lookup(diffs, setting_name); + if (results) + new_results = FALSE; + + if (!_nm_setting_diff(a, a_setting, b, b_setting, flags, invert_results, &results)) + diff_found = TRUE; + + if (new_results && results) + g_hash_table_insert(diffs, g_strdup(setting_name), results); + } + + return diff_found; +} + +/** + * nm_connection_diff: + * @a: a #NMConnection + * @b: a second #NMConnection to compare with the first + * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT + * @out_settings: (element-type utf8 GLib.HashTable): if the + * connections differ, on return a hash table mapping setting names to + * second-level GHashTable (utf8 to guint32), which contains the key names that + * differ mapped to one or more of %NMSettingDiffResult as a bitfield + * + * Compares two #NMConnection objects for similarity, with comparison behavior + * modified by a set of flags. See nm_setting_compare() for a description of + * each flag's behavior. If the connections differ, settings and keys within + * each setting that differ are added to the returned @out_settings hash table. + * No values are returned, only key names. + * + * Returns: %TRUE if the connections contain the same values, %FALSE if they do + * not + **/ +gboolean +nm_connection_diff(NMConnection * a, + NMConnection * b, + NMSettingCompareFlags flags, + GHashTable ** out_settings) +{ + GHashTable *diffs; + gboolean diff_found = FALSE; + + g_return_val_if_fail(NM_IS_CONNECTION(a), FALSE); + g_return_val_if_fail(!out_settings || !*out_settings, FALSE); + g_return_val_if_fail(!b || NM_IS_CONNECTION(b), FALSE); + + if (a == b) + return TRUE; + + diffs = g_hash_table_new_full(nm_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_hash_table_destroy); + + /* Diff A to B, then B to A to capture keys in B that aren't in A */ + if (diff_one_connection(a, b, flags, FALSE, diffs)) + diff_found = TRUE; + if (b && diff_one_connection(b, a, flags, TRUE, diffs)) + diff_found = TRUE; + + nm_assert(diff_found == (g_hash_table_size(diffs) != 0)); + + if (g_hash_table_size(diffs) == 0) { + g_hash_table_destroy(diffs); + diffs = NULL; + } + + NM_SET_OUT(out_settings, diffs); + + return !diff_found; +} + +NMSetting * +_nm_connection_find_base_type_setting(NMConnection *connection) +{ + NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE(connection); + GHashTableIter iter; + NMSetting * setting = NULL; + NMSetting * s_iter; + NMSettingPriority setting_prio = NM_SETTING_PRIORITY_USER; + NMSettingPriority s_iter_prio; + + g_hash_table_iter_init(&iter, priv->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &s_iter)) { + s_iter_prio = _nm_setting_get_base_type_priority(s_iter); + if (s_iter_prio == NM_SETTING_PRIORITY_INVALID) + continue; + + if (setting) { + if (s_iter_prio > setting_prio) { + continue; + } else if (s_iter_prio == setting_prio) { + NMSettingConnection *s_con = nm_connection_get_setting_connection(connection); + const char * type; + + if (s_con) { + type = nm_setting_connection_get_connection_type(s_con); + if (type) + return nm_connection_get_setting_by_name(connection, type); + } + return NULL; + } + } + setting = s_iter; + setting_prio = s_iter_prio; + } + return setting; +} + +static gboolean +_normalize_connection_uuid(NMConnection *self) +{ + NMSettingConnection *s_con = nm_connection_get_setting_connection(self); + char uuid[37]; + + nm_assert(s_con); + + if (nm_setting_connection_get_uuid(s_con)) + return FALSE; + + g_object_set(s_con, NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf(uuid), NULL); + return TRUE; +} + +static gboolean +_normalize_connection_type(NMConnection *self) +{ + NMSettingConnection *s_con = nm_connection_get_setting_connection(self); + NMSetting * s_base = NULL; + const char * type; + + type = nm_setting_connection_get_connection_type(s_con); + + if (type) { + s_base = nm_connection_get_setting_by_name(self, type); + + if (!s_base) { + GType base_type = nm_setting_lookup_type(type); + + g_return_val_if_fail(base_type, FALSE); + nm_connection_add_setting(self, g_object_new(base_type, NULL)); + return TRUE; + } + } else { + s_base = _nm_connection_find_base_type_setting(self); + g_return_val_if_fail(s_base, FALSE); + + type = nm_setting_get_name(s_base); + g_object_set(s_con, NM_SETTING_CONNECTION_TYPE, type, NULL); + return TRUE; + } + + return FALSE; +} + +const char * +_nm_connection_detect_bluetooth_type(NMConnection *self) +{ + NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth(self); + + if (s_bt && nm_setting_bluetooth_get_connection_type(s_bt)) { + if (nm_connection_get_setting_gsm(self) || nm_connection_get_setting_cdma(self)) + return NM_SETTING_BLUETOOTH_TYPE_DUN; + if (nm_connection_get_setting_bridge(self)) + return NM_SETTING_BLUETOOTH_TYPE_NAP; + return NM_SETTING_BLUETOOTH_TYPE_PANU; + } + + /* NULL means the connection is not a bluetooth type, or it needs + * no normalization, as the type is set explicitly. */ + return NULL; +} + +const char * +_nm_connection_detect_slave_type(NMConnection *connection, NMSetting **out_s_port) +{ + NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE(connection); + GHashTableIter iter; + const char * slave_type = NULL; + NMSetting * s_port = NULL, *s_iter; + + g_hash_table_iter_init(&iter, priv->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &s_iter)) { + const char *name = nm_setting_get_name(s_iter); + const char *i_slave_type = NULL; + + if (!strcmp(name, NM_SETTING_BRIDGE_PORT_SETTING_NAME)) + i_slave_type = NM_SETTING_BRIDGE_SETTING_NAME; + else if (!strcmp(name, NM_SETTING_TEAM_PORT_SETTING_NAME)) + i_slave_type = NM_SETTING_TEAM_SETTING_NAME; + else if (!strcmp(name, NM_SETTING_OVS_PORT_SETTING_NAME)) + i_slave_type = NM_SETTING_OVS_BRIDGE_SETTING_NAME; + else if (!strcmp(name, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) + i_slave_type = NM_SETTING_OVS_PORT_SETTING_NAME; + else + continue; + + if (slave_type) { + /* there are more then one matching port types, cannot detect the slave type. */ + slave_type = NULL; + s_port = NULL; + break; + } + slave_type = i_slave_type; + s_port = s_iter; + } + + if (out_s_port) + *out_s_port = s_port; + return slave_type; +} + +static gboolean +_normalize_connection_slave_type(NMConnection *self) +{ + NMSettingConnection *s_con = nm_connection_get_setting_connection(self); + const char * slave_type, *port_type; + + if (!s_con) + return FALSE; + if (!nm_setting_connection_get_master(s_con)) + return FALSE; + + slave_type = nm_setting_connection_get_slave_type(s_con); + if (slave_type) { + if (_nm_setting_slave_type_is_valid(slave_type, &port_type) && port_type) { + NMSetting *s_port; + + s_port = nm_connection_get_setting_by_name(self, port_type); + if (!s_port) { + GType p_type = nm_setting_lookup_type(port_type); + + g_return_val_if_fail(p_type, FALSE); + nm_connection_add_setting(self, g_object_new(p_type, NULL)); + return TRUE; + } + } + } else { + if ((slave_type = _nm_connection_detect_slave_type(self, NULL))) { + g_object_set(s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, NULL); + return TRUE; + } + } + return FALSE; +} + +static gboolean +_normalize_ethernet_link_neg(NMConnection *self) +{ + NMSettingWired *s_wired = nm_connection_get_setting_wired(self); + + if (s_wired) { + guint32 speed = nm_setting_wired_get_speed(s_wired); + const char *duplex = nm_setting_wired_get_duplex(s_wired); + + if ((speed && !duplex) || (!speed && duplex)) { + speed = 0; + duplex = NULL; + g_object_set(s_wired, + NM_SETTING_WIRED_SPEED, + (guint) speed, + NM_SETTING_WIRED_DUPLEX, + duplex, + NULL); + return TRUE; + } + } + + return FALSE; +} + +/** + * _supports_addr_family: + * @self: a #NMConnection + * @family: AF_* + * + * Check whether the connection supports certain L3 address family, + * in order to be able to tell whether is should have the corresponding + * setting ("ipv4" for AF_INET and "ipv6" for AF_INET6). + * + * If AF_UNSPEC is given, then the function checks whether the connection + * supports any L3 configuration at all. + * + * Returns: %TRUE if the AF is supported, %FALSE otherwise + **/ +static gboolean +_supports_addr_family(NMConnection *self, int family) +{ + const char * connection_type = nm_connection_get_connection_type(self); + NMSettingConnection *s_con; + + g_return_val_if_fail(connection_type, TRUE); + if (strcmp(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) + return TRUE; + if (strcmp(connection_type, NM_SETTING_WPAN_SETTING_NAME) == 0) + return FALSE; + if (strcmp(connection_type, NM_SETTING_6LOWPAN_SETTING_NAME) == 0) + return family == AF_INET6 || family == AF_UNSPEC; + if ((s_con = nm_connection_get_setting_connection(self)) + && (nm_streq0(nm_setting_connection_get_slave_type(s_con), NM_SETTING_VRF_SETTING_NAME))) + return TRUE; + + return !nm_setting_connection_get_master(nm_connection_get_setting_connection(self)); +} + +static gboolean +_normalize_ip_config(NMConnection *self, GHashTable *parameters) +{ + NMSettingIPConfig *s_ip4, *s_ip6; + NMSettingProxy * s_proxy; + NMSetting * setting; + gboolean changed = FALSE; + guint num, i; + + s_ip4 = nm_connection_get_setting_ip4_config(self); + s_ip6 = nm_connection_get_setting_ip6_config(self); + s_proxy = nm_connection_get_setting_proxy(self); + + if (_supports_addr_family(self, AF_INET)) { + if (!s_ip4) { + const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; + + if (nm_connection_is_type(self, NM_SETTING_WIREGUARD_SETTING_NAME)) + default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + + /* But if no IP4 setting was specified, assume the caller was just + * being lazy and use the default method. + */ + setting = nm_setting_ip4_config_new(); + + g_object_set(setting, NM_SETTING_IP_CONFIG_METHOD, default_ip4_method, NULL); + nm_connection_add_setting(self, setting); + changed = TRUE; + } else { + if (nm_setting_ip_config_get_gateway(s_ip4) + && nm_setting_ip_config_get_never_default(s_ip4)) { + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, NULL, NULL); + changed = TRUE; + } + + if (nm_streq0(nm_setting_ip_config_get_method(s_ip4), + NM_SETTING_IP4_CONFIG_METHOD_DISABLED) + && !nm_setting_ip_config_get_may_fail(s_ip4)) { + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); + changed = TRUE; + } + + num = nm_setting_ip_config_get_num_addresses(s_ip4); + if (num > 1 + && nm_streq0(nm_setting_ip_config_get_method(s_ip4), + NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { + for (i = num - 1; i > 0; i--) + nm_setting_ip_config_remove_address(s_ip4, i); + changed = TRUE; + } + } + } else { + if (s_ip4) { + nm_connection_remove_setting(self, NM_TYPE_SETTING_IP4_CONFIG); + changed = TRUE; + } + } + + if (_supports_addr_family(self, AF_INET6)) { + if (!s_ip6) { + const char *default_ip6_method = NULL; + + if (parameters) + default_ip6_method = + g_hash_table_lookup(parameters, + NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD); + if (!default_ip6_method) { + if (nm_connection_is_type(self, NM_SETTING_WIREGUARD_SETTING_NAME)) + default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + else + default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; + } + + /* If no IP6 setting was specified, then assume that means IP6 config is + * allowed to fail. + */ + setting = nm_setting_ip6_config_new(); + + g_object_set(setting, + NM_SETTING_IP_CONFIG_METHOD, + default_ip6_method, + NM_SETTING_IP_CONFIG_MAY_FAIL, + TRUE, + NULL); + nm_connection_add_setting(self, setting); + changed = TRUE; + } else { + const char *token; + + token = nm_setting_ip6_config_get_token((NMSettingIP6Config *) s_ip6); + if (token + && nm_setting_ip6_config_get_addr_gen_mode((NMSettingIP6Config *) s_ip6) + == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { + struct in6_addr i6_token; + char normalized[NM_UTILS_INET_ADDRSTRLEN]; + + if (inet_pton(AF_INET6, token, &i6_token) == 1 + && _nm_utils_inet6_is_token(&i6_token)) { + _nm_utils_inet6_ntop(&i6_token, normalized); + if (g_strcmp0(token, normalized)) { + g_object_set(s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, normalized, NULL); + changed = TRUE; + } + } + } + + if (nm_setting_ip_config_get_gateway(s_ip6) + && nm_setting_ip_config_get_never_default(s_ip6)) { + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, NULL, NULL); + changed = TRUE; + } + + if (NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip6), + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED) + && !nm_setting_ip_config_get_may_fail(s_ip6)) { + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); + changed = TRUE; + } + } + } else { + if (s_ip6) { + nm_connection_remove_setting(self, NM_TYPE_SETTING_IP6_CONFIG); + changed = TRUE; + } + } + + if (_supports_addr_family(self, AF_UNSPEC)) { + if (!s_proxy) { + setting = nm_setting_proxy_new(); + nm_connection_add_setting(self, setting); + changed = TRUE; + } + } else { + if (s_proxy) { + nm_connection_remove_setting(self, NM_TYPE_SETTING_PROXY); + changed = TRUE; + } + } + + return changed; +} + +static gboolean +_normalize_infiniband_mtu(NMConnection *self) +{ + NMSettingInfiniband *s_infini = nm_connection_get_setting_infiniband(self); + + if (!s_infini || nm_setting_infiniband_get_mtu(s_infini) <= NM_INFINIBAND_MAX_MTU + || !NM_IN_STRSET(nm_setting_infiniband_get_transport_mode(s_infini), + "datagram", + "connected")) + return FALSE; + + g_object_set(s_infini, NM_SETTING_INFINIBAND_MTU, (guint) NM_INFINIBAND_MAX_MTU, NULL); + return TRUE; +} + +static gboolean +_normalize_bond_mode(NMConnection *self) +{ + NMSettingBond *s_bond = nm_connection_get_setting_bond(self); + + /* Convert mode from numeric to string notation */ + if (s_bond) { + const char *mode = nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_MODE); + int mode_int = nm_utils_bond_mode_string_to_int(mode); + + if (mode_int != -1) { + const char *mode_new = nm_utils_bond_mode_int_to_string(mode_int); + + if (!nm_streq0(mode_new, mode)) { + nm_setting_bond_add_option(s_bond, NM_SETTING_BOND_OPTION_MODE, mode_new); + return TRUE; + } + } + } + return FALSE; +} + +static gboolean +_normalize_bond_options(NMConnection *self) +{ + NMSettingBond *s_bond = nm_connection_get_setting_bond(self); + gboolean changed = FALSE; + const char * name, *mode_str; + NMBondMode mode; + guint32 num, i; + + /* Strip away unsupported options for current mode */ + if (s_bond) { + mode_str = nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_MODE); + mode = _nm_setting_bond_mode_from_string(mode_str); + if (mode == NM_BOND_MODE_UNKNOWN) + return FALSE; +again: + num = nm_setting_bond_get_num_options(s_bond); + for (i = 0; i < num; i++) { + if (nm_setting_bond_get_option(s_bond, i, &name, NULL) + && !_nm_setting_bond_option_supported(name, mode)) { + nm_setting_bond_remove_option(s_bond, name); + changed = TRUE; + goto again; + } + } + } + + return changed; +} + +static gboolean +_normalize_wireless_mac_address_randomization(NMConnection *self) +{ + NMSettingWireless * s_wifi = nm_connection_get_setting_wireless(self); + const char * cloned_mac_address; + NMSettingMacRandomization mac_address_randomization; + + if (!s_wifi) + return FALSE; + + mac_address_randomization = nm_setting_wireless_get_mac_address_randomization(s_wifi); + if (!NM_IN_SET(mac_address_randomization, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + NM_SETTING_MAC_RANDOMIZATION_NEVER, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS)) + return FALSE; + + cloned_mac_address = nm_setting_wireless_get_cloned_mac_address(s_wifi); + if (cloned_mac_address) { + if (nm_streq(cloned_mac_address, "random")) { + if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS) + return FALSE; + mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_ALWAYS; + } else if (nm_streq(cloned_mac_address, "permanent")) { + if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_NEVER) + return FALSE; + mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER; + } else { + if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) + return FALSE; + mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_DEFAULT; + } + g_object_set(s_wifi, + NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, + mac_address_randomization, + NULL); + return TRUE; + } + if (mac_address_randomization != NM_SETTING_MAC_RANDOMIZATION_DEFAULT) { + g_object_set(s_wifi, + NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, + mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS ? "random" + : "permanent", + NULL); + return TRUE; + } + return FALSE; +} + +static gboolean +_normalize_macsec(NMConnection *self) +{ + NMSettingMacsec *s_macsec = nm_connection_get_setting_macsec(self); + gboolean changed = FALSE; + + if (!s_macsec) + return FALSE; + + if (nm_setting_macsec_get_mode(s_macsec) != NM_SETTING_MACSEC_MODE_PSK) { + if (nm_setting_macsec_get_mka_cak(s_macsec)) { + g_object_set(s_macsec, NM_SETTING_MACSEC_MKA_CAK, NULL, NULL); + changed = TRUE; + } + if (nm_setting_macsec_get_mka_ckn(s_macsec)) { + g_object_set(s_macsec, NM_SETTING_MACSEC_MKA_CKN, NULL, NULL); + changed = TRUE; + } + } + + return changed; +} + +static gboolean +_normalize_team_config(NMConnection *self) +{ + NMSettingTeam *s_team = nm_connection_get_setting_team(self); + + if (s_team) { + const char *config = nm_setting_team_get_config(s_team); + + if (config && !*config) { + g_object_set(s_team, NM_SETTING_TEAM_CONFIG, NULL, NULL); + return TRUE; + } + } + return FALSE; +} + +static gboolean +_normalize_team_port_config(NMConnection *self) +{ + NMSettingTeamPort *s_team_port = nm_connection_get_setting_team_port(self); + + if (s_team_port) { + const char *config = nm_setting_team_port_get_config(s_team_port); + + if (config && !*config) { + g_object_set(s_team_port, NM_SETTING_TEAM_PORT_CONFIG, NULL, NULL); + return TRUE; + } + } + return FALSE; +} + +static gboolean +_normalize_bluetooth_type(NMConnection *self) +{ + const char *type = _nm_connection_detect_bluetooth_type(self); + + if (type) { + g_object_set(nm_connection_get_setting_bluetooth(self), + NM_SETTING_BLUETOOTH_TYPE, + type, + NULL); + return TRUE; + } + return FALSE; +} + +static gboolean +_normalize_ovs_interface_type(NMConnection *self) +{ + NMSettingOvsInterface *s_ovs_interface = nm_connection_get_setting_ovs_interface(self); + gboolean modified; + int v; + + if (!s_ovs_interface) + return FALSE; + + v = _nm_setting_ovs_interface_verify_interface_type( + s_ovs_interface, + nm_setting_ovs_interface_get_interface_type(s_ovs_interface), + self, + TRUE, + &modified, + NULL, + NULL); + if (v != TRUE) + g_return_val_if_reached(modified); + + return modified; +} + +static gboolean +_normalize_ip_tunnel_wired_setting(NMConnection *self) +{ + NMSettingIPTunnel *s_ip_tunnel; + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel(self); + if (!s_ip_tunnel) + return FALSE; + + if (nm_connection_get_setting_wired(self) + && !NM_IN_SET(nm_setting_ip_tunnel_get_mode(s_ip_tunnel), + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { + nm_connection_remove_setting(self, NM_TYPE_SETTING_WIRED); + return TRUE; + } + + return FALSE; +} + +static gboolean +_normalize_sriov_vf_order(NMConnection *self) +{ + NMSettingSriov *s_sriov; + + s_sriov = NM_SETTING_SRIOV(nm_connection_get_setting(self, NM_TYPE_SETTING_SRIOV)); + if (!s_sriov) + return FALSE; + + return _nm_setting_sriov_sort_vfs(s_sriov); +} + +static gboolean +_normalize_bridge_vlan_order(NMConnection *self) +{ + NMSettingBridge *s_bridge; + + s_bridge = nm_connection_get_setting_bridge(self); + if (!s_bridge) + return FALSE; + + return _nm_setting_bridge_sort_vlans(s_bridge); +} + +static gboolean +_normalize_bridge_port_vlan_order(NMConnection *self) +{ + NMSettingBridgePort *s_port; + + s_port = nm_connection_get_setting_bridge_port(self); + if (!s_port) + return FALSE; + + return _nm_setting_bridge_port_sort_vlans(s_port); +} + +static gboolean +_normalize_gsm_auto_config(NMConnection *self) +{ + NMSettingGsm *s_gsm; + + s_gsm = nm_connection_get_setting_gsm(self); + if (!s_gsm) + return FALSE; + + if (!nm_setting_gsm_get_auto_config(s_gsm)) + return FALSE; + + if (!nm_setting_gsm_get_apn(s_gsm) && !nm_setting_gsm_get_username(s_gsm) + && !nm_setting_gsm_get_password(s_gsm)) + return FALSE; + + g_object_set(s_gsm, NM_SETTING_GSM_AUTO_CONFIG, FALSE, NULL); + return TRUE; +} + +static gboolean +_normalize_required_settings(NMConnection *self) +{ + NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth(self); + NMSetting * s_bridge; + gboolean changed = FALSE; + + if (nm_connection_get_setting_vlan(self)) { + if (!nm_connection_get_setting_wired(self)) { + nm_connection_add_setting(self, nm_setting_wired_new()); + changed = TRUE; + } + } + if (s_bt + && nm_streq0(nm_setting_bluetooth_get_connection_type(s_bt), + NM_SETTING_BLUETOOTH_TYPE_NAP)) { + if (!nm_connection_get_setting_bridge(self)) { + s_bridge = nm_setting_bridge_new(); + g_object_set(s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL); + nm_connection_add_setting(self, s_bridge); + changed = TRUE; + } + } + return changed; +} + +static gboolean +_normalize_invalid_slave_port_settings(NMConnection *self) +{ + NMSettingConnection *s_con = nm_connection_get_setting_connection(self); + const char * slave_type; + gboolean changed = FALSE; + + slave_type = nm_setting_connection_get_slave_type(s_con); + + if (!nm_streq0(slave_type, NM_SETTING_BRIDGE_SETTING_NAME) + && _nm_connection_remove_setting(self, NM_TYPE_SETTING_BRIDGE_PORT)) + changed = TRUE; + + if (!nm_streq0(slave_type, NM_SETTING_TEAM_SETTING_NAME) + && _nm_connection_remove_setting(self, NM_TYPE_SETTING_TEAM_PORT)) + changed = TRUE; + + return changed; +} + +/** + * nm_connection_verify: + * @connection: the #NMConnection to verify + * @error: location to store error, or %NULL + * + * Validates the connection and all its settings. Each setting's properties + * have allowed values, and some values are dependent on other values. For + * example, if a Wi-Fi connection is security enabled, the #NMSettingWireless + * setting object's 'security' property must contain the setting name of the + * #NMSettingWirelessSecurity object, which must also be present in the + * connection for the connection to be valid. As another example, the + * #NMSettingWired object's 'mac-address' property must be a validly formatted + * MAC address. The returned #GError contains information about which + * setting and which property failed validation, and how it failed validation. + * + * Returns: %TRUE if the connection is valid, %FALSE if it is not + **/ +gboolean +nm_connection_verify(NMConnection *connection, GError **error) +{ + NMSettingVerifyResult result; + + result = _nm_connection_verify(connection, error); + + /* we treat normalizable connections as valid. */ + if (result == NM_SETTING_VERIFY_NORMALIZABLE) + g_clear_error(error); + + return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE; +} + +NMSettingVerifyResult +_nm_connection_verify(NMConnection *connection, GError **error) +{ + NMSettingIPConfig *s_ip4, *s_ip6; + NMSettingProxy * s_proxy; + gs_free NMSetting **settings = NULL; + gs_free_error GError *normalizable_error = NULL; + NMSettingVerifyResult normalizable_error_type = NM_SETTING_VERIFY_SUCCESS; + guint i; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), NM_SETTING_VERIFY_ERROR); + g_return_val_if_fail(!error || !*error, NM_SETTING_VERIFY_ERROR); + + settings = nm_connection_get_settings(connection, NULL); + if (!settings || !NM_IS_SETTING_CONNECTION(settings[0])) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("setting not found")); + g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return NM_SETTING_VERIFY_ERROR; + } + + for (i = 0; settings[i]; i++) { + GError * verify_error = NULL; + NMSettingVerifyResult verify_result; + + nm_assert(NM_IS_SETTING(settings[i])); + nm_assert(NM_IS_SETTING_CONNECTION(settings[i]) == (i == 0)); + + /* verify all settings. We stop if we find the first non-normalizable + * @NM_SETTING_VERIFY_ERROR. If we find normalizable errors we continue + * but remember the error to return it to the user. + * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR has a higher priority then + * @NM_SETTING_VERIFY_NORMALIZABLE, so, if we encounter such an error type, + * we remember it instead (to return it as output). + **/ + verify_result = _nm_setting_verify(settings[i], connection, &verify_error); + if (verify_result == NM_SETTING_VERIFY_NORMALIZABLE + || verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR) { + if (verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR + && normalizable_error_type == NM_SETTING_VERIFY_NORMALIZABLE) { + /* NORMALIZABLE_ERROR has higher priority. */ + g_clear_error(&normalizable_error); + } + if (!normalizable_error) { + g_propagate_error(&normalizable_error, verify_error); + verify_error = NULL; + normalizable_error_type = verify_result; + } + } else if (verify_result != NM_SETTING_VERIFY_SUCCESS) { + g_propagate_error(error, verify_error); + g_return_val_if_fail(verify_result == NM_SETTING_VERIFY_ERROR, NM_SETTING_VERIFY_ERROR); + return NM_SETTING_VERIFY_ERROR; + } + g_clear_error(&verify_error); + } + + s_ip4 = nm_connection_get_setting_ip4_config(connection); + s_ip6 = nm_connection_get_setting_ip6_config(connection); + s_proxy = nm_connection_get_setting_proxy(connection); + + nm_assert(normalizable_error_type != NM_SETTING_VERIFY_ERROR); + if (NM_IN_SET(normalizable_error_type, + NM_SETTING_VERIFY_SUCCESS, + NM_SETTING_VERIFY_NORMALIZABLE)) { + if (_supports_addr_family(connection, AF_INET)) { + if (!s_ip4 && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { + g_set_error_literal(&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("setting is required for non-slave connections")); + g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME); + + /* having a master without IP config was not a verify() error, accept + * it for backward compatibility. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; + } + } else { + if (s_ip4) { + g_clear_error(&normalizable_error); + g_set_error_literal(&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("setting not allowed in slave connection")); + g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME); + /* having a slave with IP config *was* and is a verify() error. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + } + + if (_supports_addr_family(connection, AF_INET6)) { + if (!s_ip6 && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { + g_set_error_literal(&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("setting is required for non-slave connections")); + g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME); + + /* having a master without IP config was not a verify() error, accept + * it for backward compatibility. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; + } + } else { + if (s_ip6) { + g_clear_error(&normalizable_error); + g_set_error_literal(&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("setting not allowed in slave connection")); + g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME); + /* having a slave with IP config *was* and is a verify() error. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + } + + if (_supports_addr_family(connection, AF_UNSPEC)) { + if (!s_proxy && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { + g_set_error_literal(&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("setting is required for non-slave connections")); + g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_PROXY_SETTING_NAME); + + /* having a master without proxy config was not a verify() error, accept + * it for backward compatibility. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; + } + } else { + if (s_proxy) { + g_clear_error(&normalizable_error); + g_set_error_literal(&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("setting not allowed in slave connection")); + g_prefix_error(&normalizable_error, "%s: ", NM_SETTING_PROXY_SETTING_NAME); + /* having a slave with proxy config *was* and is a verify() error. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + } + } + + if (normalizable_error_type != NM_SETTING_VERIFY_SUCCESS) { + g_propagate_error(error, normalizable_error); + normalizable_error = NULL; + return normalizable_error_type; + } + + return NM_SETTING_VERIFY_SUCCESS; +} + +/** + * nm_connection_verify_secrets: + * @connection: the #NMConnection to verify in + * @error: location to store error, or %NULL + * + * Verifies the secrets in the connection. + * + * Returns: %TRUE if the secrets are valid, %FALSE if they are not + * + * Since: 1.2 + **/ +gboolean +nm_connection_verify_secrets(NMConnection *connection, GError **error) +{ + GHashTableIter iter; + NMSetting * setting; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + + g_hash_table_iter_init(&iter, NM_CONNECTION_GET_PRIVATE(connection)->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) { + if (!nm_setting_verify_secrets(setting, connection, error)) + return FALSE; + } + return TRUE; +} + +static gboolean +_connection_normalize(NMConnection *connection, + GHashTable * parameters, + gboolean * modified, + GError ** error) +{ + NMSettingVerifyResult success; + gboolean was_modified; + +#if NM_MORE_ASSERTS > 10 + /* only call this _nm_connection_verify() confirms that the connection + * requires normalization and is normalizable. */ + nm_assert(NM_IN_SET(_nm_connection_verify(connection, NULL), + NM_SETTING_VERIFY_NORMALIZABLE, + NM_SETTING_VERIFY_NORMALIZABLE_ERROR)); +#endif + + /* Try to perform all kind of normalizations on the settings to fix it. + * We only do this, after verifying that the connection contains no un-normalizable + * errors, because in that case we rather fail without touching the settings. */ + + was_modified = FALSE; + + was_modified |= _normalize_connection_uuid(connection); + was_modified |= _normalize_connection_type(connection); + was_modified |= _normalize_connection_slave_type(connection); + was_modified |= _normalize_required_settings(connection); + was_modified |= _normalize_invalid_slave_port_settings(connection); + was_modified |= _normalize_ip_config(connection, parameters); + was_modified |= _normalize_ethernet_link_neg(connection); + was_modified |= _normalize_infiniband_mtu(connection); + was_modified |= _normalize_bond_mode(connection); + was_modified |= _normalize_bond_options(connection); + was_modified |= _normalize_wireless_mac_address_randomization(connection); + was_modified |= _normalize_macsec(connection); + was_modified |= _normalize_team_config(connection); + was_modified |= _normalize_team_port_config(connection); + was_modified |= _normalize_bluetooth_type(connection); + was_modified |= _normalize_ovs_interface_type(connection); + was_modified |= _normalize_ip_tunnel_wired_setting(connection); + was_modified |= _normalize_sriov_vf_order(connection); + was_modified |= _normalize_bridge_vlan_order(connection); + was_modified |= _normalize_bridge_port_vlan_order(connection); + was_modified |= _normalize_gsm_auto_config(connection); + + was_modified = !!was_modified; + + /* Verify anew */ + success = _nm_connection_verify(connection, error); + + NM_SET_OUT(modified, was_modified); + + if (success != NM_SETTING_VERIFY_SUCCESS) { + /* we would expect, that after normalization, the connection can be verified. + * Also treat NM_SETTING_VERIFY_NORMALIZABLE as failure, because there is something + * odd going on. */ + if (error && !*error) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("Unexpected failure to normalize the connection")); + } + g_warning("connection did not verify after normalization: %s", + error ? (*error)->message : "??"); + g_return_val_if_reached(FALSE); + } + + /* we would expect, that the connection was modified during normalization. */ + g_return_val_if_fail(was_modified, TRUE); + + return TRUE; +} + +/** + * nm_connection_normalize: + * @connection: the #NMConnection to normalize + * @parameters: (allow-none) (element-type utf8 gpointer): a #GHashTable with + * normalization parameters to allow customization of the normalization by providing + * specific arguments. Unknown arguments will be ignored and the default will be + * used. The keys must be strings compared with g_str_equal() function. + * The values are opaque and depend on the parameter name. + * @modified: (out) (allow-none): outputs whether any settings were modified. + * @error: location to store error, or %NULL. Contains the reason, + * why the connection is invalid, if the function returns an error. + * + * Does some basic normalization and fixup of well known inconsistencies + * and deprecated fields. If the connection was modified in any way, + * the output parameter @modified is set %TRUE. + * + * Finally the connection will be verified and %TRUE returns if the connection + * is valid. As this function only performs some specific normalization steps + * it cannot repair all connections. If the connection has errors that + * cannot be normalized, the connection will not be modified. + * + * Returns: %TRUE if the connection is valid, %FALSE if it is not + **/ +gboolean +nm_connection_normalize(NMConnection *connection, + GHashTable * parameters, + gboolean * modified, + GError ** error) +{ + NMSettingVerifyResult success; + gs_free_error GError *normalizable_error = NULL; + + success = _nm_connection_verify(connection, &normalizable_error); + + if (!NM_IN_SET(success, NM_SETTING_VERIFY_NORMALIZABLE, NM_SETTING_VERIFY_NORMALIZABLE_ERROR)) { + if (normalizable_error) { + nm_assert(success == NM_SETTING_VERIFY_ERROR); + g_propagate_error(error, g_steal_pointer(&normalizable_error)); + } else + nm_assert(success == NM_SETTING_VERIFY_SUCCESS); + + NM_SET_OUT(modified, FALSE); + + if (success != NM_SETTING_VERIFY_SUCCESS) { + if (error && !*error) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("Unexpected failure to verify the connection")); + return FALSE; + } + return FALSE; + } + + if (error && *error) + return FALSE; + return TRUE; + } + + return _connection_normalize(connection, parameters, modified, error); +} + +gboolean +_nm_connection_ensure_normalized(NMConnection * connection, + gboolean allow_modify, + const char * expected_uuid, + gboolean coerce_uuid, + NMConnection **out_connection_clone, + GError ** error) +{ + gs_unref_object NMConnection *connection_clone = NULL; + gs_free_error GError *local = NULL; + NMSettingVerifyResult vresult; + + nm_assert(NM_IS_CONNECTION(connection)); + nm_assert(!out_connection_clone || !*out_connection_clone); + nm_assert(!expected_uuid || nm_utils_is_uuid(expected_uuid)); + + if (expected_uuid) { + if (nm_streq0(expected_uuid, nm_connection_get_uuid(connection))) + expected_uuid = NULL; + else if (!coerce_uuid || (!allow_modify && !out_connection_clone)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unexpected uuid %s instead of %s"), + nm_connection_get_uuid(connection), + expected_uuid); + return FALSE; + } + } + + vresult = _nm_connection_verify(connection, &local); + if (vresult != NM_SETTING_VERIFY_SUCCESS) { + if (!NM_IN_SET(vresult, + NM_SETTING_VERIFY_NORMALIZABLE, + NM_SETTING_VERIFY_NORMALIZABLE_ERROR)) { + g_propagate_error(error, g_steal_pointer(&local)); + return FALSE; + } + if (!allow_modify) { + if (!out_connection_clone) { + /* even NM_SETTING_VERIFY_NORMALIZABLE is treated as an error. We could normalize, + * but are not allowed to (and no out argument is provided for cloning). */ + g_propagate_error(error, g_steal_pointer(&local)); + return FALSE; + } + connection_clone = nm_simple_connection_new_clone(connection); + connection = connection_clone; + } + if (!_connection_normalize(connection, NULL, NULL, error)) + g_return_val_if_reached(FALSE); + } + + if (expected_uuid) { + NMSettingConnection *s_con; + + if (!allow_modify && !connection_clone) { + nm_assert(out_connection_clone); + connection_clone = nm_simple_connection_new_clone(connection); + connection = connection_clone; + } + s_con = nm_connection_get_setting_connection(connection); + g_object_set(s_con, NM_SETTING_CONNECTION_UUID, expected_uuid, NULL); + } + + NM_SET_OUT(out_connection_clone, g_steal_pointer(&connection_clone)); + return TRUE; +} + +/*****************************************************************************/ + +#if NM_MORE_ASSERTS +static void +_nmtst_connection_unchanging_changed_cb(NMConnection *connection, gpointer user_data) +{ + nm_assert_not_reached(); +} + +static void +_nmtst_connection_unchanging_secrets_updated_cb(NMConnection *connection, + const char * setting_name, + gpointer user_data) +{ + nm_assert_not_reached(); +} + +const char _nmtst_connection_unchanging_user_data = 0; + +void +nmtst_connection_assert_unchanging(NMConnection *connection) +{ + if (!connection) + return; + + nm_assert(NM_IS_CONNECTION(connection)); + + if (g_signal_handler_find(connection, + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + (gpointer) &_nmtst_connection_unchanging_user_data) + != 0) { + /* avoid connecting the assertion handler multiple times. */ + return; + } + + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + G_CALLBACK(_nmtst_connection_unchanging_changed_cb), + (gpointer) &_nmtst_connection_unchanging_user_data); + g_signal_connect(connection, + NM_CONNECTION_SECRETS_CLEARED, + G_CALLBACK(_nmtst_connection_unchanging_changed_cb), + (gpointer) &_nmtst_connection_unchanging_user_data); + g_signal_connect(connection, + NM_CONNECTION_SECRETS_UPDATED, + G_CALLBACK(_nmtst_connection_unchanging_secrets_updated_cb), + (gpointer) &_nmtst_connection_unchanging_user_data); +} +#endif + +/*****************************************************************************/ + +/** + * nm_connection_update_secrets: + * @connection: the #NMConnection + * @setting_name: the setting object name to which the secrets apply + * @secrets: a #GVariant of secrets, of type %NM_VARIANT_TYPE_CONNECTION + * or %NM_VARIANT_TYPE_SETTING + * @error: location to store error, or %NULL + * + * Update the specified setting's secrets, given a dictionary of secrets + * intended for that setting (deserialized from D-Bus for example). Will also + * extract the given setting's secrets hash if given a connection dictionary. + * If @setting_name is %NULL, expects a fully serialized #NMConnection as + * returned by nm_connection_to_dbus() and will update all secrets from all + * settings contained in @secrets. + * + * Returns: %TRUE if the secrets were successfully updated, %FALSE if the update + * failed (tried to update secrets for a setting that doesn't exist, etc) + **/ +gboolean +nm_connection_update_secrets(NMConnection *connection, + const char * setting_name, + GVariant * secrets, + GError ** error) +{ + NMSetting * setting; + gboolean success = TRUE; + gboolean updated = FALSE; + GVariant * setting_dict = NULL; + GVariantIter iter; + const char * key; + gboolean full_connection; + int success_detail; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + + full_connection = g_variant_is_of_type(secrets, NM_VARIANT_TYPE_CONNECTION); + + g_return_val_if_fail(full_connection || g_variant_is_of_type(secrets, NM_VARIANT_TYPE_SETTING), + FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + g_return_val_if_fail(setting_name || full_connection, FALSE); + + /* Empty @secrets means success */ + if (g_variant_n_children(secrets) == 0) + return TRUE; + + if (setting_name) { + /* Update just one setting's secrets */ + setting = nm_connection_get_setting_by_name(connection, setting_name); + if (!setting) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_SETTING_NOT_FOUND, + setting_name); + return FALSE; + } + + if (full_connection) { + setting_dict = g_variant_lookup_value(secrets, setting_name, NM_VARIANT_TYPE_SETTING); + if (!setting_dict) { + /* The connection dictionary didn't contain any secrets for + * @setting_name; just return success. + */ + return TRUE; + } + } + + g_signal_handlers_block_by_func(setting, (GCallback) setting_changed_cb, connection); + success_detail = _nm_setting_update_secrets(setting, setting_dict ?: secrets, error); + g_signal_handlers_unblock_by_func(setting, (GCallback) setting_changed_cb, connection); + + nm_clear_pointer(&setting_dict, g_variant_unref); + + if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) { + nm_assert(!error || *error); + return FALSE; + } + if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) + updated = TRUE; + } else { + /* check first, whether all the settings exist... */ + g_variant_iter_init(&iter, secrets); + while (g_variant_iter_next(&iter, "{&s@a{sv}}", &key, NULL)) { + setting = nm_connection_get_setting_by_name(connection, key); + if (!setting) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_SETTING_NOT_FOUND, + key); + return FALSE; + } + } + + /* Update each setting with any secrets from the connection dictionary */ + g_variant_iter_init(&iter, secrets); + while (g_variant_iter_next(&iter, "{&s@a{sv}}", &key, &setting_dict)) { + gs_free_error GError *local = NULL; + + /* Update the secrets for this setting */ + setting = nm_connection_get_setting_by_name(connection, key); + + g_signal_handlers_block_by_func(setting, (GCallback) setting_changed_cb, connection); + success_detail = + _nm_setting_update_secrets(setting, setting_dict, error ? &local : NULL); + g_signal_handlers_unblock_by_func(setting, (GCallback) setting_changed_cb, connection); + + g_variant_unref(setting_dict); + + if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) { + if (success) { + if (error) { + nm_assert(local); + g_propagate_error(error, g_steal_pointer(&local)); + error = NULL; + } else + nm_assert(!local); + success = FALSE; + } + break; + } + if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) + updated = TRUE; + } + } + + if (updated) + g_signal_emit(connection, signals[SECRETS_UPDATED], 0, setting_name); + + return success; +} + +/** + * nm_connection_need_secrets: + * @connection: the #NMConnection + * @hints: (out) (element-type utf8) (allow-none) (transfer container): + * the address of a pointer to a #GPtrArray, initialized to %NULL, which on + * return points to an allocated #GPtrArray containing the property names of + * secrets of the #NMSetting which may be required; the caller owns the array + * and must free the array itself with g_ptr_array_free(), but not free its + * elements + * + * Returns the name of the first setting object in the connection which would + * need secrets to make a successful connection. The returned hints are only + * intended as a guide to what secrets may be required, because in some + * circumstances, there is no way to conclusively determine exactly which + * secrets are needed. + * + * Returns: the setting name of the #NMSetting object which has invalid or + * missing secrets + **/ +const char * +nm_connection_need_secrets(NMConnection *connection, GPtrArray **hints) +{ + NMConnectionPrivate *priv; + GHashTableIter hiter; + GSList * settings = NULL; + GSList * iter; + const char * name = NULL; + NMSetting * setting; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + if (hints) + g_return_val_if_fail(*hints == NULL, NULL); + + priv = NM_CONNECTION_GET_PRIVATE(connection); + + /* Get list of settings in priority order */ + g_hash_table_iter_init(&hiter, priv->settings); + while (g_hash_table_iter_next(&hiter, NULL, (gpointer) &setting)) + settings = g_slist_insert_sorted(settings, setting, _nm_setting_compare_priority); + + for (iter = settings; iter; iter = g_slist_next(iter)) { + GPtrArray *secrets; + + setting = NM_SETTING(iter->data); + secrets = _nm_setting_need_secrets(setting); + if (secrets) { + if (hints) + *hints = secrets; + else + g_ptr_array_free(secrets, TRUE); + + name = nm_setting_get_name(setting); + break; + } + } + + g_slist_free(settings); + return name; +} + +/** + * nm_connection_clear_secrets: + * @connection: the #NMConnection + * + * Clears and frees any secrets that may be stored in the connection, to avoid + * keeping secret data in memory when not needed. + **/ +void +nm_connection_clear_secrets(NMConnection *connection) +{ + return nm_connection_clear_secrets_with_flags(connection, NULL, NULL); +} + +/** + * nm_connection_clear_secrets_with_flags: + * @connection: the #NMConnection + * @func: (scope call) (allow-none): function to be called to determine whether a + * specific secret should be cleared or not. If %NULL, all secrets are cleared. + * @user_data: caller-supplied data passed to @func + * + * Clears and frees secrets determined by @func. + **/ +void +nm_connection_clear_secrets_with_flags(NMConnection * connection, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data) +{ + GHashTableIter iter; + NMSetting * setting; + + g_return_if_fail(NM_IS_CONNECTION(connection)); + + g_hash_table_iter_init(&iter, NM_CONNECTION_GET_PRIVATE(connection)->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) { + g_signal_handlers_block_by_func(setting, (GCallback) setting_changed_cb, connection); + _nm_setting_clear_secrets(setting, func, user_data); + g_signal_handlers_unblock_by_func(setting, (GCallback) setting_changed_cb, connection); + } + + g_signal_emit(connection, signals[SECRETS_CLEARED], 0); +} + +static gboolean +_clear_secrets_by_secret_flags_cb(NMSetting * setting, + const char * secret, + NMSettingSecretFlags flags, + gpointer user_data) +{ + NMSettingSecretFlags filter_flags = GPOINTER_TO_UINT(user_data); + gboolean remove_secret; + + if (filter_flags == NM_SETTING_SECRET_FLAG_NONE) { + /* Can't use bitops with SECRET_FLAG_NONE so handle that specifically */ + remove_secret = (flags != NM_SETTING_SECRET_FLAG_NONE); + } else { + /* Otherwise, if the secret has at least one of the desired flags keep it */ + remove_secret = !NM_FLAGS_ANY(flags, filter_flags); + } + + return remove_secret; +} + +/** + * _nm_connection_clear_secrets_by_secret_flags: + * @self: the #NMConnection to filter (will be modified) + * @filter_flags: the secret flags to control whether to drop/remove + * a secret or to keep it. The meaning of the filter flags is to + * preserve the secrets. The secrets that have matching (see below) + * flags are kept, the others are dropped. + * + * Removes/drops secrets from @self according to @filter_flags. + * If @filter_flags is %NM_SETTING_SECRET_NONE, then only secrets that + * have %NM_SETTING_SECRET_NONE flags are kept. + * Otherwise, only secrets with secret flags are kept that have at least + * one of the filter flags. + */ +void +_nm_connection_clear_secrets_by_secret_flags(NMConnection *self, NMSettingSecretFlags filter_flags) +{ + nm_connection_clear_secrets_with_flags(self, + _clear_secrets_by_secret_flags_cb, + GUINT_TO_POINTER(filter_flags)); +} + +/*****************************************************************************/ + +/*****************************************************************************/ + +/* Returns always a non-NULL, floating variant that must + * be unrefed by the caller. */ +GVariant * +_nm_connection_for_each_secret(NMConnection * self, + GVariant * secrets, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data) +{ + GVariantBuilder secrets_builder; + GVariantBuilder setting_builder; + GVariantIter secrets_iter; + GVariantIter * setting_iter; + const char * setting_name; + + /* This function, given a dict of dicts representing new secrets of + * an NMConnection, walks through each toplevel dict (which represents a + * NMSetting), and for each setting, walks through that setting dict's + * properties. For each property that's a secret, it will check that + * secret's flags in the backing NMConnection object, and call a supplied + * callback. + * + * The one complexity is that the VPN setting's 'secrets' property is + * *also* a dict (since the key/value pairs are arbitrary and known + * only to the VPN plugin itself). That means we have three levels of + * dicts that we potentially have to traverse here. The differences + * are handled by the virtual for_each_secret() function. + */ + + g_return_val_if_fail(callback, NULL); + + g_variant_iter_init(&secrets_iter, secrets); + g_variant_builder_init(&secrets_builder, NM_VARIANT_TYPE_CONNECTION); + while (g_variant_iter_next(&secrets_iter, "{&sa{sv}}", &setting_name, &setting_iter)) { + _nm_unused nm_auto_free_variant_iter GVariantIter *setting_iter_free = setting_iter; + NMSetting * setting; + const char * secret_name; + GVariant * val; + + setting = nm_connection_get_setting_by_name(self, setting_name); + if (!setting) + continue; + + g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); + while (g_variant_iter_next(setting_iter, "{&sv}", &secret_name, &val)) { + _nm_unused gs_unref_variant GVariant *val_free = val; + + NM_SETTING_GET_CLASS(setting)->for_each_secret(setting, + secret_name, + val, + remove_non_secrets, + callback, + callback_data, + &setting_builder); + } + + g_variant_builder_add(&secrets_builder, "{sa{sv}}", setting_name, &setting_builder); + } + + return g_variant_builder_end(&secrets_builder); +} + +/*****************************************************************************/ + +typedef struct { + NMConnectionFindSecretFunc find_func; + gpointer find_func_data; + gboolean found; +} FindSecretData; + +static gboolean +find_secret_for_each_func(NMSettingSecretFlags flags, gpointer user_data) +{ + FindSecretData *data = user_data; + + if (!data->found) + data->found = data->find_func(flags, data->find_func_data); + return FALSE; +} + +gboolean +_nm_connection_find_secret(NMConnection * self, + GVariant * secrets, + NMConnectionFindSecretFunc callback, + gpointer callback_data) +{ + gs_unref_variant GVariant *dummy = NULL; + FindSecretData data = { + .find_func = callback, + .find_func_data = callback_data, + .found = FALSE, + }; + + dummy = _nm_connection_for_each_secret(self, secrets, FALSE, find_secret_for_each_func, &data); + return data.found; +} + +/*****************************************************************************/ + +/** + * nm_connection_to_dbus: + * @connection: the #NMConnection + * @flags: serialization flags, e.g. %NM_CONNECTION_SERIALIZE_ALL + * + * Converts the #NMConnection into a #GVariant of type + * %NM_VARIANT_TYPE_CONNECTION describing the connection, suitable for + * marshalling over D-Bus or otherwise serializing. + * + * Returns: (transfer none): a new floating #GVariant describing the connection, + * its settings, and each setting's properties. + **/ +GVariant * +nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags) +{ + return nm_connection_to_dbus_full(connection, flags, NULL); +} + +GVariant * +nm_connection_to_dbus_full(NMConnection * connection, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + GVariantBuilder builder; + gboolean any = FALSE; + gs_free NMSetting **settings = NULL; + guint settings_len = 0; + guint i; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + + settings = nm_connection_get_settings(connection, &settings_len); + for (i = 0; i < settings_len; i++) { + NMSetting *setting = settings[i]; + GVariant * setting_dict; + + setting_dict = _nm_setting_to_dbus(setting, connection, flags, options); + if (!setting_dict) + continue; + if (!any) { + any = TRUE; + g_variant_builder_init(&builder, NM_VARIANT_TYPE_CONNECTION); + } + g_variant_builder_add(&builder, "{s@a{sv}}", nm_setting_get_name(setting), setting_dict); + } + + if (!any) + return NULL; + + return g_variant_builder_end(&builder); +} + +/** + * nm_connection_is_type: + * @connection: the #NMConnection + * @type: a setting name to check the connection's type against (like + * %NM_SETTING_WIRELESS_SETTING_NAME or %NM_SETTING_WIRED_SETTING_NAME) + * + * A convenience function to check if the given @connection is a particular + * type (ie wired, Wi-Fi, ppp, etc). Checks the #NMSettingConnection:type + * property of the connection and matches that against @type. + * + * Returns: %TRUE if the connection is of the given @type, %FALSE if not + **/ +gboolean +nm_connection_is_type(NMConnection *connection, const char *type) +{ + g_return_val_if_fail(type, FALSE); + + return nm_streq0(type, nm_connection_get_connection_type(connection)); +} + +static int +_get_settings_sort(gconstpointer p_a, gconstpointer p_b, gpointer unused) +{ + NMSetting *a = *((NMSetting **) p_a); + NMSetting *b = *((NMSetting **) p_b); + + nm_assert(NM_IS_SETTING(a)); + nm_assert(NM_IS_SETTING(b)); + nm_assert(a != b); + nm_assert(G_OBJECT_TYPE(a) != G_OBJECT_TYPE(b)); + + NM_CMP_RETURN(_nm_setting_compare_priority(a, b)); + NM_CMP_DIRECT_STRCMP(nm_setting_get_name(a), nm_setting_get_name(b)); + + nm_assert_not_reached(); + return 0; +} + +/** + * nm_connection_get_settings: + * @connection: the #NMConnection instance + * @out_length: (allow-none) (out): the length of the returned array + * + * Retrieves the settings in @connection. + * + * The returned array is %NULL-terminated. + * + * Returns: (array length=out_length) (transfer container): a + * %NULL-terminated array containing every setting of + * @connection. + * If the connection has no settings, %NULL is returned. + * + * Since: 1.10 + */ +NMSetting ** +nm_connection_get_settings(NMConnection *connection, guint *out_length) +{ + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + + return (NMSetting **) nm_utils_hash_values_to_array( + NM_CONNECTION_GET_PRIVATE(connection)->settings, + _get_settings_sort, + NULL, + out_length); +} + +/** + * nm_connection_for_each_setting_value: + * @connection: the #NMConnection + * @func: (scope call): user-supplied function called for each setting's property + * @user_data: user data passed to @func at each invocation + * + * Iterates over the properties of each #NMSetting object in the #NMConnection, + * calling the supplied user function for each property. + **/ +void +nm_connection_for_each_setting_value(NMConnection * connection, + NMSettingValueIterFn func, + gpointer user_data) +{ + gs_free NMSetting **settings = NULL; + guint i, length = 0; + + g_return_if_fail(NM_IS_CONNECTION(connection)); + g_return_if_fail(func); + + settings = nm_connection_get_settings(connection, &length); + for (i = 0; i < length; i++) + nm_setting_enumerate_values(settings[i], func, user_data); +} + +/** + * _nm_connection_aggregate: + * @connection: the #NMConnection for which values are to be aggregated. + * @type: one of the supported aggregate types. + * @arg: the input/output argument that depends on @type. + * + * For example, with %NM_CONNECTION_AGGREGATE_ANY_SECRETS and + * %NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS @arg is a boolean + * output argument. It is either %NULL or a pointer to an gboolean + * out-argument. The function will always set @arg if given. + * Also, the return value of the function is likewise the result + * that is set to @arg. + * + * Returns: a boolean result with the meaning depending on the aggregation + * type @type. + */ +gboolean +_nm_connection_aggregate(NMConnection *connection, NMConnectionAggregateType type, gpointer arg) +{ + NMConnectionPrivate *priv; + GHashTableIter iter; + NMSetting * setting; + gboolean arg_boolean; + gboolean completed_early; + gpointer my_arg; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + + switch (type) { + case NM_CONNECTION_AGGREGATE_ANY_SECRETS: + arg_boolean = FALSE; + my_arg = &arg_boolean; + goto good; + case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: + arg_boolean = FALSE; + my_arg = &arg_boolean; + goto good; + } + g_return_val_if_reached(FALSE); + +good: + priv = NM_CONNECTION_GET_PRIVATE(connection); + + completed_early = FALSE; + g_hash_table_iter_init(&iter, priv->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) { + if (_nm_setting_aggregate(setting, type, my_arg)) { + completed_early = TRUE; + break; + } + nm_assert(my_arg != &arg_boolean || !arg_boolean); + } + + if (my_arg == &arg_boolean) { + nm_assert(completed_early == arg_boolean); + if (arg) + *((gboolean *) arg) = arg_boolean; + return arg_boolean; + } + + nm_assert_not_reached(); + return FALSE; +} + +/** + * nm_connection_dump: + * @connection: the #NMConnection + * + * Print the connection (including secrets!) to stdout. For debugging + * purposes ONLY, should NOT be used for serialization of the setting, + * or machine-parsed in any way. The output format is not guaranteed to + * be stable and may change at any time. + **/ +void +nm_connection_dump(NMConnection *connection) +{ + GHashTableIter iter; + NMSetting * setting; + char * str; + + if (!connection) + return; + + g_hash_table_iter_init(&iter, NM_CONNECTION_GET_PRIVATE(connection)->settings); + while (g_hash_table_iter_next(&iter, NULL, (gpointer) &setting)) { + str = nm_setting_to_string(setting); + g_print("%s\n", str); + g_free(str); + } +} + +/** + * nm_connection_set_path: + * @connection: the #NMConnection + * @path: the D-Bus path of the connection as given by the settings service + * which provides the connection + * + * Sets the D-Bus path of the connection. This property is not serialized, and + * is only for the reference of the caller. Sets the #NMConnection:path + * property. + **/ +void +nm_connection_set_path(NMConnection *connection, const char *path) +{ + NMConnectionPrivate *priv; + + g_return_if_fail(NM_IS_CONNECTION(connection)); + + priv = NM_CONNECTION_GET_PRIVATE(connection); + + g_free(priv->path); + priv->path = g_strdup(path); +} + +/** + * nm_connection_get_path: + * @connection: the #NMConnection + * + * Returns the connection's D-Bus path. + * + * Returns: the D-Bus path of the connection, previously set by a call to + * nm_connection_set_path(). + **/ +const char * +nm_connection_get_path(NMConnection *connection) +{ + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + + return NM_CONNECTION_GET_PRIVATE(connection)->path; +} + +/** + * nm_connection_get_interface_name: + * @connection: The #NMConnection + * + * Returns the interface name as stored in NMSettingConnection:interface_name. + * If the connection contains no NMSettingConnection, it will return %NULL. + * + * For hardware devices and software devices created outside of NetworkManager, + * this name is used to match the device. for software devices created by + * NetworkManager, this is the name of the created interface. + * + * Returns: Name of the kernel interface or %NULL + */ +const char * +nm_connection_get_interface_name(NMConnection *connection) +{ + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection(connection); + return s_con ? nm_setting_connection_get_interface_name(s_con) : NULL; +} + +NMConnectionMultiConnect +_nm_connection_get_multi_connect(NMConnection *connection) +{ + NMSettingConnection * s_con; + NMConnectionMultiConnect multi_connect; + const NMConnectionMultiConnect DEFAULT = NM_CONNECTION_MULTI_CONNECT_SINGLE; + + /* connection.multi_connect property cannot be specified via regular + * connection defaults in NetworkManager.conf, because those are per-device, + * and we need to determine the multi_connect independent of a particular + * device. + * + * There is however still a default-value, so theoretically, the default + * value could be specified in NetworkManager.conf. Just not as [connection*] + * and indepdented of a device. */ + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) + return DEFAULT; + + multi_connect = nm_setting_connection_get_multi_connect(s_con); + return multi_connect == NM_CONNECTION_MULTI_CONNECT_DEFAULT ? DEFAULT : multi_connect; +} + +gboolean +_nm_connection_verify_required_interface_name(NMConnection *connection, GError **error) +{ + const char *interface_name; + + if (!connection) + return TRUE; + + interface_name = nm_connection_get_interface_name(connection); + if (interface_name) + return TRUE; + + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME); + return FALSE; +} + +/** + * nm_connection_get_uuid: + * @connection: the #NMConnection + * + * A shortcut to return the UUID from the connection's #NMSettingConnection. + * + * Returns: the UUID from the connection's 'connection' setting + **/ +const char * +nm_connection_get_uuid(NMConnection *connection) +{ + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection(connection); + return s_con ? nm_setting_connection_get_uuid(s_con) : NULL; +} + +/** + * nm_connection_get_id: + * @connection: the #NMConnection + * + * A shortcut to return the ID from the connection's #NMSettingConnection. + * + * Returns: the ID from the connection's 'connection' setting + **/ +const char * +nm_connection_get_id(NMConnection *connection) +{ + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection(connection); + return s_con ? nm_setting_connection_get_id(s_con) : NULL; +} + +/** + * nm_connection_get_connection_type: + * @connection: the #NMConnection + * + * A shortcut to return the type from the connection's #NMSettingConnection. + * + * Returns: the type from the connection's 'connection' setting + **/ +const char * +nm_connection_get_connection_type(NMConnection *connection) +{ + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection(connection); + return s_con ? nm_setting_connection_get_connection_type(s_con) : NULL; +} + +/** + * nm_connection_is_virtual: + * @connection: an #NMConnection + * + * Checks if @connection refers to a virtual device (and thus can potentially be + * activated even if the device it refers to doesn't exist). + * + * Returns: whether @connection refers to a virtual device + */ +gboolean +nm_connection_is_virtual(NMConnection *connection) +{ + const char *type; + + type = nm_connection_get_connection_type(connection); + if (!type) + return FALSE; + + if (NM_IN_STRSET(type, + NM_SETTING_6LOWPAN_SETTING_NAME, + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_DUMMY_SETTING_NAME, + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_MACSEC_SETTING_NAME, + NM_SETTING_MACVLAN_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_TEAM_SETTING_NAME, + NM_SETTING_TUN_SETTING_NAME, + NM_SETTING_VETH_SETTING_NAME, + NM_SETTING_VLAN_SETTING_NAME, + NM_SETTING_VRF_SETTING_NAME, + NM_SETTING_VXLAN_SETTING_NAME, + NM_SETTING_WIREGUARD_SETTING_NAME)) + return TRUE; + + if (nm_streq(type, NM_SETTING_INFINIBAND_SETTING_NAME)) { + NMSettingInfiniband *s_ib; + + s_ib = nm_connection_get_setting_infiniband(connection); + return s_ib && nm_setting_infiniband_get_virtual_interface_name(s_ib); + } + + if (nm_streq(type, NM_SETTING_BLUETOOTH_SETTING_NAME)) + return !!_nm_connection_get_setting_bluetooth_for_nap(connection); + + if (nm_streq(type, NM_SETTING_PPPOE_SETTING_NAME)) { + NMSettingPppoe *s_pppoe; + + s_pppoe = nm_connection_get_setting_pppoe(connection); + return !!nm_setting_pppoe_get_parent(s_pppoe); + } + + return FALSE; +} + +/** + * nm_connection_get_virtual_device_description: + * @connection: an #NMConnection for a virtual device type + * + * Returns the name that nm_device_disambiguate_names() would + * return for the virtual device that would be created for @connection. + * Eg, "VLAN (eth1.1)". + * + * Returns: (transfer full): the name of @connection's device, + * or %NULL if @connection is not a virtual connection type + */ +char * +nm_connection_get_virtual_device_description(NMConnection *connection) +{ + const char *type; + const char *iface = NULL, *display_type = NULL; + + type = nm_connection_get_connection_type(connection); + if (!type) + return NULL; + + iface = nm_connection_get_interface_name(connection); + + if (!strcmp(type, NM_SETTING_BOND_SETTING_NAME)) + display_type = _("Bond"); + else if (!strcmp(type, NM_SETTING_TEAM_SETTING_NAME)) + display_type = _("Team"); + else if (!strcmp(type, NM_SETTING_BRIDGE_SETTING_NAME)) + display_type = _("Bridge"); + else if (!strcmp(type, NM_SETTING_VLAN_SETTING_NAME)) + display_type = _("VLAN"); + else if (!strcmp(type, NM_SETTING_INFINIBAND_SETTING_NAME)) { + display_type = _("InfiniBand"); + iface = nm_setting_infiniband_get_virtual_interface_name( + nm_connection_get_setting_infiniband(connection)); + } else if (!strcmp(type, NM_SETTING_IP_TUNNEL_SETTING_NAME)) + display_type = _("IP Tunnel"); + + if (!iface || !display_type) + return NULL; + + return g_strdup_printf("%s (%s)", display_type, iface); +} + +/*****************************************************************************/ + +/** + * nm_connection_get_setting_802_1x: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSetting8021x the connection might contain. + * + * Returns: (transfer none): an #NMSetting8021x if the connection contains one, otherwise %NULL + **/ +NMSetting8021x * +nm_connection_get_setting_802_1x(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_802_1X); +} + +/** + * nm_connection_get_setting_bluetooth: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingBluetooth the connection might contain. + * + * Returns: (transfer none): an #NMSettingBluetooth if the connection contains one, otherwise %NULL + **/ +NMSettingBluetooth * +nm_connection_get_setting_bluetooth(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_BLUETOOTH); +} + +/** + * nm_connection_get_setting_bond: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingBond the connection might contain. + * + * Returns: (transfer none): an #NMSettingBond if the connection contains one, otherwise %NULL + **/ +NMSettingBond * +nm_connection_get_setting_bond(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_BOND); +} + +/** + * nm_connection_get_setting_team: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingTeam the connection might contain. + * + * Returns: (transfer none): an #NMSettingTeam if the connection contains one, otherwise %NULL + **/ +NMSettingTeam * +nm_connection_get_setting_team(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_TEAM); +} + +/** + * nm_connection_get_setting_team_port: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingTeamPort the connection might contain. + * + * Returns: (transfer none): an #NMSettingTeamPort if the connection contains one, otherwise %NULL + **/ +NMSettingTeamPort * +nm_connection_get_setting_team_port(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_TEAM_PORT); +} + +/** + * nm_connection_get_setting_bridge: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingBridge the connection might contain. + * + * Returns: (transfer none): an #NMSettingBridge if the connection contains one, otherwise %NULL + **/ +NMSettingBridge * +nm_connection_get_setting_bridge(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_BRIDGE); +} + +/** + * nm_connection_get_setting_cdma: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingCdma the connection might contain. + * + * Returns: (transfer none): an #NMSettingCdma if the connection contains one, otherwise %NULL + **/ +NMSettingCdma * +nm_connection_get_setting_cdma(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_CDMA); +} + +/** + * nm_connection_get_setting_connection: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingConnection the connection might contain. + * + * Returns: (transfer none): an #NMSettingConnection if the connection contains one, otherwise %NULL + **/ +NMSettingConnection * +nm_connection_get_setting_connection(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_CONNECTION); +} + +/** + * nm_connection_get_setting_dcb: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingDcb the connection might contain. + * + * Returns: (transfer none): an #NMSettingDcb if the connection contains one, otherwise NULL + **/ +NMSettingDcb * +nm_connection_get_setting_dcb(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_DCB); +} + +/** + * nm_connection_get_setting_dummy: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingDummy the connection might contain. + * + * Returns: (transfer none): an #NMSettingDummy if the connection contains one, otherwise %NULL + * + * Since: 1.8 + **/ +NMSettingDummy * +nm_connection_get_setting_dummy(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_DUMMY); +} + +/** + * nm_connection_get_setting_generic: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingGeneric the connection might contain. + * + * Returns: (transfer none): an #NMSettingGeneric if the connection contains one, otherwise NULL + **/ +NMSettingGeneric * +nm_connection_get_setting_generic(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_GENERIC); +} + +/** + * nm_connection_get_setting_gsm: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingGsm the connection might contain. + * + * Returns: (transfer none): an #NMSettingGsm if the connection contains one, otherwise %NULL + **/ +NMSettingGsm * +nm_connection_get_setting_gsm(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_GSM); +} + +/** + * nm_connection_get_setting_infiniband: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingInfiniband the connection might contain. + * + * Returns: (transfer none): an #NMSettingInfiniband if the connection contains one, otherwise %NULL + **/ +NMSettingInfiniband * +nm_connection_get_setting_infiniband(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_INFINIBAND); +} + +/** + * nm_connection_get_setting_ip4_config: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingIP4Config the connection might contain. + * + * Note that it returns the value as type #NMSettingIPConfig, since the vast + * majority of IPv4-setting-related methods are on that type, not + * #NMSettingIP4Config. + * + * Returns: (type NMSettingIP4Config) (transfer none): an #NMSettingIP4Config if the + * connection contains one, otherwise %NULL + **/ +NMSettingIPConfig * +nm_connection_get_setting_ip4_config(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_IP4_CONFIG); +} + +/** + * nm_connection_get_setting_ip_tunnel: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingIPTunnel the connection might contain. + * + * Returns: (transfer none): an #NMSettingIPTunnel if the connection contains one, otherwise %NULL + * + * Since: 1.2 + **/ +NMSettingIPTunnel * +nm_connection_get_setting_ip_tunnel(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_IP_TUNNEL); +} + +/** + * nm_connection_get_setting_ip6_config: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingIP6Config the connection might contain. + * + * Note that it returns the value as type #NMSettingIPConfig, since the vast + * majority of IPv6-setting-related methods are on that type, not + * #NMSettingIP6Config. + * + * Returns: (type NMSettingIP6Config) (transfer none): an #NMSettingIP6Config if the + * connection contains one, otherwise %NULL + **/ +NMSettingIPConfig * +nm_connection_get_setting_ip6_config(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_IP6_CONFIG); +} + +/** + * nm_connection_get_setting_macsec: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingMacsec the connection might contain. + * + * Returns: (transfer none): an #NMSettingMacsec if the connection contains one, otherwise %NULL + * + * Since: 1.6 + **/ +NMSettingMacsec * +nm_connection_get_setting_macsec(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_MACSEC); +} + +/** + * nm_connection_get_setting_macvlan: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingMacvlan the connection might contain. + * + * Returns: (transfer none): an #NMSettingMacvlan if the connection contains one, otherwise %NULL + * + * Since: 1.2 + **/ +NMSettingMacvlan * +nm_connection_get_setting_macvlan(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_MACVLAN); +} + +/** + * nm_connection_get_setting_olpc_mesh: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOlpcMesh the connection might contain. + * + * Returns: (transfer none): an #NMSettingOlpcMesh if the connection contains one, otherwise %NULL + **/ +NMSettingOlpcMesh * +nm_connection_get_setting_olpc_mesh(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_OLPC_MESH); +} + +/** + * nm_connection_get_setting_ovs_bridge: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOvsBridge the connection might contain. + * + * Returns: (transfer none): an #NMSettingOvsBridge if the connection contains one, otherwise %NULL + * + * Since: 1.10 + **/ +NMSettingOvsBridge * +nm_connection_get_setting_ovs_bridge(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_OVS_BRIDGE); +} + +/** + * nm_connection_get_setting_ovs_interface: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOvsInterface the connection might contain. + * + * Returns: (transfer none): an #NMSettingOvsInterface if the connection contains one, otherwise %NULL + * + * Since: 1.10 + **/ +NMSettingOvsInterface * +nm_connection_get_setting_ovs_interface(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_OVS_INTERFACE); +} + +/** + * nm_connection_get_setting_ovs_patch: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOvsPatch the connection might contain. + * + * Returns: (transfer none): an #NMSettingOvsPatch if the connection contains one, otherwise %NULL + * + * Since: 1.10 + **/ +NMSettingOvsPatch * +nm_connection_get_setting_ovs_patch(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_OVS_PATCH); +} + +/** + * nm_connection_get_setting_ovs_port: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOvsPort the connection might contain. + * + * Returns: (transfer none): an #NMSettingOvsPort if the connection contains one, otherwise %NULL + * + * Since: 1.10 + **/ +NMSettingOvsPort * +nm_connection_get_setting_ovs_port(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_OVS_PORT); +} + +/** + * nm_connection_get_setting_ppp: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingPpp the connection might contain. + * + * Returns: (transfer none): an #NMSettingPpp if the connection contains one, otherwise %NULL + **/ +NMSettingPpp * +nm_connection_get_setting_ppp(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_PPP); +} + +/** + * nm_connection_get_setting_pppoe: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingPppoe the connection might contain. + * + * Returns: (transfer none): an #NMSettingPppoe if the connection contains one, otherwise %NULL + **/ +NMSettingPppoe * +nm_connection_get_setting_pppoe(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_PPPOE); +} + +/** + * nm_connection_get_setting_proxy: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingProxy the connection might contain. + * + * Returns: (transfer none): an #NMSettingProxy if the connection contains one, otherwise %NULL + * + * Since: 1.6 + **/ +NMSettingProxy * +nm_connection_get_setting_proxy(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_PROXY); +} + +/** + * nm_connection_get_setting_serial: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingSerial the connection might contain. + * + * Returns: (transfer none): an #NMSettingSerial if the connection contains one, otherwise %NULL + **/ +NMSettingSerial * +nm_connection_get_setting_serial(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_SERIAL); +} + +/** + * nm_connection_get_setting_tc_config: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingTCConfig the connection might contain. + * + * Returns: (transfer none): an #NMSettingTCConfig if the connection contains one, otherwise %NULL + * + * Since: 1.12 + **/ +NMSettingTCConfig * +nm_connection_get_setting_tc_config(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_TC_CONFIG); +} + +/** + * nm_connection_get_setting_tun: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingTun the connection might contain. + * + * Returns: (transfer none): an #NMSettingTun if the connection contains one, otherwise %NULL + * + * Since: 1.2 + **/ +NMSettingTun * +nm_connection_get_setting_tun(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_TUN); +} + +/** + * nm_connection_get_setting_vpn: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingVpn the connection might contain. + * + * Returns: (transfer none): an #NMSettingVpn if the connection contains one, otherwise %NULL + **/ +NMSettingVpn * +nm_connection_get_setting_vpn(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_VPN); +} + +/** + * nm_connection_get_setting_vxlan: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingVxlan the connection might contain. + * + * Returns: (transfer none): an #NMSettingVxlan if the connection contains one, otherwise %NULL + * + * Since: 1.2 + **/ +NMSettingVxlan * +nm_connection_get_setting_vxlan(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_VXLAN); +} + +/** + * nm_connection_get_setting_wimax: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingWimax the connection might contain. + * + * Returns: (transfer none): an #NMSettingWimax if the connection contains one, otherwise %NULL + **/ +NMSettingWimax * +nm_connection_get_setting_wimax(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_WIMAX); +} + +/** + * nm_connection_get_setting_wired: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingWired the connection might contain. + * + * Returns: (transfer none): an #NMSettingWired if the connection contains one, otherwise %NULL + **/ +NMSettingWired * +nm_connection_get_setting_wired(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_WIRED); +} + +/** + * nm_connection_get_setting_adsl: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingAdsl the connection might contain. + * + * Returns: (transfer none): an #NMSettingAdsl if the connection contains one, otherwise %NULL + **/ +NMSettingAdsl * +nm_connection_get_setting_adsl(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_ADSL); +} + +/** + * nm_connection_get_setting_wireless: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingWireless the connection might contain. + * + * Returns: (transfer none): an #NMSettingWireless if the connection contains one, otherwise %NULL + **/ +NMSettingWireless * +nm_connection_get_setting_wireless(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_WIRELESS); +} + +/** + * nm_connection_get_setting_wireless_security: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingWirelessSecurity the connection might contain. + * + * Returns: (transfer none): an #NMSettingWirelessSecurity if the connection contains one, otherwise %NULL + **/ +NMSettingWirelessSecurity * +nm_connection_get_setting_wireless_security(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); +} + +/** + * nm_connection_get_setting_bridge_port: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingBridgePort the connection might contain. + * + * Returns: (transfer none): an #NMSettingBridgePort if the connection contains one, otherwise %NULL + **/ +NMSettingBridgePort * +nm_connection_get_setting_bridge_port(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_BRIDGE_PORT); +} + +/** + * nm_connection_get_setting_vlan: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingVlan the connection might contain. + * + * Returns: (transfer none): an #NMSettingVlan if the connection contains one, otherwise %NULL + **/ +NMSettingVlan * +nm_connection_get_setting_vlan(NMConnection *connection) +{ + return _connection_get_setting_check(connection, NM_TYPE_SETTING_VLAN); +} + +NMSettingBluetooth * +_nm_connection_get_setting_bluetooth_for_nap(NMConnection *connection) +{ + NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth(connection); + + if (s_bt + && nm_streq0(nm_setting_bluetooth_get_connection_type(s_bt), NM_SETTING_BLUETOOTH_TYPE_NAP)) + return s_bt; + return NULL; +} + +/*****************************************************************************/ + +static void +nm_connection_private_free(NMConnectionPrivate *priv) +{ + NMConnection *self = priv->self; + + g_hash_table_foreach_remove(priv->settings, _setting_release_hfr, self); + g_hash_table_destroy(priv->settings); + g_free(priv->path); + + g_slice_free(NMConnectionPrivate, priv); +} + +static NMConnectionPrivate * +nm_connection_get_private(NMConnection *connection) +{ + GQuark key; + NMConnectionPrivate *priv; + + nm_assert(NM_IS_CONNECTION(connection)); + + key = NM_CACHED_QUARK("NMConnectionPrivate"); + + priv = g_object_get_qdata((GObject *) connection, key); + if (G_UNLIKELY(!priv)) { + priv = g_slice_new0(NMConnectionPrivate); + g_object_set_qdata_full((GObject *) connection, + key, + priv, + (GDestroyNotify) nm_connection_private_free); + + priv->self = connection; + priv->settings = g_hash_table_new_full(nm_direct_hash, NULL, NULL, g_object_unref); + } + + return priv; +} + +static void +nm_connection_default_init(NMConnectionInterface *iface) +{ + /** + * NMConnection::secrets-updated: + * @connection: the object on which the signal is emitted + * @setting_name: the setting name of the #NMSetting for which secrets were + * updated + * + * The ::secrets-updated signal is emitted when the secrets of a setting + * have been changed. + */ + signals[SECRETS_UPDATED] = g_signal_new(NM_CONNECTION_SECRETS_UPDATED, + NM_TYPE_CONNECTION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(NMConnectionInterface, secrets_updated), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + /** + * NMConnection::secrets-cleared: + * @connection: the object on which the signal is emitted + * + * The ::secrets-cleared signal is emitted when the secrets of a connection + * are cleared. + */ + signals[SECRETS_CLEARED] = g_signal_new(NM_CONNECTION_SECRETS_CLEARED, + NM_TYPE_CONNECTION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(NMConnectionInterface, secrets_cleared), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + /** + * NMConnection::changed: + * @connection: the object on which the signal is emitted + * + * The ::changed signal is emitted when any property of any property + * (including secrets) of any setting of the connection is modified, + * or when settings are added or removed. + */ + signals[CHANGED] = g_signal_new(NM_CONNECTION_CHANGED, + NM_TYPE_CONNECTION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(NMConnectionInterface, changed), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +} diff --git a/src/libnm-core-impl/nm-crypto-gnutls.c b/src/libnm-core-impl/nm-crypto-gnutls.c new file mode 100644 index 0000000000..0f6da6175e --- /dev/null +++ b/src/libnm-core-impl/nm-crypto-gnutls.c @@ -0,0 +1,415 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Dan Williams + * Copyright (C) 2007 - 2015 Red Hat, Inc. + */ + +#include "nm-glib-aux/nm-default-glib-i18n-lib.h" + +#include "nm-crypto-impl.h" + +#include +#include +#include +#include + +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-errors.h" + +/*****************************************************************************/ + +static gboolean +_get_cipher_info(NMCryptoCipherType cipher, int *out_cipher_mech, guint8 *out_real_iv_len) +{ + static const int cipher_mechs[] = { + [NM_CRYPTO_CIPHER_DES_EDE3_CBC] = GNUTLS_CIPHER_3DES_CBC, + [NM_CRYPTO_CIPHER_DES_CBC] = GNUTLS_CIPHER_DES_CBC, + [NM_CRYPTO_CIPHER_AES_128_CBC] = GNUTLS_CIPHER_AES_128_CBC, + [NM_CRYPTO_CIPHER_AES_192_CBC] = GNUTLS_CIPHER_AES_192_CBC, + [NM_CRYPTO_CIPHER_AES_256_CBC] = GNUTLS_CIPHER_AES_256_CBC, + }; + + g_return_val_if_fail(_NM_INT_NOT_NEGATIVE(cipher) + && (gsize) cipher < G_N_ELEMENTS(cipher_mechs), + FALSE); + + if (cipher_mechs[cipher] == 0) + return FALSE; + + NM_SET_OUT(out_cipher_mech, cipher_mechs[cipher]); + NM_SET_OUT(out_real_iv_len, nm_crypto_cipher_get_info(cipher)->real_iv_len); + return TRUE; +} + +/*****************************************************************************/ + +gboolean +_nm_crypto_init(GError **error) +{ + static gboolean initialized = FALSE; + + if (initialized) + return TRUE; + + if (gnutls_global_init() != 0) { + gnutls_global_deinit(); + g_set_error_literal(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Failed to initialize the crypto engine.")); + return FALSE; + } + + initialized = TRUE; + return TRUE; +} + +/*****************************************************************************/ + +guint8 * +_nmtst_crypto_decrypt(NMCryptoCipherType cipher, + const guint8 * data, + gsize data_len, + const guint8 * iv, + gsize iv_len, + const guint8 * key, + gsize key_len, + gsize * out_len, + GError ** error) +{ + gnutls_cipher_hd_t ctx; + gnutls_datum_t key_dt, iv_dt; + int err; + int cipher_mech; + nm_auto_clear_secret_ptr NMSecretPtr output = {0}; + guint8 pad_i, pad_len; + guint8 real_iv_len; + + if (!_get_cipher_info(cipher, &cipher_mech, &real_iv_len)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + _("Unsupported key cipher for decryption")); + return NULL; + } + + if (!_nm_crypto_init(error)) + return NULL; + + if (iv_len < real_iv_len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Invalid IV length (must be at least %u)."), + (guint) real_iv_len); + return NULL; + } + + output.len = data_len; + output.bin = g_malloc(data_len); + + key_dt.data = (unsigned char *) key; + key_dt.size = key_len; + iv_dt.data = (unsigned char *) iv; + iv_dt.size = iv_len; + + err = gnutls_cipher_init(&ctx, cipher_mech, &key_dt, &iv_dt); + if (err < 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to initialize the decryption cipher context: %s (%s)"), + gnutls_strerror_name(err), + gnutls_strerror(err)); + return NULL; + } + + err = gnutls_cipher_decrypt2(ctx, data, data_len, output.bin, output.len); + + gnutls_cipher_deinit(ctx); + + if (err < 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to decrypt the private key: %s (%s)"), + gnutls_strerror_name(err), + gnutls_strerror(err)); + return NULL; + } + + pad_len = output.len > 0 ? output.bin[output.len - 1] : 0; + + /* Check if the padding at the end of the decrypted data is valid */ + if (pad_len == 0 || pad_len > real_iv_len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to decrypt the private key: unexpected padding length.")); + return NULL; + } + + /* Validate tail padding; last byte is the padding size, and all pad bytes + * should contain the padding size. + */ + for (pad_i = 1; pad_i <= pad_len; ++pad_i) { + if (output.bin[data_len - pad_i] != pad_len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to decrypt the private key.")); + return NULL; + } + } + + *out_len = output.len - pad_len; + return g_steal_pointer(&output.bin); +} + +guint8 * +_nmtst_crypto_encrypt(NMCryptoCipherType cipher, + const guint8 * data, + gsize data_len, + const guint8 * iv, + gsize iv_len, + const guint8 * key, + gsize key_len, + gsize * out_len, + GError ** error) +{ + gnutls_cipher_hd_t ctx; + gnutls_datum_t key_dt, iv_dt; + int err; + int cipher_mech; + nm_auto_clear_secret_ptr NMSecretPtr output = {0}; + nm_auto_clear_secret_ptr NMSecretPtr padded_buf = {0}; + gsize i, pad_len; + + nm_assert(iv_len); + + if (cipher == NM_CRYPTO_CIPHER_DES_CBC || !_get_cipher_info(cipher, &cipher_mech, NULL)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + _("Unsupported key cipher for encryption")); + return NULL; + } + + if (!_nm_crypto_init(error)) + return NULL; + + key_dt.data = (unsigned char *) key; + key_dt.size = key_len; + iv_dt.data = (unsigned char *) iv; + iv_dt.size = iv_len; + + err = gnutls_cipher_init(&ctx, cipher_mech, &key_dt, &iv_dt); + if (err < 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _("Failed to initialize the encryption cipher context: %s (%s)"), + gnutls_strerror_name(err), + gnutls_strerror(err)); + return NULL; + } + + /* If data_len % ivlen == 0, then we add another complete block + * onto the end so that the decrypter knows there's padding. + */ + pad_len = iv_len - (data_len % iv_len); + + padded_buf.len = data_len + pad_len; + padded_buf.bin = g_malloc(padded_buf.len); + memcpy(padded_buf.bin, data, data_len); + for (i = 0; i < pad_len; i++) + padded_buf.bin[data_len + i] = (guint8)(pad_len & 0xFF); + + output.len = padded_buf.len; + output.bin = g_malloc(output.len); + + err = gnutls_cipher_encrypt2(ctx, padded_buf.bin, padded_buf.len, output.bin, output.len); + + gnutls_cipher_deinit(ctx); + + if (err < 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _("Failed to encrypt the data: %s (%s)"), + gnutls_strerror_name(err), + gnutls_strerror(err)); + return NULL; + } + + *out_len = output.len; + return g_steal_pointer(&output.bin); +} + +gboolean +_nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error) +{ + gnutls_x509_crt_t der; + gnutls_datum_t dt; + int err; + + if (!_nm_crypto_init(error)) + return FALSE; + + err = gnutls_x509_crt_init(&der); + if (err < 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Error initializing certificate data: %s"), + gnutls_strerror(err)); + return FALSE; + } + + /* Try DER first */ + dt.data = (unsigned char *) data; + dt.size = len; + err = gnutls_x509_crt_import(der, &dt, GNUTLS_X509_FMT_DER); + if (err == GNUTLS_E_SUCCESS) { + gnutls_x509_crt_deinit(der); + return TRUE; + } + + /* And PEM next */ + err = gnutls_x509_crt_import(der, &dt, GNUTLS_X509_FMT_PEM); + gnutls_x509_crt_deinit(der); + if (err == GNUTLS_E_SUCCESS) + return TRUE; + + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Couldn't decode certificate: %s"), + gnutls_strerror(err)); + return FALSE; +} + +gboolean +_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error) +{ + gnutls_pkcs12_t p12; + gnutls_datum_t dt; + int err; + + g_return_val_if_fail(data != NULL, FALSE); + + if (!_nm_crypto_init(error)) + return FALSE; + + dt.data = (unsigned char *) data; + dt.size = data_len; + + err = gnutls_pkcs12_init(&p12); + if (err < 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Couldn't initialize PKCS#12 decoder: %s"), + gnutls_strerror(err)); + return FALSE; + } + + /* DER first */ + err = gnutls_pkcs12_import(p12, &dt, GNUTLS_X509_FMT_DER, 0); + if (err < 0) { + /* PEM next */ + err = gnutls_pkcs12_import(p12, &dt, GNUTLS_X509_FMT_PEM, 0); + if (err < 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Couldn't decode PKCS#12 file: %s"), + gnutls_strerror(err)); + gnutls_pkcs12_deinit(p12); + return FALSE; + } + } + + err = gnutls_pkcs12_verify_mac(p12, password); + + gnutls_pkcs12_deinit(p12); + + if (err != GNUTLS_E_SUCCESS) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Couldn't verify PKCS#12 file: %s"), + gnutls_strerror(err)); + return FALSE; + } + + return TRUE; +} + +gboolean +_nm_crypto_verify_pkcs8(const guint8 *data, + gsize data_len, + gboolean is_encrypted, + const char * password, + GError ** error) +{ + gnutls_x509_privkey_t p8; + gnutls_datum_t dt; + int err; + + g_return_val_if_fail(data != NULL, FALSE); + + if (!_nm_crypto_init(error)) + return FALSE; + + err = gnutls_x509_privkey_init(&p8); + if (err < 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Couldn't initialize PKCS#8 decoder: %s"), + gnutls_strerror(err)); + return FALSE; + } + + dt.data = (unsigned char *) data; + dt.size = data_len; + + err = gnutls_x509_privkey_import_pkcs8(p8, + &dt, + GNUTLS_X509_FMT_DER, + is_encrypted ? password : NULL, + is_encrypted ? 0 : GNUTLS_PKCS_PLAIN); + + gnutls_x509_privkey_deinit(p8); + + if (err < 0) { + if (err == GNUTLS_E_UNKNOWN_CIPHER_TYPE) { + /* HACK: gnutls < 3.5.4 doesn't support all the cipher types that openssl + * can use with PKCS#8, so if we encounter one, we have to assume + * the given password works. gnutls needs to unsuckify, apparently. + * Specifically, by default openssl uses pbeWithMD5AndDES-CBC + * which gnutls does not support. + */ + } else { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Couldn't decode PKCS#8 file: %s"), + gnutls_strerror(err)); + return FALSE; + } + } + + return TRUE; +} + +gboolean +_nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error) +{ + if (!_nm_crypto_init(error)) + return FALSE; + + gnutls_rnd(GNUTLS_RND_RANDOM, buffer, buffer_len); + return TRUE; +} diff --git a/src/libnm-core-impl/nm-crypto-impl.h b/src/libnm-core-impl/nm-crypto-impl.h new file mode 100644 index 0000000000..0fd8f194d4 --- /dev/null +++ b/src/libnm-core-impl/nm-crypto-impl.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Dan Williams + * Copyright (C) 2007 - 2018 Red Hat, Inc. + */ + +#ifndef __NM_CRYPTO_IMPL_H__ +#define __NM_CRYPTO_IMPL_H__ + +#include "nm-crypto.h" + +gboolean _nm_crypto_init(GError **error); + +gboolean _nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error); + +gboolean _nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error); + +gboolean +_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error); + +gboolean _nm_crypto_verify_pkcs8(const guint8 *data, + gsize data_len, + gboolean is_encrypted, + const char * password, + GError ** error); + +/*****************************************************************************/ + +guint8 *_nmtst_crypto_encrypt(NMCryptoCipherType cipher, + const guint8 * data, + gsize data_len, + const guint8 * iv, + gsize iv_len, + const guint8 * key, + gsize key_len, + gsize * out_len, + GError ** error); + +guint8 *_nmtst_crypto_decrypt(NMCryptoCipherType cipher, + const guint8 * data, + gsize data_len, + const guint8 * iv, + gsize iv_len, + const guint8 * key, + gsize key_len, + gsize * out_len, + GError ** error); + +#endif /* __NM_CRYPTO_IMPL_H__ */ diff --git a/src/libnm-core-impl/nm-crypto-nss.c b/src/libnm-core-impl/nm-crypto-nss.c new file mode 100644 index 0000000000..24a53f5dfe --- /dev/null +++ b/src/libnm-core-impl/nm-crypto-nss.c @@ -0,0 +1,548 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Dan Williams + * Copyright (C) 2007 - 2009 Red Hat, Inc. + */ + +#include "nm-glib-aux/nm-default-glib-i18n-lib.h" + +#include "nm-crypto-impl.h" + +NM_PRAGMA_WARNING_DISABLE("-Wstrict-prototypes") +#include +#include +#include +#include +#include +#include +#include +#include +#include +NM_PRAGMA_WARNING_REENABLE + +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-errors.h" + +/*****************************************************************************/ + +static gboolean +_get_cipher_info(NMCryptoCipherType cipher, + CK_MECHANISM_TYPE *out_cipher_mech, + guint8 * out_real_iv_len) +{ + static const CK_MECHANISM_TYPE cipher_mechs[] = { + [NM_CRYPTO_CIPHER_DES_EDE3_CBC] = CKM_DES3_CBC_PAD, + [NM_CRYPTO_CIPHER_DES_CBC] = CKM_DES_CBC_PAD, + [NM_CRYPTO_CIPHER_AES_128_CBC] = CKM_AES_CBC_PAD, + [NM_CRYPTO_CIPHER_AES_192_CBC] = CKM_AES_CBC_PAD, + [NM_CRYPTO_CIPHER_AES_256_CBC] = CKM_AES_CBC_PAD, + }; + + g_return_val_if_fail(_NM_INT_NOT_NEGATIVE(cipher) + && (gsize) cipher < G_N_ELEMENTS(cipher_mechs), + FALSE); + + if (!cipher_mechs[cipher]) + return FALSE; + + NM_SET_OUT(out_cipher_mech, cipher_mechs[cipher]); + NM_SET_OUT(out_real_iv_len, nm_crypto_cipher_get_info(cipher)->real_iv_len); + return TRUE; +} + +/*****************************************************************************/ + +gboolean +_nm_crypto_init(GError **error) +{ + static gboolean initialized = FALSE; + SECStatus ret; + + if (initialized) + return TRUE; + + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1); + ret = NSS_NoDB_Init(NULL); + if (ret != SECSuccess) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Failed to initialize the crypto engine: %d."), + PR_GetError()); + PR_Cleanup(); + return FALSE; + } + + SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1); + SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1); + SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); + SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1); + SEC_PKCS12EnableCipher(PKCS12_DES_56, 1); + SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1); + SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1); + + initialized = TRUE; + return TRUE; +} + +guint8 * +_nmtst_crypto_decrypt(NMCryptoCipherType cipher, + const guint8 * data, + gsize data_len, + const guint8 * iv, + gsize iv_len, + const guint8 * key, + gsize key_len, + gsize * out_len, + GError ** error) +{ + CK_MECHANISM_TYPE cipher_mech; + PK11SlotInfo * slot = NULL; + SECItem key_item; + PK11SymKey * sym_key = NULL; + SECItem * sec_param = NULL; + PK11Context * ctx = NULL; + nm_auto_clear_secret_ptr NMSecretPtr output = {0}; + SECStatus s; + gboolean success = FALSE; + int decrypted_len = 0; + unsigned extra = 0; + unsigned pad_len = 0; + guint32 i; + guint8 real_iv_len; + + if (!_get_cipher_info(cipher, &cipher_mech, &real_iv_len)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + _("Unsupported key cipher for decryption")); + return NULL; + } + + if (iv_len < real_iv_len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Invalid IV length (must be at least %u)."), + (guint) real_iv_len); + return NULL; + } + + if (!_nm_crypto_init(error)) + return NULL; + + slot = PK11_GetBestSlot(cipher_mech, NULL); + if (!slot) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Failed to initialize the decryption cipher slot.")); + goto out; + } + + key_item.data = (unsigned char *) key; + key_item.len = key_len; + sym_key = PK11_ImportSymKey(slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL); + if (!sym_key) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to set symmetric key for decryption.")); + goto out; + } + + key_item.data = (unsigned char *) iv; + key_item.len = real_iv_len; + sec_param = PK11_ParamFromIV(cipher_mech, &key_item); + if (!sec_param) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to set IV for decryption.")); + goto out; + } + + ctx = PK11_CreateContextBySymKey(cipher_mech, CKA_DECRYPT, sym_key, sec_param); + if (!ctx) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to initialize the decryption context.")); + goto out; + } + + output.len = data_len; + output.bin = g_malloc(data_len); + + s = PK11_CipherOp(ctx, + (unsigned char *) output.bin, + &decrypted_len, + output.len, + data, + data_len); + if (s != SECSuccess) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to decrypt the private key: %d."), + PORT_GetError()); + goto out; + } + + if (decrypted_len > data_len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to decrypt the private key: decrypted data too large.")); + goto out; + } + + s = PK11_DigestFinal(ctx, + (unsigned char *) &output.bin[decrypted_len], + &extra, + data_len - decrypted_len); + if (s != SECSuccess) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to finalize decryption of the private key: %d."), + PORT_GetError()); + goto out; + } + + decrypted_len += extra; + pad_len = data_len - decrypted_len; + + /* Check if the padding at the end of the decrypted data is valid */ + if (pad_len == 0 || pad_len > real_iv_len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to decrypt the private key: unexpected padding length.")); + goto out; + } + + /* Validate tail padding; last byte is the padding size, and all pad bytes + * should contain the padding size. + */ + for (i = pad_len; i > 0; i--) { + if (output.bin[data_len - i] != pad_len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Failed to decrypt the private key.")); + goto out; + } + } + + success = TRUE; + +out: + if (ctx) + PK11_DestroyContext(ctx, PR_TRUE); + if (sym_key) + PK11_FreeSymKey(sym_key); + if (sec_param) + SECITEM_FreeItem(sec_param, PR_TRUE); + if (slot) + PK11_FreeSlot(slot); + + if (!success) + return NULL; + + if (decrypted_len < output.len) + nm_explicit_bzero(&output.bin[decrypted_len], output.len - decrypted_len); + *out_len = decrypted_len; + return g_steal_pointer(&output.bin); +} + +guint8 * +_nmtst_crypto_encrypt(NMCryptoCipherType cipher, + const guint8 * data, + gsize data_len, + const guint8 * iv, + gsize iv_len, + const guint8 * key, + gsize key_len, + gsize * out_len, + GError ** error) +{ + SECStatus ret; + CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; + PK11SlotInfo * slot = NULL; + SECItem key_item = {.data = (unsigned char *) key, .len = key_len}; + SECItem iv_item = {.data = (unsigned char *) iv, .len = iv_len}; + PK11SymKey * sym_key = NULL; + SECItem * sec_param = NULL; + PK11Context * ctx = NULL; + nm_auto_clear_secret_ptr NMSecretPtr padded_buf = {0}; + nm_auto_clear_secret_ptr NMSecretPtr output = {0}; + int encrypted_len = 0, i; + gboolean success = FALSE; + gsize pad_len; + + if (cipher == NM_CRYPTO_CIPHER_DES_CBC || !_get_cipher_info(cipher, &cipher_mech, NULL)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + _("Unsupported key cipher for encryption")); + return NULL; + } + + if (!_nm_crypto_init(error)) + return NULL; + + slot = PK11_GetBestSlot(cipher_mech, NULL); + if (!slot) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Failed to initialize the encryption cipher slot.")); + return NULL; + } + + sym_key = PK11_ImportSymKey(slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); + if (!sym_key) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _("Failed to set symmetric key for encryption.")); + goto out; + } + + sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); + if (!sec_param) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _("Failed to set IV for encryption.")); + goto out; + } + + ctx = PK11_CreateContextBySymKey(cipher_mech, CKA_ENCRYPT, sym_key, sec_param); + if (!ctx) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _("Failed to initialize the encryption context.")); + goto out; + } + + /* If data->len % ivlen == 0, then we add another complete block + * onto the end so that the decrypter knows there's padding. + */ + pad_len = iv_len - (data_len % iv_len); + + padded_buf.len = data_len + pad_len; + padded_buf.bin = g_malloc(padded_buf.len); + + memcpy(padded_buf.bin, data, data_len); + for (i = 0; i < pad_len; i++) + padded_buf.bin[data_len + i] = (guint8)(pad_len & 0xFF); + + output.len = padded_buf.len; + output.bin = g_malloc(output.len); + + ret = + PK11_CipherOp(ctx, output.bin, &encrypted_len, output.len, padded_buf.bin, padded_buf.len); + if (ret != SECSuccess) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _("Failed to encrypt: %d."), + PORT_GetError()); + goto out; + } + + if (encrypted_len != output.len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_ENCRYPTION_FAILED, + _("Unexpected amount of data after encrypting.")); + goto out; + } + + success = TRUE; + +out: + if (ctx) + PK11_DestroyContext(ctx, PR_TRUE); + if (sec_param) + SECITEM_FreeItem(sec_param, PR_TRUE); + if (sym_key) + PK11_FreeSymKey(sym_key); + if (slot) + PK11_FreeSlot(slot); + + if (!success) + return NULL; + + *out_len = output.len; + return g_steal_pointer(&output.bin); +} + +gboolean +_nm_crypto_verify_x509(const guint8 *data, gsize len, GError **error) +{ + CERTCertificate *cert; + + if (!_nm_crypto_init(error)) + return FALSE; + + /* Try DER/PEM first */ + cert = CERT_DecodeCertFromPackage((char *) data, len); + if (!cert) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Couldn't decode certificate: %d"), + PORT_GetError()); + return FALSE; + } + + CERT_DestroyCertificate(cert); + return TRUE; +} + +gboolean +_nm_crypto_verify_pkcs12(const guint8 *data, gsize data_len, const char *password, GError **error) +{ + SEC_PKCS12DecoderContext *p12ctx = NULL; + SECItem pw = {0}; + PK11SlotInfo * slot = NULL; + SECStatus s; + gboolean success = FALSE; + + g_return_val_if_fail(!error || !*error, FALSE); + + if (!_nm_crypto_init(error)) + return FALSE; + + /* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do + * any conversions for us. + */ + if (password && *password) { + nm_auto_clear_secret_ptr NMSecretPtr ucs2_password = {0}; + + if (g_utf8_validate(password, -1, NULL)) { + long ucs2_chars; + + ucs2_password.bin = + (guint8 *) g_utf8_to_utf16(password, strlen(password), NULL, &ucs2_chars, NULL); + + /* cannot fail, because password is valid UTF-8*/ + nm_assert(ucs2_password.bin && ucs2_chars > 0); + + ucs2_password.len = ucs2_chars * 2; + } + + if (!ucs2_password.bin || ucs2_password.len == 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_PASSWORD, + _("Password must be UTF-8")); + return FALSE; + } + + pw.data = PORT_ZAlloc(ucs2_password.len + 2); + memcpy(pw.data, ucs2_password.bin, ucs2_password.len); + pw.len = ucs2_password.len + 2; + +#if __BYTE_ORDER == __LITTLE_ENDIAN + { + guint16 *p, *p_end; + + p_end = (guint16 *) &(((guint8 *) pw.data)[ucs2_password.len]); + for (p = (guint16 *) pw.data; p < p_end; p++) + *p = GUINT16_SWAP_LE_BE(*p); + } +#endif + } + + slot = PK11_GetInternalKeySlot(); + if (!slot) { + g_set_error(error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize slot")); + goto out; + } + + p12ctx = SEC_PKCS12DecoderStart(&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); + if (!p12ctx) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Couldn't initialize PKCS#12 decoder: %d"), + PORT_GetError()); + goto out; + } + + s = SEC_PKCS12DecoderUpdate(p12ctx, (guint8 *) data, data_len); + if (s != SECSuccess) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Couldn't decode PKCS#12 file: %d"), + PORT_GetError()); + goto out; + } + + s = SEC_PKCS12DecoderVerify(p12ctx); + if (s != SECSuccess) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + _("Couldn't verify PKCS#12 file: %d"), + PORT_GetError()); + goto out; + } + + success = TRUE; + +out: + if (p12ctx) + SEC_PKCS12DecoderFinish(p12ctx); + if (slot) + PK11_FreeSlot(slot); + + if (pw.data) + SECITEM_ZfreeItem(&pw, PR_FALSE); + + return success; +} + +gboolean +_nm_crypto_verify_pkcs8(const guint8 *data, + gsize data_len, + gboolean is_encrypted, + const char * password, + GError ** error) +{ + g_return_val_if_fail(data != NULL, FALSE); + + if (!_nm_crypto_init(error)) + return FALSE; + + /* NSS apparently doesn't do PKCS#8 natively, but you have to put the + * PKCS#8 key into a PKCS#12 file and import that?? So until we figure + * all that out, we can only assume the password is valid. + */ + return TRUE; +} + +gboolean +_nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error) +{ + SECStatus s; + + if (!_nm_crypto_init(error)) + return FALSE; + + s = PK11_GenerateRandom(buffer, buffer_len); + if (s != SECSuccess) { + g_set_error_literal(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Could not generate random data.")); + return FALSE; + } + return TRUE; +} diff --git a/src/libnm-core-impl/nm-crypto.c b/src/libnm-core-impl/nm-crypto.c new file mode 100644 index 0000000000..46888d45b8 --- /dev/null +++ b/src/libnm-core-impl/nm-crypto.c @@ -0,0 +1,1084 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Dan Williams + * Copyright (C) 2007 - 2018 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-crypto.h" + +#include +#include +#include + +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-glib-aux/nm-io-utils.h" + +#include "nm-crypto-impl.h" +#include "nm-utils.h" +#include "nm-errors.h" + +#define PEM_RSA_KEY_BEGIN "-----BEGIN RSA PRIVATE KEY-----" +#define PEM_RSA_KEY_END "-----END RSA PRIVATE KEY-----" + +#define PEM_DSA_KEY_BEGIN "-----BEGIN DSA PRIVATE KEY-----" +#define PEM_DSA_KEY_END "-----END DSA PRIVATE KEY-----" + +#define PEM_CERT_BEGIN "-----BEGIN CERTIFICATE-----" +#define PEM_CERT_END "-----END CERTIFICATE-----" + +#define PEM_PKCS8_ENC_KEY_BEGIN "-----BEGIN ENCRYPTED PRIVATE KEY-----" +#define PEM_PKCS8_ENC_KEY_END "-----END ENCRYPTED PRIVATE KEY-----" + +#define PEM_PKCS8_DEC_KEY_BEGIN "-----BEGIN PRIVATE KEY-----" +#define PEM_PKCS8_DEC_KEY_END "-----END PRIVATE KEY-----" + +#define PEM_TPM2_WRAPPED_KEY_BEGIN "-----BEGIN TSS2 PRIVATE KEY-----" +#define PEM_TPM2_WRAPPED_KEY_END "-----END TSS2 PRIVATE KEY-----" + +#define PEM_TPM2_OLD_WRAPPED_KEY_BEGIN "-----BEGIN TSS2 KEY BLOB-----" +#define PEM_TPM2_OLD_WRAPPED_KEY_END "-----END TSS2 KEY BLOB-----" + +/*****************************************************************************/ + +static const NMCryptoCipherInfo cipher_infos[] = { +#define _CI(_cipher, _name, _digest_len, _real_iv_len) \ + [(_cipher) -1] = {.cipher = _cipher, \ + .name = ""_name \ + "", \ + .digest_len = _digest_len, \ + .real_iv_len = _real_iv_len} + _CI(NM_CRYPTO_CIPHER_DES_EDE3_CBC, "DES-EDE3-CBC", 24, 8), + _CI(NM_CRYPTO_CIPHER_DES_CBC, "DES-CBC", 8, 8), + _CI(NM_CRYPTO_CIPHER_AES_128_CBC, "AES-128-CBC", 16, 16), + _CI(NM_CRYPTO_CIPHER_AES_192_CBC, "AES-192-CBC", 24, 16), + _CI(NM_CRYPTO_CIPHER_AES_256_CBC, "AES-256-CBC", 32, 16), +}; + +const NMCryptoCipherInfo * +nm_crypto_cipher_get_info(NMCryptoCipherType cipher) +{ + g_return_val_if_fail(cipher > NM_CRYPTO_CIPHER_UNKNOWN + && (gsize) cipher < G_N_ELEMENTS(cipher_infos) + 1, + NULL); + +#if NM_MORE_ASSERTS > 10 + { + int i, j; + + for (i = 0; i < (int) G_N_ELEMENTS(cipher_infos); i++) { + const NMCryptoCipherInfo *info = &cipher_infos[i]; + + nm_assert(info->cipher == (NMCryptoCipherType)(i + 1)); + nm_assert(info->name && info->name[0]); + for (j = 0; j < i; j++) + nm_assert(g_ascii_strcasecmp(info->name, cipher_infos[j].name) != 0); + } + } +#endif + + return &cipher_infos[cipher - 1]; +} + +const NMCryptoCipherInfo * +nm_crypto_cipher_get_info_by_name(const char *cipher_name, gssize p_len) +{ + int i; + + nm_assert(nm_crypto_cipher_get_info(NM_CRYPTO_CIPHER_DES_CBC)->cipher + == NM_CRYPTO_CIPHER_DES_CBC); + + if (p_len < 0) { + if (!cipher_name) + return FALSE; + p_len = strlen(cipher_name); + } + + for (i = 0; i < (int) G_N_ELEMENTS(cipher_infos); i++) { + const NMCryptoCipherInfo *info = &cipher_infos[i]; + + if ((gsize) p_len == strlen(info->name) + && g_ascii_strncasecmp(info->name, cipher_name, p_len) == 0) + return info; + } + return NULL; +} + +/*****************************************************************************/ + +static gboolean +find_tag(const char *tag, const guint8 *data, gsize data_len, gsize start_at, gsize *out_pos) +{ + const guint8 *p; + gsize taglen; + + nm_assert(out_pos); + nm_assert(start_at <= data_len); + + taglen = strlen(tag); + + p = memmem(&data[start_at], data_len - start_at, tag, taglen); + if (!p) + return FALSE; + + *out_pos = p - data; + + nm_assert(memcmp(&data[*out_pos], tag, taglen) == 0); + + return TRUE; +} + +#define DEK_INFO_TAG "DEK-Info: " +#define PROC_TYPE_TAG "Proc-Type: " + +static char * +_extract_line(const guint8 **p, const guint8 *p_end) +{ + const guint8 *x, *x0; + + nm_assert(p); + nm_assert(p_end); + nm_assert(*p); + nm_assert(*p < p_end); + + x = x0 = *p; + while (TRUE) { + if (x == p_end) { + *p = p_end; + break; + } + if (*x == '\0') { + /* the data contains embedded NUL. This is the end. */ + *p = p_end; + break; + } + if (*x == '\n') { + *p = x + 1; + break; + } + x++; + } + + if (x == x0) + return NULL; + return g_strndup((char *) x0, x - x0); +} + +static gboolean +parse_old_openssl_key_file(const guint8 * data, + gsize data_len, + NMSecretPtr * out_parsed, + NMCryptoKeyType * out_key_type, + NMCryptoCipherType *out_cipher, + char ** out_iv, + GError ** error) +{ + gsize start = 0, end = 0; + nm_auto_free_secret char * str = NULL; + char * str_p; + gsize str_len; + int enc_tags = 0; + NMCryptoKeyType key_type; + nm_auto_clear_secret_ptr NMSecretPtr parsed = {0}; + nm_auto_free_secret char * iv = NULL; + NMCryptoCipherType cipher = NM_CRYPTO_CIPHER_UNKNOWN; + const char * start_tag; + const char * end_tag; + const guint8 * data_start, *data_end; + + nm_assert(!out_parsed || (out_parsed->len == 0 && !out_parsed->bin)); + nm_assert(!out_iv || !*out_iv); + + NM_SET_OUT(out_key_type, NM_CRYPTO_KEY_TYPE_UNKNOWN); + NM_SET_OUT(out_cipher, NM_CRYPTO_CIPHER_UNKNOWN); + + if (find_tag(PEM_RSA_KEY_BEGIN, data, data_len, 0, &start)) { + key_type = NM_CRYPTO_KEY_TYPE_RSA; + start_tag = PEM_RSA_KEY_BEGIN; + end_tag = PEM_RSA_KEY_END; + } else if (find_tag(PEM_DSA_KEY_BEGIN, data, data_len, 0, &start)) { + key_type = NM_CRYPTO_KEY_TYPE_DSA; + start_tag = PEM_DSA_KEY_BEGIN; + end_tag = PEM_DSA_KEY_END; + } else { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("PEM key file had no start tag")); + return FALSE; + } + + start += strlen(start_tag); + if (!find_tag(end_tag, data, data_len, start, &end)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("PEM key file had no end tag '%s'."), + end_tag); + return FALSE; + } + + str_len = end - start + 1; + str = g_new(char, str_len); + str[0] = '\0'; + str_p = str; + + data_start = &data[start]; + data_end = &data[end]; + + while (data_start < data_end) { + nm_auto_free_secret char *line = NULL; + char * p; + + line = _extract_line(&data_start, data_end); + if (!line) + continue; + + p = nm_secret_strchomp(nm_str_skip_leading_spaces(line)); + + if (!strncmp(p, PROC_TYPE_TAG, strlen(PROC_TYPE_TAG))) { + if (enc_tags++ != 0 || str_p != str) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: Proc-Type was not first tag.")); + return FALSE; + } + + p += strlen(PROC_TYPE_TAG); + if (strcmp(p, "4,ENCRYPTED")) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: unknown Proc-Type tag '%s'."), + p); + return FALSE; + } + } else if (!strncmp(p, DEK_INFO_TAG, strlen(DEK_INFO_TAG))) { + const NMCryptoCipherInfo *cipher_info; + char * comma; + gsize p_len; + + if (enc_tags++ != 1 || str_p != str) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: DEK-Info was not the second tag.")); + return FALSE; + } + + p += strlen(DEK_INFO_TAG); + + /* Grab the IV first */ + comma = strchr(p, ','); + if (!comma || (*(comma + 1) == '\0')) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: no IV found in DEK-Info tag.")); + return FALSE; + } + p_len = comma - p; + comma++; + if (!g_ascii_isxdigit(*comma)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: invalid format of IV in DEK-Info tag.")); + return FALSE; + } + nm_free_secret(iv); + iv = g_strdup(comma); + + /* Get the private key cipher */ + cipher_info = nm_crypto_cipher_get_info_by_name(p, p_len); + if (!cipher_info) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: unknown private key cipher '%s'."), + p); + return FALSE; + } + cipher = cipher_info->cipher; + } else { + if (enc_tags == 1) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + "Malformed PEM file: both Proc-Type and DEK-Info tags are required."); + return FALSE; + } + nm_utils_strbuf_append_str(&str_p, &str_len, p); + nm_assert(str_len > 0); + } + } + + parsed.bin = (guint8 *) g_base64_decode(str, &parsed.len); + if (!parsed.bin || parsed.len == 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Could not decode private key.")); + nm_secret_ptr_clear(&parsed); + return FALSE; + } + + NM_SET_OUT(out_key_type, key_type); + NM_SET_OUT(out_iv, g_steal_pointer(&iv)); + NM_SET_OUT(out_cipher, cipher); + nm_secret_ptr_move(out_parsed, &parsed); + return TRUE; +} + +static gboolean +parse_pkcs8_key_file(const guint8 *data, + gsize data_len, + NMSecretPtr * parsed, + gboolean * out_encrypted, + GError ** error) +{ + gsize start = 0, end = 0; + const char * start_tag = NULL, *end_tag = NULL; + gboolean encrypted = FALSE; + nm_auto_free_secret char *der_base64 = NULL; + + nm_assert(parsed); + nm_assert(!parsed->bin); + nm_assert(parsed->len == 0); + nm_assert(out_encrypted); + + /* Try encrypted first, decrypted next */ + if (find_tag(PEM_PKCS8_ENC_KEY_BEGIN, data, data_len, 0, &start)) { + start_tag = PEM_PKCS8_ENC_KEY_BEGIN; + end_tag = PEM_PKCS8_ENC_KEY_END; + encrypted = TRUE; + } else if (find_tag(PEM_PKCS8_DEC_KEY_BEGIN, data, data_len, 0, &start)) { + start_tag = PEM_PKCS8_DEC_KEY_BEGIN; + end_tag = PEM_PKCS8_DEC_KEY_END; + encrypted = FALSE; + } else { + g_set_error_literal(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to find expected PKCS#8 start tag.")); + return FALSE; + } + + start += strlen(start_tag); + if (!find_tag(end_tag, data, data_len, start, &end)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to find expected PKCS#8 end tag '%s'."), + end_tag); + return FALSE; + } + + /* g_base64_decode() wants a NULL-terminated string */ + der_base64 = g_strndup((char *) &data[start], end - start); + + parsed->bin = (guint8 *) g_base64_decode(der_base64, &parsed->len); + if (!parsed->bin || parsed->len == 0) { + g_set_error_literal(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to decode PKCS#8 private key.")); + nm_secret_ptr_clear(parsed); + return FALSE; + } + + *out_encrypted = encrypted; + return TRUE; +} + +static gboolean +parse_tpm2_wrapped_key_file(const guint8 *data, + gsize data_len, + gboolean * out_encrypted, + GError ** error) +{ + gsize start = 0, end = 0; + const char *start_tag = NULL, *end_tag = NULL; + + nm_assert(out_encrypted); + + if (find_tag(PEM_TPM2_WRAPPED_KEY_BEGIN, data, data_len, 0, &start)) { + start_tag = PEM_TPM2_WRAPPED_KEY_BEGIN; + end_tag = PEM_TPM2_WRAPPED_KEY_END; + } else if (find_tag(PEM_TPM2_OLD_WRAPPED_KEY_BEGIN, data, data_len, 0, &start)) { + start_tag = PEM_TPM2_OLD_WRAPPED_KEY_BEGIN; + end_tag = PEM_TPM2_OLD_WRAPPED_KEY_END; + } else { + g_set_error_literal(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to find expected TSS start tag.")); + return FALSE; + } + + start += strlen(start_tag); + if (!find_tag(end_tag, data, data_len, start, &end)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to find expected TSS end tag '%s'."), + end_tag); + return FALSE; + } + + *out_encrypted = FALSE; + return TRUE; +} + +static gboolean +file_read_contents(const char *filename, NMSecretPtr *out_contents, GError **error) +{ + nm_assert(out_contents); + nm_assert(out_contents->len == 0); + nm_assert(!out_contents->str); + + return nm_utils_file_get_contents(-1, + filename, + 100 * 1024 * 1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, + &out_contents->str, + &out_contents->len, + NULL, + error); +} + +GBytes * +nm_crypto_read_file(const char *filename, GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; + + g_return_val_if_fail(filename, NULL); + + if (!file_read_contents(filename, &contents, error)) + return NULL; + return nm_secret_copy_to_gbytes(contents.bin, contents.len); +} + +/* + * Convert a hex string into bytes. + */ +static guint8 * +_nmtst_convert_iv(const char *src, gsize *out_len, GError **error) +{ + gsize i, num; + gs_free guint8 *c = NULL; + int c0, c1; + + nm_assert(src); + + num = strlen(src); + if (num == 0 || (num % 2) != 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("IV must be an even number of bytes in length.")); + return NULL; + } + + num /= 2; + c = g_malloc(num + 1); + + /* defensively add trailing NUL. This function returns binary data, + * do not assume it's NUL terminated. */ + c[num] = '\0'; + + for (i = 0; i < num; i++) { + if (((c0 = nm_utils_hexchar_to_int(*(src++))) < 0) + || ((c1 = nm_utils_hexchar_to_int(*(src++))) < 0)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("IV contains non-hexadecimal digits.")); + nm_explicit_bzero(c, i); + return FALSE; + } + + c[i] = (c0 << 4) + c1; + } + *out_len = num; + return g_steal_pointer(&c); +} + +guint8 * +nmtst_crypto_make_des_aes_key(NMCryptoCipherType cipher, + const guint8 * salt, + gsize salt_len, + const char * password, + gsize * out_len, + GError ** error) +{ + guint8 * key; + const NMCryptoCipherInfo *cipher_info; + + g_return_val_if_fail(salt != NULL, NULL); + g_return_val_if_fail(salt_len >= 8, NULL); + g_return_val_if_fail(password != NULL, NULL); + g_return_val_if_fail(out_len != NULL, NULL); + + *out_len = 0; + + cipher_info = nm_crypto_cipher_get_info(cipher); + + g_return_val_if_fail(cipher_info, NULL); + + if (password[0] == '\0') + return NULL; + + key = g_malloc(cipher_info->digest_len); + + nm_crypto_md5_hash(salt, + 8, + (guint8 *) password, + strlen(password), + key, + cipher_info->digest_len); + + *out_len = cipher_info->digest_len; + return key; +} + +static gboolean +_nmtst_decrypt_key(NMCryptoCipherType cipher, + const guint8 * data, + gsize data_len, + const char * iv, + const char * password, + NMSecretPtr * parsed, + GError ** error) +{ + nm_auto_clear_secret_ptr NMSecretPtr bin_iv = {0}; + nm_auto_clear_secret_ptr NMSecretPtr key = {0}; + + nm_assert(password); + nm_assert(cipher != NM_CRYPTO_CIPHER_UNKNOWN); + nm_assert(iv); + nm_assert(parsed); + nm_assert(!parsed->bin); + nm_assert(parsed->len == 0); + + bin_iv.bin = _nmtst_convert_iv(iv, &bin_iv.len, error); + if (!bin_iv.bin) + return FALSE; + + if (bin_iv.len < 8) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("IV must contain at least 8 characters")); + return FALSE; + } + + /* Convert the password and IV into a DES or AES key */ + key.bin = + nmtst_crypto_make_des_aes_key(cipher, bin_iv.bin, bin_iv.len, password, &key.len, error); + if (!key.bin || !key.len) + return FALSE; + + parsed->bin = _nmtst_crypto_decrypt(cipher, + data, + data_len, + bin_iv.bin, + bin_iv.len, + key.bin, + key.len, + &parsed->len, + error); + if (!parsed->bin || parsed->len == 0) { + nm_secret_ptr_clear(parsed); + return FALSE; + } + + return TRUE; +} + +GBytes * +nmtst_crypto_decrypt_openssl_private_key_data(const guint8 * data, + gsize data_len, + const char * password, + NMCryptoKeyType *out_key_type, + GError ** error) +{ + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + nm_auto_clear_secret_ptr NMSecretPtr parsed = {0}; + nm_auto_free_secret char * iv = NULL; + NMCryptoCipherType cipher = NM_CRYPTO_CIPHER_UNKNOWN; + + g_return_val_if_fail(data != NULL, NULL); + + NM_SET_OUT(out_key_type, NM_CRYPTO_KEY_TYPE_UNKNOWN); + + if (!_nm_crypto_init(error)) + return NULL; + + if (!parse_old_openssl_key_file(data, data_len, &parsed, &key_type, &cipher, &iv, NULL)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Unable to determine private key type.")); + return NULL; + } + + NM_SET_OUT(out_key_type, key_type); + + if (password) { + nm_auto_clear_secret_ptr NMSecretPtr parsed2 = {0}; + + if (cipher == NM_CRYPTO_CIPHER_UNKNOWN || !iv) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_PASSWORD, + _("Password provided, but key was not encrypted.")); + return NULL; + } + + if (!_nmtst_decrypt_key(cipher, parsed.bin, parsed.len, iv, password, &parsed2, error)) + return NULL; + + return nm_secret_copy_to_gbytes(parsed2.bin, parsed2.len); + } + + if (cipher != NM_CRYPTO_CIPHER_UNKNOWN || iv) + return NULL; + + return nm_secret_copy_to_gbytes(parsed.bin, parsed.len); +} + +GBytes * +nmtst_crypto_decrypt_openssl_private_key(const char * file, + const char * password, + NMCryptoKeyType *out_key_type, + GError ** error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; + + if (!_nm_crypto_init(error)) + return NULL; + + if (!file_read_contents(file, &contents, error)) + return NULL; + + return nmtst_crypto_decrypt_openssl_private_key_data(contents.bin, + contents.len, + password, + out_key_type, + error); +} + +static gboolean +extract_pem_cert_data(const guint8 *contents, + gsize contents_len, + NMSecretPtr * out_cert, + GError ** error) +{ + gsize start = 0; + gsize end = 0; + nm_auto_free_secret char *der_base64 = NULL; + + nm_assert(contents); + nm_assert(out_cert); + nm_assert(out_cert->len == 0); + nm_assert(!out_cert->ptr); + + if (!find_tag(PEM_CERT_BEGIN, contents, contents_len, 0, &start)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("PEM certificate had no start tag '%s'."), + PEM_CERT_BEGIN); + return FALSE; + } + + start += strlen(PEM_CERT_BEGIN); + if (!find_tag(PEM_CERT_END, contents, contents_len, start, &end)) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("PEM certificate had no end tag '%s'."), + PEM_CERT_END); + return FALSE; + } + + /* g_base64_decode() wants a NULL-terminated string */ + der_base64 = g_strndup((const char *) &contents[start], end - start); + + out_cert->bin = (guint8 *) g_base64_decode(der_base64, &out_cert->len); + if (!out_cert->bin || !out_cert->len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to decode certificate.")); + nm_secret_ptr_clear(out_cert); + return FALSE; + } + + return TRUE; +} + +gboolean +nm_crypto_load_and_verify_certificate(const char * file, + NMCryptoFileFormat *out_file_format, + GBytes ** out_certificate, + GError ** error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; + + g_return_val_if_fail(file, FALSE); + nm_assert(!error || !*error); + + if (!_nm_crypto_init(error)) + goto out; + + if (!file_read_contents(file, &contents, error)) + goto out; + + if (contents.len == 0) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Certificate file is empty")); + goto out; + } + + /* Check for PKCS#12 */ + if (nm_crypto_is_pkcs12_data(contents.bin, contents.len, NULL)) { + NM_SET_OUT(out_file_format, NM_CRYPTO_FILE_FORMAT_PKCS12); + NM_SET_OUT(out_certificate, nm_secret_copy_to_gbytes(contents.bin, contents.len)); + return TRUE; + } + + /* Check for plain DER format */ + if (contents.len > 2 && contents.bin[0] == 0x30 && contents.bin[1] == 0x82) { + if (_nm_crypto_verify_x509(contents.bin, contents.len, NULL)) { + NM_SET_OUT(out_file_format, NM_CRYPTO_FILE_FORMAT_X509); + NM_SET_OUT(out_certificate, nm_secret_copy_to_gbytes(contents.bin, contents.len)); + return TRUE; + } + } else { + nm_auto_clear_secret_ptr NMSecretPtr pem_cert = {0}; + + if (extract_pem_cert_data(contents.bin, contents.len, &pem_cert, NULL)) { + if (_nm_crypto_verify_x509(pem_cert.bin, pem_cert.len, NULL)) { + NM_SET_OUT(out_file_format, NM_CRYPTO_FILE_FORMAT_X509); + NM_SET_OUT(out_certificate, nm_secret_copy_to_gbytes(contents.bin, contents.len)); + return TRUE; + } + } + } + + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to recognize certificate")); + +out: + NM_SET_OUT(out_file_format, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + NM_SET_OUT(out_certificate, NULL); + return FALSE; +} + +gboolean +nm_crypto_is_pkcs12_data(const guint8 *data, gsize data_len, GError **error) +{ + GError * local = NULL; + gboolean success; + + if (!data_len) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Certificate file is empty")); + return FALSE; + } + + g_return_val_if_fail(data != NULL, FALSE); + + if (!_nm_crypto_init(error)) + return FALSE; + + success = _nm_crypto_verify_pkcs12(data, data_len, NULL, &local); + if (success == FALSE) { + /* If the error was just a decryption error, then it's pkcs#12 */ + if (local) { + if (g_error_matches(local, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED)) { + success = TRUE; + g_error_free(local); + } else + g_propagate_error(error, local); + } + } + return success; +} + +gboolean +nm_crypto_is_pkcs12_file(const char *file, GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; + + g_return_val_if_fail(file != NULL, FALSE); + + if (!_nm_crypto_init(error)) + return FALSE; + + if (!file_read_contents(file, &contents, error)) + return FALSE; + + return nm_crypto_is_pkcs12_data(contents.bin, contents.len, error); +} + +/* Verifies that a private key can be read, and if a password is given, that + * the private key can be decrypted with that password. + */ +NMCryptoFileFormat +nm_crypto_verify_private_key_data(const guint8 *data, + gsize data_len, + const char * password, + gboolean * out_is_encrypted, + GError ** error) +{ + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gboolean is_encrypted = FALSE; + + g_return_val_if_fail(data != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + g_return_val_if_fail(out_is_encrypted == NULL || *out_is_encrypted == FALSE, + NM_CRYPTO_FILE_FORMAT_UNKNOWN); + + if (!_nm_crypto_init(error)) + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + + /* Check for PKCS#12 first */ + if (nm_crypto_is_pkcs12_data(data, data_len, NULL)) { + is_encrypted = TRUE; + if (!password || _nm_crypto_verify_pkcs12(data, data_len, password, error)) + format = NM_CRYPTO_FILE_FORMAT_PKCS12; + } else { + nm_auto_clear_secret_ptr NMSecretPtr parsed = {0}; + + /* Maybe it's PKCS#8 */ + if (parse_pkcs8_key_file(data, data_len, &parsed, &is_encrypted, NULL)) { + if (!password + || _nm_crypto_verify_pkcs8(parsed.bin, parsed.len, is_encrypted, password, error)) + format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; + } else if (parse_tpm2_wrapped_key_file(data, data_len, &is_encrypted, NULL)) { + format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; + } else { + NMCryptoCipherType cipher; + nm_auto_free_secret char *iv = NULL; + + /* Or it's old-style OpenSSL */ + if (parse_old_openssl_key_file(data, data_len, NULL, NULL, &cipher, &iv, NULL)) { + format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; + is_encrypted = (cipher != NM_CRYPTO_CIPHER_UNKNOWN && iv); + } + } + } + + if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN && error && !*error) { + g_set_error(error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("not a valid private key")); + } + + if (out_is_encrypted) + *out_is_encrypted = is_encrypted; + return format; +} + +NMCryptoFileFormat +nm_crypto_verify_private_key(const char *filename, + const char *password, + gboolean * out_is_encrypted, + GError ** error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; + + g_return_val_if_fail(filename != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + + if (!_nm_crypto_init(error)) + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + + if (!file_read_contents(filename, &contents, error)) + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + + return nm_crypto_verify_private_key_data(contents.bin, + contents.len, + password, + out_is_encrypted, + error); +} + +void +nm_crypto_md5_hash(const guint8 *salt, + gsize salt_len, + const guint8 *password, + gsize password_len, + guint8 * buffer, + gsize buflen) +{ + nm_auto_free_checksum GChecksum * ctx = NULL; + nm_auto_clear_static_secret_ptr const NMSecretPtr digest = + NM_SECRET_PTR_STATIC(NM_UTILS_CHECKSUM_LENGTH_MD5); + gsize bufidx = 0; + int i; + + g_return_if_fail(password_len == 0 || password); + g_return_if_fail(buffer); + g_return_if_fail(buflen > 0); + g_return_if_fail(salt_len == 0 || salt); + + ctx = g_checksum_new(G_CHECKSUM_MD5); + + for (;;) { + if (password_len > 0) + g_checksum_update(ctx, (const guchar *) password, password_len); + if (salt_len > 0) + g_checksum_update(ctx, (const guchar *) salt, salt_len); + + nm_utils_checksum_get_digest_len(ctx, digest.bin, NM_UTILS_CHECKSUM_LENGTH_MD5); + + for (i = 0; i < NM_UTILS_CHECKSUM_LENGTH_MD5; i++) { + if (bufidx >= buflen) + return; + buffer[bufidx++] = digest.bin[i]; + } + + g_checksum_reset(ctx); + g_checksum_update(ctx, digest.ptr, NM_UTILS_CHECKSUM_LENGTH_MD5); + } +} + +gboolean +nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error) +{ + return _nm_crypto_randomize(buffer, buffer_len, error); +} + +/** + * nmtst_crypto_rsa_key_encrypt: + * @data: (array length=len): RSA private key data to be encrypted + * @len: length of @data + * @in_password: (allow-none): existing password to use, if any + * @out_password: (out) (allow-none): if @in_password was %NULL, a random + * password will be generated and returned in this argument + * @error: detailed error information on return, if an error occurred + * + * Encrypts the given RSA private key data with the given password (or generates + * a password if no password was given) and converts the data to PEM format + * suitable for writing to a file. It uses Triple DES cipher for the encryption. + * + * Returns: (transfer full): on success, PEM-formatted data suitable for writing + * to a PEM-formatted certificate/private key file. + **/ +GBytes * +nmtst_crypto_rsa_key_encrypt(const guint8 *data, + gsize len, + const char * in_password, + char ** out_password, + GError ** error) +{ + guint8 salt[8]; + nm_auto_clear_secret_ptr NMSecretPtr key = {0}; + nm_auto_clear_secret_ptr NMSecretPtr enc = {0}; + gs_unref_ptrarray GPtrArray *pem = NULL; + nm_auto_free_secret char * tmp_password = NULL; + nm_auto_free_secret char * enc_base64 = NULL; + gsize enc_base64_len; + const char * p; + gsize ret_len, ret_idx; + guint i; + NMSecretBuf * ret; + + g_return_val_if_fail(data, NULL); + g_return_val_if_fail(len > 0, NULL); + g_return_val_if_fail(!out_password || !*out_password, NULL); + + /* Make the password if needed */ + if (!in_password) { + nm_auto_clear_static_secret_ptr NMSecretPtr pw_buf = NM_SECRET_PTR_STATIC(32); + + if (!nm_crypto_randomize(pw_buf.bin, pw_buf.len, error)) + return NULL; + tmp_password = nm_utils_bin2hexstr(pw_buf.bin, pw_buf.len, -1); + in_password = tmp_password; + } + + if (!nm_crypto_randomize(salt, sizeof(salt), error)) + return NULL; + + key.bin = nmtst_crypto_make_des_aes_key(NM_CRYPTO_CIPHER_DES_EDE3_CBC, + salt, + sizeof(salt), + in_password, + &key.len, + NULL); + if (!key.bin) + g_return_val_if_reached(NULL); + + enc.bin = _nmtst_crypto_encrypt(NM_CRYPTO_CIPHER_DES_EDE3_CBC, + data, + len, + salt, + sizeof(salt), + key.bin, + key.len, + &enc.len, + error); + if (!enc.bin) + return NULL; + + /* What follows is not the most efficient way to construct the pem + * file line-by-line. At least, it makes sure, that the data will be cleared + * again and not left around in memory. + * + * If this would not be test code, we should improve the implementation + * to avoid some of the copying. */ + pem = g_ptr_array_new_with_free_func((GDestroyNotify) nm_free_secret); + + g_ptr_array_add(pem, g_strdup("-----BEGIN RSA PRIVATE KEY-----\n")); + g_ptr_array_add(pem, g_strdup("Proc-Type: 4,ENCRYPTED\n")); + + /* Convert the salt to a hex string */ + g_ptr_array_add( + pem, + g_strdup_printf("DEK-Info: %s,", + nm_crypto_cipher_get_info(NM_CRYPTO_CIPHER_DES_EDE3_CBC)->name)); + g_ptr_array_add(pem, nm_utils_bin2hexstr(salt, sizeof(salt), sizeof(salt) * 2)); + g_ptr_array_add(pem, g_strdup("\n\n")); + + /* Convert the encrypted key to a base64 string */ + enc_base64 = g_base64_encode((const guchar *) enc.bin, enc.len); + enc_base64_len = strlen(enc_base64); + for (p = enc_base64; (p - enc_base64) < (ptrdiff_t) enc_base64_len; p += 64) { + g_ptr_array_add(pem, g_strndup(p, 64)); + g_ptr_array_add(pem, g_strdup("\n")); + } + + g_ptr_array_add(pem, g_strdup("-----END RSA PRIVATE KEY-----\n")); + + ret_len = 0; + for (i = 0; i < pem->len; i++) + ret_len += strlen(pem->pdata[i]); + + ret = nm_secret_buf_new(ret_len + 1); + ret_idx = 0; + for (i = 0; i < pem->len; i++) { + const char *line = pem->pdata[i]; + gsize line_l = strlen(line); + + memcpy(&ret->bin[ret_idx], line, line_l); + ret_idx += line_l; + nm_assert(ret_idx <= ret_len); + } + nm_assert(ret_idx == ret_len); + ret->bin[ret_len] = '\0'; + + NM_SET_OUT(out_password, g_strdup(tmp_password)); + return nm_secret_buf_to_gbytes_take(ret, ret_len); +} diff --git a/src/libnm-core-impl/nm-crypto.h b/src/libnm-core-impl/nm-crypto.h new file mode 100644 index 0000000000..8665a234bf --- /dev/null +++ b/src/libnm-core-impl/nm-crypto.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Dan Williams + * Copyright (C) 2007 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_CRYPTO_H__ +#define __NM_CRYPTO_H__ + +typedef enum { + NM_CRYPTO_CIPHER_UNKNOWN, + NM_CRYPTO_CIPHER_DES_EDE3_CBC, + NM_CRYPTO_CIPHER_DES_CBC, + NM_CRYPTO_CIPHER_AES_128_CBC, + NM_CRYPTO_CIPHER_AES_192_CBC, + NM_CRYPTO_CIPHER_AES_256_CBC, +} NMCryptoCipherType; + +typedef struct { + const char * name; + NMCryptoCipherType cipher; + guint8 digest_len; + guint8 real_iv_len; +} NMCryptoCipherInfo; + +const NMCryptoCipherInfo *nm_crypto_cipher_get_info(NMCryptoCipherType cipher); +const NMCryptoCipherInfo *nm_crypto_cipher_get_info_by_name(const char *cipher_name, gssize p_len); + +typedef enum { + NM_CRYPTO_KEY_TYPE_UNKNOWN = 0, + NM_CRYPTO_KEY_TYPE_RSA, + NM_CRYPTO_KEY_TYPE_DSA +} NMCryptoKeyType; + +typedef enum { + NM_CRYPTO_FILE_FORMAT_UNKNOWN = 0, + NM_CRYPTO_FILE_FORMAT_X509, + NM_CRYPTO_FILE_FORMAT_RAW_KEY, + NM_CRYPTO_FILE_FORMAT_PKCS12 +} NMCryptoFileFormat; + +/*****************************************************************************/ + +GBytes *nm_crypto_read_file(const char *filename, GError **error); + +gboolean nm_crypto_load_and_verify_certificate(const char * file, + NMCryptoFileFormat *out_file_format, + GBytes ** out_certificat, + GError ** error); + +gboolean nm_crypto_is_pkcs12_file(const char *file, GError **error); + +gboolean nm_crypto_is_pkcs12_data(const guint8 *data, gsize len, GError **error); + +NMCryptoFileFormat nm_crypto_verify_private_key_data(const guint8 *data, + gsize data_len, + const char * password, + gboolean * out_is_encrypted, + GError ** error); + +NMCryptoFileFormat nm_crypto_verify_private_key(const char *file, + const char *password, + gboolean * out_is_encrypted, + GError ** error); + +void nm_crypto_md5_hash(const guint8 *salt, + gsize salt_len, + const guint8 *password, + gsize password_len, + guint8 * buffer, + gsize buflen); + +gboolean nm_crypto_randomize(void *buffer, gsize buffer_len, GError **error); + +/*****************************************************************************/ + +GBytes *nmtst_crypto_decrypt_openssl_private_key_data(const guint8 * data, + gsize data_len, + const char * password, + NMCryptoKeyType *out_key_type, + GError ** error); + +GBytes *nmtst_crypto_decrypt_openssl_private_key(const char * file, + const char * password, + NMCryptoKeyType *out_key_type, + GError ** error); + +GBytes *nmtst_crypto_rsa_key_encrypt(const guint8 *data, + gsize len, + const char * in_password, + char ** out_password, + GError ** error); + +guint8 *nmtst_crypto_make_des_aes_key(NMCryptoCipherType cipher, + const guint8 * salt, + gsize salt_len, + const char * password, + gsize * out_len, + GError ** error); + +/*****************************************************************************/ + +#endif /* __NM_CRYPTO_H__ */ diff --git a/src/libnm-core-impl/nm-dbus-utils.c b/src/libnm-core-impl/nm-dbus-utils.c new file mode 100644 index 0000000000..a272f08ce9 --- /dev/null +++ b/src/libnm-core-impl/nm-dbus-utils.c @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "libnm-core-intern/nm-core-internal.h" + +typedef struct { + char * signal_name; + const GVariantType *signature; +} NMDBusSignalData; + +static void +dbus_signal_data_free(gpointer data, GClosure *closure) +{ + NMDBusSignalData *sd = data; + + g_free(sd->signal_name); + g_slice_free(NMDBusSignalData, sd); +} + +static void +dbus_signal_meta_marshal(GClosure * closure, + GValue * return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + NMDBusSignalData *sd = marshal_data; + const char * signal_name; + GVariant * parameters, *param; + GValue * closure_params; + gsize n_params, i; + + g_return_if_fail(n_param_values == 4); + + signal_name = g_value_get_string(¶m_values[2]); + parameters = g_value_get_variant(¶m_values[3]); + + if (strcmp(signal_name, sd->signal_name) != 0) + return; + + if (sd->signature) { + if (!g_variant_is_of_type(parameters, sd->signature)) { + g_warning("%p: got signal '%s' but parameters were of type '%s', not '%s'", + g_value_get_object(¶m_values[0]), + signal_name, + g_variant_get_type_string(parameters), + g_variant_type_peek_string(sd->signature)); + return; + } + + n_params = g_variant_n_children(parameters) + 1; + } else + n_params = 1; + + closure_params = g_new0(GValue, n_params); + g_value_init(&closure_params[0], G_TYPE_OBJECT); + g_value_copy(¶m_values[0], &closure_params[0]); + + for (i = 1; i < n_params; i++) { + param = g_variant_get_child_value(parameters, i - 1); + if (g_variant_is_of_type(param, G_VARIANT_TYPE("ay")) + || g_variant_is_of_type(param, G_VARIANT_TYPE("aay"))) { + /* g_dbus_gvariant_to_gvalue() thinks 'ay' means "non-UTF-8 NUL-terminated string" */ + g_value_init(&closure_params[i], G_TYPE_VARIANT); + g_value_set_variant(&closure_params[i], param); + } else + g_dbus_gvariant_to_gvalue(param, &closure_params[i]); + g_variant_unref(param); + } + + g_cclosure_marshal_generic(closure, NULL, n_params, closure_params, invocation_hint, NULL); + + for (i = 0; i < n_params; i++) + g_value_unset(&closure_params[i]); + g_free(closure_params); +} + +/** + * _nm_dbus_signal_connect_data: + * @proxy: a #GDBusProxy + * @signal_name: the D-Bus signal to connect to + * @signature: (allow-none): the signal's type signature (must be a tuple) + * @c_handler: the signal handler function + * @data: (allow-none): data to pass to @c_handler + * @destroy_data: (allow-none): closure destroy notify for @data + * @connect_flags: connection flags + * + * Connects to the D-Bus signal @signal_name on @proxy. @c_handler must be a + * void function whose first argument is a #GDBusProxy, followed by arguments + * for each element of @signature, ending with a #gpointer argument for @data. + * + * The argument types in @c_handler correspond to the types output by + * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular: + * - both 16-bit and 32-bit integers are passed as #int/#guint + * - 'as' values are passed as #GStrv (char **) + * - all other array, tuple, and dict types are passed as #GVariant + * + * If @signature is %NULL, then the signal's parameters will be ignored, and + * @c_handler should take only the #GDBusProxy and #gpointer arguments. + * + * Returns: the signal handler ID, which can be used with + * g_signal_handler_remove(). Beware that because of the way the signal is + * connected, you will not be able to remove it with + * g_signal_handlers_disconnect_by_func(), although + * g_signal_handlers_disconnect_by_data() will work correctly. + */ +gulong +_nm_dbus_signal_connect_data(GDBusProxy * proxy, + const char * signal_name, + const GVariantType *signature, + GCallback c_handler, + gpointer data, + GClosureNotify destroy_data, + GConnectFlags connect_flags) +{ + NMDBusSignalData *sd; + GClosure * closure; + gboolean swapped = !!(connect_flags & G_CONNECT_SWAPPED); + gboolean after = !!(connect_flags & G_CONNECT_AFTER); + + g_return_val_if_fail(G_IS_DBUS_PROXY(proxy), 0); + g_return_val_if_fail(signal_name != NULL, 0); + g_return_val_if_fail(signature == NULL || g_variant_type_is_tuple(signature), 0); + g_return_val_if_fail(c_handler != NULL, 0); + + sd = g_slice_new(NMDBusSignalData); + sd->signal_name = g_strdup(signal_name); + sd->signature = signature; + + closure = (swapped ? g_cclosure_new_swap : g_cclosure_new)(c_handler, data, destroy_data); + g_closure_set_marshal(closure, g_cclosure_marshal_generic); + g_closure_set_meta_marshal(closure, sd, dbus_signal_meta_marshal); + g_closure_add_finalize_notifier(closure, sd, dbus_signal_data_free); + + return g_signal_connect_closure(proxy, "g-signal", closure, after); +} + +/** + * _nm_dbus_signal_connect: + * @proxy: a #GDBusProxy + * @signal_name: the D-Bus signal to connect to + * @signature: the signal's type signature (must be a tuple) + * @c_handler: the signal handler function + * @data: (allow-none): data to pass to @c_handler + * + * Simplified version of _nm_dbus_signal_connect_data() with fewer arguments. + * + * Returns: the signal handler ID, as with _nm_signal_connect_data(). + */ + +/** + * _nm_dbus_typecheck_response: + * @response: the #GVariant response to check. + * @reply_type: the expected reply type. It may be %NULL to perform no + * checking. + * @error: (allow-none): the error in case the @reply_type does not match. + * + * Returns: %TRUE, if @response is of the expected @reply_type. + */ +gboolean +_nm_dbus_typecheck_response(GVariant *response, const GVariantType *reply_type, GError **error) +{ + g_return_val_if_fail(response, FALSE); + + if (!reply_type) + return TRUE; + if (g_variant_is_of_type(response, reply_type)) + return TRUE; + + /* This is the same error code that g_dbus_connection_call() returns if + * @reply_type doesn't match. + */ + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Method returned type '%s', but expected '%s'"), + g_variant_get_type_string(response), + g_variant_type_peek_string(reply_type)); + return FALSE; +} + +/** + * _nm_dbus_proxy_call_finish: + * @proxy: A #GDBusProxy. + * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to + * g_dbus_proxy_call(). + * @reply_type: (allow-none): the expected type of the reply, or %NULL + * @error: Return location for error or %NULL. + * + * Finishes an operation started with g_dbus_proxy_call(), as with + * g_dbus_proxy_call_finish(), except thatif @reply_type is non-%NULL, then it + * will also check that the response matches that type signature, and return + * an error if not. + * + * Returns: %NULL if @error is set. Otherwise, a #GVariant tuple with + * return values. Free with g_variant_unref(). + */ +GVariant * +_nm_dbus_proxy_call_finish(GDBusProxy * proxy, + GAsyncResult * res, + const GVariantType *reply_type, + GError ** error) +{ + GVariant *variant; + + variant = g_dbus_proxy_call_finish(proxy, res, error); + if (variant && !_nm_dbus_typecheck_response(variant, reply_type, error)) + nm_clear_pointer(&variant, g_variant_unref); + return variant; +} + +GVariant * +_nm_dbus_connection_call_finish(GDBusConnection * dbus_connection, + GAsyncResult * result, + const GVariantType *reply_type, + GError ** error) +{ + GVariant *variant; + + variant = g_dbus_connection_call_finish(dbus_connection, result, error); + if (variant && !_nm_dbus_typecheck_response(variant, reply_type, error)) + nm_clear_pointer(&variant, g_variant_unref); + return variant; +} + +/** + * _nm_dbus_error_has_name: + * @error: (allow-none): a #GError, or %NULL + * @dbus_error_name: a D-Bus error name + * + * Checks if @error is set and corresponds to the D-Bus error @dbus_error_name. + * + * This should only be used for "foreign" D-Bus errors (eg, errors + * from BlueZ or wpa_supplicant). All NetworkManager D-Bus errors + * should be properly mapped by gdbus to one of the domains/codes in + * nm-errors.h. + * + * Returns: %TRUE or %FALSE + */ +gboolean +_nm_dbus_error_has_name(GError *error, const char *dbus_error_name) +{ + gboolean has_name = FALSE; + + if (error && g_dbus_error_is_remote_error(error)) { + char *error_name; + + error_name = g_dbus_error_get_remote_error(error); + has_name = !g_strcmp0(error_name, dbus_error_name); + g_free(error_name); + } + + return has_name; +} diff --git a/src/libnm-core-impl/nm-default-libnm-core.h b/src/libnm-core-impl/nm-default-libnm-core.h new file mode 100644 index 0000000000..6eb84b947a --- /dev/null +++ b/src/libnm-core-impl/nm-default-libnm-core.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_DEFAULT_LIBNM_CORE_H__ +#define __NM_DEFAULT_LIBNM_CORE_H__ + +/*****************************************************************************/ + +#include "nm-glib-aux/nm-default-glib-i18n-lib.h" + +#undef NETWORKMANAGER_COMPILATION +#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE + +/*****************************************************************************/ + +#include "nm-version.h" + +/*****************************************************************************/ + +#endif /* __NM_DEFAULT_LIBNM_CORE_H__ */ diff --git a/src/libnm-core-impl/nm-errors.c b/src/libnm-core-impl/nm-errors.c new file mode 100644 index 0000000000..ea4ca5e9e6 --- /dev/null +++ b/src/libnm-core-impl/nm-errors.c @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2004 - 2014 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-errors.h" + +#include "nm-vpn-dbus-interface.h" +#include "libnm-core-intern/nm-core-internal.h" + +NM_CACHED_QUARK_FCN("nm-agent-manager-error-quark", nm_agent_manager_error_quark); +NM_CACHED_QUARK_FCN("nm-connection-error-quark", nm_connection_error_quark); +NM_CACHED_QUARK_FCN("nm-crypto-error-quark", nm_crypto_error_quark); +NM_CACHED_QUARK_FCN("nm-device-error-quark", nm_device_error_quark); +NM_CACHED_QUARK_FCN("nm-secret-agent-error-quark", nm_secret_agent_error_quark); +NM_CACHED_QUARK_FCN("nm-settings-error-quark", nm_settings_error_quark); +NM_CACHED_QUARK_FCN("nm-vpn-plugin-error-quark", nm_vpn_plugin_error_quark); + +static void +register_error_domain(GQuark domain, const char *interface, GType enum_type) +{ + nm_auto_unref_gtypeclass GEnumClass *enum_class = g_type_class_ref(enum_type); + guint i; + + for (i = 0; i < enum_class->n_values; i++) { + const GEnumValue *e = &enum_class->values[i]; + char error_name[200]; + + nm_assert(e && e->value_nick && !strchr(e->value_nick, '-')); + + nm_sprintf_buf(error_name, "%s.%s", interface, e->value_nick); + if (!g_dbus_error_register_error(domain, e->value, error_name)) + nm_assert_not_reached(); + } +} + +void +_nm_dbus_errors_init(void) +{ + register_error_domain(NM_AGENT_MANAGER_ERROR, + NM_DBUS_INTERFACE_AGENT_MANAGER, + NM_TYPE_AGENT_MANAGER_ERROR); + register_error_domain(NM_CONNECTION_ERROR, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + NM_TYPE_CONNECTION_ERROR); + register_error_domain(NM_DEVICE_ERROR, NM_DBUS_INTERFACE_DEVICE, NM_TYPE_DEVICE_ERROR); + register_error_domain(NM_MANAGER_ERROR, NM_DBUS_INTERFACE, NM_TYPE_MANAGER_ERROR); + register_error_domain(NM_SECRET_AGENT_ERROR, + NM_DBUS_INTERFACE_SECRET_AGENT, + NM_TYPE_SECRET_AGENT_ERROR); + register_error_domain(NM_SETTINGS_ERROR, NM_DBUS_INTERFACE_SETTINGS, NM_TYPE_SETTINGS_ERROR); + register_error_domain(NM_VPN_PLUGIN_ERROR, NM_DBUS_VPN_ERROR_PREFIX, NM_TYPE_VPN_PLUGIN_ERROR); +} diff --git a/src/libnm-core-impl/nm-keyfile-utils.c b/src/libnm-core-impl/nm-keyfile-utils.c new file mode 100644 index 0000000000..6e1a255314 --- /dev/null +++ b/src/libnm-core-impl/nm-keyfile-utils.c @@ -0,0 +1,684 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2010 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "libnm-core-intern/nm-keyfile-utils.h" + +#include + +#include "nm-glib-aux/nm-str-buf.h" + +#include "nm-keyfile.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wireless-security.h" + +#include "libnm-core-intern/nm-keyfile-internal.h" + +/*****************************************************************************/ + +/** + * nm_key_file_get_boolean: + * @kf: the #GKeyFile + * @group: the group + * @key: the key + * @default_value: the default value if the value is set or not parsable as a boolean. + * + * Replacement for g_key_file_get_boolean() (which uses g_key_file_parse_value_as_boolean()). + * g_key_file_get_boolean() seems odd to me, because it accepts trailing ASCII whitespace, + * but not leading. + * This uses _nm_utils_ascii_str_to_bool(), which accepts trailing and leading whitespace, + * case-insensitive words, and also strings like "on" and "off". + * _nm_utils_ascii_str_to_bool() is our way to parse booleans from string, and we should + * use that one consistently. + * + * Also, it doesn't have g_key_file_get_boolean()'s odd API to require an error argument + * to detect parsing failures. + * + * Returns: either %TRUE or %FALSE if the key exists and is parsable as a boolean. + * Otherwise, @default_value. Sets errno to ENODATA, EINVAL or 0, depending on whether + * the key exists, whether the value is invalid, or success. + */ +int +nm_key_file_get_boolean(GKeyFile *kf, const char *group, const char *key, int default_value) +{ + int v; + gs_free char *value = NULL; + + value = g_key_file_get_value(kf, group, key, NULL); + + if (!value) { + errno = ENODATA; + return default_value; + } + v = _nm_utils_ascii_str_to_bool(value, -1); + if (v != -1) { + errno = 0; + return v; + } + errno = EINVAL; + return default_value; +} + +/*****************************************************************************/ + +typedef struct { + const char *setting; + const char *alias; +} SettingAlias; + +static const SettingAlias alias_list[] = { + {NM_SETTING_WIRED_SETTING_NAME, "ethernet"}, + {NM_SETTING_WIRELESS_SETTING_NAME, "wifi"}, + {NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, "wifi-security"}, +}; + +const char * +nm_keyfile_plugin_get_alias_for_setting_name(const char *setting_name) +{ + guint i; + + g_return_val_if_fail(setting_name != NULL, NULL); + + for (i = 0; i < G_N_ELEMENTS(alias_list); i++) { + if (nm_streq(setting_name, alias_list[i].setting)) + return alias_list[i].alias; + } + return NULL; +} + +const char * +nm_keyfile_plugin_get_setting_name_for_alias(const char *alias) +{ + guint i; + + g_return_val_if_fail(alias != NULL, NULL); + + for (i = 0; i < G_N_ELEMENTS(alias_list); i++) { + if (nm_streq(alias, alias_list[i].alias)) + return alias_list[i].setting; + } + return NULL; +} + +/*****************************************************************************/ + +char ** +nm_keyfile_plugin_kf_get_string_list(GKeyFile * kf, + const char *group, + const char *key, + gsize * out_length, + GError ** error) +{ + char ** list; + const char *alias; + GError * local = NULL; + gsize l; + + list = g_key_file_get_string_list(kf, group, key, &l, &local); + if (nm_g_error_matches(local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { + alias = nm_keyfile_plugin_get_alias_for_setting_name(group); + if (alias) { + g_clear_error(&local); + list = g_key_file_get_string_list(kf, alias, key, &l, &local); + } + } + if (local) + g_propagate_error(error, local); + if (!list) + l = 0; + NM_SET_OUT(out_length, l); + return list; +} + +guint * +nm_keyfile_plugin_kf_get_integer_list_uint(GKeyFile * key_file, + const char *group_name, + const char *key, + gsize * out_length, + GError ** error) +{ + GError * key_file_error = NULL; + gs_strfreev char **values = NULL; + gs_free guint *int_values = NULL; + gsize i, num_ints; + + NM_SET_OUT(out_length, 0); + + g_return_val_if_fail(key_file != NULL, NULL); + g_return_val_if_fail(group_name != NULL, NULL); + g_return_val_if_fail(key != NULL, NULL); + + values = + nm_keyfile_plugin_kf_get_string_list(key_file, group_name, key, &num_ints, &key_file_error); + + if (key_file_error) + g_propagate_error(error, key_file_error); + if (!values) + return NULL; + + int_values = g_new(guint, num_ints); + + for (i = 0; i < num_ints; i++) { + gint64 v; + + G_STATIC_ASSERT_EXPR(sizeof(v) > sizeof(guint)); + v = _nm_utils_ascii_str_to_int64(values[i], 10, 0, G_MAXUINT, -1); + if (v == -1) { + g_set_error(error, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("Value cannot be interpreted as a list of numbers.")); + return NULL; + } + + int_values[i] = v; + } + + NM_SET_OUT(out_length, num_ints); + return g_steal_pointer(&int_values); +} + +void +nm_keyfile_plugin_kf_set_string_list(GKeyFile * kf, + const char * group, + const char * key, + const char *const *list, + gsize length) +{ + const char *alias; + + alias = nm_keyfile_plugin_get_alias_for_setting_name(group); + g_key_file_set_string_list(kf, alias ?: group, key, list, length); +} + +void +nm_keyfile_plugin_kf_set_integer_list_uint(GKeyFile * kf, + const char * group, + const char * key, + const guint *data, + gsize length) +{ + nm_auto_str_buf NMStrBuf strbuf = {}; + gsize i; + + g_return_if_fail(kf); + g_return_if_fail(!length || data); + g_return_if_fail(group && group[0]); + g_return_if_fail(key && key[0]); + + nm_str_buf_init(&strbuf, length * 4u + 2u, FALSE); + for (i = 0; i < length; i++) + nm_str_buf_append_printf(&strbuf, "%u;", data[i]); + nm_keyfile_plugin_kf_set_value(kf, group, key, nm_str_buf_get_str(&strbuf)); +} + +void +nm_keyfile_plugin_kf_set_integer_list_uint8(GKeyFile * kf, + const char * group, + const char * key, + const guint8 *data, + gsize length) +{ + nm_auto_str_buf NMStrBuf strbuf = {}; + gsize i; + + g_return_if_fail(kf); + g_return_if_fail(!length || data); + g_return_if_fail(group && group[0]); + g_return_if_fail(key && key[0]); + + nm_str_buf_init(&strbuf, length * 4u + 2u, FALSE); + for (i = 0; i < length; i++) + nm_str_buf_append_printf(&strbuf, "%u;", (guint) data[i]); + nm_keyfile_plugin_kf_set_value(kf, group, key, nm_str_buf_get_str(&strbuf)); +} + +#define DEFINE_KF_WRAPPER_GET(fcn_name, get_ctype, key_file_get_fcn) \ + get_ctype fcn_name(GKeyFile *kf, const char *group, const char *key, GError **error) \ + { \ + get_ctype val; \ + const char *alias; \ + GError * local = NULL; \ + \ + val = key_file_get_fcn(kf, group, key, &local); \ + if (nm_g_error_matches(local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \ + alias = nm_keyfile_plugin_get_alias_for_setting_name(group); \ + if (alias) { \ + g_clear_error(&local); \ + val = key_file_get_fcn(kf, alias, key, &local); \ + } \ + } \ + if (local) \ + g_propagate_error(error, local); \ + return val; \ + } + +DEFINE_KF_WRAPPER_GET(nm_keyfile_plugin_kf_get_string, char *, g_key_file_get_string); +DEFINE_KF_WRAPPER_GET(nm_keyfile_plugin_kf_get_boolean, gboolean, g_key_file_get_boolean); +DEFINE_KF_WRAPPER_GET(nm_keyfile_plugin_kf_get_value, char *, g_key_file_get_value); + +#define DEFINE_KF_WRAPPER_SET(fcn_name, set_ctype, key_file_set_fcn) \ + void fcn_name(GKeyFile *kf, const char *group, const char *key, set_ctype value) \ + { \ + const char *alias; \ + \ + alias = nm_keyfile_plugin_get_alias_for_setting_name(group); \ + key_file_set_fcn(kf, alias ?: group, key, value); \ + } + +DEFINE_KF_WRAPPER_SET(nm_keyfile_plugin_kf_set_string, const char *, g_key_file_set_string); +DEFINE_KF_WRAPPER_SET(nm_keyfile_plugin_kf_set_boolean, gboolean, g_key_file_set_boolean); +DEFINE_KF_WRAPPER_SET(nm_keyfile_plugin_kf_set_value, const char *, g_key_file_set_value); + +gint64 +nm_keyfile_plugin_kf_get_int64(GKeyFile * kf, + const char *group, + const char *key, + guint base, + gint64 min, + gint64 max, + gint64 fallback, + GError ** error) +{ + gs_free char *s = NULL; + int errsv; + gint64 v; + + s = nm_keyfile_plugin_kf_get_value(kf, group, key, error); + if (!s) { + errno = ENODATA; + return fallback; + } + + v = _nm_utils_ascii_str_to_int64(s, base, min, max, fallback); + errsv = errno; + if (errsv != 0 && error) { + g_set_error(error, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("value is not an integer in range [%lld, %lld]"), + (long long) min, + (long long) max); + errno = errsv; + } + return v; +} + +char ** +nm_keyfile_plugin_kf_get_keys(GKeyFile *kf, const char *group, gsize *out_length, GError **error) +{ + char ** keys; + const char *alias; + GError * local = NULL; + gsize l; + + keys = g_key_file_get_keys(kf, group, &l, &local); + if (nm_g_error_matches(local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { + alias = nm_keyfile_plugin_get_alias_for_setting_name(group); + if (alias) { + g_clear_error(&local); + keys = g_key_file_get_keys(kf, alias, &l, error ? &local : NULL); + } + } + nm_assert((!local) != (!keys)); + if (!keys) + l = 0; + nm_assert(l == NM_PTRARRAY_LEN(keys)); + NM_SET_OUT(out_length, l); + if (local) + g_propagate_error(error, local); + return keys; +} + +gboolean +nm_keyfile_plugin_kf_has_key(GKeyFile *kf, const char *group, const char *key, GError **error) +{ + gboolean has; + const char *alias; + GError * local = NULL; + + has = g_key_file_has_key(kf, group, key, &local); + if (nm_g_error_matches(local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { + alias = nm_keyfile_plugin_get_alias_for_setting_name(group); + if (alias) { + g_clear_error(&local); + has = g_key_file_has_key(kf, alias, key, &local); + } + } + if (local) + g_propagate_error(error, local); + return has; +} + +/*****************************************************************************/ + +void +_nm_keyfile_copy(GKeyFile *dst, GKeyFile *src) +{ + gs_strfreev char **groups = NULL; + guint g, k; + + groups = g_key_file_get_groups(src, NULL); + for (g = 0; groups && groups[g]; g++) { + const char * group = groups[g]; + gs_strfreev char **keys = NULL; + + keys = g_key_file_get_keys(src, group, NULL, NULL); + if (!keys) + continue; + + for (k = 0; keys[k]; k++) { + const char * key = keys[k]; + gs_free char *value = NULL; + + value = g_key_file_get_value(src, group, key, NULL); + if (value) + g_key_file_set_value(dst, group, key, value); + else + g_key_file_remove_key(dst, group, key, NULL); + } + } +} + +/*****************************************************************************/ + +gboolean +_nm_keyfile_a_contains_all_in_b(GKeyFile *kf_a, GKeyFile *kf_b) +{ + gs_strfreev char **groups = NULL; + guint i, j; + + if (kf_a == kf_b) + return TRUE; + if (!kf_a || !kf_b) + return FALSE; + + groups = g_key_file_get_groups(kf_a, NULL); + for (i = 0; groups && groups[i]; i++) { + gs_strfreev char **keys = NULL; + + keys = g_key_file_get_keys(kf_a, groups[i], NULL, NULL); + if (!keys) + continue; + + for (j = 0; keys[j]; j++) { + gs_free char *key_a = g_key_file_get_value(kf_a, groups[i], keys[j], NULL); + gs_free char *key_b = g_key_file_get_value(kf_b, groups[i], keys[j], NULL); + + if (g_strcmp0(key_a, key_b) != 0) + return FALSE; + } + } + return TRUE; +} + +static gboolean +_nm_keyfile_equals_ordered(GKeyFile *kf_a, GKeyFile *kf_b) +{ + gs_strfreev char **groups = NULL; + gs_strfreev char **groups_b = NULL; + guint i, j; + + if (kf_a == kf_b) + return TRUE; + if (!kf_a || !kf_b) + return FALSE; + + groups = g_key_file_get_groups(kf_a, NULL); + groups_b = g_key_file_get_groups(kf_b, NULL); + if (!groups && !groups_b) + return TRUE; + if (!groups || !groups_b) + return FALSE; + for (i = 0; groups[i] && groups_b[i] && !strcmp(groups[i], groups_b[i]); i++) + ; + if (groups[i] || groups_b[i]) + return FALSE; + + for (i = 0; groups[i]; i++) { + gs_strfreev char **keys = NULL; + gs_strfreev char **keys_b = NULL; + + keys = g_key_file_get_keys(kf_a, groups[i], NULL, NULL); + keys_b = g_key_file_get_keys(kf_b, groups[i], NULL, NULL); + + if ((!keys) != (!keys_b)) + return FALSE; + if (!keys) + continue; + + for (j = 0; keys[j] && keys_b[j] && !strcmp(keys[j], keys_b[j]); j++) + ; + if (keys[j] || keys_b[j]) + return FALSE; + + for (j = 0; keys[j]; j++) { + gs_free char *key_a = g_key_file_get_value(kf_a, groups[i], keys[j], NULL); + gs_free char *key_b = g_key_file_get_value(kf_b, groups[i], keys[j], NULL); + + if (g_strcmp0(key_a, key_b) != 0) + return FALSE; + } + } + return TRUE; +} + +gboolean +_nm_keyfile_equals(GKeyFile *kf_a, GKeyFile *kf_b, gboolean consider_order) +{ + if (!consider_order) { + return _nm_keyfile_a_contains_all_in_b(kf_a, kf_b) + && _nm_keyfile_a_contains_all_in_b(kf_b, kf_a); + } else { + return _nm_keyfile_equals_ordered(kf_a, kf_b); + } +} + +gboolean +_nm_keyfile_has_values(GKeyFile *keyfile) +{ + gs_strfreev char **groups = NULL; + + g_return_val_if_fail(keyfile, FALSE); + + groups = g_key_file_get_groups(keyfile, NULL); + return groups && groups[0]; +} + +/*****************************************************************************/ + +static const char * +_keyfile_key_encode(const char *name, char **out_to_free) +{ + NMStrBuf str; + gsize len; + gsize i; + + nm_assert(name); + nm_assert(out_to_free && !*out_to_free); + + /* See g_key_file_is_key_name(). + * + * GKeyFile allows all UTF-8 characters (even non-well formed sequences), + * except: + * - no empty keys + * - no leading/trailing ' ' + * - no '=', '[', ']' + * + * We do something more strict here. All non-ASCII characters, all non-printable + * characters, and all invalid characters are escaped with "\\XX". + * + * We don't escape \\, unless it is followed by two hex digits. + */ + + if (!name[0]) { + /* empty keys are backslash encoded. Note that usually + * \\00 is not a valid encode, the only exception is the empty + * word. */ + return "\\00"; + } + + /* find the first character that needs escaping. */ + i = 0; + if (name[0] != ' ') { + for (;; i++) { + const guchar ch = (guchar) name[i]; + + if (ch == '\0') + return name; + + if (ch < 0x20 || ch >= 127 || NM_IN_SET(ch, '=', '[', ']') + || (ch == '\\' && g_ascii_isxdigit(name[i + 1]) && g_ascii_isxdigit(name[i + 2])) + || (ch == ' ' && name[i + 1] == '\0')) + break; + } + } else if (name[1] == '\0') + return "\\20"; + + len = i + strlen(&name[i]); + nm_assert(len == strlen(name)); + + nm_str_buf_init(&str, len + 15u, FALSE); + + if (name[0] == ' ') { + nm_assert(i == 0); + nm_str_buf_append(&str, "\\20"); + i = 1; + } else + nm_str_buf_append_len(&str, name, i); + + for (;; i++) { + const guchar ch = (guchar) name[i]; + + if (ch == '\0') + break; + + if (ch < 0x20 || ch >= 127 || NM_IN_SET(ch, '=', '[', ']') + || (ch == '\\' && g_ascii_isxdigit(name[i + 1]) && g_ascii_isxdigit(name[i + 2])) + || (ch == ' ' && name[i + 1] == '\0')) { + nm_str_buf_append_c(&str, '\\'); + nm_str_buf_append_c_hex(&str, ch, TRUE); + } else + nm_str_buf_append_c(&str, (char) ch); + } + + return (*out_to_free = nm_str_buf_finalize(&str, NULL)); +} + +static const char * +_keyfile_key_decode(const char *key, char **out_to_free) +{ + char *out; + gsize len; + gsize i; + gsize j; + + nm_assert(key); + nm_assert(out_to_free && !*out_to_free); + + if (!key[0]) + return ""; + + for (i = 0; TRUE; i++) { + const char ch = key[i]; + + if (ch == '\0') + return key; + if (ch == '\\' && g_ascii_isxdigit(key[i + 1]) && g_ascii_isxdigit(key[i + 2])) + break; + } + + len = i + strlen(&key[i]); + + if (len == 3 && nm_streq(key, "\\00")) + return ""; + + nm_assert(len == strlen(key)); + + out = g_new(char, len + 1u); + + memcpy(out, key, sizeof(char) * i); + + j = i; + for (;;) { + const char ch = key[i]; + char ch1, ch2; + unsigned v; + + if (ch == '\0') + break; + + if (ch == '\\' && g_ascii_isxdigit((ch1 = key[i + 1])) + && g_ascii_isxdigit((ch2 = key[i + 2]))) { + v = (g_ascii_xdigit_value(ch1) << 4) + g_ascii_xdigit_value(ch2); + if (v != 0) { + out[j++] = (char) v; + i += 3; + continue; + } + } + out[j++] = ch; + i++; + } + + nm_assert(j <= len); + out[j] = '\0'; + return (*out_to_free = out); +} + +/*****************************************************************************/ + +const char * +nm_keyfile_key_encode(const char *name, char **out_to_free) +{ + const char *key; + + key = _keyfile_key_encode(name, out_to_free); +#if NM_MORE_ASSERTS > 5 + nm_assert(key); + nm_assert(!*out_to_free || key == *out_to_free); + nm_assert(!*out_to_free || !nm_streq0(name, key)); + { + gs_free char *to_free2 = NULL; + const char * name2; + + name2 = _keyfile_key_decode(key, &to_free2); + /* name2, the result of encode()+decode() is identical to name. + * That is because + * - encode() is a injective function. + * - decode() is a surjective function, however for output + * values of encode() is behaves injective too. */ + nm_assert(nm_streq0(name2, name)); + } +#endif + return key; +} + +const char * +nm_keyfile_key_decode(const char *key, char **out_to_free) +{ + const char *name; + + name = _keyfile_key_decode(key, out_to_free); +#if NM_MORE_ASSERTS > 5 + nm_assert(name); + nm_assert(!*out_to_free || name == *out_to_free); + { + gs_free char *to_free2 = NULL; + const char * key2; + + key2 = _keyfile_key_encode(name, &to_free2); + /* key2, the result of decode+encode may not be identical + * to the original key. That is, decode() is a surjective + * function mapping different keys to the same name. + * However, decode() behaves injective for input that + * are valid output of encode(). */ + nm_assert(key2); + } +#endif + return name; +} diff --git a/src/libnm-core-impl/nm-keyfile.c b/src/libnm-core-impl/nm-keyfile.c new file mode 100644 index 0000000000..4e12f13c7e --- /dev/null +++ b/src/libnm-core-impl/nm-keyfile.c @@ -0,0 +1,4443 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2008 - 2009 Novell, Inc. + * Copyright (C) 2008 - 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "libnm-core-intern/nm-keyfile-internal.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nm-glib-aux/nm-str-buf.h" +#include "nm-glib-aux/nm-secret-utils.h" +#include "systemd/nm-sd-utils-shared.h" +#include "libnm-core-aux-intern/nm-common-macros.h" + +#include "libnm-core-intern/nm-core-internal.h" +#include "nm-keyfile.h" +#include "nm-setting-user.h" +#include "nm-setting-ovs-external-ids.h" + +#include "libnm-core-intern/nm-keyfile-utils.h" + +#define ETHERNET_S390_OPTIONS_GROUP_NAME "ethernet-s390-options" + +#define OVS_EXTERNAL_IDS_DATA_PREFIX "data." + +/*****************************************************************************/ + +typedef struct _ParseInfoProperty ParseInfoProperty; + +typedef struct { + NMConnection * connection; + GKeyFile * keyfile; + const char * base_dir; + NMKeyfileReadHandler read_handler; + void * user_data; + GError * error; + const char * group; + NMSetting * setting; +} KeyfileReaderInfo; + +typedef struct { + NMConnection * connection; + GKeyFile * keyfile; + GError * error; + NMKeyfileWriteHandler write_handler; + void * user_data; +} KeyfileWriterInfo; + +/*****************************************************************************/ + +static void +_key_file_handler_data_init(NMKeyfileHandlerData *handler_data, + NMKeyfileHandlerType handler_type, + const char * kf_group_name, + const char * kf_key, + NMSetting * cur_setting, + const char * cur_property, + GError ** p_error) +{ + nm_assert(handler_data); + nm_assert(p_error && !*p_error); + + handler_data->type = handler_type; + handler_data->p_error = p_error; + handler_data->kf_group_name = kf_group_name; + handler_data->kf_key = kf_key; + handler_data->cur_setting = cur_setting; + handler_data->cur_property = cur_property; +} + +static void +_key_file_handler_data_init_read(NMKeyfileHandlerData *handler_data, + NMKeyfileHandlerType handler_type, + KeyfileReaderInfo * info, + const char * kf_key, + const char * cur_property) +{ + _key_file_handler_data_init(handler_data, + handler_type, + info->group, + kf_key, + info->setting, + cur_property, + &info->error); +} + +static void +_key_file_handler_data_init_write(NMKeyfileHandlerData *handler_data, + NMKeyfileHandlerType handler_type, + KeyfileWriterInfo * info, + const char * kf_group, + const char * kf_key, + NMSetting * cur_setting, + const char * cur_property) +{ + _key_file_handler_data_init(handler_data, + handler_type, + kf_group, + kf_key, + cur_setting, + cur_property, + &info->error); +} + +_nm_printf(5, 6) static void _handle_warn(KeyfileReaderInfo * info, + const char * kf_key, + const char * cur_property, + NMKeyfileWarnSeverity severity, + const char * fmt, + ...) +{ + NMKeyfileHandlerData handler_data; + + _key_file_handler_data_init_read(&handler_data, + NM_KEYFILE_HANDLER_TYPE_WARN, + info, + kf_key, + cur_property); + handler_data.warn = (NMKeyfileHandlerDataWarn){ + .severity = severity, + .message = NULL, + .fmt = fmt, + }; + + va_start(handler_data.warn.ap, fmt); + + info->read_handler(info->keyfile, + info->connection, + NM_KEYFILE_HANDLER_TYPE_WARN, + &handler_data, + info->user_data); + + va_end(handler_data.warn.ap); + + g_free(handler_data.warn.message); +} + +#define handle_warn(arg_info, arg_kf_key, arg_property_name, arg_severity, ...) \ + ({ \ + KeyfileReaderInfo *_info = (arg_info); \ + \ + nm_assert(!_info->error); \ + \ + if (_info->read_handler) { \ + _handle_warn(_info, (arg_kf_key), (arg_property_name), (arg_severity), __VA_ARGS__); \ + } \ + _info->error == NULL; \ + }) + +/*****************************************************************************/ + +static gboolean +_secret_flags_persist_secret(NMSettingSecretFlags flags) +{ + return flags == NM_SETTING_SECRET_FLAG_NONE; +} + +/*****************************************************************************/ +/* Some setting properties also contain setting names, such as + * NMSettingConnection's 'type' property (which specifies the base type of the + * connection, e.g. ethernet or wifi) or 'slave-type' (specifies type of slave + * connection, e.g. bond or bridge). This function handles translating those + * properties' values to the real setting name if they are an alias. + */ +static void +setting_alias_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + const char * key_setting_name; + gs_free char *s = NULL; + + s = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); + if (!s) + return; + + key_setting_name = nm_keyfile_plugin_get_setting_name_for_alias(s); + g_object_set(G_OBJECT(setting), key, key_setting_name ?: s, NULL); +} + +static void +sriov_vfs_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + gs_unref_ptrarray GPtrArray *vfs = NULL; + gs_strfreev char ** keys = NULL; + gsize n_keys = 0; + int i; + + keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); + if (n_keys == 0) + return; + + vfs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_sriov_vf_unref); + + for (i = 0; i < n_keys; i++) { + gs_free char *value = NULL; + NMSriovVF * vf; + const char * rest; + + if (!g_str_has_prefix(keys[i], "vf.")) + continue; + + rest = &keys[i][3]; + + if (!NM_STRCHAR_ALL(rest, ch, g_ascii_isdigit(ch))) + continue; + + value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, keys[i], NULL); + + vf = _nm_utils_sriov_vf_from_strparts(rest, value, TRUE, NULL); + if (vf) + g_ptr_array_add(vfs, vf); + } + + g_object_set(G_OBJECT(setting), key, vfs, NULL); +} + +static void +read_array_of_uint(GKeyFile *file, NMSetting *setting, const char *key) +{ + gs_unref_array GArray *array = NULL; + gs_free_error GError *error = NULL; + gs_free guint *tmp = NULL; + gsize length; + + tmp = nm_keyfile_plugin_kf_get_integer_list_uint(file, + nm_setting_get_name(setting), + key, + &length, + &error); + if (error) + return; + + array = g_array_sized_new(FALSE, FALSE, sizeof(guint), length); + g_array_append_vals(array, tmp, length); + g_object_set(setting, key, array, NULL); +} + +static gboolean +get_one_int(KeyfileReaderInfo *info, + const char * kf_key, + const char * property_name, + const char * str, + guint32 max_val, + guint32 * out) +{ + gint64 tmp; + + nm_assert((!info) == (!property_name)); + nm_assert((!info) == (!kf_key)); + + if (!str || !str[0]) { + if (info) { + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring missing number")); + } + return FALSE; + } + + tmp = _nm_utils_ascii_str_to_int64(str, 10, 0, max_val, -1); + if (tmp == -1) { + if (info) { + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid number '%s'"), + str); + } + return FALSE; + } + + *out = (guint32) tmp; + return TRUE; +} + +static gpointer +build_address(KeyfileReaderInfo *info, + const char * kf_key, + const char * property_name, + int family, + const char * address_str, + guint32 plen) +{ + NMIPAddress *addr; + GError * error = NULL; + + g_return_val_if_fail(address_str, NULL); + + addr = nm_ip_address_new(family, address_str, plen, &error); + if (!addr) { + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid %s address: %s"), + family == AF_INET ? "IPv4" : "IPv6", + error->message); + g_error_free(error); + } + + return addr; +} + +static gpointer +build_route(KeyfileReaderInfo *info, + const char * kf_key, + const char * property_name, + int family, + const char * dest_str, + guint32 plen, + const char * gateway_str, + const char * metric_str) +{ + NMIPRoute *route; + guint32 u32; + gint64 metric = -1; + GError * error = NULL; + + g_return_val_if_fail(dest_str, NULL); + + /* Next hop */ + if (gateway_str && gateway_str[0]) { + if (!nm_utils_ipaddr_is_valid(family, gateway_str)) { + /* Try workaround for routes written by broken keyfile writer. + * Due to bug bgo#719851, an older version of writer would have + * written "a:b:c:d::/plen,metric" if the gateway was ::, instead + * of "a:b:c:d::/plen,,metric" or "a:b:c:d::/plen,::,metric" + * Try workaround by interpreting gateway_str as metric to accept such + * invalid routes. This broken syntax should not be not officially + * supported. + **/ + if (family == AF_INET6 && !metric_str + && get_one_int(NULL, NULL, NULL, gateway_str, G_MAXUINT32, &u32)) { + metric = u32; + gateway_str = NULL; + } else { + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid gateway '%s' for %s route"), + gateway_str, + family == AF_INET ? "IPv4" : "IPv6"); + return NULL; + } + } + } else + gateway_str = NULL; + + /* parse metric, default to -1 */ + if (metric_str) { + if (!get_one_int(info, kf_key, property_name, metric_str, G_MAXUINT32, &u32)) + return NULL; + metric = u32; + } + + route = nm_ip_route_new(family, dest_str, plen, gateway_str, metric, &error); + if (!route) { + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid %s route: %s"), + family == AF_INET ? "IPv4" : "IPv6", + error->message); + g_error_free(error); + } + + return route; +} + +/* On success, returns pointer to the zero-terminated field (original @current). + * The @current * pointer target is set to point to the rest of the input + * or %NULL if there is no more input. Sets error to %NULL for convenience. + * + * On failure, returns %NULL (unspecified). The @current pointer target is + * resets to its original value to allow skipping fields. The @error target + * is set to the character that breaks the parsing or %NULL if @current was %NULL. + * + * When @current target is %NULL, gracefully fail returning %NULL while + * leaving the @current target %NULL end setting @error to %NULL; + */ +static const char * +read_field(char **current, const char **out_err_str, const char *characters, const char *delimiters) +{ + const char *start; + + nm_assert(current); + nm_assert(out_err_str); + nm_assert(characters); + nm_assert(delimiters); + + *out_err_str = NULL; + + if (!*current) { + /* graceful failure, leave '*current' NULL */ + return NULL; + } + + /* fail on empty input */ + if (!**current) + return NULL; + + /* remember beginning of input */ + start = *current; + + while (**current && strchr(characters, **current)) + (*current)++; + if (**current) + if (strchr(delimiters, **current)) { + /* success, more data available */ + *(*current)++ = '\0'; + return start; + } else { + /* error, bad character */ + *out_err_str = *current; + *current = (char *) start; + return NULL; + } + else { + /* success, end of input */ + *current = NULL; + return start; + } +} + +/*****************************************************************************/ + +#define NM_DBUS_SERVICE_OPENCONNECT "org.freedesktop.NetworkManager.openconnect" +#define NM_OPENCONNECT_KEY_GATEWAY "gateway" +#define NM_OPENCONNECT_KEY_COOKIE "cookie" +#define NM_OPENCONNECT_KEY_GWCERT "gwcert" +#define NM_OPENCONNECT_KEY_XMLCONFIG "xmlconfig" +#define NM_OPENCONNECT_KEY_LASTHOST "lasthost" +#define NM_OPENCONNECT_KEY_AUTOCONNECT "autoconnect" +#define NM_OPENCONNECT_KEY_CERTSIGS "certsigs" + +static void +openconnect_fix_secret_flags(NMSetting *setting) +{ + NMSettingVpn * s_vpn; + NMSettingSecretFlags flags; + + /* Huge hack. There were some openconnect changes that needed to happen + * pretty late, too late to get into distros. Migration has already + * happened for many people, and their secret flags are wrong. But we + * don't want to require re-migration, so we have to fix it up here. Ugh. + */ + + if (!NM_IS_SETTING_VPN(setting)) + return; + + s_vpn = NM_SETTING_VPN(setting); + + if (!nm_streq0(nm_setting_vpn_get_service_type(s_vpn), NM_DBUS_SERVICE_OPENCONNECT)) + return; + + /* These are different for every login session, and should not be stored */ + flags = NM_SETTING_SECRET_FLAG_NOT_SAVED; + nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_GATEWAY, flags, NULL); + nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_COOKIE, flags, NULL); + nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_GWCERT, flags, NULL); + + /* These are purely internal data for the auth-dialog, and should be stored */ + flags = 0; + nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_XMLCONFIG, flags, NULL); + nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_LASTHOST, flags, NULL); + nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_AUTOCONNECT, flags, NULL); + nm_setting_set_secret_flags(NM_SETTING(s_vpn), NM_OPENCONNECT_KEY_CERTSIGS, flags, NULL); +} + +/*****************************************************************************/ + +#define IP_ADDRESS_CHARS "0123456789abcdefABCDEF:.%" +#define DIGITS "0123456789" +#define DELIMITERS "/;," + +/* The following IPv4 and IPv6 address formats are supported: + * + * address (DEPRECATED) + * address/plen + * address/gateway (DEPRECATED) + * address/plen,gateway + * + * The following IPv4 and IPv6 route formats are supported: + * + * address/plen (NETWORK dev DEVICE) + * address/plen,gateway (NETWORK via GATEWAY dev DEVICE) + * address/plen,,metric (NETWORK dev DEVICE metric METRIC) + * address/plen,gateway,metric (NETWORK via GATEWAY dev DEVICE metric METRIC) + * + * For backward, forward and sideward compatibility, slash (/), + * semicolon (;) and comma (,) are interchangeable. The choice of + * separator in the above examples is therefore not significant. + * + * Leaving out the prefix length is discouraged and DEPRECATED. The + * default value of IPv6 prefix length was 64 and has not been + * changed. The default for IPv4 is now 24, which is the closest + * IPv4 equivalent. These defaults may just as well be changed to + * match the iproute2 defaults (32 for IPv4 and 128 for IPv6). + */ +static gpointer +read_one_ip_address_or_route(KeyfileReaderInfo *info, + const char * property_name, + const char * setting_name, + const char * kf_key, + gboolean ipv6, + gboolean route, + char ** out_gateway, + NMSetting * setting) +{ + guint plen; + gpointer result; + const char * address_str; + const char * plen_str; + const char * gateway_str; + const char * metric_str; + const char * err_str = NULL; + char * current; + gs_free char *value = NULL; + gs_free char *value_orig = NULL; + +#define VALUE_ORIG() \ + (value_orig \ + ?: (value_orig = \ + nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, kf_key, NULL))) + + value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, kf_key, NULL); + if (!value) + return NULL; + + current = value; + + /* get address field */ + address_str = read_field(¤t, &err_str, IP_ADDRESS_CHARS, DELIMITERS); + if (err_str) { + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("unexpected character '%c' for address %s: '%s' (position %td)"), + *err_str, + kf_key, + VALUE_ORIG(), + err_str - current); + return NULL; + } + /* get prefix length field (skippable) */ + plen_str = read_field(¤t, &err_str, DIGITS, DELIMITERS); + /* get gateway field */ + gateway_str = read_field(¤t, &err_str, IP_ADDRESS_CHARS, DELIMITERS); + if (err_str) { + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("unexpected character '%c' for %s: '%s' (position %td)"), + *err_str, + kf_key, + VALUE_ORIG(), + err_str - current); + return NULL; + } + /* for routes, get metric */ + if (route) { + metric_str = read_field(¤t, &err_str, DIGITS, DELIMITERS); + if (err_str) { + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("unexpected character '%c' in prefix length for %s: '%s' (position %td)"), + *err_str, + kf_key, + VALUE_ORIG(), + err_str - current); + return NULL; + } + } else + metric_str = NULL; + if (current) { + /* there is still some data */ + if (*current) { + /* another field follows */ + handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("garbage at the end of value %s: '%s'"), + kf_key, + VALUE_ORIG()); + return NULL; + } else { + /* semicolon at the end of input */ + if (!handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_INFO, + _("deprecated semicolon at the end of value %s: '%s'"), + kf_key, + VALUE_ORIG())) + return NULL; + } + } + +#define DEFAULT_PREFIX(for_route, for_ipv6) \ + ((for_route) ? ((for_ipv6) ? 128 : 24) : ((for_ipv6) ? 64 : 24)) + + /* parse plen, fallback to defaults */ + if (plen_str) { + if (!get_one_int(info, kf_key, property_name, plen_str, ipv6 ? 128 : 32, &plen)) { + plen = DEFAULT_PREFIX(route, ipv6); + if (info->error + || !handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid prefix length for %s '%s', defaulting to %d"), + kf_key, + VALUE_ORIG(), + plen)) + return NULL; + } + } else { + plen = DEFAULT_PREFIX(route, ipv6); + if (!handle_warn(info, + kf_key, + property_name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("missing prefix length for %s '%s', defaulting to %d"), + kf_key, + VALUE_ORIG(), + plen)) + return NULL; + } + + /* build the appropriate data structure for NetworkManager settings */ + if (route) { + result = build_route(info, + kf_key, + property_name, + ipv6 ? AF_INET6 : AF_INET, + address_str, + plen, + gateway_str, + metric_str); + } else { + result = build_address(info, + kf_key, + property_name, + ipv6 ? AF_INET6 : AF_INET, + address_str, + plen); + if (!result) + return NULL; + if (gateway_str) + NM_SET_OUT(out_gateway, g_strdup(gateway_str)); + } + +#undef VALUE_ORIG + + return result; +} + +static void +fill_route_attributes(GKeyFile * kf, + NMIPRoute * route, + const char *setting, + const char *key, + int family) +{ + gs_free char * value = NULL; + gs_unref_hashtable GHashTable *hash = NULL; + GHashTableIter iter; + char * name; + GVariant * variant; + + value = nm_keyfile_plugin_kf_get_string(kf, setting, key, NULL); + if (!value || !value[0]) + return; + + hash = nm_utils_parse_variant_attributes(value, + ',', + '=', + TRUE, + nm_ip_route_get_variant_attribute_spec(), + NULL); + if (hash) { + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) { + if (nm_ip_route_attribute_validate(name, variant, family, NULL, NULL)) + nm_ip_route_set_attribute(route, name, g_variant_ref(variant)); + } + } +} + +typedef struct { + const char *s_key; + gint32 key_idx; + gint8 key_type; +} BuildListData; + +typedef enum { + BUILD_LIST_TYPE_ADDRESSES, + BUILD_LIST_TYPE_ROUTES, + BUILD_LIST_TYPE_ROUTING_RULES, +} BuildListType; + +static int +_build_list_data_cmp(gconstpointer p_a, gconstpointer p_b, gpointer user_data) +{ + const BuildListData *a = p_a; + const BuildListData *b = p_b; + + NM_CMP_FIELD(a, b, key_idx); + NM_CMP_FIELD(a, b, key_type); + NM_CMP_FIELD_STR(a, b, s_key); + return 0; +} + +static gboolean +_build_list_data_is_shadowed(const BuildListData *build_list, gsize build_list_len, gsize idx) +{ + /* the keyfile contains duplicate keys, which are both returned + * by g_key_file_get_keys() (WHY??). + * + * Skip the earlier one. */ + return idx + 1 < build_list_len && build_list[idx].key_idx == build_list[idx + 1].key_idx + && build_list[idx].key_type == build_list[idx + 1].key_type + && nm_streq(build_list[idx].s_key, build_list[idx + 1].s_key); +} + +static gboolean +_build_list_match_key_w_name_impl(const char *key, + const char *base_name, + gsize base_name_l, + gint32 * out_key_idx) +{ + gint64 v; + + /* some very strict parsing. */ + + /* the key must start with base_name. */ + if (strncmp(key, base_name, base_name_l) != 0) + return FALSE; + + key += base_name_l; + if (key[0] == '\0') { + /* if key is identical to base_name, that's good. */ + NM_SET_OUT(out_key_idx, -1); + return TRUE; + } + + /* if base_name is followed by a zero, then it must be + * only a zero, nothing else. */ + if (key[0] == '0') { + if (key[1] != '\0') + return FALSE; + NM_SET_OUT(out_key_idx, 0); + return TRUE; + } + + /* otherwise, it can only be followed by a non-zero decimal. */ + if (!(key[0] >= '1' && key[0] <= '9')) + return FALSE; + /* and all remaining chars must be decimals too. */ + if (!NM_STRCHAR_ALL(&key[1], ch, g_ascii_isdigit(ch))) + return FALSE; + + /* and it must be convertible to a (positive) int. */ + v = _nm_utils_ascii_str_to_int64(key, 10, 0, G_MAXINT32, -1); + if (v < 0) + return FALSE; + + /* good */ + NM_SET_OUT(out_key_idx, v); + return TRUE; +} + +#define _build_list_match_key_w_name(key, base_name, out_key_idx) \ + _build_list_match_key_w_name_impl(key, base_name, NM_STRLEN(base_name), out_key_idx) + +static BuildListData * +_build_list_create(GKeyFile * keyfile, + const char * group_name, + BuildListType build_list_type, + gsize * out_build_list_len, + char *** out_keys_strv) +{ + gs_strfreev char **keys = NULL; + gsize i_keys, n_keys; + gs_free BuildListData *build_list = NULL; + gsize build_list_len = 0; + + nm_assert(out_build_list_len && *out_build_list_len == 0); + nm_assert(out_keys_strv && !*out_keys_strv); + + keys = nm_keyfile_plugin_kf_get_keys(keyfile, group_name, &n_keys, NULL); + if (n_keys == 0) + return NULL; + + for (i_keys = 0; i_keys < n_keys; i_keys++) { + const char *s_key = keys[i_keys]; + gint32 key_idx; + gint8 key_type = 0; + + switch (build_list_type) { + case BUILD_LIST_TYPE_ROUTES: + if (_build_list_match_key_w_name(s_key, "route", &key_idx)) + key_type = 0; + else if (_build_list_match_key_w_name(s_key, "routes", &key_idx)) + key_type = 1; + else + continue; + break; + case BUILD_LIST_TYPE_ADDRESSES: + if (_build_list_match_key_w_name(s_key, "address", &key_idx)) + key_type = 0; + else if (_build_list_match_key_w_name(s_key, "addresses", &key_idx)) + key_type = 1; + else + continue; + break; + case BUILD_LIST_TYPE_ROUTING_RULES: + if (_build_list_match_key_w_name(s_key, "routing-rule", &key_idx)) + key_type = 0; + else + continue; + break; + default: + nm_assert_not_reached(); + break; + } + + if (G_UNLIKELY(!build_list)) + build_list = g_new(BuildListData, n_keys - i_keys); + + build_list[build_list_len++] = (BuildListData){ + .s_key = s_key, + .key_idx = key_idx, + .key_type = key_type, + }; + } + + if (build_list_len == 0) + return NULL; + + if (build_list_len > 1) { + g_qsort_with_data(build_list, + build_list_len, + sizeof(BuildListData), + _build_list_data_cmp, + NULL); + } + + *out_build_list_len = build_list_len; + *out_keys_strv = g_steal_pointer(&keys); + return g_steal_pointer(&build_list); +} + +static void +ip_address_or_route_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *setting_key) +{ + const char * setting_name = nm_setting_get_name(setting); + gboolean is_ipv6 = nm_streq(setting_name, "ipv6"); + gboolean is_routes = nm_streq(setting_key, "routes"); + gs_free char * gateway = NULL; + gs_unref_ptrarray GPtrArray *list = NULL; + gs_strfreev char ** keys = NULL; + gs_free BuildListData *build_list = NULL; + gsize i_build_list, build_list_len = 0; + + build_list = _build_list_create(info->keyfile, + setting_name, + is_routes ? BUILD_LIST_TYPE_ROUTES : BUILD_LIST_TYPE_ADDRESSES, + &build_list_len, + &keys); + if (!build_list) + return; + + list = g_ptr_array_new_with_free_func(is_routes ? (GDestroyNotify) nm_ip_route_unref + : (GDestroyNotify) nm_ip_address_unref); + + for (i_build_list = 0; i_build_list < build_list_len; i_build_list++) { + const char *s_key; + gpointer item; + + if (_build_list_data_is_shadowed(build_list, build_list_len, i_build_list)) + continue; + + s_key = build_list[i_build_list].s_key; + item = read_one_ip_address_or_route(info, + setting_key, + setting_name, + s_key, + is_ipv6, + is_routes, + gateway ? NULL : &gateway, + setting); + if (item && is_routes) { + char options_key[128]; + + nm_sprintf_buf(options_key, "%s_options", s_key); + fill_route_attributes(info->keyfile, + item, + setting_name, + options_key, + is_ipv6 ? AF_INET6 : AF_INET); + } + + if (info->error) + return; + + if (item) + g_ptr_array_add(list, item); + } + + if (list->len >= 1) + g_object_set(setting, setting_key, list, NULL); + + if (gateway) + g_object_set(setting, "gateway", gateway, NULL); +} + +static void +ip_routing_rule_parser_full(KeyfileReaderInfo * info, + const NMMetaSettingInfo * setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty * pip, + NMSetting * setting) +{ + const char * setting_name = nm_setting_get_name(setting); + gboolean is_ipv6 = nm_streq(setting_name, "ipv6"); + gs_strfreev char **keys = NULL; + gs_free BuildListData *build_list = NULL; + gsize i_build_list, build_list_len = 0; + + build_list = _build_list_create(info->keyfile, + setting_name, + BUILD_LIST_TYPE_ROUTING_RULES, + &build_list_len, + &keys); + if (!build_list) + return; + + for (i_build_list = 0; i_build_list < build_list_len; i_build_list++) { + nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL; + gs_free char * value = NULL; + gs_free_error GError *local = NULL; + + if (_build_list_data_is_shadowed(build_list, build_list_len, i_build_list)) + continue; + + value = nm_keyfile_plugin_kf_get_string(info->keyfile, + setting_name, + build_list[i_build_list].s_key, + NULL); + if (!value) + continue; + + rule = nm_ip_routing_rule_from_string( + value, + (NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE + | (is_ipv6 ? NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 + : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET)), + NULL, + &local); + if (!rule) { + if (!handle_warn(info, + build_list[i_build_list].s_key, + property_info->name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid value for \"%s\": %s"), + build_list[i_build_list].s_key, + local->message)) + return; + continue; + } + + nm_setting_ip_config_add_routing_rule(NM_SETTING_IP_CONFIG(setting), rule); + } +} + +static void +_parser_full_ovs_external_ids_data(KeyfileReaderInfo * info, + const NMMetaSettingInfo * setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty * pip, + NMSetting * setting) +{ + const char * setting_name = NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME; + gs_strfreev char **keys = NULL; + gsize n_keys; + gsize i; + + nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)); + nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)); + nm_assert(nm_streq(setting_name, setting_info->setting_name)); + nm_assert(nm_streq(setting_name, nm_setting_get_name(setting))); + + keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); + + for (i = 0; i < n_keys; i++) { + const char * key = keys[i]; + gs_free char *name_to_free = NULL; + gs_free char *value = NULL; + const char * name; + + if (!NM_STR_HAS_PREFIX(key, OVS_EXTERNAL_IDS_DATA_PREFIX)) + continue; + + value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); + if (!value) + continue; + + name = &key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)]; + name = nm_keyfile_key_decode(name, &name_to_free); + nm_setting_ovs_external_ids_set_data(NM_SETTING_OVS_EXTERNAL_IDS(setting), name, value); + } +} + +static void +ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + int addr_family; + gs_strfreev char **list = NULL; + gsize i, n, length; + + nm_assert(NM_IS_SETTING_IP4_CONFIG(setting) || NM_IS_SETTING_IP6_CONFIG(setting)); + + list = nm_keyfile_plugin_kf_get_string_list(info->keyfile, + nm_setting_get_name(setting), + key, + &length, + NULL); + nm_assert(length == NM_PTRARRAY_LEN(list)); + if (length == 0) + return; + + addr_family = NM_IS_SETTING_IP4_CONFIG(setting) ? AF_INET : AF_INET6; + + n = 0; + for (i = 0; i < length; i++) { + NMIPAddr addr; + + if (inet_pton(addr_family, list[i], &addr) <= 0) { + if (!handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid DNS server IPv%c address '%s'"), + nm_utils_addr_family_to_char(addr_family), + list[i])) { + do { + nm_clear_g_free(&list[i]); + } while (++i < length); + return; + } + nm_clear_g_free(&list[i]); + continue; + } + + if (n != i) + list[n] = g_steal_pointer(&list[i]); + n++; + } + + g_object_set(setting, key, list, NULL); +} + +static void +ip6_addr_gen_mode_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + NMSettingIP6ConfigAddrGenMode addr_gen_mode; + const char * setting_name = nm_setting_get_name(setting); + gs_free char * s = NULL; + + s = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); + if (s) { + if (!nm_utils_enum_from_str(nm_setting_ip6_config_addr_gen_mode_get_type(), + s, + (int *) &addr_gen_mode, + NULL)) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid option '%s', use one of [%s]"), + s, + "eui64,stable-privacy"); + return; + } + } else + addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64; + + g_object_set(G_OBJECT(setting), key, (int) addr_gen_mode, NULL); +} + +static void +mac_address_parser(KeyfileReaderInfo *info, + NMSetting * setting, + const char * key, + gsize addr_len, + gboolean cloned_mac_addr) +{ + const char * setting_name = nm_setting_get_name(setting); + char addr_str[NM_UTILS_HWADDR_LEN_MAX * 3]; + guint8 addr_bin[NM_UTILS_HWADDR_LEN_MAX]; + gs_free char *tmp_string = NULL; + gs_free guint *int_list = NULL; + const char * mac_str; + gsize int_list_len; + gsize i; + + nm_assert(addr_len > 0); + nm_assert(addr_len <= NM_UTILS_HWADDR_LEN_MAX); + + tmp_string = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); + + if (cloned_mac_addr && NM_CLONED_MAC_IS_SPECIAL(tmp_string)) { + mac_str = tmp_string; + goto out; + } + + if (tmp_string && nm_utils_hwaddr_aton(tmp_string, addr_bin, addr_len)) + goto good_addr_bin; + + /* Old format; list of ints */ + int_list = nm_keyfile_plugin_kf_get_integer_list_uint(info->keyfile, + setting_name, + key, + &int_list_len, + NULL); + if (int_list_len == addr_len) { + for (i = 0; i < addr_len; i++) { + const guint val = int_list[i]; + + if (val > 255) + break; + addr_bin[i] = (guint8) val; + } + if (i == addr_len) + goto good_addr_bin; + } + + handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid MAC address")); + return; + +good_addr_bin: + nm_utils_bin2hexstr_full(addr_bin, addr_len, ':', TRUE, addr_str); + mac_str = addr_str; + +out: + g_object_set(setting, key, mac_str, NULL); +} + +static void +mac_address_parser_ETHER(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + mac_address_parser(info, setting, key, ETH_ALEN, FALSE); +} + +static void +mac_address_parser_ETHER_cloned(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + mac_address_parser(info, setting, key, ETH_ALEN, TRUE); +} + +static void +mac_address_parser_INFINIBAND(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + mac_address_parser(info, setting, key, INFINIBAND_ALEN, FALSE); +} + +static void +read_hash_of_string(KeyfileReaderInfo *info, + GKeyFile * file, + NMSetting * setting, + const char * kf_group) +{ + gs_strfreev char **keys = NULL; + const char *const *iter; + const char * setting_name = nm_setting_get_name(setting); + gboolean is_vpn; + gsize n_keys; + + nm_assert((NM_IS_SETTING_VPN(setting) && nm_streq(kf_group, NM_SETTING_VPN_DATA)) + || (NM_IS_SETTING_VPN(setting) && nm_streq(kf_group, NM_SETTING_VPN_SECRETS)) + || (NM_IS_SETTING_BOND(setting) && nm_streq(kf_group, NM_SETTING_BOND_OPTIONS)) + || (NM_IS_SETTING_USER(setting) && nm_streq(kf_group, NM_SETTING_USER_DATA))); + + keys = nm_keyfile_plugin_kf_get_keys(file, setting_name, &n_keys, NULL); + if (n_keys == 0) + return; + + if ((is_vpn = NM_IS_SETTING_VPN(setting)) || NM_IS_SETTING_BOND(setting)) { + for (iter = (const char *const *) keys; *iter; iter++) { + const char * kf_key = *iter; + gs_free char *to_free = NULL; + gs_free char *value = NULL; + const char * name; + + value = nm_keyfile_plugin_kf_get_string(file, setting_name, kf_key, NULL); + if (!value) + continue; + + name = nm_keyfile_key_decode(kf_key, &to_free); + + if (is_vpn) { + /* Add any item that's not a class property to the data hash */ + if (!g_object_class_find_property(G_OBJECT_GET_CLASS(setting), name)) + nm_setting_vpn_add_data_item(NM_SETTING_VPN(setting), name, value); + } else { + if (!nm_streq(name, "interface-name")) { + gs_free_error GError *error = NULL; + + if (!_nm_setting_bond_validate_option(name, value, &error)) { + if (!handle_warn(info, + kf_key, + name, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid bond option %s%s%s = %s%s%s: %s"), + NM_PRINT_FMT_QUOTE_STRING(name), + NM_PRINT_FMT_QUOTE_STRING(value), + error->message)) + return; + } else + nm_setting_bond_add_option(NM_SETTING_BOND(setting), name, value); + } + } + } + openconnect_fix_secret_flags(setting); + return; + } + + if (NM_IS_SETTING_USER(setting)) { + gs_unref_hashtable GHashTable *data = NULL; + + data = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); + for (iter = (const char *const *) keys; *iter; iter++) { + gs_free char *to_free = NULL; + char * value = NULL; + const char * name; + + value = nm_keyfile_plugin_kf_get_string(file, setting_name, *iter, NULL); + if (!value) + continue; + name = nm_keyfile_key_decode(*iter, &to_free); + g_hash_table_insert(data, g_steal_pointer(&to_free) ?: g_strdup(name), value); + } + g_object_set(setting, NM_SETTING_USER_DATA, data, NULL); + return; + } + + nm_assert_not_reached(); +} + +static gsize +unescape_semicolons(char *str) +{ + gsize i, j; + + for (i = 0, j = 0; str[i];) { + if (str[i] == '\\' && str[i + 1] == ';') + i++; + str[j++] = str[i++]; + } + nm_explicit_bzero(&str[j], i - j); + return j; +} + +static GBytes * +get_bytes(KeyfileReaderInfo *info, + const char * setting_name, + const char * key, + gboolean zero_terminate, + gboolean unescape_semicolon) +{ + nm_auto_free_secret char *tmp_string = NULL; + gboolean may_be_int_list = TRUE; + gsize length; + GBytes * result; + + /* New format: just a string + * Old format: integer list; e.g. 11;25;38; + */ + tmp_string = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); + if (!tmp_string) + return NULL; + + /* if the string is empty, we return an empty GBytes array. + * Note that for NM_SETTING_802_1X_PASSWORD_RAW both %NULL and + * an empty GBytes are valid, and shall be destinguished. */ + if (!tmp_string[0]) { + /* note that even if @zero_terminate is TRUE, we return an empty + * byte-array. The reason is that zero_terminate is there to terminate + * *valid* strings. It's not there to terminated invalid (empty) strings. + */ + return g_bytes_new_static("", 0); + } + + for (length = 0; tmp_string[length]; length++) { + const char ch = tmp_string[length]; + + if (!g_ascii_isspace(ch) && !g_ascii_isdigit(ch) && ch != ';') { + may_be_int_list = FALSE; + length += strlen(&tmp_string[length]); + break; + } + } + + /* Try to parse the string as a integer list. */ + if (may_be_int_list && length > 0) { + nm_auto_free_secret_buf NMSecretBuf *bin = NULL; + const char *const s = tmp_string; + gsize i, d; + + bin = nm_secret_buf_new(length / 2 + 3); + +#define DIGIT(c) ((c) - '0') + i = 0; + d = 0; + while (TRUE) { + int n; + + /* leading whitespace */ + while (g_ascii_isspace(s[i])) + i++; + if (s[i] == '\0') + break; + /* then expect 1 to 3 digits */ + if (!g_ascii_isdigit(s[i])) { + d = 0; + break; + } + n = DIGIT(s[i]); + i++; + if (g_ascii_isdigit(s[i])) { + n = 10 * n + DIGIT(s[i]); + i++; + if (g_ascii_isdigit(s[i])) { + n = 10 * n + DIGIT(s[i]); + i++; + } + } + if (n > 255) { + d = 0; + break; + } + + nm_assert(d < bin->len); + bin->bin[d++] = n; + + /* allow whitespace after the digit. */ + while (g_ascii_isspace(s[i])) + i++; + /* need a semicolon as separator. */ + if (s[i] != ';') { + d = 0; + break; + } + i++; + } +#undef DIGIT + + /* Old format; list of ints. We already did a strict validation of the + * string format before. We expect that this conversion cannot fail. */ + if (d > 0) { + /* note that @zero_terminate does not add a terminating '\0' to + * binary data as an integer list. If the bytes are expressed as + * an integer list, all potential NUL characters are supposed to + * be included there explicitly. + * + * However, in the spirit of defensive programming, we do append a + * NUL character to the buffer, although this character is hidden + * and only a mitigation for bugs. */ + + if (d + 10 < bin->len) { + /* hm, too much unused memory. Copy the memory to a suitable + * sized buffer. */ + return nm_secret_copy_to_gbytes(bin->bin, d); + } + + nm_assert(d < bin->len); + bin->bin[d] = '\0'; + return nm_secret_buf_to_gbytes_take(g_steal_pointer(&bin), d); + } + } + + /* Handle as a simple string (ie, new format) */ + if (unescape_semicolon) + length = unescape_semicolons(tmp_string); + if (zero_terminate) + length++; + if (length == 0) + return NULL; + + result = + g_bytes_new_with_free_func(tmp_string, length, (GDestroyNotify) nm_free_secret, tmp_string); + tmp_string = NULL; + return result; +} + +static void +ssid_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + gs_unref_bytes GBytes *bytes = NULL; + + bytes = get_bytes(info, setting_name, key, FALSE, TRUE); + if (!bytes) { + handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid SSID")); + return; + } + g_object_set(setting, key, bytes, NULL); +} + +static void +password_raw_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + gs_unref_bytes GBytes *bytes = NULL; + + bytes = get_bytes(info, setting_name, key, FALSE, TRUE); + if (!bytes) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid raw password")); + return; + } + g_object_set(setting, key, bytes, NULL); +} + +static char * +get_cert_path(const char *base_dir, const guint8 *cert_path, gsize cert_path_len) +{ + const char *base; + char * p = NULL, *path, *tmp; + + g_return_val_if_fail(base_dir != NULL, NULL); + g_return_val_if_fail(cert_path != NULL, NULL); + + path = g_strndup((char *) cert_path, cert_path_len); + + if (path[0] == '/') + return path; + + base = path; + p = strrchr(path, '/'); + if (p) + base = p + 1; + + tmp = g_build_path("/", base_dir, base, NULL); + g_free(path); + return tmp; +} + +static const char *certext[] = {".pem", ".cert", ".crt", ".cer", ".p12", ".der", ".key"}; + +static gboolean +has_cert_ext(const char *path) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS(certext); i++) { + if (g_str_has_suffix(path, certext[i])) + return TRUE; + } + return FALSE; +} + +char * +nm_keyfile_detect_unqualified_path_scheme(const char * base_dir, + gconstpointer pdata, + gsize data_len, + gboolean consider_exists, + gboolean * out_exists) +{ + const char * data = pdata; + gboolean exists = FALSE; + gsize validate_len; + gsize path_len, pathuri_len; + gs_free char *path = NULL; + gs_free char *pathuri = NULL; + + g_return_val_if_fail(base_dir && base_dir[0] == '/', NULL); + + if (!pdata) + return NULL; + if (data_len == -1) + data_len = strlen(data); + if (data_len > 500 || data_len < 1) + return NULL; + + /* If there's a trailing zero tell g_utf8_validate() to validate until the zero */ + if (data[data_len - 1] == '\0') { + /* setting it to -1, would mean we accept data to contain NUL characters before the + * end. Don't accept any NUL in [0 .. data_len-1[ . */ + validate_len = data_len - 1; + } else + validate_len = data_len; + if (validate_len == 0 || g_utf8_validate((const char *) data, validate_len, NULL) == FALSE) + return NULL; + + /* Might be a bare path without the file:// prefix; in that case + * if it's an absolute path, use that, otherwise treat it as a + * relative path to the current directory. + */ + + path = get_cert_path(base_dir, (const guint8 *) data, data_len); + + /* FIXME(keyfile-parse-in-memory): it is wrong that keyfile reader makes decisions based on + * the file systems content. The serialization/parsing should be entirely in-memory. */ + if (!memchr(data, '/', data_len) && !has_cert_ext(path)) { + if (!consider_exists) + return NULL; + exists = g_file_test(path, G_FILE_TEST_EXISTS); + if (!exists) + return NULL; + } else if (out_exists) + exists = g_file_test(path, G_FILE_TEST_EXISTS); + + /* Construct the proper value as required for the PATH scheme. + * + * When returning TRUE, we must also be sure that @data_len does not look like + * the deprecated format of list of integers. With this implementation that is the + * case, as long as @consider_exists is FALSE. */ + path_len = strlen(path); + pathuri_len = (NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + 1) + path_len; + pathuri = g_new(char, pathuri_len); + memcpy(pathuri, + NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, + NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)); + memcpy(&pathuri[NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)], path, path_len + 1); + if (nm_setting_802_1x_check_cert_scheme(pathuri, pathuri_len, NULL) + != NM_SETTING_802_1X_CK_SCHEME_PATH) + return NULL; + + NM_SET_OUT(out_exists, exists); + return g_steal_pointer(&pathuri); +} + +#define HAS_SCHEME_PREFIX(bin, bin_len, scheme) \ + ({ \ + const char *const _bin = (bin); \ + const gsize _bin_len = (bin_len); \ + \ + nm_assert(_bin &&_bin_len > 0); \ + \ + (_bin_len > NM_STRLEN(scheme) + 1 && _bin[_bin_len - 1] == '\0' \ + && memcmp(_bin, scheme, NM_STRLEN(scheme)) == 0); \ + }) + +static void +cert_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + gs_unref_bytes GBytes *bytes = NULL; + const char * bin = NULL; + gsize bin_len = 0; + char * path; + gboolean path_exists; + + bytes = get_bytes(info, setting_name, key, TRUE, FALSE); + if (bytes) + bin = g_bytes_get_data(bytes, &bin_len); + if (bin_len == 0) { + if (!info->error) { + handle_warn(info, key, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid key/cert value")); + } + return; + } + + if (HAS_SCHEME_PREFIX(bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)) { + const char * path2 = &bin[NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)]; + gs_free char *path2_free = NULL; + + if (nm_setting_802_1x_check_cert_scheme(bin, bin_len, NULL) + != NM_SETTING_802_1X_CK_SCHEME_PATH) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key/cert value path \"%s\""), + bin); + return; + } + + g_object_set(setting, key, bytes, NULL); + + if (path2[0] != '/') { + /* we want to read absolute paths because we use keyfile as exchange + * between different processes which might not have the same cwd. */ + path2_free = get_cert_path(info->base_dir, + (const guint8 *) path2, + bin_len - NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) - 1); + path2 = path2_free; + } + + /* FIXME(keyfile-parse-in-memory): keyfile reader must not access the file system and + * (in a first step) only operate in memory-only. If the presence of files should be checked, + * then by invoking a callback (and possibly keyfile settings plugin would + * collect the file names to be checked and check them later). */ + if (!g_file_test(path2, G_FILE_TEST_EXISTS)) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, + _("certificate or key file '%s' does not exist"), + path2); + } + return; + } + + if (HAS_SCHEME_PREFIX(bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11)) { + if (nm_setting_802_1x_check_cert_scheme(bin, bin_len, NULL) + != NM_SETTING_802_1X_CK_SCHEME_PKCS11) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid PKCS#11 URI \"%s\""), + bin); + return; + } + + g_object_set(setting, key, bytes, NULL); + return; + } + + if (HAS_SCHEME_PREFIX(bin, bin_len, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)) { + const char *cdata = bin + NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB); + gsize cdata_len = bin_len - NM_STRLEN(NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB) - 1; + gs_free guchar *bin_decoded = NULL; + gsize bin_decoded_len = 0; + gsize i; + gboolean valid_base64; + gs_unref_bytes GBytes *val = NULL; + + /* Let's be strict here. We expect valid base64, no funny stuff!! + * We didn't write such invalid data ourselfes and refuse to read it as blob. */ + if ((valid_base64 = (cdata_len % 4 == 0))) { + for (i = 0; i < cdata_len; i++) { + char c = cdata[i]; + + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') + || (c == '+' || c == '/'))) { + if (c != '=' || i < cdata_len - 2) + valid_base64 = FALSE; + else { + for (; i < cdata_len; i++) { + if (cdata[i] != '=') + valid_base64 = FALSE; + } + } + break; + } + } + } + if (valid_base64) + bin_decoded = g_base64_decode(cdata, &bin_decoded_len); + + if (bin_decoded_len == 0) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key/cert value data:;base64, is not base64")); + return; + } + + if (nm_setting_802_1x_check_cert_scheme(bin_decoded, bin_decoded_len, NULL) + != NM_SETTING_802_1X_CK_SCHEME_BLOB) { + /* The blob probably starts with "file://". Setting the cert data will confuse NMSetting8021x. + * In fact this is a limitation of NMSetting8021x which does not support setting blobs that start + * with file://. Just warn and return TRUE to signal that we ~handled~ the setting. */ + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key/cert value data:;base64,file://")); + return; + } + + val = g_bytes_new_take(g_steal_pointer(&bin_decoded), bin_decoded_len); + g_object_set(setting, key, val, NULL); + return; + } + + /* If not, it might be a plain path */ + path = + nm_keyfile_detect_unqualified_path_scheme(info->base_dir, bin, bin_len, TRUE, &path_exists); + if (path) { + gs_unref_bytes GBytes *val = NULL; + + /* Construct the proper value as required for the PATH scheme */ + val = g_bytes_new_take(path, strlen(path) + 1); + g_object_set(setting, key, val, NULL); + + /* Warn if the certificate didn't exist */ + if (!path_exists) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, + _("certificate or key file '%s' does not exist"), + path); + } + return; + } + + if (nm_setting_802_1x_check_cert_scheme(bin, bin_len, NULL) + != NM_SETTING_802_1X_CK_SCHEME_BLOB) { + /* The blob probably starts with "file://" but contains invalid characters for a path. + * Setting the cert data will confuse NMSetting8021x. + * In fact, NMSetting8021x does not support setting such binary data, so just warn and + * continue. */ + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key/cert value is not a valid blob")); + return; + } + + g_object_set(setting, key, bytes, NULL); +} + +static int +_parity_from_char(int ch) +{ +#if NM_MORE_ASSERTS > 5 + { + static char check = 0; + + if (check == 0) { + nm_auto_unref_gtypeclass GEnumClass *klass = + g_type_class_ref(NM_TYPE_SETTING_SERIAL_PARITY); + guint i; + + check = 1; + + /* In older versions, parity was G_TYPE_CHAR/gint8, and the character + * value was stored as integer. + * For example parity=69 equals parity=E, meaning NM_SETTING_SERIAL_PARITY_EVEN. + * + * That means, certain values are reserved. Assert that these numbers + * are not reused when we extend NMSettingSerialParity enum. + * Actually, since NM_SETTING_SERIAL_PARITY is g_param_spec_enum(), + * we anyway cannot extend the enum without breaking API... + * + * [1] commit "a91e60902e libnm-core: make NMSettingSerial:parity an enum" + * [2] https://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=a91e60902eabae1de93d61323dae6ac894b5d40f + */ + g_assert(G_IS_ENUM_CLASS(klass)); + for (i = 0; i < klass->n_values; i++) { + const GEnumValue *v = &klass->values[i]; + int num = v->value; + + g_assert(_parity_from_char(num) == -1); + g_assert(!NM_IN_SET(num, 'e', 'E', 'o', 'O', 'n', 'N')); + } + } + } +#endif + + switch (ch) { + case 'E': + case 'e': + return NM_SETTING_SERIAL_PARITY_EVEN; + case 'O': + case 'o': + return NM_SETTING_SERIAL_PARITY_ODD; + case 'N': + case 'n': + return NM_SETTING_SERIAL_PARITY_NONE; + } + + return -1; +} + +static void +parity_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + gs_free_error GError *err = NULL; + int parity; + gs_free char * tmp_str = NULL; + gint64 i64; + + /* Keyfile traditionally stored this as the ASCII value for 'E', 'o', or 'n'. + * We now accept either that or the (case-insensitive) character itself (but + * still always write it the old way, for backward compatibility). + */ + tmp_str = nm_keyfile_plugin_kf_get_value(info->keyfile, setting_name, key, &err); + if (err) + goto out_err; + + if (tmp_str && tmp_str[0] != '\0' && tmp_str[1] == '\0') { + /* the ASCII characters like 'E' are taken directly... */ + parity = _parity_from_char(tmp_str[0]); + if (parity >= 0) + goto parity_good; + } + + i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT, G_MAXINT, G_MININT64); + if (i64 != G_MININT64 && errno == 0) { + if ((parity = _parity_from_char(i64)) >= 0) { + /* another oddity: the string is a valid number. However, if the numeric values + * is one of the supported ASCII codes, accept it (like 69 for 'E'). + */ + goto parity_good; + } + + /* Finally, take the numeric value as is. */ + parity = i64; + goto parity_good; + } + + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid parity value '%s'"), + tmp_str ?: ""); + return; + +parity_good: + nm_g_object_set_property_enum(G_OBJECT(setting), + key, + NM_TYPE_SETTING_SERIAL_PARITY, + parity, + &err); + +out_err: + if (!err) + return; + if (nm_keyfile_error_is_not_found(err)) { + /* ignore such errors. The key is not present. */ + return; + } + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid setting: %s"), + err->message); +} + +static void +team_config_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + gs_free char *conf = NULL; + gs_free_error GError *error = NULL; + + conf = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); + + g_object_set(G_OBJECT(setting), key, conf, NULL); + + if (conf && !nm_setting_verify(setting, NULL, &error)) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid team configuration: %s"), + error->message); + g_object_set(G_OBJECT(setting), key, NULL, NULL); + } +} + +static void +bridge_vlan_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + gs_unref_ptrarray GPtrArray *vlans = NULL; + gs_free char * value = NULL; + gs_free const char ** strv = NULL; + const char *const * iter; + GError * local = NULL; + NMBridgeVlan * vlan; + + value = nm_keyfile_plugin_kf_get_string(info->keyfile, nm_setting_get_name(setting), key, NULL); + if (!value || !value[0]) + return; + + vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); + + strv = nm_utils_escaped_tokens_split(value, ","); + if (strv) { + for (iter = strv; *iter; iter++) { + vlan = nm_bridge_vlan_from_str(*iter, &local); + if (!vlan) { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + "invalid bridge VLAN: %s", + local->message); + g_clear_error(&local); + continue; + } + g_ptr_array_add(vlans, vlan); + } + } + + if (vlans->len > 0) + g_object_set(setting, key, vlans, NULL); +} + +static void +qdisc_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + gs_unref_ptrarray GPtrArray *qdiscs = NULL; + gs_strfreev char ** keys = NULL; + gsize n_keys = 0; + int i; + + keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); + if (n_keys == 0) + return; + + qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref); + + for (i = 0; i < n_keys; i++) { + NMTCQdisc * qdisc; + const char * qdisc_parent; + gs_free char *qdisc_rest = NULL; + gs_free char *qdisc_str = NULL; + gs_free_error GError *err = NULL; + + if (!g_str_has_prefix(keys[i], "qdisc.")) + continue; + + qdisc_parent = keys[i] + sizeof("qdisc.") - 1; + qdisc_rest = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, keys[i], NULL); + qdisc_str = g_strdup_printf( + "%s%s %s", + _nm_utils_parse_tc_handle(qdisc_parent, NULL) != TC_H_UNSPEC ? "parent " : "", + qdisc_parent, + qdisc_rest); + + qdisc = nm_utils_tc_qdisc_from_str(qdisc_str, &err); + if (!qdisc) { + handle_warn(info, + keys[i], + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid qdisc: %s"), + err->message); + } else { + g_ptr_array_add(qdiscs, qdisc); + } + } + + if (qdiscs->len >= 1) + g_object_set(setting, key, qdiscs, NULL); +} + +static void +tfilter_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char * setting_name = nm_setting_get_name(setting); + gs_unref_ptrarray GPtrArray *tfilters = NULL; + gs_strfreev char ** keys = NULL; + gsize n_keys = 0; + int i; + + keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); + if (n_keys == 0) + return; + + tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref); + + for (i = 0; i < n_keys; i++) { + NMTCTfilter * tfilter; + const char * tfilter_parent; + gs_free char *tfilter_rest = NULL; + gs_free char *tfilter_str = NULL; + gs_free_error GError *err = NULL; + + if (!g_str_has_prefix(keys[i], "tfilter.")) + continue; + + tfilter_parent = keys[i] + sizeof("tfilter.") - 1; + tfilter_rest = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, keys[i], NULL); + tfilter_str = g_strdup_printf( + "%s%s %s", + _nm_utils_parse_tc_handle(tfilter_parent, NULL) != TC_H_UNSPEC ? "parent " : "", + tfilter_parent, + tfilter_rest); + + tfilter = nm_utils_tc_tfilter_from_str(tfilter_str, &err); + if (!tfilter) { + handle_warn(info, + keys[i], + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid tfilter: %s"), + err->message); + } else { + g_ptr_array_add(tfilters, tfilter); + } + } + + if (tfilters->len >= 1) + g_object_set(setting, key, tfilters, NULL); +} + +/*****************************************************************************/ + +/* Some setting properties also contain setting names, such as + * NMSettingConnection's 'type' property (which specifies the base type of the + * connection, eg ethernet or wifi) or the 802-11-wireless setting's + * 'security' property which specifies whether or not the AP requires + * encryption. This function handles translating those properties' values + * from the real setting name to the more-readable alias. + */ +static void +setting_alias_writer(KeyfileWriterInfo *info, + NMSetting * setting, + const char * key, + const GValue * value) +{ + const char *str, *alias; + + str = g_value_get_string(value); + alias = nm_keyfile_plugin_get_alias_for_setting_name(str); + nm_keyfile_plugin_kf_set_string(info->keyfile, nm_setting_get_name(setting), key, alias ?: str); +} + +static void +sriov_vfs_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + GPtrArray *vfs; + guint i; + + vfs = g_value_get_boxed(value); + if (!vfs) + return; + + for (i = 0; i < vfs->len; i++) { + const NMSriovVF *vf = vfs->pdata[i]; + gs_free char * kf_value = NULL; + char kf_key[32]; + + kf_value = nm_utils_sriov_vf_to_str(vf, TRUE, NULL); + if (!kf_value) + continue; + + nm_sprintf_buf(kf_key, "vf.%u", nm_sriov_vf_get_index(vf)); + + nm_keyfile_plugin_kf_set_string(info->keyfile, + nm_setting_get_name(setting), + kf_key, + kf_value); + } +} + +static void +write_array_of_uint(GKeyFile *file, NMSetting *setting, const char *key, const GValue *value) +{ + GArray *array; + + array = g_value_get_boxed(value); + + nm_assert(!array || g_array_get_element_size(array) == sizeof(guint)); + + if (!array || !array->len) + return; + + nm_keyfile_plugin_kf_set_integer_list_uint(file, + nm_setting_get_name(setting), + key, + (const guint *) array->data, + array->len); +} + +static void +dns_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + char **list; + + list = g_value_get_boxed(value); + if (list && list[0]) { + nm_keyfile_plugin_kf_set_string_list(info->keyfile, + nm_setting_get_name(setting), + key, + (const char **) list, + g_strv_length(list)); + } +} + +static void +ip6_addr_gen_mode_writer(KeyfileWriterInfo *info, + NMSetting * setting, + const char * key, + const GValue * value) +{ + NMSettingIP6ConfigAddrGenMode addr_gen_mode; + gs_free char * str = NULL; + + addr_gen_mode = (NMSettingIP6ConfigAddrGenMode) g_value_get_int(value); + str = nm_utils_enum_to_str(nm_setting_ip6_config_addr_gen_mode_get_type(), addr_gen_mode); + nm_keyfile_plugin_kf_set_string(info->keyfile, nm_setting_get_name(setting), key, str); +} + +static void +write_ip_values(GKeyFile * file, + const char *setting_name, + GPtrArray * array, + const char *gateway, + gboolean is_route) +{ + if (array->len > 0) { + nm_auto_str_buf NMStrBuf output = NM_STR_BUF_INIT(2 * INET_ADDRSTRLEN + 10, FALSE); + int addr_family; + guint i; + const char * addr; + const char * gw; + guint32 plen; + char key_name[64]; + char * key_name_idx; + + addr_family = + nm_streq(setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME) ? AF_INET : AF_INET6; + + strcpy(key_name, is_route ? "route" : "address"); + key_name_idx = key_name + strlen(key_name); + + for (i = 0; i < array->len; i++) { + gint64 metric = -1; + + if (is_route) { + NMIPRoute *route = array->pdata[i]; + + addr = nm_ip_route_get_dest(route); + plen = nm_ip_route_get_prefix(route); + gw = nm_ip_route_get_next_hop(route); + metric = nm_ip_route_get_metric(route); + } else { + NMIPAddress *address = array->pdata[i]; + + addr = nm_ip_address_get_address(address); + plen = nm_ip_address_get_prefix(address); + gw = (i == 0) ? gateway : NULL; + } + + nm_str_buf_set_size(&output, 0, FALSE, FALSE); + nm_str_buf_append_printf(&output, "%s/%u", addr, plen); + if (metric != -1 || gw) { + /* Older versions of the plugin do not support the form + * "a.b.c.d/plen,,metric", so, we always have to write the + * gateway, even if there isn't one. + * The current version supports reading of the above form. + */ + if (!gw) { + if (addr_family == AF_INET) + gw = "0.0.0.0"; + else + gw = "::"; + } + + nm_str_buf_append_c(&output, ','); + nm_str_buf_append(&output, gw); + if (is_route && metric != -1) + nm_str_buf_append_printf(&output, ",%lu", (unsigned long) metric); + } + + sprintf(key_name_idx, "%u", i + 1); + nm_keyfile_plugin_kf_set_string(file, + setting_name, + key_name, + nm_str_buf_get_str(&output)); + + if (is_route) { + gs_free char *attributes = NULL; + + attributes = + nm_utils_format_variant_attributes(_nm_ip_route_get_attributes(array->pdata[i]), + ',', + '='); + if (attributes) { + g_strlcat(key_name, "_options", sizeof(key_name)); + nm_keyfile_plugin_kf_set_string(file, setting_name, key_name, attributes); + } + } + } + } +} + +static void +addr_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + GPtrArray * array; + const char *setting_name = nm_setting_get_name(setting); + const char *gateway = nm_setting_ip_config_get_gateway(NM_SETTING_IP_CONFIG(setting)); + + array = (GPtrArray *) g_value_get_boxed(value); + if (array && array->len) + write_ip_values(info->keyfile, setting_name, array, gateway, FALSE); +} + +static void +route_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + GPtrArray * array; + const char *setting_name = nm_setting_get_name(setting); + + array = (GPtrArray *) g_value_get_boxed(value); + if (array && array->len) + write_ip_values(info->keyfile, setting_name, array, NULL, TRUE); +} + +static void +bridge_vlan_writer(KeyfileWriterInfo *info, + NMSetting * setting, + const char * key, + const GValue * value) +{ + GPtrArray *vlans; + + vlans = g_value_get_boxed(value); + if (vlans && vlans->len > 0) { + const guint string_initial_size = vlans->len * 10u; + nm_auto_str_buf NMStrBuf string = NM_STR_BUF_INIT(string_initial_size, FALSE); + guint i; + + for (i = 0; i < vlans->len; i++) { + gs_free char *vlan_str = NULL; + + vlan_str = nm_bridge_vlan_to_str(vlans->pdata[i], NULL); + if (i > 0) + nm_str_buf_append_c(&string, ','); + nm_utils_escaped_tokens_escape_strbuf_assert(vlan_str, ",", &string); + } + + nm_keyfile_plugin_kf_set_string(info->keyfile, + nm_setting_get_name(setting), + "vlans", + nm_str_buf_get_str(&string)); + } +} + +static void +wired_s390_options_parser_full(KeyfileReaderInfo * info, + const NMMetaSettingInfo * setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty * pip, + NMSetting * setting) +{ + NMSettingWired * s_wired = NM_SETTING_WIRED(setting); + gs_strfreev char **keys = NULL; + gsize n_keys; + gsize i; + + keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, + ETHERNET_S390_OPTIONS_GROUP_NAME, + &n_keys, + NULL); + for (i = 0; i < n_keys; i++) { + gs_free char *value = NULL; + gs_free char *key_to_free = NULL; + + value = nm_keyfile_plugin_kf_get_string(info->keyfile, + ETHERNET_S390_OPTIONS_GROUP_NAME, + keys[i], + NULL); + if (!value) + continue; + + nm_setting_wired_add_s390_option(s_wired, + nm_keyfile_key_decode(keys[i], &key_to_free), + value); + } +} + +static void +wired_s390_options_writer_full(KeyfileWriterInfo * info, + const NMMetaSettingInfo * setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty * pip, + NMSetting * setting) +{ + NMSettingWired *s_wired = NM_SETTING_WIRED(setting); + guint i, n; + + n = nm_setting_wired_get_num_s390_options(s_wired); + for (i = 0; i < n; i++) { + gs_free char *key_to_free = NULL; + const char * opt_key; + const char * opt_val; + + nm_setting_wired_get_s390_option(s_wired, i, &opt_key, &opt_val); + nm_keyfile_plugin_kf_set_string(info->keyfile, + ETHERNET_S390_OPTIONS_GROUP_NAME, + nm_keyfile_key_encode(opt_key, &key_to_free), + opt_val); + } +} + +static void +ip_routing_rule_writer_full(KeyfileWriterInfo * info, + const NMMetaSettingInfo * setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty * pip, + NMSetting * setting) +{ + const char * setting_name = nm_setting_get_name(setting); + NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG(setting); + guint i, j, n; + char key_name_full[100] = "routing-rule"; + char * key_name_num = &key_name_full[NM_STRLEN("routing-rule")]; + + n = nm_setting_ip_config_get_num_routing_rules(s_ip); + j = 0; + for (i = 0; i < n; i++) { + NMIPRoutingRule *rule = nm_setting_ip_config_get_routing_rule(s_ip, i); + gs_free char * str = NULL; + + str = + nm_ip_routing_rule_to_string(rule, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE, NULL, NULL); + if (!str) + continue; + + sprintf(key_name_num, "%u", ++j); + nm_keyfile_plugin_kf_set_string(info->keyfile, setting_name, key_name_full, str); + } +} + +static void +qdisc_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + nm_auto_free_gstring GString *key_name = NULL; + nm_auto_free_gstring GString *value_str = NULL; + GPtrArray * array; + guint i; + + array = g_value_get_boxed(value); + if (!array || !array->len) + return; + + for (i = 0; i < array->len; i++) { + NMTCQdisc *qdisc = array->pdata[i]; + + nm_gstring_prepare(&key_name); + nm_gstring_prepare(&value_str); + + g_string_append(key_name, "qdisc."); + _nm_utils_string_append_tc_parent(key_name, NULL, nm_tc_qdisc_get_parent(qdisc)); + _nm_utils_string_append_tc_qdisc_rest(value_str, qdisc); + + nm_keyfile_plugin_kf_set_string(info->keyfile, + NM_SETTING_TC_CONFIG_SETTING_NAME, + key_name->str, + value_str->str); + } +} + +static void +tfilter_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + nm_auto_free_gstring GString *key_name = NULL; + nm_auto_free_gstring GString *value_str = NULL; + GPtrArray * array; + guint i; + + array = g_value_get_boxed(value); + if (!array || !array->len) + return; + + for (i = 0; i < array->len; i++) { + NMTCTfilter *tfilter = array->pdata[i]; + + nm_gstring_prepare(&key_name); + nm_gstring_prepare(&value_str); + + g_string_append(key_name, "tfilter."); + _nm_utils_string_append_tc_parent(key_name, NULL, nm_tc_tfilter_get_parent(tfilter)); + _nm_utils_string_append_tc_tfilter_rest(value_str, tfilter, NULL); + + nm_keyfile_plugin_kf_set_string(info->keyfile, + NM_SETTING_TC_CONFIG_SETTING_NAME, + key_name->str, + value_str->str); + } +} + +static void +_writer_full_ovs_external_ids_data(KeyfileWriterInfo * info, + const NMMetaSettingInfo * setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty * pip, + NMSetting * setting) +{ + GHashTable * hash; + NMUtilsNamedValue data_static[300u / sizeof(NMUtilsNamedValue)]; + gs_free NMUtilsNamedValue *data_free = NULL; + const NMUtilsNamedValue * data; + guint data_len; + char full_key_static[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + 300u]; + guint i; + + nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)); + nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)); + + hash = _nm_setting_ovs_external_ids_get_data(NM_SETTING_OVS_EXTERNAL_IDS(setting)); + if (!hash) + return; + + data = nm_utils_named_values_from_strdict(hash, &data_len, data_static, &data_free); + if (data_len == 0) + return; + + memcpy(full_key_static, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)); + + for (i = 0; i < data_len; i++) { + const char * key = data[i].name; + const char * val = data[i].value_str; + gs_free char *escaped_key_to_free = NULL; + const char * escaped_key; + gsize len; + gs_free char *full_key_free = NULL; + char * full_key = full_key_static; + + escaped_key = nm_keyfile_key_encode(key, &escaped_key_to_free); + + len = strlen(escaped_key) + 1u; + if (len >= G_N_ELEMENTS(full_key_static) - NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)) { + full_key_free = g_new(char, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + len); + full_key = full_key_free; + memcpy(full_key, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)); + } + memcpy(&full_key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)], escaped_key, len); + + nm_keyfile_plugin_kf_set_string(info->keyfile, + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + full_key, + val); + } +} + +static void +write_hash_of_string(GKeyFile *file, NMSetting *setting, const char *key, const GValue *value) +{ + GHashTable * hash; + const char * group_name = nm_setting_get_name(setting); + gboolean vpn_secrets = FALSE; + gs_free const char **keys = NULL; + guint i, l; + + nm_assert((NM_IS_SETTING_VPN(setting) && nm_streq(key, NM_SETTING_VPN_DATA)) + || (NM_IS_SETTING_VPN(setting) && nm_streq(key, NM_SETTING_VPN_SECRETS)) + || (NM_IS_SETTING_BOND(setting) && nm_streq(key, NM_SETTING_BOND_OPTIONS)) + || (NM_IS_SETTING_USER(setting) && nm_streq(key, NM_SETTING_USER_DATA))); + + /* Write VPN secrets out to a different group to keep them separate */ + if (NM_IS_SETTING_VPN(setting) && nm_streq(key, NM_SETTING_VPN_SECRETS)) { + group_name = NM_KEYFILE_GROUP_VPN_SECRETS; + vpn_secrets = TRUE; + } + + hash = g_value_get_boxed(value); + + keys = nm_utils_strdict_get_keys(hash, TRUE, &l); + for (i = 0; i < l; i++) { + gs_free char *to_free = NULL; + const char * property, *data; + + property = keys[i]; + + /* Handle VPN secrets specially; they are nested in the property's hash; + * we don't want to write them if the secret is not saved, not required, + * or owned by a user's secret agent. + */ + if (vpn_secrets) { + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + if (!nm_setting_get_secret_flags(setting, property, &secret_flags, NULL)) + nm_assert_not_reached(); + if (!_secret_flags_persist_secret(secret_flags)) + continue; + } + + data = g_hash_table_lookup(hash, property); + nm_keyfile_plugin_kf_set_string(file, + group_name, + nm_keyfile_key_encode(property, &to_free), + data); + } +} + +static void +ssid_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + GBytes * bytes; + const guint8 *ssid_data; + gsize ssid_len; + const char * setting_name = nm_setting_get_name(setting); + gboolean new_format = TRUE; + gsize semicolons = 0; + gsize i; + + g_return_if_fail(G_VALUE_HOLDS(value, G_TYPE_BYTES)); + + bytes = g_value_get_boxed(value); + if (!bytes) + return; + ssid_data = g_bytes_get_data(bytes, &ssid_len); + if (!ssid_data || !ssid_len) { + nm_keyfile_plugin_kf_set_string(info->keyfile, setting_name, key, ""); + return; + } + + /* Check whether each byte is printable. If not, we have to use an + * integer list, otherwise we can just use a string. + */ + for (i = 0; i < ssid_len; i++) { + const char c = ssid_data[i]; + + if (!g_ascii_isprint(c)) { + new_format = FALSE; + break; + } + if (c == ';') + semicolons++; + } + + if (new_format) { + gs_free char *ssid = NULL; + + if (semicolons == 0) + ssid = g_strndup((char *) ssid_data, ssid_len); + else { + /* Escape semicolons with backslashes to make strings + * containing ';', such as '16;17;' unambiguous */ + gsize j = 0; + + ssid = g_malloc(ssid_len + semicolons + 1); + for (i = 0; i < ssid_len; i++) { + if (ssid_data[i] == ';') + ssid[j++] = '\\'; + ssid[j++] = ssid_data[i]; + } + ssid[j] = '\0'; + } + nm_keyfile_plugin_kf_set_string(info->keyfile, setting_name, key, ssid); + } else + nm_keyfile_plugin_kf_set_integer_list_uint8(info->keyfile, + setting_name, + key, + ssid_data, + ssid_len); +} + +static void +password_raw_writer(KeyfileWriterInfo *info, + NMSetting * setting, + const char * key, + const GValue * value) +{ + const char * setting_name = nm_setting_get_name(setting); + GBytes * array; + gsize len; + const guint8 *data; + + g_return_if_fail(G_VALUE_HOLDS(value, G_TYPE_BYTES)); + + array = (GBytes *) g_value_get_boxed(value); + if (!array) + return; + data = g_bytes_get_data(array, &len); + if (!data) + len = 0; + nm_keyfile_plugin_kf_set_integer_list_uint8(info->keyfile, setting_name, key, data, len); +} + +/*****************************************************************************/ + +static void +cert_writer_default(NMConnection * connection, + GKeyFile * file, + NMSetting8021x * setting, + const char * setting_name, + const NMSetting8021xSchemeVtable *vtable) +{ + NMSetting8021xCKScheme scheme; + + scheme = vtable->scheme_func(setting); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + gs_free char *path_free = NULL; + gs_free char *base_dir = NULL; + gs_free char *tmp = NULL; + const char * path; + + path = vtable->path_func(setting); + g_assert(path); + + /* If the path is relative, make it an absolute path. + * Relative paths make a keyfile not easily usable in another + * context. */ + if (path[0] && path[0] != '/') { + base_dir = g_get_current_dir(); + path_free = g_strconcat(base_dir, "/", path, NULL); + path = path_free; + } else + base_dir = g_path_get_dirname(path); + + /* path cannot start with "file://" or "data:;base64,", because it is an absolute path. + * Still, make sure that a prefix-less path will be recognized. This can happen + * for example if the path is longer then 500 chars. */ + tmp = nm_keyfile_detect_unqualified_path_scheme(base_dir, path, -1, FALSE, NULL); + if (tmp) + nm_clear_g_free(&tmp); + else { + tmp = g_strconcat(NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL); + path = tmp; + } + + /* Path contains at least a '/', hence it cannot be recognized as the old + * binary format consisting of a list of integers. */ + + nm_keyfile_plugin_kf_set_string(file, setting_name, vtable->setting_key, path); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + GBytes * blob; + const guint8 *blob_data; + gsize blob_len; + gs_free char *blob_base64 = NULL; + gs_free char *val = NULL; + + blob = vtable->blob_func(setting); + g_assert(blob); + blob_data = g_bytes_get_data(blob, &blob_len); + + blob_base64 = g_base64_encode(blob_data, blob_len); + val = g_strconcat(NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB, blob_base64, NULL); + + nm_keyfile_plugin_kf_set_string(file, setting_name, vtable->setting_key, val); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { + nm_keyfile_plugin_kf_set_string(file, + setting_name, + vtable->setting_key, + vtable->uri_func(setting)); + } else { + /* scheme_func() returns UNKNOWN in all other cases. The only valid case + * where a scheme is allowed to be UNKNOWN, is unsetting the value. In this + * case, we don't expect the writer to be called, because the default value + * will not be serialized. + * The only other reason for the scheme to be UNKNOWN is an invalid cert. + * But our connection verifies, so that cannot happen either. */ + g_return_if_reached(); + } +} + +static void +cert_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + const NMSetting8021xSchemeVtable *vtable = NULL; + const char * setting_name; + guint i; + + for (i = 0; nm_setting_8021x_scheme_vtable[i].setting_key; i++) { + if (nm_streq0(nm_setting_8021x_scheme_vtable[i].setting_key, key)) { + vtable = &nm_setting_8021x_scheme_vtable[i]; + break; + } + } + if (!vtable) + g_return_if_reached(); + + setting_name = nm_setting_get_name(NM_SETTING(setting)); + + if (info->write_handler) { + NMKeyfileHandlerData handler_data; + + _key_file_handler_data_init_write(&handler_data, + NM_KEYFILE_HANDLER_TYPE_WRITE_CERT, + info, + setting_name, + vtable->setting_key, + setting, + key); + handler_data.write_cert = (NMKeyfileHandlerDataWriteCert){ + .vtable = vtable, + }; + + if (info->write_handler(info->connection, + info->keyfile, + NM_KEYFILE_HANDLER_TYPE_WRITE_CERT, + &handler_data, + info->user_data)) + return; + if (info->error) + return; + } + + cert_writer_default(info->connection, + info->keyfile, + NM_SETTING_802_1X(setting), + setting_name, + vtable); +} + +/*****************************************************************************/ + +struct _ParseInfoProperty { + const char *property_name; + union { + void (*parser)(KeyfileReaderInfo *info, NMSetting *setting, const char *key); + void (*parser_full)(KeyfileReaderInfo * info, + const NMMetaSettingInfo * setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty * pip, + NMSetting * setting); + }; + union { + void (*writer)(KeyfileWriterInfo *info, + NMSetting * setting, + const char * key, + const GValue * value); + void (*writer_full)(KeyfileWriterInfo * info, + const NMMetaSettingInfo * setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty * pip, + NMSetting * setting); + }; + bool parser_skip; + bool parser_no_check_key : 1; + bool writer_skip : 1; + bool has_writer_full : 1; + bool has_parser_full : 1; + + /* usually, we skip to write values that have their + * default value. By setting this flag to TRUE, also + * default values are written. */ + bool writer_persist_default : 1; +}; + +#define PARSE_INFO_PROPERTY(_property_name, ...) \ + (&((const ParseInfoProperty){.property_name = _property_name, __VA_ARGS__})) + +#define PARSE_INFO_PROPERTIES(...) \ + .properties = ((const ParseInfoProperty *const[]){ \ + __VA_ARGS__ NULL, \ + }) + +typedef struct { + const ParseInfoProperty *const *properties; +} ParseInfoSetting; + +#define PARSE_INFO_SETTING(setting_type, ...) \ + [setting_type] = (&((const ParseInfoSetting){__VA_ARGS__})) + +static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_WIRELESS, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_WIRELESS_BSSID, .parser = mac_address_parser_ETHER, ), + PARSE_INFO_PROPERTY(NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, + .parser = mac_address_parser_ETHER_cloned, ), + PARSE_INFO_PROPERTY(NM_SETTING_WIRELESS_MAC_ADDRESS, + .parser = mac_address_parser_ETHER, ), + PARSE_INFO_PROPERTY(NM_SETTING_WIRELESS_SSID, + .parser = ssid_parser, + .writer = ssid_writer, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_802_1X, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_802_1X_CA_CERT, + .parser = cert_parser, + .writer = cert_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_802_1X_CLIENT_CERT, + .parser = cert_parser, + .writer = cert_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PASSWORD_RAW, + .parser = password_raw_parser, + .writer = password_raw_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PHASE2_CA_CERT, + .parser = cert_parser, + .writer = cert_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + .parser = cert_parser, + .writer = cert_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + .parser = cert_parser, + .writer = cert_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_802_1X_PRIVATE_KEY, + .parser = cert_parser, + .writer = cert_writer, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_WIRED, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_WIRED_CLONED_MAC_ADDRESS, + .parser = mac_address_parser_ETHER_cloned, ), + PARSE_INFO_PROPERTY(NM_SETTING_WIRED_MAC_ADDRESS, .parser = mac_address_parser_ETHER, ), + PARSE_INFO_PROPERTY(NM_SETTING_WIRED_S390_OPTIONS, + .parser_no_check_key = TRUE, + .parser_full = wired_s390_options_parser_full, + .writer_full = wired_s390_options_writer_full, + .has_parser_full = TRUE, + .has_writer_full = TRUE, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_BLUETOOTH, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_BLUETOOTH_BDADDR, + .parser = mac_address_parser_ETHER, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_BOND, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_BOND_OPTIONS, .parser_no_check_key = TRUE, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_BRIDGE, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_BRIDGE_MAC_ADDRESS, + .parser = mac_address_parser_ETHER, ), + PARSE_INFO_PROPERTY(NM_SETTING_BRIDGE_VLANS, + .parser_no_check_key = TRUE, + .parser = bridge_vlan_parser, + .writer = bridge_vlan_writer, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_BRIDGE_PORT, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_BRIDGE_PORT_VLANS, + .parser_no_check_key = TRUE, + .parser = bridge_vlan_parser, + .writer = bridge_vlan_writer, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_CONNECTION, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_CONNECTION_READ_ONLY, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_CONNECTION_TYPE, + .parser = setting_alias_parser, + .writer = setting_alias_writer, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_INFINIBAND, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_INFINIBAND_MAC_ADDRESS, + .parser = mac_address_parser_INFINIBAND, ), ), ), + PARSE_INFO_SETTING(NM_META_SETTING_TYPE_IP4_CONFIG, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ADDRESSES, + .parser_no_check_key = TRUE, + .parser = ip_address_or_route_parser, + .writer = addr_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_DNS, + .parser_no_check_key = TRUE, + .parser = ip_dns_parser, + .writer = dns_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_GATEWAY, .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ROUTES, + .parser_no_check_key = TRUE, + .parser = ip_address_or_route_parser, + .writer = route_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ROUTING_RULES, + .parser_no_check_key = TRUE, + .parser_full = ip_routing_rule_parser_full, + .writer_full = ip_routing_rule_writer_full, + .has_parser_full = TRUE, + .has_writer_full = TRUE, ), ), ), + PARSE_INFO_SETTING(NM_META_SETTING_TYPE_IP6_CONFIG, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + .parser_no_check_key = TRUE, + .parser = ip6_addr_gen_mode_parser, + .writer = ip6_addr_gen_mode_writer, + .writer_persist_default = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ADDRESSES, + .parser_no_check_key = TRUE, + .parser = ip_address_or_route_parser, + .writer = addr_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_DNS, + .parser_no_check_key = TRUE, + .parser = ip_dns_parser, + .writer = dns_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_GATEWAY, .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ROUTES, + .parser_no_check_key = TRUE, + .parser = ip_address_or_route_parser, + .writer = route_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_IP_CONFIG_ROUTING_RULES, + .parser_no_check_key = TRUE, + .parser_full = ip_routing_rule_parser_full, + .writer_full = ip_routing_rule_writer_full, + .has_parser_full = TRUE, + .has_writer_full = TRUE, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_OVS_EXTERNAL_IDS_DATA, + .parser_no_check_key = TRUE, + .parser_full = _parser_full_ovs_external_ids_data, + .writer_full = _writer_full_ovs_external_ids_data, + .has_parser_full = TRUE, + .has_writer_full = TRUE, ), ), ), + PARSE_INFO_SETTING(NM_META_SETTING_TYPE_SERIAL, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_SERIAL_PARITY, + .parser = parity_parser, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_SRIOV, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_SRIOV_VFS, + .parser_no_check_key = TRUE, + .parser = sriov_vfs_parser, + .writer = sriov_vfs_writer, ), ), ), + PARSE_INFO_SETTING(NM_META_SETTING_TYPE_TC_CONFIG, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_TC_CONFIG_QDISCS, + .parser_no_check_key = TRUE, + .parser = qdisc_parser, + .writer = qdisc_writer, ), + PARSE_INFO_PROPERTY(NM_SETTING_TC_CONFIG_TFILTERS, + .parser_no_check_key = TRUE, + .parser = tfilter_parser, + .writer = tfilter_writer, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_TEAM, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_CONFIG, .parser = team_config_parser, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_LINK_WATCHERS, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_MCAST_REJOIN_COUNT, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER, .parser_skip = TRUE, .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_ACTIVE, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_FAST_RATE, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_MIN_PORTS, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_SYS_PRIO, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_TX_BALANCER, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_RUNNER_TX_HASH, + .parser_skip = TRUE, + .writer_skip = TRUE, ), ), ), + PARSE_INFO_SETTING(NM_META_SETTING_TYPE_TEAM_PORT, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_TEAM_CONFIG, + .parser = team_config_parser, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_LACP_KEY, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_LACP_PRIO, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_LINK_WATCHERS, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_PRIO, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_QUEUE_ID, + .parser_skip = TRUE, + .writer_skip = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_TEAM_PORT_STICKY, + .parser_skip = TRUE, + .writer_skip = TRUE, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_USER, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_USER_DATA, .parser_no_check_key = TRUE, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_VLAN, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_VLAN_FLAGS, .writer_persist_default = TRUE, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_VPN, + PARSE_INFO_PROPERTIES( + PARSE_INFO_PROPERTY(NM_SETTING_VPN_DATA, .parser_no_check_key = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_VPN_PERSISTENT, .parser_no_check_key = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_VPN_SECRETS, .parser_no_check_key = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_VPN_SERVICE_TYPE, .parser_no_check_key = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_VPN_TIMEOUT, .parser_no_check_key = TRUE, ), + PARSE_INFO_PROPERTY(NM_SETTING_VPN_USER_NAME, .parser_no_check_key = TRUE, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_WIMAX, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_WIMAX_MAC_ADDRESS, + .parser = mac_address_parser_ETHER, ), ), ), +}; + +static void +_parse_info_find(NMSetting * setting, + const char * property_name, + const NMMetaSettingInfo **out_setting_info, + const ParseInfoSetting ** out_parse_info_setting, + const ParseInfoProperty **out_parse_info_property) +{ + const NMMetaSettingInfo *setting_info; + const ParseInfoSetting * pis; + const ParseInfoProperty *pip; + +#if NM_MORE_ASSERTS > 10 + { + guint i, j; + static int asserted = FALSE; + + if (!asserted) { + for (i = 0; i < G_N_ELEMENTS(parse_infos); i++) { + pis = parse_infos[i]; + + if (!pis) + continue; + if (!pis->properties) + continue; + + g_assert(pis->properties[0]); + for (j = 0; pis->properties[j]; j++) { + const ParseInfoProperty *pip0; + const ParseInfoProperty *pipj = pis->properties[j]; + + g_assert(pipj->property_name); + if (j > 0 && (pip0 = pis->properties[j - 1]) + && strcmp(pip0->property_name, pipj->property_name) >= 0) { + g_error("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", + i, + j - 1, + nm_meta_setting_infos[i].setting_name, + pip0->property_name, + nm_meta_setting_infos[i].setting_name, + pipj->property_name); + } + } + } + asserted = TRUE; + } + } +#endif + + if (!NM_IS_SETTING(setting) || !(setting_info = NM_SETTING_GET_CLASS(setting)->setting_info)) { + /* handle invalid setting objects gracefully. */ + NM_SET_OUT(out_setting_info, NULL); + NM_SET_OUT(out_parse_info_setting, NULL); + NM_SET_OUT(out_parse_info_property, NULL); + return; + } + + nm_assert(setting_info->setting_name); + nm_assert(_NM_INT_NOT_NEGATIVE(setting_info->meta_type)); + nm_assert(setting_info->meta_type < G_N_ELEMENTS(parse_infos)); + + pis = parse_infos[setting_info->meta_type]; + + pip = NULL; + if (pis && property_name) { + gssize idx; + + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(ParseInfoProperty, property_name) == 0); + + idx = nm_utils_ptrarray_find_binary_search((gconstpointer *) pis->properties, + NM_PTRARRAY_LEN(pis->properties), + &property_name, + nm_strcmp_p_with_data, + NULL, + NULL, + NULL); + if (idx >= 0) + pip = pis->properties[idx]; + } + + NM_SET_OUT(out_setting_info, setting_info); + NM_SET_OUT(out_parse_info_setting, pis); + NM_SET_OUT(out_parse_info_property, pip); +} + +/*****************************************************************************/ + +static void +read_one_setting_value(KeyfileReaderInfo * info, + NMSetting * setting, + const NMSettInfoProperty *property_info) +{ + GKeyFile * keyfile = info->keyfile; + gs_free_error GError * err = NULL; + const NMMetaSettingInfo *setting_info; + const ParseInfoProperty *pip; + gs_free char * tmp_str = NULL; + const char * key; + GType type; + guint64 u64; + gint64 i64; + + nm_assert(!info->error); + nm_assert(!property_info->param_spec + || nm_streq(property_info->param_spec->name, property_info->name)); + + key = property_info->name; + + _parse_info_find(setting, key, &setting_info, NULL, &pip); + + nm_assert(setting_info); + + if (!pip) { + if (nm_streq(key, NM_SETTING_NAME)) + return; + if (!property_info->param_spec) + return; + if ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) + != G_PARAM_WRITABLE) + return; + } else { + if (pip->parser_skip) + return; + if (pip->has_parser_full) { + pip->parser_full(info, setting_info, property_info, pip, setting); + return; + } + } + + nm_assert(property_info->param_spec); + nm_assert((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) + == G_PARAM_WRITABLE); + + /* Check for the exact key in the GKeyFile if required. Most setting + * properties map 1:1 to a key in the GKeyFile, but for those properties + * like IP addresses and routes where more than one value is actually + * encoded by the setting property, this won't be true. + */ + if ((!pip || !pip->parser_no_check_key) + && !nm_keyfile_plugin_kf_has_key(keyfile, setting_info->setting_name, key, &err)) { + /* Key doesn't exist or an error occurred, thus nothing to do. */ + if (err) { + if (!handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("error loading setting value: %s"), + err->message)) + return; + } + return; + } + + if (pip && pip->parser) { + pip->parser(info, setting, key); + return; + } + + type = G_PARAM_SPEC_VALUE_TYPE(property_info->param_spec); + + if (type == G_TYPE_STRING) { + gs_free char *str_val = NULL; + + str_val = nm_keyfile_plugin_kf_get_string(keyfile, setting_info->setting_name, key, &err); + if (!err) + nm_g_object_set_property_string_take(G_OBJECT(setting), + key, + g_steal_pointer(&str_val), + &err); + } else if (type == G_TYPE_UINT) { + tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); + if (!err) { + u64 = _nm_utils_ascii_str_to_uint64(tmp_str, 0, 0, G_MAXUINT, G_MAXUINT64); + if (u64 == G_MAXUINT64 && errno != 0) { + g_set_error_literal(&err, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("value cannot be interpreted as integer")); + } else + nm_g_object_set_property_uint(G_OBJECT(setting), key, u64, &err); + } + } else if (type == G_TYPE_INT) { + tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); + if (!err) { + i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT, G_MAXINT, G_MININT64); + if (i64 == G_MININT64 && errno != 0) { + g_set_error_literal(&err, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("value cannot be interpreted as integer")); + } else + nm_g_object_set_property_int(G_OBJECT(setting), key, i64, &err); + } + } else if (type == G_TYPE_BOOLEAN) { + gboolean bool_val; + + bool_val = nm_keyfile_plugin_kf_get_boolean(keyfile, setting_info->setting_name, key, &err); + if (!err) + nm_g_object_set_property_boolean(G_OBJECT(setting), key, bool_val, &err); + } else if (type == G_TYPE_CHAR) { + tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); + if (!err) { + /* As documented by glib, G_TYPE_CHAR is really a (signed!) gint8. */ + i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT8, G_MAXINT8, G_MININT64); + if (i64 == G_MININT64 && errno != 0) { + g_set_error_literal(&err, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("value cannot be interpreted as integer")); + } else + nm_g_object_set_property_char(G_OBJECT(setting), key, i64, &err); + } + } else if (type == G_TYPE_UINT64) { + tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); + if (!err) { + u64 = _nm_utils_ascii_str_to_uint64(tmp_str, 0, 0, G_MAXUINT64, G_MAXUINT64); + if (u64 == G_MAXUINT64 && errno != 0) { + g_set_error_literal(&err, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("value cannot be interpreted as integer")); + } else + nm_g_object_set_property_uint64(G_OBJECT(setting), key, u64, &err); + } + } else if (type == G_TYPE_INT64) { + tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); + if (!err) { + i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT64, G_MAXINT64, G_MAXINT64); + if (i64 == G_MAXINT64 && errno != 0) { + g_set_error_literal(&err, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("value cannot be interpreted as integer")); + } else + nm_g_object_set_property_int64(G_OBJECT(setting), key, i64, &err); + } + } else if (type == G_TYPE_BYTES) { + nm_auto_unref_bytearray GByteArray *array = NULL; + gs_unref_bytes GBytes *bytes = NULL; + gs_free guint *tmp = NULL; + gsize length; + int i; + gboolean already_warned = FALSE; + + tmp = nm_keyfile_plugin_kf_get_integer_list_uint(keyfile, + setting_info->setting_name, + key, + &length, + NULL); + + array = g_byte_array_sized_new(length); + for (i = 0; i < length; i++) { + const guint val = tmp[i]; + unsigned char v = (unsigned char) (val & 0xFF); + + if (val > 255u) { + if (!already_warned + && !handle_warn( + info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("ignoring invalid byte element '%u' (not between 0 and 255 inclusive)"), + val)) + return; + already_warned = TRUE; + } else + g_byte_array_append(array, (const unsigned char *) &v, sizeof(v)); + } + + bytes = g_byte_array_free_to_bytes(g_steal_pointer(&array)); + g_object_set(setting, key, bytes, NULL); + } else if (type == G_TYPE_STRV) { + gs_strfreev char **sa = NULL; + gsize length; + + sa = nm_keyfile_plugin_kf_get_string_list(keyfile, + setting_info->setting_name, + key, + &length, + NULL); + g_object_set(setting, key, sa, NULL); + } else if (type == G_TYPE_HASH_TABLE) { + read_hash_of_string(info, keyfile, setting, key); + } else if (type == G_TYPE_ARRAY) { + read_array_of_uint(keyfile, setting, key); + } else if (G_TYPE_IS_FLAGS(type)) { + tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); + if (!err) { + u64 = _nm_utils_ascii_str_to_uint64(tmp_str, 0, 0, G_MAXUINT, G_MAXUINT64); + if (u64 == G_MAXUINT64 && errno != 0) { + g_set_error_literal(&err, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("value cannot be interpreted as integer")); + } else + nm_g_object_set_property_flags(G_OBJECT(setting), key, type, u64, &err); + } + } else if (G_TYPE_IS_ENUM(type)) { + tmp_str = nm_keyfile_plugin_kf_get_value(keyfile, setting_info->setting_name, key, &err); + if (!err) { + i64 = _nm_utils_ascii_str_to_int64(tmp_str, 0, G_MININT, G_MAXINT, G_MAXINT64); + if (i64 == G_MAXINT64 && errno != 0) { + g_set_error_literal(&err, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("value cannot be interpreted as integer")); + } else + nm_g_object_set_property_enum(G_OBJECT(setting), key, type, i64, &err); + } + } else + g_return_if_reached(); + + if (err) { + if (nm_keyfile_error_is_not_found(err)) { + /* ignore such errors. The key is not present. */ + } else { + handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid setting: %s"), + err->message); + } + } +} + +static void +_read_setting(KeyfileReaderInfo *info) +{ + const NMSettInfoSetting *sett_info; + gs_unref_object NMSetting *setting = NULL; + const char * alias; + GType type; + guint i; + + alias = nm_keyfile_plugin_get_setting_name_for_alias(info->group); + if (!alias) + alias = info->group; + + type = nm_setting_lookup_type(alias); + if (!type) { + handle_warn(info, + NULL, + NULL, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid setting name '%s'"), + info->group); + return; + } + + setting = g_object_new(type, NULL); + + info->setting = setting; + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); + + if (sett_info->detail.gendata_info) { + gs_free char **keys = NULL; + gsize k, n_keys; + + keys = g_key_file_get_keys(info->keyfile, info->group, &n_keys, NULL); + if (!keys) + n_keys = 0; + if (n_keys > 0) { + GHashTable *h = _nm_setting_option_hash(setting, TRUE); + + nm_utils_strv_sort(keys, n_keys); + for (k = 0; k < n_keys; k++) { + gs_free char *key = keys[k]; + gs_free_error GError *local = NULL; + const GVariantType * variant_type; + GVariant * variant; + + /* a GKeyFile can return duplicate keys, there is just no API to make sense + * of them. Skip them. */ + if (k + 1 < n_keys && nm_streq(key, keys[k + 1])) + continue; + + /* currently, the API is very simple. The setting class just returns + * the desired variant type, and keyfile reader will try to parse + * it accordingly. Note, that this does currently not allow, that + * a particular key can contain different variant types, nor is it + * very flexible in general. + * + * We add flexibility when we need it. Keep it simple for now. */ + variant_type = + sett_info->detail.gendata_info->get_variant_type(sett_info, key, &local); + if (!variant_type) { + if (!handle_warn(info, + key, + NULL, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key '%s.%s'"), + info->group, + key)) + break; + continue; + } + + if (g_variant_type_equal(variant_type, G_VARIANT_TYPE_BOOLEAN)) { + gboolean v; + + v = g_key_file_get_boolean(info->keyfile, info->group, key, &local); + if (local) { + if (!handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' is not boolean"), + info->group, + key)) + break; + continue; + } + variant = g_variant_new_boolean(v); + } else if (g_variant_type_equal(variant_type, G_VARIANT_TYPE_UINT32)) { + guint64 v; + + v = g_key_file_get_uint64(info->keyfile, info->group, key, &local); + + if (local) { + if (!handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' is not a uint32"), + info->group, + key)) + break; + continue; + } + variant = g_variant_new_uint32((guint32) v); + } else { + nm_assert_not_reached(); + continue; + } + + g_hash_table_insert(h, g_steal_pointer(&key), g_variant_take_ref(variant)); + } + for (; k < n_keys; k++) + g_free(keys[k]); + } + } + + for (i = 0; i < sett_info->property_infos_len; i++) { + read_one_setting_value(info, setting, &sett_info->property_infos[i]); + if (info->error) + goto out; + } + +out: + info->setting = NULL; + if (!info->error) + nm_connection_add_setting(info->connection, g_steal_pointer(&setting)); +} + +static void +_read_setting_wireguard_peer(KeyfileReaderInfo *info) +{ + gs_unref_object NMSettingWireGuard *s_wg_new = NULL; + nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; + gs_free_error GError *error = NULL; + NMSettingWireGuard * s_wg; + gs_free char * str = NULL; + const char * cstr = NULL; + const char * key; + gint64 i64; + gs_strfreev char ** sa = NULL; + gsize n_sa; + + peer = nm_wireguard_peer_new(); + + nm_assert(g_str_has_prefix(info->group, NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)); + cstr = &info->group[NM_STRLEN(NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)]; + if (!nm_utils_base64secret_normalize(cstr, NM_WIREGUARD_PUBLIC_KEY_LEN, &str) + || !nm_streq0(str, cstr)) { + /* the group name must be identical to the normalized(!) key, so that it + * is uniquely identified. */ + handle_warn(info, + NULL, + NM_SETTING_WIREGUARD_PEERS, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid peer public key in section '%s'"), + info->group); + return; + } + nm_wireguard_peer_set_public_key(peer, cstr, TRUE); + nm_clear_g_free(&str); + + key = NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY; + str = nm_keyfile_plugin_kf_get_string(info->keyfile, info->group, key, NULL); + if (str) { + if (!nm_wireguard_peer_set_preshared_key(peer, str, FALSE)) { + if (!handle_warn(info, + key, + NM_SETTING_WIREGUARD_PEERS, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' is not a valid 256 bit key in base64 encoding"), + info->group, + key)) + return; + } + nm_clear_g_free(&str); + } + + key = NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS; + i64 = nm_keyfile_plugin_kf_get_int64(info->keyfile, + info->group, + key, + 0, + 0, + NM_SETTING_SECRET_FLAG_ALL, + -1, + NULL); + if (errno != ENODATA) { + if (i64 == -1 || !_nm_setting_secret_flags_valid(i64)) { + if (!handle_warn(info, + key, + NM_SETTING_WIREGUARD_PEERS, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' is not a valid secret flag"), + info->group, + key)) + return; + } else + nm_wireguard_peer_set_preshared_key_flags(peer, i64); + } + + key = NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE; + i64 = nm_keyfile_plugin_kf_get_int64(info->keyfile, + info->group, + key, + 0, + 0, + G_MAXUINT32, + -1, + NULL); + if (errno != ENODATA) { + if (i64 == -1) { + if (!handle_warn(info, + key, + NM_SETTING_WIREGUARD_PEERS, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' is not a integer in range 0 to 2^32"), + info->group, + key)) + return; + } else + nm_wireguard_peer_set_persistent_keepalive(peer, i64); + } + + key = NM_WIREGUARD_PEER_ATTR_ENDPOINT; + str = nm_keyfile_plugin_kf_get_string(info->keyfile, info->group, key, NULL); + if (str && str[0]) { + if (!nm_wireguard_peer_set_endpoint(peer, str, FALSE)) { + if (!handle_warn(info, + key, + NM_SETTING_WIREGUARD_PEERS, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' is not a valid endpoint"), + info->group, + key)) + return; + } + } + nm_clear_g_free(&str); + + key = NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS; + sa = nm_keyfile_plugin_kf_get_string_list(info->keyfile, info->group, key, &n_sa, NULL); + if (n_sa > 0) { + gboolean has_error = FALSE; + gsize i; + + for (i = 0; i < n_sa; i++) { + if (!nm_utils_parse_inaddr_prefix_bin(AF_UNSPEC, sa[i], NULL, NULL, NULL)) { + has_error = TRUE; + continue; + } + nm_wireguard_peer_append_allowed_ip(peer, sa[i], TRUE); + } + if (has_error) { + if (!handle_warn(info, + key, + NM_SETTING_WIREGUARD_PEERS, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' has invalid allowed-ips"), + info->group, + key)) + return; + } + } + + if (info->error) + return; + + if (!nm_wireguard_peer_is_valid(peer, TRUE, TRUE, &error)) { + handle_warn(info, + NULL, + NM_SETTING_WIREGUARD_PEERS, + NM_KEYFILE_WARN_SEVERITY_WARN, + _("peer '%s' is invalid: %s"), + info->group, + error->message); + return; + } + + s_wg = NM_SETTING_WIREGUARD( + nm_connection_get_setting(info->connection, NM_TYPE_SETTING_WIREGUARD)); + if (!s_wg) { + s_wg_new = NM_SETTING_WIREGUARD(nm_setting_wireguard_new()); + s_wg = s_wg_new; + } + + nm_setting_wireguard_append_peer(s_wg, peer); + + if (s_wg_new) { + nm_connection_add_setting(info->connection, NM_SETTING(g_steal_pointer(&s_wg_new))); + } +} + +static void +_read_setting_vpn_secrets(KeyfileReaderInfo *info) +{ + gs_strfreev char **keys = NULL; + gsize i, n_keys; + NMSettingVpn * s_vpn; + + s_vpn = nm_connection_get_setting_vpn(info->connection); + if (!s_vpn) { + /* if we don't also have a [vpn] section (which must be parsed earlier), + * we don't do anything. */ + nm_assert(!g_key_file_has_group(info->keyfile, "vpn")); + return; + } + + keys = + nm_keyfile_plugin_kf_get_keys(info->keyfile, NM_KEYFILE_GROUP_VPN_SECRETS, &n_keys, NULL); + for (i = 0; i < n_keys; i++) { + gs_free char *secret = NULL; + + secret = nm_keyfile_plugin_kf_get_string(info->keyfile, + NM_KEYFILE_GROUP_VPN_SECRETS, + keys[i], + NULL); + if (secret) + nm_setting_vpn_add_secret(s_vpn, keys[i], secret); + } +} + +gboolean +nm_keyfile_read_ensure_id(NMConnection *connection, const char *fallback_id) +{ + NMSettingConnection *s_con; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + g_return_val_if_fail(fallback_id, FALSE); + + s_con = nm_connection_get_setting_connection(connection); + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(s_con), FALSE); + + if (nm_setting_connection_get_id(s_con)) + return FALSE; + + g_object_set(s_con, NM_SETTING_CONNECTION_ID, fallback_id, NULL); + return TRUE; +} + +gboolean +nm_keyfile_read_ensure_uuid(NMConnection *connection, const char *fallback_uuid_seed) +{ + NMSettingConnection *s_con; + gs_free char * hashed_uuid = NULL; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + g_return_val_if_fail(fallback_uuid_seed, FALSE); + + s_con = nm_connection_get_setting_connection(connection); + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(s_con), FALSE); + + if (nm_setting_connection_get_uuid(s_con)) + return FALSE; + + hashed_uuid = _nm_utils_uuid_generate_from_strings("keyfile", fallback_uuid_seed, NULL); + g_object_set(s_con, NM_SETTING_CONNECTION_UUID, hashed_uuid, NULL); + return TRUE; +} + +/** + * nm_keyfile_read: + * @keyfile: the keyfile from which to create the connection + * @base_dir: when reading certificates from files with relative name, + * the relative path is made absolute using @base_dir. This must + * be an absolute path. + * @handler_flags: the #NMKeyfileHandlerFlags. + * @handler: (allow-none) (scope call): read handler + * @user_data: user data for read handler + * @error: (allow-none) (out): error + * + * Tries to create a NMConnection from a keyfile. The resulting keyfile is + * not normalized and might not even verify. + * + * Returns: (transfer full): on success, returns the created connection. + * + * Since: 1.30 + */ +NMConnection * +nm_keyfile_read(GKeyFile * keyfile, + const char * base_dir, + NMKeyfileHandlerFlags handler_flags, + NMKeyfileReadHandler handler, + void * user_data, + GError ** error) +{ + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + gs_strfreev char ** groups = NULL; + gsize n_groups; + gsize i; + gboolean vpn_secrets = FALSE; + KeyfileReaderInfo info; + + g_return_val_if_fail(keyfile, NULL); + g_return_val_if_fail(!error || !*error, NULL); + g_return_val_if_fail(base_dir && base_dir[0] == '/', NULL); + g_return_val_if_fail(handler_flags == NM_KEYFILE_HANDLER_FLAGS_NONE, NULL); + + connection = nm_simple_connection_new(); + + info = (KeyfileReaderInfo){ + .connection = connection, + .keyfile = keyfile, + .base_dir = base_dir, + .read_handler = handler, + .user_data = user_data, + }; + + groups = g_key_file_get_groups(keyfile, &n_groups); + if (!groups) + n_groups = 0; + + for (i = 0; i < n_groups; i++) { + info.group = groups[i]; + + if (nm_streq(groups[i], NM_KEYFILE_GROUP_VPN_SECRETS)) { + /* Only read out secrets when needed */ + vpn_secrets = TRUE; + } else if (NM_STR_HAS_PREFIX(groups[i], NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER)) + _read_setting_wireguard_peer(&info); + else if (NM_IN_STRSET(groups[i], + NM_KEYFILE_GROUP_NMMETA, + ETHERNET_S390_OPTIONS_GROUP_NAME)) { + /* pass */ + } else + _read_setting(&info); + + info.group = NULL; + + if (info.error) + goto out_with_info_error; + } + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) { + s_con = NM_SETTING_CONNECTION(nm_setting_connection_new()); + nm_connection_add_setting(connection, NM_SETTING(s_con)); + } + + /* Make sure that we have 'interface-name' even if it was specified in the + * "wrong" (ie, deprecated) group. + */ + if (!nm_setting_connection_get_interface_name(s_con) + && nm_setting_connection_get_connection_type(s_con)) { + gs_free char *interface_name = NULL; + + interface_name = g_key_file_get_string(keyfile, + nm_setting_connection_get_connection_type(s_con), + "interface-name", + NULL); + if (interface_name) + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name, NULL); + } + + if (vpn_secrets) { + info.group = NM_KEYFILE_GROUP_VPN_SECRETS; + _read_setting_vpn_secrets(&info); + info.group = NULL; + if (info.error) + goto out_with_info_error; + } + + return g_steal_pointer(&connection); + +out_with_info_error: + g_propagate_error(error, info.error); + return NULL; +} + +/*****************************************************************************/ + +static void +write_setting_value(KeyfileWriterInfo * info, + NMSetting * setting, + const NMSettInfoProperty *property_info) +{ + const NMMetaSettingInfo *setting_info; + const ParseInfoProperty *pip; + const char * key; + char numstr[64]; + GValue value; + GType type; + + nm_assert(!info->error); + nm_assert(!property_info->param_spec + || nm_streq(property_info->param_spec->name, property_info->name)); + + key = property_info->name; + + _parse_info_find(setting, key, &setting_info, NULL, &pip); + + if (!pip) { + if (!setting_info) { + /* the setting type is unknown. That is highly unexpected + * (and as this is currently only called from NetworkManager + * daemon, not possible). + * + * Still, handle it gracefully, because later keyfile writer will become + * public API of libnm, where @setting is (untrusted) user input. + * + * Gracefully here just means: ignore the setting. */ + return; + } + if (!property_info->param_spec) + return; + if (nm_streq(key, NM_SETTING_NAME)) + return; + } else { + if (pip->has_writer_full) { + pip->writer_full(info, setting_info, property_info, pip, setting); + return; + } + if (pip->writer_skip) + return; + } + + nm_assert(property_info->param_spec); + + /* Don't write secrets that are owned by user secret agents or aren't + * supposed to be saved. VPN secrets are handled specially though since + * the secret flags there are in a third-level hash in the 'secrets' + * property. + */ + if ((property_info->param_spec->flags & NM_SETTING_PARAM_SECRET) + && !NM_IS_SETTING_VPN(setting)) { + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + if (!nm_setting_get_secret_flags(setting, key, &secret_flags, NULL)) + g_return_if_reached(); + if (!_secret_flags_persist_secret(secret_flags)) + return; + } + + value = (GValue){0}; + + g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(property_info->param_spec)); + g_object_get_property(G_OBJECT(setting), property_info->param_spec->name, &value); + + if ((!pip || !pip->writer_persist_default) + && g_param_value_defaults(property_info->param_spec, &value)) { + nm_assert(!g_key_file_has_key(info->keyfile, setting_info->setting_name, key, NULL)); + goto out_unset_value; + } + + if (pip && pip->writer) { + pip->writer(info, setting, key, &value); + goto out_unset_value; + } + + type = G_VALUE_TYPE(&value); + if (type == G_TYPE_STRING) { + const char *str; + + str = g_value_get_string(&value); + if (str) + nm_keyfile_plugin_kf_set_string(info->keyfile, setting_info->setting_name, key, str); + } else if (type == G_TYPE_UINT) { + nm_sprintf_buf(numstr, "%u", g_value_get_uint(&value)); + nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); + } else if (type == G_TYPE_INT) { + nm_sprintf_buf(numstr, "%d", g_value_get_int(&value)); + nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); + } else if (type == G_TYPE_UINT64) { + nm_sprintf_buf(numstr, "%" G_GUINT64_FORMAT, g_value_get_uint64(&value)); + nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); + } else if (type == G_TYPE_INT64) { + nm_sprintf_buf(numstr, "%" G_GINT64_FORMAT, g_value_get_int64(&value)); + nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); + } else if (type == G_TYPE_BOOLEAN) { + nm_keyfile_plugin_kf_set_value(info->keyfile, + setting_info->setting_name, + key, + g_value_get_boolean(&value) ? "true" : "false"); + } else if (type == G_TYPE_CHAR) { + nm_sprintf_buf(numstr, "%d", (int) g_value_get_schar(&value)); + nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); + } else if (type == G_TYPE_BYTES) { + GBytes * bytes; + const guint8 *data; + gsize len = 0; + + bytes = g_value_get_boxed(&value); + data = bytes ? g_bytes_get_data(bytes, &len) : NULL; + + if (data != NULL && len > 0) + nm_keyfile_plugin_kf_set_integer_list_uint8(info->keyfile, + setting_info->setting_name, + key, + data, + len); + } else if (type == G_TYPE_STRV) { + char **array; + + array = (char **) g_value_get_boxed(&value); + nm_keyfile_plugin_kf_set_string_list(info->keyfile, + setting_info->setting_name, + key, + (const char **const) array, + g_strv_length(array)); + } else if (type == G_TYPE_HASH_TABLE) { + write_hash_of_string(info->keyfile, setting, key, &value); + } else if (type == G_TYPE_ARRAY) { + write_array_of_uint(info->keyfile, setting, key, &value); + } else if (G_VALUE_HOLDS_FLAGS(&value)) { + nm_sprintf_buf(numstr, "%u", g_value_get_flags(&value)); + nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); + } else if (G_VALUE_HOLDS_ENUM(&value)) { + nm_sprintf_buf(numstr, "%d", g_value_get_enum(&value)); + nm_keyfile_plugin_kf_set_value(info->keyfile, setting_info->setting_name, key, numstr); + } else + g_return_if_reached(); + +out_unset_value: + g_value_unset(&value); +} + +static void +_write_setting_wireguard(NMSetting *setting, KeyfileWriterInfo *info) +{ + NMSettingWireGuard *s_wg; + guint i_peer, n_peers; + + s_wg = NM_SETTING_WIREGUARD(setting); + + n_peers = nm_setting_wireguard_get_peers_len(s_wg); + for (i_peer = 0; i_peer < n_peers; i_peer++) { + NMWireGuardPeer * peer = nm_setting_wireguard_get_peer(s_wg, i_peer); + const char * public_key; + char group[NM_STRLEN(NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER) + 200]; + NMSettingSecretFlags secret_flags; + gboolean any_key = FALSE; + guint i_aip, n_aip; + const char * cstr; + guint32 u32; + + public_key = nm_wireguard_peer_get_public_key(peer); + if (!public_key || !public_key[0] + || !NM_STRCHAR_ALL(public_key, ch, nm_sd_utils_unbase64char(ch, TRUE) >= 0)) { + /* invalid peer. Skip it */ + continue; + } + + if (g_snprintf(group, + sizeof(group), + "%s%s", + NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER, + nm_wireguard_peer_get_public_key(peer)) + >= sizeof(group)) { + /* Too long. Not a valid public key. Skip the peer. */ + continue; + } + + cstr = nm_wireguard_peer_get_endpoint(peer); + if (cstr) { + g_key_file_set_string(info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ENDPOINT, cstr); + any_key = TRUE; + } + + secret_flags = nm_wireguard_peer_get_preshared_key_flags(peer); + if (_secret_flags_persist_secret(secret_flags)) { + cstr = nm_wireguard_peer_get_preshared_key(peer); + if (cstr) { + g_key_file_set_string(info->keyfile, + group, + NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, + cstr); + any_key = TRUE; + } + } + + /* usually, we don't persist the secret-flags 0 (because they are the default). + * For WireGuard peers, the default secret-flags for preshared-key are 4 (not-required). + * So, in this case behave differently: a missing preshared-key-flag setting means + * "not-required". */ + if (secret_flags != NM_SETTING_SECRET_FLAG_NOT_REQUIRED) { + g_key_file_set_int64(info->keyfile, + group, + NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS, + secret_flags); + any_key = TRUE; + } + + u32 = nm_wireguard_peer_get_persistent_keepalive(peer); + if (u32) { + g_key_file_set_uint64(info->keyfile, + group, + NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE, + u32); + any_key = TRUE; + } + + n_aip = nm_wireguard_peer_get_allowed_ips_len(peer); + if (n_aip > 0) { + gs_free const char **strv = NULL; + + strv = g_new(const char *, ((gsize) n_aip) + 1); + for (i_aip = 0; i_aip < n_aip; i_aip++) + strv[i_aip] = nm_wireguard_peer_get_allowed_ip(peer, i_aip, NULL); + strv[n_aip] = NULL; + g_key_file_set_string_list(info->keyfile, + group, + NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS, + strv, + n_aip); + any_key = TRUE; + } + + if (!any_key) { + /* we cannot omit all keys. At an empty endpoint. */ + g_key_file_set_string(info->keyfile, group, NM_WIREGUARD_PEER_ATTR_ENDPOINT, ""); + } + } +} + +/** + * nm_keyfile_write: + * @connection: the #NMConnection to persist to keyfile. + * @handler_flags: the #NMKeyfileHandlerFlags. + * @handler: (allow-none) (scope call): optional handler for events and + * to override the default behavior. + * @user_data: argument for @handler. + * @error: the #GError in case writing fails. + * + * @connection must verify as a valid profile according to + * nm_connection_verify(). + * + * Returns: (transfer full): a new #GKeyFile or %NULL on error. + * + * Since: 1.30 + */ +GKeyFile * +nm_keyfile_write(NMConnection * connection, + NMKeyfileHandlerFlags handler_flags, + NMKeyfileWriteHandler handler, + void * user_data, + GError ** error) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + GError * local = NULL; + KeyfileWriterInfo info; + gs_free NMSetting **settings = NULL; + guint n_settings = 0; + guint i; + guint j; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + g_return_val_if_fail(!error || !*error, NULL); + g_return_val_if_fail(handler_flags == NM_KEYFILE_HANDLER_FLAGS_NONE, NULL); + + /* Technically, we might not require that a profile is valid in + * order to serialize it. Like also nm_keyfile_read() does not + * ensure that the read profile validates. + * + * However, if the profile does not validate, then there might be + * unexpected edge cases when we try to serialize it. Edge cases + * that might result in dangerous crash. + * + * So, for now we require valid profiles. */ + if (!nm_connection_verify(connection, error ? &local : NULL)) { + if (error) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("the profile is not valid: %s"), + local->message); + g_error_free(local); + } else + nm_assert(!local); + return NULL; + } + + keyfile = g_key_file_new(); + + info = (KeyfileWriterInfo){ + .connection = connection, + .keyfile = keyfile, + .error = NULL, + .write_handler = handler, + .user_data = user_data, + }; + + settings = nm_connection_get_settings(connection, &n_settings); + for (i = 0; i < n_settings; i++) { + const NMSettInfoSetting *sett_info; + NMSetting * setting = settings[i]; + const char * setting_name; + const char * setting_alias; + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); + + setting_name = sett_info->setting_class->setting_info->setting_name; + + if (sett_info->detail.gendata_info) { + guint k, n_keys; + const char *const *keys; + + nm_assert(!nm_keyfile_plugin_get_alias_for_setting_name( + sett_info->setting_class->setting_info->setting_name)); + + n_keys = _nm_setting_option_get_all(setting, &keys, NULL); + + if (n_keys > 0) { + GHashTable *h = _nm_setting_option_hash(setting, FALSE); + + for (k = 0; k < n_keys; k++) { + const char *key = keys[k]; + GVariant * v; + + v = g_hash_table_lookup(h, key); + + if (g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) { + g_key_file_set_boolean(info.keyfile, + setting_name, + key, + g_variant_get_boolean(v)); + } else if (g_variant_is_of_type(v, G_VARIANT_TYPE_UINT32)) { + g_key_file_set_uint64(info.keyfile, + setting_name, + key, + (guint64) g_variant_get_uint32(v)); + } else { + /* BUG: The variant type is not implemented. Since the connection + * verifies, this can only mean we either wrongly didn't reject + * the connection as invalid, or we didn't properly implement the + * variant type. */ + nm_assert_not_reached(); + continue; + } + } + } + } + + for (j = 0; j < sett_info->property_infos_len; j++) { + const NMSettInfoProperty *property_info = + _nm_sett_info_property_info_get_sorted(sett_info, j); + + write_setting_value(&info, setting, property_info); + if (info.error) + goto out_with_info_error; + } + + setting_alias = nm_keyfile_plugin_get_alias_for_setting_name(setting_name); + if ((setting_alias && g_key_file_has_group(info.keyfile, setting_alias)) + || g_key_file_has_group(info.keyfile, setting_name)) { + /* we have a section for the setting. Nothing to do. */ + } else { + /* ensure the group is present. There is no API for that, so add and remove + * a dummy key. */ + g_key_file_set_value(info.keyfile, setting_alias ?: setting_name, ".X", "1"); + g_key_file_remove_key(info.keyfile, setting_alias ?: setting_name, ".X", NULL); + } + + if (NM_IS_SETTING_WIREGUARD(setting)) { + _write_setting_wireguard(setting, &info); + if (info.error) + goto out_with_info_error; + } + + nm_assert(!info.error); + } + + nm_assert(!info.error); + + return g_steal_pointer(&keyfile); + +out_with_info_error: + g_propagate_error(error, info.error); + return NULL; +} + +/*****************************************************************************/ + +static const char temp_letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* + * Check '.[a-zA-Z0-9]{6}' file suffix used for temporary files by g_file_set_contents() (mkstemp()). + */ +static gboolean +check_mkstemp_suffix(const char *path) +{ + const char *ptr; + + nm_assert(path); + + /* Matches *.[a-zA-Z0-9]{6} suffix of mkstemp()'s temporary files */ + ptr = strrchr(path, '.'); + if (ptr && strspn(&ptr[1], temp_letters) == 6 && ptr[7] == '\0') + return TRUE; + return FALSE; +} + +#define SWP_TAG ".swp" +#define SWPX_TAG ".swpx" +#define PEM_TAG ".pem" +#define DER_TAG ".der" + +gboolean +nm_keyfile_utils_ignore_filename(const char *filename, gboolean require_extension) +{ + const char *base; + gsize l; + + /* ignore_filename() must mirror nm_keyfile_utils_create_filename() */ + + g_return_val_if_fail(filename, TRUE); + + base = strrchr(filename, '/'); + if (base) + base++; + else + base = filename; + + if (!base[0]) { + /* this check above with strrchr() also rejects "/some/path/with/trailing/slash/", + * but that is fine, because such a path would name a directory, and we are not + * interested in directories. */ + return TRUE; + } + + if (base[0] == '.') { + /* don't allow hidden files */ + return TRUE; + } + + if (require_extension) { + if (!NM_STR_HAS_SUFFIX_WITH_MORE(base, NM_KEYFILE_PATH_SUFFIX_NMCONNECTION)) + return TRUE; + return FALSE; + } + + l = strlen(base); + + /* Ignore backup files */ + if (base[l - 1] == '~') + return TRUE; + + /* Ignore temporary files + * + * This check is also important to ignore .nmload files (see + * %NM_KEYFILE_PATH_SUFFIX_NMMETA). */ + if (check_mkstemp_suffix(base)) + return TRUE; + + /* Ignore 802.1x certificates and keys */ + if (NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(base, PEM_TAG) + || NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(base, DER_TAG)) + return TRUE; + + return FALSE; +} + +char * +nm_keyfile_utils_create_filename(const char *name, gboolean with_extension) +{ + /* keyfile used to escape with '*', do not change that behavior. + * + * But for newly added escapings, use '_' instead. + * Also, @with_extension is new-style. */ + const char ESCAPE_CHAR = with_extension ? '_' : '*'; + const char ESCAPE_CHAR2 = '_'; + NMStrBuf str; + char * p; + gsize len; + gsize i; + + g_return_val_if_fail(name && name[0], NULL); + + nm_str_buf_init(&str, 0, FALSE); + + len = strlen(name); + + p = nm_str_buf_append_len0(&str, name, len); + + /* Convert '/' to ESCAPE_CHAR */ + for (i = 0; i < len; i++) { + if (p[i] == '/') + p[i] = ESCAPE_CHAR; + } + + /* nm_keyfile_utils_create_filename() must avoid anything that ignore_filename() would reject. + * We can escape here more aggressively then what we would read back. */ + if (p[0] == '.') + p[0] = ESCAPE_CHAR2; + if (p[str.len - 1] == '~') + p[str.len - 1] = ESCAPE_CHAR2; + + if (check_mkstemp_suffix(p) || NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(p, PEM_TAG) + || NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(p, DER_TAG)) + nm_str_buf_append_c(&str, ESCAPE_CHAR2); + + if (with_extension) + nm_str_buf_append(&str, NM_KEYFILE_PATH_SUFFIX_NMCONNECTION); + + p = nm_str_buf_finalize(&str, NULL); + + /* nm_keyfile_utils_create_filename() must mirror ignore_filename() */ + nm_assert(!strchr(p, '/')); + nm_assert(!nm_keyfile_utils_ignore_filename(p, with_extension)); + + return p; +} + +/*****************************************************************************/ + +/** + * nm_keyfile_handler_data_fail_with_error: + * @handler_data: the #NMKeyfileHandlerData + * @src: (transfer full): error to move into the return location + * + * Set the error for the handler. This lets the operation fail + * with the provided error. You may only set the error once. + * + * @src must be non-%NULL. + * + * Note that @src is no longer valid after this call. If you want + * to keep using the same GError*, you need to set it to %NULL + * after calling this function on it. + * + * Since: 1.30 + */ +void +nm_keyfile_handler_data_fail_with_error(NMKeyfileHandlerData *handler_data, GError *src) +{ + g_return_if_fail(handler_data); + g_return_if_fail(handler_data->p_error && !*handler_data->p_error); + g_return_if_fail(src); + + *handler_data->p_error = src; +} + +/** + * nm_keyfile_handler_data_get_context: + * @handler_data: the #NMKeyfileHandlerData for any event. + * @out_kf_group_name: (out) (allow-none) (transfer none): if the event is in the + * context of a keyfile group, the group name. + * @out_kf_key_name: (out) (allow-none) (transfer none): if the event is in the + * context of a keyfile value, the key name. + * @out_cur_setting: (out) (allow-none) (transfer none): if the event happens while + * handling a particular #NMSetting instance. + * @out_cur_property_name: (out) (allow-none) (transfer none): the property name if applicable. + * + * Get context information of the current event. This function can be called + * on all events, but the context information may be unset. + * + * Since: 1.30 + */ +void +nm_keyfile_handler_data_get_context(const NMKeyfileHandlerData *handler_data, + const char ** out_kf_group_name, + const char ** out_kf_key_name, + NMSetting ** out_cur_setting, + const char ** out_cur_property_name) +{ + g_return_if_fail(handler_data); + + NM_SET_OUT(out_kf_group_name, handler_data->kf_group_name); + NM_SET_OUT(out_kf_key_name, handler_data->kf_key); + NM_SET_OUT(out_cur_setting, handler_data->cur_setting); + NM_SET_OUT(out_cur_property_name, handler_data->cur_property); +} + +const char * +_nm_keyfile_handler_data_warn_get_message(const NMKeyfileHandlerData *handler_data) +{ + nm_assert(handler_data); + nm_assert(handler_data->type == NM_KEYFILE_HANDLER_TYPE_WARN); + + if (!handler_data->warn.message) { + /* we cast the const away. @handler_data is const w.r.t. visible mutations + * from POV of the user. Internally, we construct the message in + * a lazy manner. It's like a mutable field in C++. */ + NM_PRAGMA_WARNING_DISABLE("-Wformat-nonliteral") + ((NMKeyfileHandlerData *) handler_data)->warn.message = + g_strdup_vprintf(handler_data->warn.fmt, + ((NMKeyfileHandlerData *) handler_data)->warn.ap); + NM_PRAGMA_WARNING_REENABLE + } + return handler_data->warn.message; +} + +/** + * nm_keyfile_handler_data_warn_get: + * @handler_data: the #NMKeyfileHandlerData for a %NM_KEYFILE_HANDLER_TYPE_WARN + * event. + * @out_message: (out) (allow-none) (transfer none): the warning message. + * @out_severity: (out) (allow-none): the #NMKeyfileWarnSeverity warning severity. + * + * Since: 1.30 + */ +void +nm_keyfile_handler_data_warn_get(const NMKeyfileHandlerData *handler_data, + const char ** out_message, + NMKeyfileWarnSeverity * out_severity) +{ + g_return_if_fail(handler_data); + g_return_if_fail(handler_data->type == NM_KEYFILE_HANDLER_TYPE_WARN); + + NM_SET_OUT(out_message, _nm_keyfile_handler_data_warn_get_message(handler_data)); + NM_SET_OUT(out_severity, handler_data->warn.severity); +} diff --git a/src/libnm-core-impl/nm-meta-setting-base-impl.c b/src/libnm-core-impl/nm-meta-setting-base-impl.c new file mode 100644 index 0000000000..523c0d5db3 --- /dev/null +++ b/src/libnm-core-impl/nm-meta-setting-base-impl.c @@ -0,0 +1,641 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 - 2018 Red Hat, Inc. + */ + +#include "nm-glib-aux/nm-default-glib-i18n-lib.h" + +#include "nm-meta-setting-base.h" + +#include "nm-setting-6lowpan.h" +#include "nm-setting-8021x.h" +#include "nm-setting-adsl.h" +#include "nm-setting-bluetooth.h" +#include "nm-setting-bond.h" +#include "nm-setting-bridge-port.h" +#include "nm-setting-bridge.h" +#include "nm-setting-cdma.h" +#include "nm-setting-connection.h" +#include "nm-setting-dcb.h" +#include "nm-setting-dummy.h" +#include "nm-setting-ethtool.h" +#include "nm-setting-generic.h" +#include "nm-setting-gsm.h" +#include "nm-setting-hostname.h" +#include "nm-setting-infiniband.h" +#include "nm-setting-ip-config.h" +#include "nm-setting-ip-tunnel.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-macsec.h" +#include "nm-setting-macvlan.h" +#include "nm-setting-match.h" +#include "nm-setting-olpc-mesh.h" +#include "nm-setting-ovs-bridge.h" +#include "nm-setting-ovs-interface.h" +#include "nm-setting-ovs-dpdk.h" +#include "nm-setting-ovs-external-ids.h" +#include "nm-setting-ovs-patch.h" +#include "nm-setting-ovs-port.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-proxy.h" +#include "nm-setting-serial.h" +#include "nm-setting-tc-config.h" +#include "nm-setting-team-port.h" +#include "nm-setting-team.h" +#include "nm-setting-tun.h" +#include "nm-setting-user.h" +#include "nm-setting-veth.h" +#include "nm-setting-vlan.h" +#include "nm-setting-vpn.h" +#include "nm-setting-vrf.h" +#include "nm-setting-vxlan.h" +#include "nm-setting-wifi-p2p.h" +#include "nm-setting-wimax.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireguard.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wpan.h" + +/*****************************************************************************/ + +const NMSetting8021xSchemeVtable nm_setting_8021x_scheme_vtable[] = { + +#define _D(_scheme_type, ...) [(_scheme_type)] = {.scheme_type = (_scheme_type), __VA_ARGS__} + + _D(NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN), + + _D(NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT, + .setting_key = NM_SETTING_802_1X_CA_CERT, + .scheme_func = nm_setting_802_1x_get_ca_cert_scheme, + .format_func = NULL, + .path_func = nm_setting_802_1x_get_ca_cert_path, + .blob_func = nm_setting_802_1x_get_ca_cert_blob, + .uri_func = nm_setting_802_1x_get_ca_cert_uri, + .passwd_func = nm_setting_802_1x_get_ca_cert_password, + .pwflag_func = nm_setting_802_1x_get_ca_cert_password_flags, + .set_cert_func = nm_setting_802_1x_set_ca_cert, + .file_suffix = "ca-cert", ), + + _D(NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT, + .setting_key = NM_SETTING_802_1X_PHASE2_CA_CERT, + .scheme_func = nm_setting_802_1x_get_phase2_ca_cert_scheme, + .format_func = NULL, + .path_func = nm_setting_802_1x_get_phase2_ca_cert_path, + .blob_func = nm_setting_802_1x_get_phase2_ca_cert_blob, + .uri_func = nm_setting_802_1x_get_phase2_ca_cert_uri, + .passwd_func = nm_setting_802_1x_get_phase2_ca_cert_password, + .pwflag_func = nm_setting_802_1x_get_phase2_ca_cert_password_flags, + .set_cert_func = nm_setting_802_1x_set_phase2_ca_cert, + .file_suffix = "inner-ca-cert", ), + + _D(NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT, + .setting_key = NM_SETTING_802_1X_CLIENT_CERT, + .scheme_func = nm_setting_802_1x_get_client_cert_scheme, + .format_func = NULL, + .path_func = nm_setting_802_1x_get_client_cert_path, + .blob_func = nm_setting_802_1x_get_client_cert_blob, + .uri_func = nm_setting_802_1x_get_client_cert_uri, + .passwd_func = nm_setting_802_1x_get_client_cert_password, + .pwflag_func = nm_setting_802_1x_get_client_cert_password_flags, + .set_cert_func = nm_setting_802_1x_set_client_cert, + .file_suffix = "client-cert", ), + + _D(NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT, + .setting_key = NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + .scheme_func = nm_setting_802_1x_get_phase2_client_cert_scheme, + .format_func = NULL, + .path_func = nm_setting_802_1x_get_phase2_client_cert_path, + .blob_func = nm_setting_802_1x_get_phase2_client_cert_blob, + .uri_func = nm_setting_802_1x_get_phase2_client_cert_uri, + .passwd_func = nm_setting_802_1x_get_phase2_client_cert_password, + .pwflag_func = nm_setting_802_1x_get_phase2_client_cert_password_flags, + .set_cert_func = nm_setting_802_1x_set_phase2_client_cert, + .file_suffix = "inner-client-cert", ), + + _D(NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY, + .setting_key = NM_SETTING_802_1X_PRIVATE_KEY, + .scheme_func = nm_setting_802_1x_get_private_key_scheme, + .format_func = nm_setting_802_1x_get_private_key_format, + .path_func = nm_setting_802_1x_get_private_key_path, + .blob_func = nm_setting_802_1x_get_private_key_blob, + .uri_func = nm_setting_802_1x_get_private_key_uri, + .passwd_func = nm_setting_802_1x_get_private_key_password, + .pwflag_func = nm_setting_802_1x_get_private_key_password_flags, + .set_private_key_func = nm_setting_802_1x_set_private_key, + .file_suffix = "private-key", + .is_secret = TRUE, ), + + _D(NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY, + .setting_key = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + .scheme_func = nm_setting_802_1x_get_phase2_private_key_scheme, + .format_func = nm_setting_802_1x_get_phase2_private_key_format, + .path_func = nm_setting_802_1x_get_phase2_private_key_path, + .blob_func = nm_setting_802_1x_get_phase2_private_key_blob, + .uri_func = nm_setting_802_1x_get_phase2_private_key_uri, + .passwd_func = nm_setting_802_1x_get_phase2_private_key_password, + .pwflag_func = nm_setting_802_1x_get_phase2_private_key_password_flags, + .set_private_key_func = nm_setting_802_1x_set_phase2_private_key, + .file_suffix = "inner-private-key", + .is_secret = TRUE, ), + +#undef _D +}; + +/*****************************************************************************/ + +const NMMetaSettingInfo nm_meta_setting_infos[] = { + [NM_META_SETTING_TYPE_6LOWPAN] = + { + .meta_type = NM_META_SETTING_TYPE_6LOWPAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_6LOWPAN_SETTING_NAME, + .get_setting_gtype = nm_setting_6lowpan_get_type, + }, + [NM_META_SETTING_TYPE_802_1X] = + { + .meta_type = NM_META_SETTING_TYPE_802_1X, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, + .setting_name = NM_SETTING_802_1X_SETTING_NAME, + .get_setting_gtype = nm_setting_802_1x_get_type, + }, + [NM_META_SETTING_TYPE_ADSL] = + { + .meta_type = NM_META_SETTING_TYPE_ADSL, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_ADSL_SETTING_NAME, + .get_setting_gtype = nm_setting_adsl_get_type, + }, + [NM_META_SETTING_TYPE_BLUETOOTH] = + { + .meta_type = NM_META_SETTING_TYPE_BLUETOOTH, + .setting_priority = NM_SETTING_PRIORITY_HW_NON_BASE, + .setting_name = NM_SETTING_BLUETOOTH_SETTING_NAME, + .get_setting_gtype = nm_setting_bluetooth_get_type, + }, + [NM_META_SETTING_TYPE_BOND] = + { + .meta_type = NM_META_SETTING_TYPE_BOND, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_BOND_SETTING_NAME, + .get_setting_gtype = nm_setting_bond_get_type, + }, + [NM_META_SETTING_TYPE_BRIDGE] = + { + .meta_type = NM_META_SETTING_TYPE_BRIDGE, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_BRIDGE_SETTING_NAME, + .get_setting_gtype = nm_setting_bridge_get_type, + }, + [NM_META_SETTING_TYPE_BRIDGE_PORT] = + { + .meta_type = NM_META_SETTING_TYPE_BRIDGE_PORT, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_BRIDGE_PORT_SETTING_NAME, + .get_setting_gtype = nm_setting_bridge_port_get_type, + }, + [NM_META_SETTING_TYPE_CDMA] = + { + .meta_type = NM_META_SETTING_TYPE_CDMA, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_CDMA_SETTING_NAME, + .get_setting_gtype = nm_setting_cdma_get_type, + }, + [NM_META_SETTING_TYPE_CONNECTION] = + { + .meta_type = NM_META_SETTING_TYPE_CONNECTION, + .setting_priority = NM_SETTING_PRIORITY_CONNECTION, + .setting_name = NM_SETTING_CONNECTION_SETTING_NAME, + .get_setting_gtype = nm_setting_connection_get_type, + }, + [NM_META_SETTING_TYPE_DCB] = + { + .meta_type = NM_META_SETTING_TYPE_DCB, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, + .setting_name = NM_SETTING_DCB_SETTING_NAME, + .get_setting_gtype = nm_setting_dcb_get_type, + }, + [NM_META_SETTING_TYPE_DUMMY] = + { + .meta_type = NM_META_SETTING_TYPE_DUMMY, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_DUMMY_SETTING_NAME, + .get_setting_gtype = nm_setting_dummy_get_type, + }, + [NM_META_SETTING_TYPE_ETHTOOL] = + { + .meta_type = NM_META_SETTING_TYPE_ETHTOOL, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_ETHTOOL_SETTING_NAME, + .get_setting_gtype = nm_setting_ethtool_get_type, + }, + [NM_META_SETTING_TYPE_GENERIC] = + { + .meta_type = NM_META_SETTING_TYPE_GENERIC, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_GENERIC_SETTING_NAME, + .get_setting_gtype = nm_setting_generic_get_type, + }, + [NM_META_SETTING_TYPE_GSM] = + { + .meta_type = NM_META_SETTING_TYPE_GSM, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_GSM_SETTING_NAME, + .get_setting_gtype = nm_setting_gsm_get_type, + }, + [NM_META_SETTING_TYPE_HOSTNAME] = + { + .meta_type = NM_META_SETTING_TYPE_HOSTNAME, + .setting_priority = NM_SETTING_PRIORITY_IP, + .setting_name = NM_SETTING_HOSTNAME_SETTING_NAME, + .get_setting_gtype = nm_setting_hostname_get_type, + }, + [NM_META_SETTING_TYPE_INFINIBAND] = + { + .meta_type = NM_META_SETTING_TYPE_INFINIBAND, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_INFINIBAND_SETTING_NAME, + .get_setting_gtype = nm_setting_infiniband_get_type, + }, + [NM_META_SETTING_TYPE_IP4_CONFIG] = + { + .meta_type = NM_META_SETTING_TYPE_IP4_CONFIG, + .setting_priority = NM_SETTING_PRIORITY_IP, + .setting_name = NM_SETTING_IP4_CONFIG_SETTING_NAME, + .get_setting_gtype = nm_setting_ip4_config_get_type, + }, + [NM_META_SETTING_TYPE_IP6_CONFIG] = + { + .meta_type = NM_META_SETTING_TYPE_IP6_CONFIG, + .setting_priority = NM_SETTING_PRIORITY_IP, + .setting_name = NM_SETTING_IP6_CONFIG_SETTING_NAME, + .get_setting_gtype = nm_setting_ip6_config_get_type, + }, + [NM_META_SETTING_TYPE_IP_TUNNEL] = + { + .meta_type = NM_META_SETTING_TYPE_IP_TUNNEL, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_IP_TUNNEL_SETTING_NAME, + .get_setting_gtype = nm_setting_ip_tunnel_get_type, + }, + [NM_META_SETTING_TYPE_MACSEC] = + { + .meta_type = NM_META_SETTING_TYPE_MACSEC, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_MACSEC_SETTING_NAME, + .get_setting_gtype = nm_setting_macsec_get_type, + }, + [NM_META_SETTING_TYPE_MACVLAN] = + { + .meta_type = NM_META_SETTING_TYPE_MACVLAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_MACVLAN_SETTING_NAME, + .get_setting_gtype = nm_setting_macvlan_get_type, + }, + [NM_META_SETTING_TYPE_MATCH] = + { + .meta_type = NM_META_SETTING_TYPE_MATCH, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_MATCH_SETTING_NAME, + .get_setting_gtype = nm_setting_match_get_type, + }, + [NM_META_SETTING_TYPE_OLPC_MESH] = + { + .meta_type = NM_META_SETTING_TYPE_OLPC_MESH, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_OLPC_MESH_SETTING_NAME, + .get_setting_gtype = nm_setting_olpc_mesh_get_type, + }, + [NM_META_SETTING_TYPE_OVS_BRIDGE] = + { + .meta_type = NM_META_SETTING_TYPE_OVS_BRIDGE, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_OVS_BRIDGE_SETTING_NAME, + .get_setting_gtype = nm_setting_ovs_bridge_get_type, + }, + [NM_META_SETTING_TYPE_OVS_DPDK] = + { + .meta_type = NM_META_SETTING_TYPE_OVS_DPDK, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_OVS_DPDK_SETTING_NAME, + .get_setting_gtype = nm_setting_ovs_dpdk_get_type, + }, + [NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS] = + { + .meta_type = NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + .get_setting_gtype = nm_setting_ovs_external_ids_get_type, + }, + [NM_META_SETTING_TYPE_OVS_INTERFACE] = + { + .meta_type = NM_META_SETTING_TYPE_OVS_INTERFACE, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_OVS_INTERFACE_SETTING_NAME, + .get_setting_gtype = nm_setting_ovs_interface_get_type, + }, + [NM_META_SETTING_TYPE_OVS_PATCH] = + { + .meta_type = NM_META_SETTING_TYPE_OVS_PATCH, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_OVS_PATCH_SETTING_NAME, + .get_setting_gtype = nm_setting_ovs_patch_get_type, + }, + [NM_META_SETTING_TYPE_OVS_PORT] = + { + .meta_type = NM_META_SETTING_TYPE_OVS_PORT, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_OVS_PORT_SETTING_NAME, + .get_setting_gtype = nm_setting_ovs_port_get_type, + }, + [NM_META_SETTING_TYPE_PPPOE] = + { + .meta_type = NM_META_SETTING_TYPE_PPPOE, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_PPPOE_SETTING_NAME, + .get_setting_gtype = nm_setting_pppoe_get_type, + }, + [NM_META_SETTING_TYPE_PPP] = + { + .meta_type = NM_META_SETTING_TYPE_PPP, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_PPP_SETTING_NAME, + .get_setting_gtype = nm_setting_ppp_get_type, + }, + [NM_META_SETTING_TYPE_PROXY] = + { + .meta_type = NM_META_SETTING_TYPE_PROXY, + .setting_priority = NM_SETTING_PRIORITY_IP, + .setting_name = NM_SETTING_PROXY_SETTING_NAME, + .get_setting_gtype = nm_setting_proxy_get_type, + }, + [NM_META_SETTING_TYPE_SERIAL] = + { + .meta_type = NM_META_SETTING_TYPE_SERIAL, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, + .setting_name = NM_SETTING_SERIAL_SETTING_NAME, + .get_setting_gtype = nm_setting_serial_get_type, + }, + [NM_META_SETTING_TYPE_SRIOV] = + { + .meta_type = NM_META_SETTING_TYPE_SRIOV, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, + .setting_name = NM_SETTING_SRIOV_SETTING_NAME, + .get_setting_gtype = nm_setting_sriov_get_type, + }, + [NM_META_SETTING_TYPE_TC_CONFIG] = + { + .meta_type = NM_META_SETTING_TYPE_TC_CONFIG, + .setting_priority = NM_SETTING_PRIORITY_IP, + .setting_name = NM_SETTING_TC_CONFIG_SETTING_NAME, + .get_setting_gtype = nm_setting_tc_config_get_type, + }, + [NM_META_SETTING_TYPE_TEAM] = + { + .meta_type = NM_META_SETTING_TYPE_TEAM, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_TEAM_SETTING_NAME, + .get_setting_gtype = nm_setting_team_get_type, + }, + [NM_META_SETTING_TYPE_TEAM_PORT] = + { + .meta_type = NM_META_SETTING_TYPE_TEAM_PORT, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_TEAM_PORT_SETTING_NAME, + .get_setting_gtype = nm_setting_team_port_get_type, + }, + [NM_META_SETTING_TYPE_TUN] = + { + .meta_type = NM_META_SETTING_TYPE_TUN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_TUN_SETTING_NAME, + .get_setting_gtype = nm_setting_tun_get_type, + }, + [NM_META_SETTING_TYPE_USER] = + { + .meta_type = NM_META_SETTING_TYPE_USER, + .setting_priority = NM_SETTING_PRIORITY_USER, + .setting_name = NM_SETTING_USER_SETTING_NAME, + .get_setting_gtype = nm_setting_user_get_type, + }, + [NM_META_SETTING_TYPE_VETH] = + { + .meta_type = NM_META_SETTING_TYPE_VETH, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_VETH_SETTING_NAME, + .get_setting_gtype = nm_setting_veth_get_type, + }, + [NM_META_SETTING_TYPE_VLAN] = + { + .meta_type = NM_META_SETTING_TYPE_VLAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_VLAN_SETTING_NAME, + .get_setting_gtype = nm_setting_vlan_get_type, + }, + [NM_META_SETTING_TYPE_VPN] = + { + .meta_type = NM_META_SETTING_TYPE_VPN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_VPN_SETTING_NAME, + .get_setting_gtype = nm_setting_vpn_get_type, + }, + [NM_META_SETTING_TYPE_VRF] = + { + .meta_type = NM_META_SETTING_TYPE_VRF, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_VRF_SETTING_NAME, + .get_setting_gtype = nm_setting_vrf_get_type, + }, + [NM_META_SETTING_TYPE_VXLAN] = + { + .meta_type = NM_META_SETTING_TYPE_VXLAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_VXLAN_SETTING_NAME, + .get_setting_gtype = nm_setting_vxlan_get_type, + }, + [NM_META_SETTING_TYPE_WIFI_P2P] = + { + .meta_type = NM_META_SETTING_TYPE_WIFI_P2P, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_WIFI_P2P_SETTING_NAME, + .get_setting_gtype = nm_setting_wifi_p2p_get_type, + }, + [NM_META_SETTING_TYPE_WIMAX] = + { + .meta_type = NM_META_SETTING_TYPE_WIMAX, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_WIMAX_SETTING_NAME, + .get_setting_gtype = nm_setting_wimax_get_type, + }, + [NM_META_SETTING_TYPE_WIRED] = + { + .meta_type = NM_META_SETTING_TYPE_WIRED, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_WIRED_SETTING_NAME, + .get_setting_gtype = nm_setting_wired_get_type, + }, + [NM_META_SETTING_TYPE_WIREGUARD] = + { + .meta_type = NM_META_SETTING_TYPE_WIREGUARD, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_WIREGUARD_SETTING_NAME, + .get_setting_gtype = nm_setting_wireguard_get_type, + }, + [NM_META_SETTING_TYPE_WIRELESS] = + { + .meta_type = NM_META_SETTING_TYPE_WIRELESS, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_WIRELESS_SETTING_NAME, + .get_setting_gtype = nm_setting_wireless_get_type, + }, + [NM_META_SETTING_TYPE_WIRELESS_SECURITY] = + { + .meta_type = NM_META_SETTING_TYPE_WIRELESS_SECURITY, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, + .setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + .get_setting_gtype = nm_setting_wireless_security_get_type, + }, + [NM_META_SETTING_TYPE_WPAN] = + { + .meta_type = NM_META_SETTING_TYPE_WPAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_WPAN_SETTING_NAME, + .get_setting_gtype = nm_setting_wpan_get_type, + }, + + [NM_META_SETTING_TYPE_UNKNOWN] = + { + .meta_type = NM_META_SETTING_TYPE_UNKNOWN, + }, +}; + +const NMMetaSettingInfo * +nm_meta_setting_infos_by_name(const char *name) +{ + gssize idx; + + if (NM_MORE_ASSERTS > 10) { + guint i, j; + + for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { + const NMMetaSettingInfo *setting_info = &nm_meta_setting_infos[i]; + + nm_assert(setting_info->meta_type == (NMMetaSettingType) i); + nm_assert(setting_info->setting_name); + nm_assert(setting_info->setting_name[0]); + nm_assert(setting_info->get_setting_gtype); + nm_assert(setting_info->setting_priority != NM_SETTING_PRIORITY_INVALID); + if (i > 0 + && strcmp(nm_meta_setting_infos[i - 1].setting_name, setting_info->setting_name) + >= 0) { + g_error("nm_meta_setting_infos[%u, \"%s\"] is wrongly sorted before " + "nm_meta_setting_infos[%u, \"%s\"]. Rearange NMMetaSettingType enum", + i - 1, + nm_meta_setting_infos[i - 1].setting_name, + i, + setting_info->setting_name); + } + for (j = 0; j < i; j++) { + const NMMetaSettingInfo *s = &nm_meta_setting_infos[j]; + + nm_assert(setting_info->get_setting_gtype != s->get_setting_gtype); + } + } + } + + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMMetaSettingInfo, setting_name) == 0); + idx = nm_utils_array_find_binary_search(nm_meta_setting_infos, + sizeof(NMMetaSettingInfo), + _NM_META_SETTING_TYPE_NUM, + &name, + nm_strcmp_p_with_data, + NULL); + + return idx >= 0 ? &nm_meta_setting_infos[idx] : NULL; +} + +const NMMetaSettingInfo * +nm_meta_setting_infos_by_gtype(GType gtype) +{ +#if _NM_META_SETTING_BASE_IMPL_LIBNM + nm_auto_unref_gtypeclass GTypeClass *gtypeclass_unref = NULL; + GTypeClass * gtypeclass; + NMSettingClass * klass; + + if (!g_type_is_a(gtype, NM_TYPE_SETTING)) + goto out_none; + + gtypeclass = g_type_class_peek(gtype); + if (!gtypeclass) + gtypeclass = gtypeclass_unref = g_type_class_ref(gtype); + + nm_assert(NM_IS_SETTING_CLASS(gtypeclass)); + + klass = (NMSettingClass *) gtypeclass; + + if (!klass->setting_info) + goto out_none; + + nm_assert(klass->setting_info->get_setting_gtype); + nm_assert(klass->setting_info->get_setting_gtype() == gtype); + + return klass->setting_info; + +out_none: + + if (NM_MORE_ASSERTS > 10) { + int i; + + /* this might hint to a bug, but it would be expected for NM_TYPE_SETTING + * and NM_TYPE_SETTING_IP_CONFIG. + * + * Assert that we didn't lookup for a gtype, which we would expect to find. + * An assertion failure here, hints to a bug in nm_setting_*_class_init(). + */ + for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) + nm_assert(nm_meta_setting_infos[i].get_setting_gtype() != gtype); + } + + return NULL; +#else + guint i; + + for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { + if (nm_meta_setting_infos[i].get_setting_gtype() == gtype) + return &nm_meta_setting_infos[i]; + } + return NULL; +#endif +} + +/*****************************************************************************/ + +NMSettingPriority +nm_meta_setting_info_get_base_type_priority(const NMMetaSettingInfo *setting_info, GType gtype) +{ + /* Historical oddity: PPPoE is a base-type even though it's not + * priority 1. It needs to be sorted *after* lower-level stuff like + * Wi-Fi security or 802.1x for secrets, but it's still allowed as a + * base type. + */ + + if (setting_info) { + if (NM_IN_SET(setting_info->setting_priority, + NM_SETTING_PRIORITY_HW_BASE, + NM_SETTING_PRIORITY_HW_NON_BASE) + || gtype == NM_TYPE_SETTING_PPPOE) + return setting_info->setting_priority; + } + + return NM_SETTING_PRIORITY_INVALID; +} + +NMSettingPriority +_nm_setting_type_get_base_type_priority(GType type) +{ + return nm_meta_setting_info_get_base_type_priority(nm_meta_setting_infos_by_gtype(type), type); +} + +/*****************************************************************************/ diff --git a/src/libnm-core-impl/nm-property-compare.c b/src/libnm-core-impl/nm-property-compare.c new file mode 100644 index 0000000000..4347d6d678 --- /dev/null +++ b/src/libnm-core-impl/nm-property-compare.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-property-compare.h" + +#include + +static int +_nm_property_compare_collection(GVariant *value1, GVariant *value2) +{ + GVariant *child1, *child2; + int i, len1, len2; + int ret; + + len1 = g_variant_n_children(value1); + len2 = g_variant_n_children(value2); + + if (len1 != len2) + return len1 < len2 ? -1 : len1 > len2; + + for (i = 0; i < len1; i++) { + child1 = g_variant_get_child_value(value1, i); + child2 = g_variant_get_child_value(value2, i); + + ret = nm_property_compare(child1, child2); + g_variant_unref(child1); + g_variant_unref(child2); + + if (ret) + return ret; + } + + return 0; +} + +static int +_nm_property_compare_vardict(GVariant *value1, GVariant *value2) +{ + GVariantIter iter; + int len1, len2; + const char * key; + GVariant * val1, *val2; + + len1 = g_variant_n_children(value1); + len2 = g_variant_n_children(value2); + + if (len1 != len2) + return len1 < len2 ? -1 : 1; + + g_variant_iter_init(&iter, value1); + while (g_variant_iter_next(&iter, "{&sv}", &key, &val1)) { + if (!g_variant_lookup(value2, key, "v", &val2)) { + g_variant_unref(val1); + return -1; + } + if (!g_variant_equal(val1, val2)) { + g_variant_unref(val1); + g_variant_unref(val2); + return -1; + } + g_variant_unref(val1); + g_variant_unref(val2); + } + + return 0; +} + +static int +_nm_property_compare_strdict(GVariant *value1, GVariant *value2) +{ + GVariantIter iter; + int len1, len2; + const char * key, *val1, *val2; + int ret; + + len1 = g_variant_n_children(value1); + len2 = g_variant_n_children(value2); + + if (len1 != len2) + return len1 < len2 ? -1 : len1 > len2; + + g_variant_iter_init(&iter, value1); + while (g_variant_iter_next(&iter, "{&s&s}", &key, &val1)) { + if (!g_variant_lookup(value2, key, "&s", &val2)) + return -1; + + ret = strcmp(val1, val2); + if (ret) + return ret; + } + + return 0; +} + +int +nm_property_compare(GVariant *value1, GVariant *value2) +{ + const GVariantType *type1; + const GVariantType *type2; + int ret; + + if (value1 == value2) + return 0; + if (!value1) + return 1; + if (!value2) + return -1; + + type1 = g_variant_get_type(value1); + type2 = g_variant_get_type(value2); + + if (!g_variant_type_equal(type1, type2)) + return type1 < type2 ? -1 : type1 > type2; + + if (g_variant_type_is_basic(type1)) + ret = g_variant_compare(value1, value2); + else if (g_variant_is_of_type(value1, G_VARIANT_TYPE("a{ss}"))) + ret = _nm_property_compare_strdict(value1, value2); + else if (g_variant_is_of_type(value1, G_VARIANT_TYPE("a{sv}"))) + ret = _nm_property_compare_vardict(value1, value2); + else if (g_variant_type_is_array(type1)) + ret = _nm_property_compare_collection(value1, value2); + else if (g_variant_type_is_tuple(type1)) + ret = _nm_property_compare_collection(value1, value2); + else { + g_warning("Don't know how to compare variant type '%s'", (const char *) type1); + ret = value1 == value2; + } + + return ret; +} diff --git a/src/libnm-core-impl/nm-property-compare.h b/src/libnm-core-impl/nm-property-compare.h new file mode 100644 index 0000000000..d422b1c8a4 --- /dev/null +++ b/src/libnm-core-impl/nm-property-compare.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_PROPERTY_COMPARE_H__ +#define __NM_PROPERTY_COMPARE_H__ + +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) + #error Cannot use this header. +#endif + +int nm_property_compare(GVariant *value1, GVariant *value2); + +#endif /* __NM_PROPERTY_COMPARE_H__ */ diff --git a/src/libnm-core-impl/nm-setting-6lowpan.c b/src/libnm-core-impl/nm-setting-6lowpan.c new file mode 100644 index 0000000000..408b39b5dd --- /dev/null +++ b/src/libnm-core-impl/nm-setting-6lowpan.c @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-6lowpan.h" + +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-6lowpan + * @short_description: Describes connection properties for 6LoWPAN interfaces + * + * The #NMSetting6Lowpan object is a #NMSetting subclass that describes properties + * necessary for connection to 6LoWPAN interfaces. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, ); + +typedef struct { + char *parent; +} NMSetting6LowpanPrivate; + +/** + * NMSetting6Lowpan: + * + * 6LoWPAN Settings + */ +struct _NMSetting6Lowpan { + NMSetting parent; +}; + +struct _NMSetting6LowpanClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSetting6Lowpan, nm_setting_6lowpan, NM_TYPE_SETTING) + +#define NM_SETTING_6LOWPAN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_6lowpan_get_parent: + * @setting: the #NMSetting6Lowpan + * + * Returns: the #NMSetting6Lowpan:parent property of the setting + * + * Since: 1.14 + **/ +const char * +nm_setting_6lowpan_get_parent(NMSetting6Lowpan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_6LOWPAN(setting), NULL); + return NM_SETTING_6LOWPAN_GET_PRIVATE(setting)->parent; +} + +/*********************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE(setting); + NMSettingConnection * s_con = NULL; + + if (connection) + s_con = nm_connection_get_setting_connection(connection); + + if (!priv->parent) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is not specified")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_6LOWPAN_SETTING_NAME, + NM_SETTING_6LOWPAN_PARENT); + return FALSE; + } + + if (nm_utils_is_uuid(priv->parent)) { + /* If we have an NMSettingConnection:master with slave-type="6lowpan", + * then it must be the same UUID. + */ + if (s_con) { + const char *master = NULL, *slave_type = NULL; + + slave_type = nm_setting_connection_get_slave_type(s_con); + if (!g_strcmp0(slave_type, NM_SETTING_6LOWPAN_SETTING_NAME)) + master = nm_setting_connection_get_master(s_con); + + if (master && g_strcmp0(priv->parent, master) != 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' value doesn't match '%s=%s'"), + priv->parent, + NM_SETTING_CONNECTION_MASTER, + master); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_6LOWPAN_SETTING_NAME, + NM_SETTING_6LOWPAN_PARENT); + return FALSE; + } + } + } else if (!nm_utils_iface_valid_name(priv->parent)) { + /* parent must be either a UUID or an interface name */ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_6LOWPAN_SETTING_NAME, + NM_SETTING_6LOWPAN_PARENT); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSetting6Lowpan * setting = NM_SETTING_6LOWPAN(object); + NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string(value, priv->parent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSetting6Lowpan * setting = NM_SETTING_6LOWPAN(object); + NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_free(priv->parent); + priv->parent = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_6lowpan_init(NMSetting6Lowpan *setting) +{} + +/** + * nm_setting_6lowpan_new: + * + * Creates a new #NMSetting6Lowpan object with default values. + * + * Returns: (transfer full): the new empty #NMSetting6Lowpan object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_6lowpan_new(void) +{ + return g_object_new(NM_TYPE_SETTING_6LOWPAN, NULL); +} + +static void +finalize(GObject *object) +{ + NMSetting6Lowpan * setting = NM_SETTING_6LOWPAN(object); + NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE(setting); + + g_free(priv->parent); + + G_OBJECT_CLASS(nm_setting_6lowpan_parent_class)->finalize(object); +} + +static void +nm_setting_6lowpan_class_init(NMSetting6LowpanClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSetting6LowpanPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSetting6Lowpan:parent: + * + * If given, specifies the parent interface name or parent connection UUID + * from which this 6LowPAN interface should be created. + * + * Since: 1.14 + **/ + obj_properties[PROP_PARENT] = g_param_spec_string( + NM_SETTING_6LOWPAN_PARENT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_6LOWPAN); +} diff --git a/src/libnm-core-impl/nm-setting-8021x.c b/src/libnm-core-impl/nm-setting-8021x.c new file mode 100644 index 0000000000..96935b5f08 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-8021x.c @@ -0,0 +1,4683 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-8021x.h" + +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-utils.h" +#include "nm-crypto.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" +#include "nm-core-enum-types.h" + +/** + * SECTION:nm-setting-8021x + * @short_description: Describes 802.1x-authenticated connection properties + * + * The #NMSetting8021x object is a #NMSetting subclass that describes + * properties necessary for connection to 802.1x-authenticated networks, such as + * WPA and WPA2 Enterprise Wi-Fi networks and wired 802.1x networks. 802.1x + * connections typically use certificates and/or EAP authentication methods to + * securely verify, identify, and authenticate the client to the network itself, + * instead of simply relying on a widely shared static key. + * + * It's a good idea to read up on wpa_supplicant configuration before using this + * setting extensively, since most of the options here correspond closely with + * the relevant wpa_supplicant configuration options. + * + * Furthermore, to get a good idea of 802.1x, EAP, TLS, TTLS, etc and their + * applications to Wi-Fi and wired networks, you'll want to get copies of the + * following books. + * + * 802.11 Wireless Networks: The Definitive Guide, Second Edition + * Author: Matthew Gast + * ISBN: 978-0596100520 + * + * Cisco Wireless LAN Security + * Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky + * ISBN: 978-1587051548 + **/ + +/*****************************************************************************/ + +static NMSetting8021xCKFormat +_crypto_format_to_ck(NMCryptoFileFormat format) +{ + G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_UNKNOWN + == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_UNKNOWN)); + G_STATIC_ASSERT( + (NM_SETTING_802_1X_CK_FORMAT_X509 == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_X509)); + G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_RAW_KEY + == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_RAW_KEY)); + G_STATIC_ASSERT((NM_SETTING_802_1X_CK_FORMAT_PKCS12 + == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_PKCS12)); + + nm_assert(NM_IN_SET(format, + NM_CRYPTO_FILE_FORMAT_UNKNOWN, + NM_CRYPTO_FILE_FORMAT_X509, + NM_CRYPTO_FILE_FORMAT_RAW_KEY, + NM_CRYPTO_FILE_FORMAT_PKCS12)); + return (NMSetting8021xCKFormat) format; +} + +/*****************************************************************************/ + +typedef void (*EAPMethodNeedSecretsFunc)(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2); + +typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self, gboolean phase2, GError **error); + +typedef struct { + const char * method; + EAPMethodNeedSecretsFunc ns_func; + EAPMethodValidateFunc v_func; +} EAPMethodsTable; + +static const EAPMethodsTable eap_methods_table[]; + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSetting8021x, + PROP_EAP, + PROP_IDENTITY, + PROP_ANONYMOUS_IDENTITY, + PROP_PAC_FILE, + PROP_CA_CERT, + PROP_CA_CERT_PASSWORD, + PROP_CA_CERT_PASSWORD_FLAGS, + PROP_CA_PATH, + PROP_SUBJECT_MATCH, + PROP_ALTSUBJECT_MATCHES, + PROP_DOMAIN_SUFFIX_MATCH, + PROP_DOMAIN_MATCH, + PROP_CLIENT_CERT, + PROP_CLIENT_CERT_PASSWORD, + PROP_CLIENT_CERT_PASSWORD_FLAGS, + PROP_PHASE1_PEAPVER, + PROP_PHASE1_PEAPLABEL, + PROP_PHASE1_FAST_PROVISIONING, + PROP_PHASE1_AUTH_FLAGS, + PROP_PHASE2_AUTH, + PROP_PHASE2_AUTHEAP, + PROP_PHASE2_CA_CERT, + PROP_PHASE2_CA_CERT_PASSWORD, + PROP_PHASE2_CA_CERT_PASSWORD_FLAGS, + PROP_PHASE2_CA_PATH, + PROP_PHASE2_SUBJECT_MATCH, + PROP_PHASE2_ALTSUBJECT_MATCHES, + PROP_PHASE2_DOMAIN_SUFFIX_MATCH, + PROP_PHASE2_DOMAIN_MATCH, + PROP_PHASE2_CLIENT_CERT, + PROP_PHASE2_CLIENT_CERT_PASSWORD, + PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, + PROP_PASSWORD, + PROP_PASSWORD_FLAGS, + PROP_PASSWORD_RAW, + PROP_PASSWORD_RAW_FLAGS, + PROP_PRIVATE_KEY, + PROP_PRIVATE_KEY_PASSWORD, + PROP_PRIVATE_KEY_PASSWORD_FLAGS, + PROP_PHASE2_PRIVATE_KEY, + PROP_PHASE2_PRIVATE_KEY_PASSWORD, + PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, + PROP_PIN, + PROP_PIN_FLAGS, + PROP_SYSTEM_CA_CERTS, + PROP_OPTIONAL, + PROP_AUTH_TIMEOUT, ); + +typedef struct { + GSList * eap; /* GSList of strings */ + char * identity; + char * anonymous_identity; + char * pac_file; + GBytes * ca_cert; + char * ca_cert_password; + char * ca_path; + char * subject_match; + GSList * altsubject_matches; + char * domain_suffix_match; + char * domain_match; + GBytes * client_cert; + char * client_cert_password; + char * phase1_peapver; + char * phase1_peaplabel; + char * phase1_fast_provisioning; + char * phase2_auth; + char * phase2_autheap; + GBytes * phase2_ca_cert; + char * phase2_ca_cert_password; + char * phase2_ca_path; + char * phase2_subject_match; + GSList * phase2_altsubject_matches; + char * phase2_domain_suffix_match; + char * phase2_domain_match; + GBytes * phase2_client_cert; + char * phase2_client_cert_password; + char * password; + GBytes * password_raw; + char * pin; + GBytes * private_key; + char * private_key_password; + GBytes * phase2_private_key; + char * phase2_private_key_password; + int auth_timeout; + NMSetting8021xAuthFlags phase1_auth_flags; + NMSettingSecretFlags ca_cert_password_flags; + NMSettingSecretFlags client_cert_password_flags; + NMSettingSecretFlags phase2_ca_cert_password_flags; + NMSettingSecretFlags phase2_client_cert_password_flags; + NMSettingSecretFlags password_flags; + NMSettingSecretFlags password_raw_flags; + NMSettingSecretFlags pin_flags; + NMSettingSecretFlags private_key_password_flags; + NMSettingSecretFlags phase2_private_key_password_flags; + bool optional : 1; + bool system_ca_certs : 1; +} NMSetting8021xPrivate; + +G_DEFINE_TYPE(NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING) + +#define NM_SETTING_802_1X_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_802_1x_check_cert_scheme: + * @pdata: (allow-none): the data pointer + * @length: the length of the data + * @error: (allow-none) (out): validation reason + * + * Determines and verifies the blob type. + * When setting certificate properties of NMSetting8021x + * the blob must be not UNKNOWN (or NULL). + * + * Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN. + * For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN. + * + * Since: 1.2 + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_check_cert_scheme(gconstpointer pdata, gsize length, GError **error) +{ + const char * data = pdata; + NMSetting8021xCKScheme scheme; + gsize prefix_length; + + g_return_val_if_fail(!length || data, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + + if (!length || !data) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("binary data missing")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + + if (length >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + && !memcmp(data, + NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, + NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH))) { + scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; + prefix_length = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + } else if (length >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11) + && !memcmp(data, + NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11, + NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11))) { + scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11; + prefix_length = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11); + } else { + scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB; + prefix_length = 0; + } + + if (scheme != NM_SETTING_802_1X_CK_SCHEME_BLOB) { + /* An actual URI must be NUL terminated, contain at least + * one non-NUL character, and contain only one trailing NUL + * character. + * And ensure it's UTF-8 valid too so we can pass it through + * D-Bus and stuff like that. */ + + if (data[length - 1] != '\0') { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("URI not NUL terminated")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + length--; + + if (length <= prefix_length) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("URI is empty")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + + if (!g_utf8_validate(data + prefix_length, length - prefix_length, NULL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("URI is not valid UTF-8")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + } + + return scheme; +} + +NMSetting8021xCKScheme +_nm_setting_802_1x_cert_get_scheme(GBytes *bytes, GError **error) +{ + const char *data; + gsize length; + + if (!bytes) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("data missing")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + + data = g_bytes_get_data(bytes, &length); + return nm_setting_802_1x_check_cert_scheme(data, length, error); +} + +static gboolean +_cert_verify_scheme(NMSetting8021xCKScheme scheme, GBytes *bytes, GError **error) +{ + GError * local = NULL; + NMSetting8021xCKScheme scheme_detected; + + nm_assert(bytes); + + scheme_detected = _nm_setting_802_1x_cert_get_scheme(bytes, &local); + if (scheme_detected == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("certificate is invalid: %s"), + local->message); + return FALSE; + } + + if (scheme_detected != scheme) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("certificate detected as invalid scheme")); + return FALSE; + } + + return TRUE; +} + +GBytes * +_nm_setting_802_1x_cert_value_to_bytes(NMSetting8021xCKScheme scheme, + const guint8 * val_bin, + gssize val_len, + GError ** error) +{ + gs_unref_bytes GBytes *bytes = NULL; + guint8 * mem; + gsize total_len; + + nm_assert(val_bin); + + switch (scheme) { + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + if (val_len < 0) + val_len = strlen((char *) val_bin) + 1; + + bytes = g_bytes_new(val_bin, val_len); + break; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + if (val_len < 0) + val_len = strlen((char *) val_bin) + 1; + + total_len = NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + ((gsize) val_len); + + mem = g_new(guint8, total_len); + memcpy(mem, + NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, + NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); + memcpy(&mem[NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)], val_bin, val_len); + bytes = g_bytes_new_take(mem, total_len); + break; + default: + g_return_val_if_reached(NULL); + } + + if (!_cert_verify_scheme(scheme, bytes, error)) + return NULL; + + return g_steal_pointer(&bytes); +} + +static const char * +_cert_get_path(GBytes *bytes) +{ + const guint8 *bin; + + nm_assert(bytes); + nm_assert(g_bytes_get_size(bytes) >= NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); + + bin = g_bytes_get_data(bytes, NULL); + + nm_assert(bin); + nm_assert(bin[g_bytes_get_size(bytes) - 1] == '\0'); + nm_assert(g_str_has_prefix((const char *) bin, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); + + return (const char *) &bin[NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)]; +} + +#define _cert_assert_scheme(cert, check_scheme, ret_val) \ + G_STMT_START \ + { \ + NMSetting8021xCKScheme scheme; \ + \ + scheme = _nm_setting_802_1x_cert_get_scheme((cert), NULL); \ + if (scheme != check_scheme) { \ + g_return_val_if_fail(scheme == check_scheme, ret_val); \ + return ret_val; \ + } \ + } \ + G_STMT_END + +#define _cert_impl_get_scheme(setting, cert_field) \ + G_STMT_START \ + { \ + NMSetting8021x *const _setting = (setting); \ + GBytes * _cert; \ + \ + g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); \ + \ + _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field; \ + \ + return _nm_setting_802_1x_cert_get_scheme(_cert, NULL); \ + } \ + G_STMT_END + +#define _cert_impl_get_blob(setting, cert_field) \ + G_STMT_START \ + { \ + NMSetting8021x *const _setting = (setting); \ + GBytes * _cert; \ + \ + g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL); \ + \ + _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field; \ + \ + _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); \ + \ + return _cert; \ + } \ + G_STMT_END + +#define _cert_impl_get_path(setting, cert_field) \ + G_STMT_START \ + { \ + NMSetting8021x *const _setting = (setting); \ + GBytes * _cert; \ + \ + g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL); \ + \ + _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field; \ + \ + _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); \ + \ + return _cert_get_path(_cert); \ + } \ + G_STMT_END + +#define _cert_impl_get_uri(setting, cert_field) \ + G_STMT_START \ + { \ + NMSetting8021x *const _setting = (setting); \ + GBytes * _cert; \ + \ + g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NULL); \ + \ + _cert = NM_SETTING_802_1X_GET_PRIVATE(_setting)->cert_field; \ + \ + _cert_assert_scheme(_cert, NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); \ + \ + return g_bytes_get_data(_cert, NULL); \ + } \ + G_STMT_END + +static gboolean +_cert_impl_set(NMSetting8021x * setting, + _PropertyEnums property, + const char * value, + const char * password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error) +{ + NMSetting8021xPrivate *priv; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gs_unref_bytes GBytes *cert = NULL; + GBytes ** p_cert = NULL; + GBytes ** p_client_cert = NULL; + char ** p_password = NULL; + _PropertyEnums notify_cert = property; + _PropertyEnums notify_password = PROP_0; + _PropertyEnums notify_client_cert = PROP_0; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + if (value) { + g_return_val_if_fail(g_utf8_validate(value, -1, NULL), FALSE); + g_return_val_if_fail(NM_IN_SET(scheme, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + NM_SETTING_802_1X_CK_SCHEME_PATH, + NM_SETTING_802_1X_CK_SCHEME_PKCS11), + FALSE); + } + + if (!value) { + /* coerce password to %NULL. It should be already. */ + password = NULL; + } + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + + if (!value) { + /* pass. */ + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { + cert = _nm_setting_802_1x_cert_value_to_bytes(scheme, (guint8 *) value, -1, error); + if (!cert) + goto err; + } else { + gs_unref_bytes GBytes *file = NULL; + + if (NM_IN_SET(property, PROP_PRIVATE_KEY, PROP_PHASE2_PRIVATE_KEY)) { + file = nm_crypto_read_file(value, error); + if (!file) + goto err; + format = nm_crypto_verify_private_key_data(g_bytes_get_data(file, NULL), + g_bytes_get_size(file), + password, + NULL, + error); + if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) + goto err; + } else { + if (!nm_crypto_load_and_verify_certificate(value, &format, &file, error)) + goto err; + } + + nm_assert(format != NM_CRYPTO_FILE_FORMAT_UNKNOWN); + nm_assert(file); + + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + cert = g_steal_pointer(&file); + if (!_cert_verify_scheme(scheme, cert, error)) + goto err; + } else { + cert = _nm_setting_802_1x_cert_value_to_bytes(scheme, (guint8 *) value, -1, error); + if (!cert) + goto err; + } + } + + switch (property) { + case PROP_CA_CERT: + case PROP_PHASE2_CA_CERT: + if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && format != NM_CRYPTO_FILE_FORMAT_X509) { + /* wpa_supplicant can only use raw x509 CA certs */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("CA certificate must be in X.509 format")); + goto err; + } + p_cert = (property == PROP_CA_CERT) ? &priv->ca_cert : &priv->phase2_ca_cert; + break; + case PROP_CLIENT_CERT: + case PROP_PHASE2_CLIENT_CERT: + if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && !NM_IN_SET(format, NM_CRYPTO_FILE_FORMAT_X509, NM_CRYPTO_FILE_FORMAT_PKCS12)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid certificate format")); + goto err; + } + p_cert = (property == PROP_CLIENT_CERT) ? &priv->client_cert : &priv->phase2_client_cert; + break; + case PROP_PRIVATE_KEY: + p_cert = &priv->private_key; + p_password = &priv->private_key_password; + p_client_cert = &priv->client_cert; + notify_password = PROP_PRIVATE_KEY_PASSWORD; + notify_client_cert = PROP_CLIENT_CERT; + break; + case PROP_PHASE2_PRIVATE_KEY: + p_cert = &priv->phase2_private_key; + p_password = &priv->phase2_private_key_password; + p_client_cert = &priv->phase2_client_cert; + notify_password = PROP_PHASE2_PRIVATE_KEY_PASSWORD; + notify_client_cert = PROP_PHASE2_CLIENT_CERT; + break; + default: + nm_assert_not_reached(); + break; + } + + /* As required by NM and wpa_supplicant, set the client-cert + * property to the same PKCS#12 data. + */ + if (cert && p_client_cert && format == NM_CRYPTO_FILE_FORMAT_PKCS12 + && !nm_gbytes_equal0(cert, *p_client_cert)) { + g_bytes_unref(*p_client_cert); + *p_client_cert = g_bytes_ref(cert); + } else + notify_client_cert = PROP_0; + + if (p_cert && !nm_gbytes_equal0(cert, *p_cert)) { + g_bytes_unref(*p_cert); + *p_cert = g_steal_pointer(&cert); + } else + notify_cert = PROP_0; + + if (p_password && !nm_streq0(password, *p_password)) { + nm_free_secret(*p_password); + *p_password = g_strdup(password); + } else + notify_password = PROP_0; + + nm_gobject_notify_together(setting, notify_cert, notify_password, notify_client_cert); + + NM_SET_OUT(out_format, _crypto_format_to_ck(format)); + return TRUE; + +err: + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + obj_properties[property]->name); + NM_SET_OUT(out_format, NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + return FALSE; +} + +static NMSetting8021xCKFormat +_cert_impl_get_key_format_from_bytes(GBytes *private_key) +{ + const char *path; + GError * error = NULL; + + if (!private_key) + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + switch (_nm_setting_802_1x_cert_get_scheme(private_key, NULL)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if (nm_crypto_is_pkcs12_data(g_bytes_get_data(private_key, NULL), + g_bytes_get_size(private_key), + NULL)) + return NM_SETTING_802_1X_CK_FORMAT_PKCS12; + return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + path = _cert_get_path(private_key); + if (nm_crypto_is_pkcs12_file(path, &error)) + return NM_SETTING_802_1X_CK_FORMAT_PKCS12; + if (error && error->domain == G_FILE_ERROR) { + g_error_free(error); + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + } + g_error_free(error); + return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; + default: + break; + } + + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; +} +#define _cert_impl_get_key_format(setting, private_key_field) \ + ({ \ + NMSetting8021x * _setting = (setting); \ + NMSetting8021xPrivate *_priv; \ + \ + g_return_val_if_fail(NM_IS_SETTING_802_1X(_setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); \ + \ + _priv = NM_SETTING_802_1X_GET_PRIVATE(_setting); \ + _cert_impl_get_key_format_from_bytes(_priv->private_key_field); \ + }) + +static gboolean +_cert_verify_property(GBytes * bytes, + const char *prop_name, + const char *password, + const char *password_prop_name, + GError ** error) +{ + GError * local = NULL; + NMSetting8021xCKScheme scheme; + + if (!bytes) + return TRUE; + + scheme = _nm_setting_802_1x_cert_get_scheme(bytes, &local); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("certificate is invalid: %s"), + local->message); + g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name); + g_error_free(local); + return FALSE; + } + + if (password && (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("password is not supported when certificate is not on a PKCS#11 token")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, password_prop_name); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +/** + * nm_setting_802_1x_get_num_eap_methods: + * @setting: the #NMSetting8021x + * + * Returns the number of eap methods allowed for use when connecting to the + * network. Generally only one EAP method is used. Use the functions + * nm_setting_802_1x_get_eap_method(), nm_setting_802_1x_add_eap_method(), + * and nm_setting_802_1x_remove_eap_method() for adding, removing, and retrieving + * allowed EAP methods. + * + * Returns: the number of allowed EAP methods + **/ +guint32 +nm_setting_802_1x_get_num_eap_methods(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); + + return g_slist_length(NM_SETTING_802_1X_GET_PRIVATE(setting)->eap); +} + +/** + * nm_setting_802_1x_get_eap_method: + * @setting: the #NMSetting8021x + * @i: the index of the EAP method name to return + * + * Returns the name of the allowed EAP method at index @i. + * + * Returns: the name of the allowed EAP method at index @i + **/ +const char * +nm_setting_802_1x_get_eap_method(NMSetting8021x *setting, guint32 i) +{ + NMSetting8021xPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + g_return_val_if_fail(i <= g_slist_length(priv->eap), NULL); + + return (const char *) g_slist_nth_data(priv->eap, i); +} + +/** + * nm_setting_802_1x_add_eap_method: + * @setting: the #NMSetting8021x + * @eap: the name of the EAP method to allow for this connection + * + * Adds an allowed EAP method. The setting is not valid until at least one + * EAP method has been added. See #NMSetting8021x:eap property for a list of + * allowed EAP methods. + * + * Returns: %TRUE if the EAP method was successfully added, %FALSE if it was + * not a valid method or if it was already allowed. + **/ +gboolean +nm_setting_802_1x_add_eap_method(NMSetting8021x *setting, const char *eap) +{ + NMSetting8021xPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + g_return_val_if_fail(eap != NULL, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + for (iter = priv->eap; iter; iter = g_slist_next(iter)) { + if (!strcmp(eap, (char *) iter->data)) + return FALSE; + } + + priv->eap = g_slist_append(priv->eap, g_ascii_strdown(eap, -1)); + _notify(setting, PROP_EAP); + return TRUE; +} + +/** + * nm_setting_802_1x_remove_eap_method: + * @setting: the #NMSetting8021x + * @i: the index of the EAP method to remove + * + * Removes the allowed EAP method at the specified index. + **/ +void +nm_setting_802_1x_remove_eap_method(NMSetting8021x *setting, guint32 i) +{ + NMSetting8021xPrivate *priv; + GSList * elt; + + g_return_if_fail(NM_IS_SETTING_802_1X(setting)); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + elt = g_slist_nth(priv->eap, i); + g_return_if_fail(elt != NULL); + + g_free(elt->data); + priv->eap = g_slist_delete_link(priv->eap, elt); + _notify(setting, PROP_EAP); +} + +/** + * nm_setting_802_1x_remove_eap_method_by_value: + * @setting: the #NMSetting8021x + * @eap: the name of the EAP method to remove + * + * Removes the allowed EAP method @method. + * + * Returns: %TRUE if the EAP method was founs and removed, %FALSE if it was not. + **/ +gboolean +nm_setting_802_1x_remove_eap_method_by_value(NMSetting8021x *setting, const char *eap) +{ + NMSetting8021xPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + g_return_val_if_fail(eap != NULL, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + for (iter = priv->eap; iter; iter = g_slist_next(iter)) { + if (!strcmp(eap, (char *) iter->data)) { + priv->eap = g_slist_delete_link(priv->eap, iter); + _notify(setting, PROP_EAP); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_802_1x_clear_eap_methods: + * @setting: the #NMSetting8021x + * + * Clears all allowed EAP methods. + **/ +void +nm_setting_802_1x_clear_eap_methods(NMSetting8021x *setting) +{ + NMSetting8021xPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_802_1X(setting)); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + g_slist_free_full(priv->eap, g_free); + priv->eap = NULL; + _notify(setting, PROP_EAP); +} + +/** + * nm_setting_802_1x_get_identity: + * @setting: the #NMSetting8021x + * + * Returns the identifier used by some EAP methods (like TLS) to + * authenticate the user. Often this is a username or login name. + * + * Returns: the user identifier + **/ +const char * +nm_setting_802_1x_get_identity(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->identity; +} + +/** + * nm_setting_802_1x_get_anonymous_identity: + * @setting: the #NMSetting8021x + * + * Returns the anonymous identifier used by some EAP methods (like TTLS) to + * authenticate the user in the outer unencrypted "phase 1" authentication. The + * inner "phase 2" authentication will use the #NMSetting8021x:identity in + * a secure form, if applicable for that EAP method. + * + * Returns: the anonymous identifier + **/ +const char * +nm_setting_802_1x_get_anonymous_identity(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->anonymous_identity; +} + +/** + * nm_setting_802_1x_get_pac_file: + * @setting: the #NMSetting8021x + * + * Returns the file containing PAC credentials used by EAP-FAST method. + * + * Returns: the PAC file + **/ +const char * +nm_setting_802_1x_get_pac_file(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->pac_file; +} + +/** + * nm_setting_802_1x_get_ca_path: + * @setting: the #NMSetting8021x + * + * Returns the path of the CA certificate directory if previously set. Systems + * will often have a directory that contains multiple individual CA certificates + * which the supplicant can then add to the verification chain. This may be + * used in addition to the #NMSetting8021x:ca-cert property to add more CA + * certificates for verifying the network to client. + * + * Returns: the CA certificate directory path + **/ +const char * +nm_setting_802_1x_get_ca_path(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_path; +} + +/** + * nm_setting_802_1x_get_system_ca_certs: + * @setting: the #NMSetting8021x + * + * Sets the #NMSetting8021x:system-ca-certs property. The + * #NMSetting8021x:ca-path and #NMSetting8021x:phase2-ca-path + * properties are ignored if the #NMSetting8021x:system-ca-certs property is + * %TRUE, in which case a system-wide CA certificate directory specified at + * compile time (using the --system-ca-path configure option) is used in place + * of these properties. + * + * Returns: %TRUE if a system CA certificate path should be used, %FALSE if not + **/ +gboolean +nm_setting_802_1x_get_system_ca_certs(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->system_ca_certs; +} + +/** + * nm_setting_802_1x_get_ca_cert_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the CA certificate. If the returned scheme + * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_ca_cert_blob(); + * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_ca_cert_path(); + * if %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use nm_setting_802_1x_get_ca_cert_uri(). + * + * Returns: scheme used to store the CA certificate (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_ca_cert_scheme(NMSetting8021x *setting) +{ + _cert_impl_get_scheme(setting, ca_cert); +} + +/** + * nm_setting_802_1x_get_ca_cert_blob: + * @setting: the #NMSetting8021x + * + * Returns the CA certificate blob if the CA certificate is stored using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use a + * CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Returns: (transfer none): the CA certificate data + **/ +GBytes * +nm_setting_802_1x_get_ca_cert_blob(NMSetting8021x *setting) +{ + _cert_impl_get_blob(setting, ca_cert); +} + +/** + * nm_setting_802_1x_get_ca_cert_path: + * @setting: the #NMSetting8021x + * + * Returns the CA certificate path if the CA certificate is stored using the + * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use a + * CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Returns: path to the CA certificate file + **/ +const char * +nm_setting_802_1x_get_ca_cert_path(NMSetting8021x *setting) +{ + _cert_impl_get_path(setting, ca_cert); +} + +/** + * nm_setting_802_1x_get_ca_cert_uri: + * @setting: the #NMSetting8021x + * + * Returns the CA certificate URI analogously to + * nm_setting_802_1x_get_ca_cert_blob() and + * nm_setting_802_1x_get_ca_cert_path(). + * + * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * 7512), but may be extended to other schemes in future (such as 'file' URIs + * for local files and 'data' URIs for inline certificate data). + * + * Returns: the URI string + * + * Since: 1.6 + **/ +const char * +nm_setting_802_1x_get_ca_cert_uri(NMSetting8021x *setting) +{ + _cert_impl_get_uri(setting, ca_cert); +} + +/** + * nm_setting_802_1x_set_ca_cert: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH + * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the CA certificate + * file (PEM or DER format). The path must be UTF-8 encoded; use + * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme + * clears the CA certificate. + * @scheme: desired storage scheme for the certificate + * @out_format: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:ca-cert property + * with the raw certificate data if using the %NM_SETTING_802_1X_CK_SCHEME_BLOB + * scheme, or with the path to the certificate file if using the + * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_ca_cert(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error) +{ + return _cert_impl_set(setting, PROP_CA_CERT, value, NULL, scheme, out_format, error); +} + +/** + * nm_setting_802_1x_get_ca_cert_password: + * @setting: the #NMSetting8021x + * + * Returns: the password used to access the CA certificate stored in + * #NMSetting8021x:ca-cert property. Only makes sense if the certificate + * is stored on a PKCS#11 token that requires a login. + * + * Since: 1.8 + **/ +const char * +nm_setting_802_1x_get_ca_cert_password(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_cert_password; +} + +/** + * nm_setting_802_1x_get_ca_cert_password_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSetting8021x:ca-cert-password + * + * Since: 1.8 + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_ca_cert_password_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->ca_cert_password_flags; +} + +/** + * nm_setting_802_1x_get_subject_match: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSetting8021x:subject-match property. This is the + * substring to be matched against the subject of the authentication + * server certificate, or %NULL no subject verification is to be + * performed. + **/ +const char * +nm_setting_802_1x_get_subject_match(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->subject_match; +} + +/** + * nm_setting_802_1x_get_num_altsubject_matches: + * @setting: the #NMSetting8021x + * + * Returns the number of entries in the + * #NMSetting8021x:altsubject-matches property of this setting. + * + * Returns: the number of altsubject-matches entries. + **/ +guint32 +nm_setting_802_1x_get_num_altsubject_matches(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); + + return g_slist_length(NM_SETTING_802_1X_GET_PRIVATE(setting)->altsubject_matches); +} + +/** + * nm_setting_802_1x_get_altsubject_match: + * @setting: the #NMSettingConnection + * @i: the zero-based index of the array of altSubjectName matches + * + * Returns the altSubjectName match at index @i. + * + * Returns: the altSubjectName match at index @i + **/ +const char * +nm_setting_802_1x_get_altsubject_match(NMSetting8021x *setting, guint32 i) +{ + NMSetting8021xPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + g_return_val_if_fail(i <= g_slist_length(priv->altsubject_matches), NULL); + + return (const char *) g_slist_nth_data(priv->altsubject_matches, i); +} + +/** + * nm_setting_802_1x_add_altsubject_match: + * @setting: the #NMSetting8021x + * @altsubject_match: the altSubjectName to allow for this connection + * + * Adds an allowed alternate subject name match. Until at least one + * match is added, the altSubjectName of the remote authentication + * server is not verified. + * + * Returns: %TRUE if the alternative subject name match was + * successfully added, %FALSE if it was already allowed. + **/ +gboolean +nm_setting_802_1x_add_altsubject_match(NMSetting8021x *setting, const char *altsubject_match) +{ + NMSetting8021xPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + g_return_val_if_fail(altsubject_match != NULL, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + for (iter = priv->altsubject_matches; iter; iter = g_slist_next(iter)) { + if (!strcmp(altsubject_match, (char *) iter->data)) + return FALSE; + } + + priv->altsubject_matches = g_slist_append(priv->altsubject_matches, g_strdup(altsubject_match)); + _notify(setting, PROP_ALTSUBJECT_MATCHES); + return TRUE; +} + +/** + * nm_setting_802_1x_remove_altsubject_match: + * @setting: the #NMSetting8021x + * @i: the index of the altSubjectName match to remove + * + * Removes the allowed altSubjectName at the specified index. + **/ +void +nm_setting_802_1x_remove_altsubject_match(NMSetting8021x *setting, guint32 i) +{ + NMSetting8021xPrivate *priv; + GSList * elt; + + g_return_if_fail(NM_IS_SETTING_802_1X(setting)); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + elt = g_slist_nth(priv->altsubject_matches, i); + g_return_if_fail(elt != NULL); + + g_free(elt->data); + priv->altsubject_matches = g_slist_delete_link(priv->altsubject_matches, elt); + _notify(setting, PROP_ALTSUBJECT_MATCHES); +} + +/** + * nm_setting_802_1x_remove_altsubject_match_by_value: + * @setting: the #NMSetting8021x + * @altsubject_match: the altSubjectName to remove + * + * Removes the allowed altSubjectName @altsubject_match. + * + * Returns: %TRUE if the alternative subject name match was found and removed, + * %FALSE if it was not. + **/ +gboolean +nm_setting_802_1x_remove_altsubject_match_by_value(NMSetting8021x *setting, + const char * altsubject_match) +{ + NMSetting8021xPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + g_return_val_if_fail(altsubject_match != NULL, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + for (iter = priv->altsubject_matches; iter; iter = g_slist_next(iter)) { + if (!strcmp(altsubject_match, (char *) iter->data)) { + priv->altsubject_matches = g_slist_delete_link(priv->altsubject_matches, iter); + _notify(setting, PROP_ALTSUBJECT_MATCHES); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_802_1x_clear_altsubject_matches: + * @setting: the #NMSetting8021x + * + * Clears all altSubjectName matches. + **/ +void +nm_setting_802_1x_clear_altsubject_matches(NMSetting8021x *setting) +{ + NMSetting8021xPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_802_1X(setting)); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + g_slist_free_full(priv->altsubject_matches, g_free); + priv->altsubject_matches = NULL; + _notify(setting, PROP_ALTSUBJECT_MATCHES); +} + +/** + * nm_setting_802_1x_get_domain_suffix_match: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSetting8021x:domain-suffix-match property. + * + * Since: 1.2 + **/ +const char * +nm_setting_802_1x_get_domain_suffix_match(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->domain_suffix_match; +} + +/** + * nm_setting_802_1x_get_domain_match: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSetting8021x:domain-match property. + * + * Since: 1.24 + **/ +const char * +nm_setting_802_1x_get_domain_match(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->domain_match; +} + +/** + * nm_setting_802_1x_get_client_cert_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the client certificate. If the returned scheme + * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_client_cert_blob(); + * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_client_cert_path(); + * if %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use nm_setting_802_1x_get_client_cert_uri(). + * + * Returns: scheme used to store the client certificate (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_client_cert_scheme(NMSetting8021x *setting) +{ + _cert_impl_get_scheme(setting, client_cert); +} + +/** + * nm_setting_802_1x_get_client_cert_blob: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: (transfer none): the client certificate data + **/ +GBytes * +nm_setting_802_1x_get_client_cert_blob(NMSetting8021x *setting) +{ + _cert_impl_get_blob(setting, client_cert); +} + +/** + * nm_setting_802_1x_get_client_cert_path: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: path to the client certificate file + **/ +const char * +nm_setting_802_1x_get_client_cert_path(NMSetting8021x *setting) +{ + _cert_impl_get_path(setting, client_cert); +} + +/** + * nm_setting_802_1x_get_client_cert_uri: + * @setting: the #NMSetting8021x + * + * Returns the client certificate URI analogously to + * nm_setting_802_1x_get_client_cert_blob() and + * nm_setting_802_1x_get_client_cert_path(). + * + * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * 7512), but may be extended to other schemes in future (such as 'file' URIs + * for local files and 'data' URIs for inline certificate data). + * + * Returns: the URI string + * + * Since: 1.6 + **/ +const char * +nm_setting_802_1x_get_client_cert_uri(NMSetting8021x *setting) +{ + _cert_impl_get_uri(setting, client_cert); +} + +/** + * nm_setting_802_1x_set_client_cert: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH + * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the client + * certificate file (PEM, DER, or PKCS#12 format). The path must be UTF-8 + * encoded; use g_filename_to_utf8() to convert if needed. Passing %NULL with + * any @scheme clears the client certificate. + * @scheme: desired storage scheme for the certificate + * @out_format: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:client-cert + * property with the raw certificate data if using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate + * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_client_cert(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error) +{ + return _cert_impl_set(setting, PROP_CLIENT_CERT, value, NULL, scheme, out_format, error); +} + +/** + * nm_setting_802_1x_get_client_cert_password: + * @setting: the #NMSetting8021x + * + * Returns: the password used to access the client certificate stored in + * #NMSetting8021x:client-cert property. Only makes sense if the certificate + * is stored on a PKCS#11 token that requires a login. + * + * Since: 1.8 + **/ +const char * +nm_setting_802_1x_get_client_cert_password(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->client_cert_password; +} + +/** + * nm_setting_802_1x_get_client_cert_password_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSetting8021x:client-cert-password + * + * Since: 1.8 + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_client_cert_password_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->client_cert_password_flags; +} + +/** + * nm_setting_802_1x_get_phase1_peapver: + * @setting: the #NMSetting8021x + * + * Returns: the "phase 1" PEAP version to be used when authenticating with + * EAP-PEAP as contained in the #NMSetting8021x:phase1-peapver property. Valid + * values are %NULL (unset), "0" (PEAP version 0), and "1" (PEAP version 1). + **/ +const char * +nm_setting_802_1x_get_phase1_peapver(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_peapver; +} + +/** + * nm_setting_802_1x_get_phase1_peaplabel: + * @setting: the #NMSetting8021x + * + * Returns: whether the "phase 1" PEAP label is new-style or old-style, to be + * used when authenticating with EAP-PEAP, as contained in the + * #NMSetting8021x:phase1-peaplabel property. Valid values are %NULL (unset), + * "0" (use old-style label), and "1" (use new-style label). See the + * wpa_supplicant documentation for more details. + **/ +const char * +nm_setting_802_1x_get_phase1_peaplabel(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_peaplabel; +} + +/** + * nm_setting_802_1x_get_phase1_fast_provisioning: + * @setting: the #NMSetting8021x + * + * Returns: whether "phase 1" PEAP fast provisioning should be used, as specified + * by the #NMSetting8021x:phase1-fast-provisioning property. See the + * wpa_supplicant documentation for more details. + **/ +const char * +nm_setting_802_1x_get_phase1_fast_provisioning(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_fast_provisioning; +} + +/** + * nm_setting_802_1x_get_phase1_auth_flags: + * @setting: the #NMSetting8021x + * + * Returns: the authentication flags for "phase 1". + * + * Since: 1.8 + */ +NMSetting8021xAuthFlags +nm_setting_802_1x_get_phase1_auth_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase1_auth_flags; +} + +/** + * nm_setting_802_1x_get_phase2_auth: + * @setting: the #NMSetting8021x + * + * Returns: the "phase 2" non-EAP (ex MD5) allowed authentication method as + * specified by the #NMSetting8021x:phase2-auth property. + **/ +const char * +nm_setting_802_1x_get_phase2_auth(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_auth; +} + +/** + * nm_setting_802_1x_get_phase2_autheap: + * @setting: the #NMSetting8021x + * + * Returns: the "phase 2" EAP-based (ex TLS) allowed authentication method as + * specified by the #NMSetting8021x:phase2-autheap property. + **/ +const char * +nm_setting_802_1x_get_phase2_autheap(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_autheap; +} + +/** + * nm_setting_802_1x_get_phase2_ca_path: + * @setting: the #NMSetting8021x + * + * Returns the path of the "phase 2" CA certificate directory if previously set. + * Systems will often have a directory that contains multiple individual CA + * certificates which the supplicant can then add to the verification chain. + * This may be used in addition to the #NMSetting8021x:phase2-ca-cert property + * to add more CA certificates for verifying the network to client. + * + * Returns: the "phase 2" CA certificate directory path + **/ +const char * +nm_setting_802_1x_get_phase2_ca_path(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_path; +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the "phase 2" CA certificate. If the + * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use + * nm_setting_802_1x_get_ca_cert_blob(); if %NM_SETTING_802_1X_CK_SCHEME_PATH, + * use nm_setting_802_1x_get_ca_cert_path(); if %NM_SETTING_802_1X_CK_SCHEME_PKCS11, + * use nm_setting_802_1x_get_ca_cert_uri(). + * + * Returns: scheme used to store the "phase 2" CA certificate (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_phase2_ca_cert_scheme(NMSetting8021x *setting) +{ + _cert_impl_get_scheme(setting, phase2_ca_cert); +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_blob: + * @setting: the #NMSetting8021x + * + * Returns the "phase 2" CA certificate blob if the CA certificate is stored + * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use + * a CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Returns: (transfer none): the "phase 2" CA certificate data + **/ +GBytes * +nm_setting_802_1x_get_phase2_ca_cert_blob(NMSetting8021x *setting) +{ + _cert_impl_get_blob(setting, phase2_ca_cert); +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_path: + * @setting: the #NMSetting8021x + * + * Returns the "phase 2" CA certificate path if the CA certificate is stored + * using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use + * a CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Returns: path to the "phase 2" CA certificate file + **/ +const char * +nm_setting_802_1x_get_phase2_ca_cert_path(NMSetting8021x *setting) +{ + _cert_impl_get_path(setting, phase2_ca_cert); +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_uri: + * @setting: the #NMSetting8021x + * + * Returns the "phase 2" CA certificate URI analogously to + * nm_setting_802_1x_get_phase2_ca_cert_blob() and + * nm_setting_802_1x_get_phase2_ca_cert_path(). + * + * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * 7512), but may be extended to other schemes in future (such as 'file' URIs + * for local files and 'data' URIs for inline certificate data). + * + * Returns: the URI string + * + * Since: 1.6 + **/ +const char * +nm_setting_802_1x_get_phase2_ca_cert_uri(NMSetting8021x *setting) +{ + _cert_impl_get_uri(setting, phase2_ca_cert); +} + +/** + * nm_setting_802_1x_set_phase2_ca_cert: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH + * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" CA + * certificate file (PEM or DER format). The path must be UTF-8 encoded; use + * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme + * clears the "phase2" CA certificate. + * @scheme: desired storage scheme for the certificate + * @out_format: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:phase2-ca-cert + * property with the raw certificate data if using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate + * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_ca_cert(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error) +{ + return _cert_impl_set(setting, PROP_PHASE2_CA_CERT, value, NULL, scheme, out_format, error); +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_password: + * @setting: the #NMSetting8021x + * + * Returns: the password used to access the "phase2" CA certificate stored in + * #NMSetting8021x:phase2-ca-cert property. Only makes sense if the certificate + * is stored on a PKCS#11 token that requires a login. + * + * Since: 1.8 + **/ +const char * +nm_setting_802_1x_get_phase2_ca_cert_password(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_cert_password; +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_password_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSetting8021x:phase2-private-key-password + * + * Since: 1.8 + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_phase2_ca_cert_password_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_ca_cert_password_flags; +} + +/** + * nm_setting_802_1x_get_phase2_subject_match: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSetting8021x:phase2-subject-match property. This is + * the substring to be matched against the subject of the "phase 2" + * authentication server certificate, or %NULL no subject verification + * is to be performed. + **/ +const char * +nm_setting_802_1x_get_phase2_subject_match(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_subject_match; +} + +/** + * nm_setting_802_1x_get_num_phase2_altsubject_matches: + * @setting: the #NMSetting8021x + * + * Returns the number of entries in the + * #NMSetting8021x:phase2-altsubject-matches property of this setting. + * + * Returns: the number of phase2-altsubject-matches entries. + **/ +guint32 +nm_setting_802_1x_get_num_phase2_altsubject_matches(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); + + return g_slist_length(NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_altsubject_matches); +} + +/** + * nm_setting_802_1x_get_phase2_domain_suffix_match: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSetting8021x:phase2-domain-suffix-match property. + * + * Since: 1.2 + **/ +const char * +nm_setting_802_1x_get_phase2_domain_suffix_match(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_domain_suffix_match; +} + +/** + * nm_setting_802_1x_get_phase2_domain_match: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSetting8021x:phase2-domain-match property. + * + * Since: 1.24 + **/ +const char * +nm_setting_802_1x_get_phase2_domain_match(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_domain_match; +} + +/** + * nm_setting_802_1x_get_phase2_altsubject_match: + * @setting: the #NMSettingConnection + * @i: the zero-based index of the array of "phase 2" altSubjectName matches + * + * Returns the "phase 2" altSubjectName match at index @i. + * + * Returns: the "phase 2" altSubjectName match at index @i + **/ +const char * +nm_setting_802_1x_get_phase2_altsubject_match(NMSetting8021x *setting, guint32 i) +{ + NMSetting8021xPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + g_return_val_if_fail(i <= g_slist_length(priv->phase2_altsubject_matches), NULL); + + return (const char *) g_slist_nth_data(priv->phase2_altsubject_matches, i); +} + +/** + * nm_setting_802_1x_add_phase2_altsubject_match: + * @setting: the #NMSetting8021x + * @phase2_altsubject_match: the "phase 2" altSubjectName to allow for this + * connection + * + * Adds an allowed alternate subject name match for "phase 2". Until + * at least one match is added, the altSubjectName of the "phase 2" + * remote authentication server is not verified. + * + * Returns: %TRUE if the "phase 2" alternative subject name match was + * successfully added, %FALSE if it was already allowed. + **/ +gboolean +nm_setting_802_1x_add_phase2_altsubject_match(NMSetting8021x *setting, + const char * phase2_altsubject_match) +{ + NMSetting8021xPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + g_return_val_if_fail(phase2_altsubject_match != NULL, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + for (iter = priv->phase2_altsubject_matches; iter; iter = g_slist_next(iter)) { + if (!strcmp(phase2_altsubject_match, (char *) iter->data)) + return FALSE; + } + + priv->phase2_altsubject_matches = + g_slist_append(priv->phase2_altsubject_matches, g_strdup(phase2_altsubject_match)); + _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES); + return TRUE; +} + +/** + * nm_setting_802_1x_remove_phase2_altsubject_match: + * @setting: the #NMSetting8021x + * @i: the index of the "phase 2" altSubjectName match to remove + * + * Removes the allowed "phase 2" altSubjectName at the specified index. + **/ +void +nm_setting_802_1x_remove_phase2_altsubject_match(NMSetting8021x *setting, guint32 i) +{ + NMSetting8021xPrivate *priv; + GSList * elt; + + g_return_if_fail(NM_IS_SETTING_802_1X(setting)); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + elt = g_slist_nth(priv->phase2_altsubject_matches, i); + g_return_if_fail(elt != NULL); + + g_free(elt->data); + priv->phase2_altsubject_matches = g_slist_delete_link(priv->phase2_altsubject_matches, elt); + _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES); +} + +/** + * nm_setting_802_1x_remove_phase2_altsubject_match_by_value: + * @setting: the #NMSetting8021x + * @phase2_altsubject_match: the "phase 2" altSubjectName to remove + * + * Removes the allowed "phase 2" altSubjectName @phase2_altsubject_match. + * + * Returns: %TRUE if the alternative subject name match for "phase 2" was found and removed, + * %FALSE if it was not. + **/ +gboolean +nm_setting_802_1x_remove_phase2_altsubject_match_by_value(NMSetting8021x *setting, + const char * phase2_altsubject_match) +{ + NMSetting8021xPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + g_return_val_if_fail(phase2_altsubject_match != NULL, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + for (iter = priv->phase2_altsubject_matches; iter; iter = g_slist_next(iter)) { + if (!strcmp(phase2_altsubject_match, (char *) iter->data)) { + priv->phase2_altsubject_matches = + g_slist_delete_link(priv->phase2_altsubject_matches, iter); + _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_802_1x_clear_phase2_altsubject_matches: + * @setting: the #NMSetting8021x + * + * Clears all "phase 2" altSubjectName matches. + **/ +void +nm_setting_802_1x_clear_phase2_altsubject_matches(NMSetting8021x *setting) +{ + NMSetting8021xPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_802_1X(setting)); + + priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + g_slist_free_full(priv->phase2_altsubject_matches, g_free); + priv->phase2_altsubject_matches = NULL; + _notify(setting, PROP_PHASE2_ALTSUBJECT_MATCHES); +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the "phase 2" client certificate. If the + * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use + * nm_setting_802_1x_get_client_cert_blob(); if + * %NM_SETTING_802_1X_CK_SCHEME_PATH, use + * nm_setting_802_1x_get_client_cert_path(); if + * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use + * nm_setting_802_1x_get_client_cert_uri(). + * + * Returns: scheme used to store the "phase 2" client certificate (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_phase2_client_cert_scheme(NMSetting8021x *setting) +{ + _cert_impl_get_scheme(setting, phase2_client_cert); +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_blob: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: (transfer none): the "phase 2" client certificate data + **/ +GBytes * +nm_setting_802_1x_get_phase2_client_cert_blob(NMSetting8021x *setting) +{ + _cert_impl_get_blob(setting, phase2_client_cert); +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_path: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: path to the "phase 2" client certificate file + **/ +const char * +nm_setting_802_1x_get_phase2_client_cert_path(NMSetting8021x *setting) +{ + _cert_impl_get_path(setting, phase2_client_cert); +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_uri: + * @setting: the #NMSetting8021x + * + * Returns the "phase 2" client certificate URI analogously to + * nm_setting_802_1x_get_phase2_ca_cert_blob() and + * nm_setting_802_1x_get_phase2_ca_cert_path(). + * + * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * 7512), but may be extended to other schemes in future (such as 'file' URIs + * for local files and 'data' URIs for inline certificate data). + * + * Returns: the URI string + * + * Since: 1.6 + **/ +const char * +nm_setting_802_1x_get_phase2_client_cert_uri(NMSetting8021x *setting) +{ + _cert_impl_get_uri(setting, phase2_client_cert); +} + +/** + * nm_setting_802_1x_set_phase2_client_cert: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH + * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" client + * certificate file (PEM, DER, or PKCS#12 format). The path must be UTF-8 + * encoded; use g_filename_to_utf8() to convert if needed. Passing %NULL with + * any @scheme clears the "phase2" client certificate. + * @scheme: desired storage scheme for the certificate + * @out_format: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:phase2-client-cert + * property with the raw certificate data if using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate + * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_client_cert(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error) +{ + return _cert_impl_set(setting, PROP_PHASE2_CLIENT_CERT, value, NULL, scheme, out_format, error); +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_password: + * @setting: the #NMSetting8021x + * + * Returns: the password used to access the "phase2" client certificate stored in + * #NMSetting8021x:phase2-client-cert property. Only makes sense if the certificate + * is stored on a PKCS#11 token that requires a login. + * + * Since: 1.8 + **/ +const char * +nm_setting_802_1x_get_phase2_client_cert_password(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_client_cert_password; +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_password_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSetting8021x:phase2-client-cert-password + * + * Since: 1.8 + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_phase2_client_cert_password_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_client_cert_password_flags; +} + +/** + * nm_setting_802_1x_get_password: + * @setting: the #NMSetting8021x + * + * Returns: the password used by the authentication method, if any, as specified + * by the #NMSetting8021x:password property + **/ +const char * +nm_setting_802_1x_get_password(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->password; +} + +/** + * nm_setting_802_1x_get_password_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the #NMSetting8021x:password + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_password_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_flags; +} + +/** + * nm_setting_802_1x_get_password_raw: + * @setting: the #NMSetting8021x + * + * Returns: (transfer none): the password used by the authentication method as a + * UTF-8-encoded array of bytes, as specified by the + * #NMSetting8021x:password-raw property + **/ +GBytes * +nm_setting_802_1x_get_password_raw(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_raw; +} + +/** + * nm_setting_802_1x_get_password_raw_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSetting8021x:password-raw + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_password_raw_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->password_raw_flags; +} + +/** + * nm_setting_802_1x_get_pin: + * @setting: the #NMSetting8021x + * + * Returns: the PIN used by the authentication method, if any, as specified + * by the #NMSetting8021x:pin property + **/ +const char * +nm_setting_802_1x_get_pin(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->pin; +} + +/** + * nm_setting_802_1x_get_pin_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSetting8021x:pin + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_pin_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->pin_flags; +} + +/** + * nm_setting_802_1x_get_private_key_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the private key. If the returned scheme is + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, use + * nm_setting_802_1x_get_client_cert_blob(); if + * %NM_SETTING_802_1X_CK_SCHEME_PATH, use + * nm_setting_802_1x_get_client_cert_path(); if + * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use + * nm_setting_802_1x_get_client_cert_uri(). + * + * Returns: scheme used to store the private key (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_private_key_scheme(NMSetting8021x *setting) +{ + _cert_impl_get_scheme(setting, private_key); +} + +/** + * nm_setting_802_1x_get_private_key_blob: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * WARNING: the private key property is not a "secret" property, and thus + * unencrypted private key data may be readable by unprivileged users. Private + * keys should always be encrypted with a private key password. + * + * Returns: (transfer none): the private key data + **/ +GBytes * +nm_setting_802_1x_get_private_key_blob(NMSetting8021x *setting) +{ + _cert_impl_get_blob(setting, private_key); +} + +/** + * nm_setting_802_1x_get_private_key_path: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: path to the private key file + **/ +const char * +nm_setting_802_1x_get_private_key_path(NMSetting8021x *setting) +{ + _cert_impl_get_path(setting, private_key); +} + +/** + * nm_setting_802_1x_get_private_key_uri: + * @setting: the #NMSetting8021x + * + * Returns the private key URI analogously to + * nm_setting_802_1x_get_private_key_blob() and + * nm_setting_802_1x_get_private_key_path(). + * + * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * 7512), but may be extended to other schemes in future (such as 'file' URIs + * for local files and 'data' URIs for inline certificate data). + * + * Returns: the URI string + * + * Since: 1.6 + **/ +const char * +nm_setting_802_1x_get_private_key_uri(NMSetting8021x *setting) +{ + _cert_impl_get_uri(setting, private_key); +} + +/** + * nm_setting_802_1x_set_private_key: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the private key file + * (PEM, DER, or PKCS#12 format). The path must be UTF-8 encoded; use + * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme + * clears the private key. + * @password: password used to decrypt the private key, or %NULL if the password + * is unknown. If the password is given but fails to decrypt the private key, + * an error is returned. + * @scheme: desired storage scheme for the private key + * @out_format: on successful return, the type of the private key added + * @error: on unsuccessful return, an error + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * This function reads a private key from disk and sets the + * #NMSetting8021x:private-key property with the private key file data if using + * the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the private + * key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * If @password is given, this function attempts to decrypt the private key to + * verify that @password is correct, and if it is, updates the + * #NMSetting8021x:private-key-password property with the given @password. If + * the decryption is unsuccessful, %FALSE is returned, @error is set, and no + * internal data is changed. If no @password is given, the private key is + * assumed to be valid, no decryption is performed, and the password may be set + * at a later time. + * + * WARNING: the private key property is not a "secret" property, and thus + * unencrypted private key data using the BLOB scheme may be readable by + * unprivileged users. Private keys should always be encrypted with a private + * key password to prevent unauthorized access to unencrypted private key data. + * + * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_private_key(NMSetting8021x * setting, + const char * value, + const char * password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error) +{ + return _cert_impl_set(setting, PROP_PRIVATE_KEY, value, password, scheme, out_format, error); +} + +/** + * nm_setting_802_1x_get_private_key_password: + * @setting: the #NMSetting8021x + * + * Returns: the private key password used to decrypt the private key if + * previously set with nm_setting_802_1x_set_private_key(), or the + * #NMSetting8021x:private-key-password property. + **/ +const char * +nm_setting_802_1x_get_private_key_password(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->private_key_password; +} + +/** + * nm_setting_802_1x_get_private_key_password_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSetting8021x:private-key-password + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_private_key_password_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->private_key_password_flags; +} + +/** + * nm_setting_802_1x_get_private_key_format: + * @setting: the #NMSetting8021x + * + * Returns: the data format of the private key data stored in the + * #NMSetting8021x:private-key property + **/ +NMSetting8021xCKFormat +nm_setting_802_1x_get_private_key_format(NMSetting8021x *setting) +{ + return _cert_impl_get_key_format(setting, private_key); +} + +/** + * nm_setting_802_1x_get_phase2_private_key_password: + * @setting: the #NMSetting8021x + * + * Returns: the private key password used to decrypt the private key if + * previously set with nm_setting_802_1x_set_phase2_private_key() or the + * #NMSetting8021x:phase2-private-key-password property. + **/ +const char * +nm_setting_802_1x_get_phase2_private_key_password(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_private_key_password; +} + +/** + * nm_setting_802_1x_get_phase2_private_key_password_flags: + * @setting: the #NMSetting8021x + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSetting8021x:phase2-private-key-password + **/ +NMSettingSecretFlags +nm_setting_802_1x_get_phase2_private_key_password_flags(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->phase2_private_key_password_flags; +} + +/** + * nm_setting_802_1x_get_phase2_private_key_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the "phase 2" private key. If the returned + * scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use + * nm_setting_802_1x_get_client_cert_blob(); if + * %NM_SETTING_802_1X_CK_SCHEME_PATH, use + * nm_setting_802_1x_get_client_cert_path(); if + * %NM_SETTING_802_1X_CK_SCHEME_PKCS11, use + * nm_setting_802_1x_get_client_cert_uri(). + * + * Returns: scheme used to store the "phase 2" private key (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_phase2_private_key_scheme(NMSetting8021x *setting) +{ + _cert_impl_get_scheme(setting, phase2_private_key); +} + +/** + * nm_setting_802_1x_get_phase2_private_key_blob: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * WARNING: the phase2 private key property is not a "secret" property, and thus + * unencrypted private key data may be readable by unprivileged users. Private + * keys should always be encrypted with a private key password. + * + * Returns: (transfer none): the "phase 2" private key data + **/ +GBytes * +nm_setting_802_1x_get_phase2_private_key_blob(NMSetting8021x *setting) +{ + _cert_impl_get_blob(setting, phase2_private_key); +} + +/** + * nm_setting_802_1x_get_phase2_private_key_path: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: path to the "phase 2" private key file + **/ +const char * +nm_setting_802_1x_get_phase2_private_key_path(NMSetting8021x *setting) +{ + _cert_impl_get_path(setting, phase2_private_key); +} + +/** + * nm_setting_802_1x_get_phase2_private_key_uri: + * @setting: the #NMSetting8021x + * + * Returns the "phase 2" private key URI analogously to + * nm_setting_802_1x_get_phase2_private_key_blob() and + * nm_setting_802_1x_get_phase2_private_key_path(). + * + * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * 7512), but may be extended to other schemes in future (such as 'file' URIs + * for local files and 'data' URIs for inline certificate data). + * + * Returns: the URI string + * + * Since: 1.6 + **/ +const char * +nm_setting_802_1x_get_phase2_private_key_uri(NMSetting8021x *setting) +{ + _cert_impl_get_uri(setting, phase2_private_key); +} + +/** + * nm_setting_802_1x_set_phase2_private_key: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" private + * key file (PEM, DER, or PKCS#12 format). The path must be UTF-8 encoded; + * use g_filename_to_utf8() to convert if needed. Passing %NULL with any + * @scheme clears the private key. + * @password: password used to decrypt the private key, or %NULL if the password + * is unknown. If the password is given but fails to decrypt the private key, + * an error is returned. + * @scheme: desired storage scheme for the private key + * @out_format: on successful return, the type of the private key added + * @error: on unsuccessful return, an error + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * This function reads a private key from disk and sets the + * #NMSetting8021x:phase2-private-key property with the private key file data if + * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the + * private key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * If @password is given, this function attempts to decrypt the private key to + * verify that @password is correct, and if it is, updates the + * #NMSetting8021x:phase2-private-key-password property with the given + * @password. If the decryption is unsuccessful, %FALSE is returned, @error is + * set, and no internal data is changed. If no @password is given, the private + * key is assumed to be valid, no decryption is performed, and the password may + * be set at a later time. + * + * WARNING: the "phase2" private key property is not a "secret" property, and + * thus unencrypted private key data using the BLOB scheme may be readable by + * unprivileged users. Private keys should always be encrypted with a private + * key password to prevent unauthorized access to unencrypted private key data. + * + * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_private_key(NMSetting8021x * setting, + const char * value, + const char * password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error) +{ + return _cert_impl_set(setting, + PROP_PHASE2_PRIVATE_KEY, + value, + password, + scheme, + out_format, + error); +} + +/** + * nm_setting_802_1x_get_phase2_private_key_format: + * @setting: the #NMSetting8021x + * + * Returns: the data format of the "phase 2" private key data stored in the + * #NMSetting8021x:phase2-private-key property + **/ +NMSetting8021xCKFormat +nm_setting_802_1x_get_phase2_private_key_format(NMSetting8021x *setting) +{ + return _cert_impl_get_key_format(setting, phase2_private_key); +} + +/** + * nm_setting_802_1x_get_auth_timeout: + * @setting: the #NMSetting8021x + * + * Returns the value contained in the #NMSetting8021x:auth-timeout property. + * + * Returns: the configured authentication timeout in seconds. Zero means the + * global default value. + * + * Since: 1.8 + **/ +int +nm_setting_802_1x_get_auth_timeout(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), 0); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->auth_timeout; +} + +/** + * nm_setting_802_1x_get_optional: + * @setting: the #NMSetting8021x + * + * Returns the value contained in the #NMSetting8021x:optional property. + * + * Returns: %TRUE if the activation should proceed even when the 802.1X + * authentication fails; %FALSE otherwise + * + * Since: 1.22 + **/ +gboolean +nm_setting_802_1x_get_optional(NMSetting8021x *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_802_1X(setting), FALSE); + + return NM_SETTING_802_1X_GET_PRIVATE(setting)->optional; +} + +/*****************************************************************************/ + +static void +need_secrets_password(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + + if ((!priv->password || !strlen(priv->password)) + && (!priv->password_raw || !g_bytes_get_size(priv->password_raw))) { + g_ptr_array_add(secrets, NM_SETTING_802_1X_PASSWORD); + g_ptr_array_add(secrets, NM_SETTING_802_1X_PASSWORD_RAW); + } +} + +static void +need_secrets_sim(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + + if (!priv->pin || !strlen(priv->pin)) + g_ptr_array_add(secrets, NM_SETTING_802_1X_PIN); +} + +static gboolean +need_private_key_password(GBytes * blob, + NMSetting8021xCKScheme scheme, + const char * path, + const char * password, + NMSettingSecretFlags flags) +{ + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + + if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + return FALSE; + + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 && flags == NM_SETTING_SECRET_FLAG_NONE) + return FALSE; + + /* Private key password is required */ + if (password) { + if (path) + format = nm_crypto_verify_private_key(path, password, NULL, NULL); + else if (blob) + format = nm_crypto_verify_private_key_data(g_bytes_get_data(blob, NULL), + g_bytes_get_size(blob), + password, + NULL, + NULL); + else + return FALSE; + } + + return (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN); +} + +static void +need_secrets_tls(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + NMSetting8021xCKScheme scheme; + GBytes * blob = NULL; + const char * path = NULL; + + if (phase2) { + scheme = nm_setting_802_1x_get_phase2_private_key_scheme(self); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) + path = nm_setting_802_1x_get_phase2_private_key_path(self); + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) + blob = nm_setting_802_1x_get_phase2_private_key_blob(self); + else if (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) + g_warning("%s: unknown phase2 private key scheme %d", __func__, scheme); + + if (need_private_key_password(blob, + scheme, + path, + priv->phase2_private_key_password, + priv->phase2_private_key_password_flags)) + g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); + + scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme(self); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && !(priv->phase2_ca_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE + || priv->phase2_ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + && !priv->phase2_ca_cert_password) + g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD); + + scheme = nm_setting_802_1x_get_phase2_client_cert_scheme(self); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && !(priv->phase2_client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED + || priv->phase2_client_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE) + && !priv->phase2_client_cert_password) + g_ptr_array_add(secrets, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD); + } else { + scheme = nm_setting_802_1x_get_private_key_scheme(self); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) + path = nm_setting_802_1x_get_private_key_path(self); + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) + blob = nm_setting_802_1x_get_private_key_blob(self); + else if (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) + g_warning("%s: unknown private key scheme %d", __func__, scheme); + + if (need_private_key_password(blob, + scheme, + path, + priv->private_key_password, + priv->private_key_password_flags)) + g_ptr_array_add(secrets, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); + + scheme = nm_setting_802_1x_get_ca_cert_scheme(self); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && !(priv->ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED + || priv->ca_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE) + && !priv->ca_cert_password) + g_ptr_array_add(secrets, NM_SETTING_802_1X_CA_CERT_PASSWORD); + + scheme = nm_setting_802_1x_get_client_cert_scheme(self); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && !(priv->client_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE + || priv->client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + && !priv->client_cert_password) + g_ptr_array_add(secrets, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD); + } +} + +static gboolean +verify_tls(NMSetting8021x *self, gboolean phase2, GError **error) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + + if (phase2) { + if (!priv->phase2_client_cert) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + return FALSE; + } else if (!g_bytes_get_size(priv->phase2_client_cert)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + return FALSE; + } + + /* Private key is required for TLS */ + if (!priv->phase2_private_key) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); + return FALSE; + } else if (!g_bytes_get_size(priv->phase2_private_key)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); + return FALSE; + } + + /* If the private key is PKCS#12, check that it matches the client cert */ + if (nm_crypto_is_pkcs12_data(g_bytes_get_data(priv->phase2_private_key, NULL), + g_bytes_get_size(priv->phase2_private_key), + NULL)) { + if (!g_bytes_equal(priv->phase2_private_key, priv->phase2_client_cert)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("has to match '%s' property for PKCS#12"), + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + return FALSE; + } + } + } else { + if (!priv->client_cert) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CLIENT_CERT); + return FALSE; + } else if (!g_bytes_get_size(priv->client_cert)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CLIENT_CERT); + return FALSE; + } + + /* Private key is required for TLS */ + if (!priv->private_key) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PRIVATE_KEY); + return FALSE; + } else if (!g_bytes_get_size(priv->private_key)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PRIVATE_KEY); + return FALSE; + } + + /* If the private key is PKCS#12, check that it matches the client cert */ + if (nm_crypto_is_pkcs12_data(g_bytes_get_data(priv->private_key, NULL), + g_bytes_get_size(priv->private_key), + NULL)) { + if (!g_bytes_equal(priv->private_key, priv->client_cert)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("has to match '%s' property for PKCS#12"), + NM_SETTING_802_1X_PRIVATE_KEY); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CLIENT_CERT); + return FALSE; + } + } + } + + return TRUE; +} + +static gboolean +verify_ttls(NMSetting8021x *self, gboolean phase2, GError **error) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + + if ((!priv->identity || !strlen(priv->identity)) + && (!priv->anonymous_identity || !strlen(priv->anonymous_identity))) { + if (!priv->identity) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + } else if (!strlen(priv->identity)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + } else if (!priv->anonymous_identity) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_ANONYMOUS_IDENTITY); + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_ANONYMOUS_IDENTITY); + } + return FALSE; + } + + if ((!priv->phase2_auth || !strlen(priv->phase2_auth)) + && (!priv->phase2_autheap || !strlen(priv->phase2_autheap))) { + if (!priv->phase2_auth) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTH); + } else if (!strlen(priv->phase2_auth)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTH); + } else if (!priv->phase2_autheap) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTHEAP); + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTHEAP); + } + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_identity(NMSetting8021x *self, gboolean phase2, GError **error) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + + if (!priv->identity) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + return FALSE; + } else if (!strlen(priv->identity)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + return FALSE; + } + + return TRUE; +} + +static void +need_secrets_phase2(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + char * method = NULL; + int i; + + g_return_if_fail(phase2 == FALSE); + + /* Check phase2_auth and phase2_autheap */ + method = priv->phase2_auth; + if (!method && priv->phase2_autheap) + method = priv->phase2_autheap; + + if (!method) { + g_warning("Couldn't find EAP method."); + g_assert_not_reached(); + return; + } + + /* Ask the configured phase2 method if it needs secrets */ + for (i = 0; eap_methods_table[i].method; i++) { + if (eap_methods_table[i].ns_func == NULL) + continue; + if (!strcmp(eap_methods_table[i].method, method)) { + (*eap_methods_table[i].ns_func)(self, secrets, TRUE); + break; + } + } +} + +static const EAPMethodsTable eap_methods_table[] = { + {"leap", need_secrets_password, verify_identity}, + {"pwd", need_secrets_password, verify_identity}, + {"md5", need_secrets_password, verify_identity}, + {"pap", need_secrets_password, verify_identity}, + {"chap", need_secrets_password, verify_identity}, + {"mschap", need_secrets_password, verify_identity}, + {"mschapv2", need_secrets_password, verify_identity}, + {"fast", need_secrets_password, verify_identity}, + {"tls", need_secrets_tls, verify_tls}, + {"peap", need_secrets_phase2, verify_ttls}, + {"ttls", need_secrets_phase2, verify_ttls}, + {"sim", need_secrets_sim, NULL}, + {"gtc", need_secrets_password, verify_identity}, + {"otp", NULL, NULL}, // FIXME: implement + {"external", NULL, NULL}, + {NULL, NULL, NULL}}; + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSetting8021x * self = NM_SETTING_802_1X(setting); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + const char * valid_eap[] = + {"leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", "external", NULL}; + GSList *iter; + + if (error) + g_return_val_if_fail(*error == NULL, FALSE); + + if (connection && priv->optional + && !nm_streq0(nm_connection_get_connection_type(connection), + NM_SETTING_WIRED_SETTING_NAME)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can be enabled only on Ethernet connections")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_OPTIONAL); + return FALSE; + } + + if (!priv->eap) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP); + return FALSE; + } + + if (!_nm_utils_string_slist_validate(priv->eap, valid_eap)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP); + return FALSE; + } + + /* Ask each configured EAP method if its valid */ + for (iter = priv->eap; iter; iter = g_slist_next(iter)) { + const char *method = (const char *) iter->data; + int i; + + for (i = 0; eap_methods_table[i].method; i++) { + if (eap_methods_table[i].v_func == NULL) + continue; + if (!strcmp(eap_methods_table[i].method, method)) { + if (!(*eap_methods_table[i].v_func)(self, FALSE, error)) + return FALSE; + break; + } + } + } + + if (!NM_IN_STRSET(priv->phase1_peapver, NULL, "0", "1")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + priv->phase1_peapver); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_PEAPVER); + return FALSE; + } + + if (!NM_IN_STRSET(priv->phase1_peaplabel, NULL, "0", "1")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + priv->phase1_peaplabel); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_PEAPLABEL); + return FALSE; + } + + if (!NM_IN_STRSET(priv->phase1_fast_provisioning, NULL, "0", "1", "2", "3")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + priv->phase1_fast_provisioning); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING); + return FALSE; + } + + if (NM_FLAGS_ANY(priv->phase1_auth_flags, ~NM_SETTING_802_1X_AUTH_FLAGS_ALL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid auth flags")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_AUTH_FLAGS); + return FALSE; + } + + if (!NM_IN_STRSET(priv->phase2_auth, + NULL, + "pap", + "chap", + "mschap", + "mschapv2", + "gtc", + "otp", + "md5", + "tls")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + priv->phase2_auth); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTH); + return FALSE; + } + + if (!NM_IN_STRSET(priv->phase2_autheap, NULL, "md5", "mschapv2", "otp", "gtc", "tls")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + priv->phase2_autheap); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTHEAP); + return FALSE; + } + + if (!_cert_verify_property(priv->ca_cert, + NM_SETTING_802_1X_CA_CERT, + priv->ca_cert_password, + NM_SETTING_802_1X_CA_CERT_PASSWORD, + error)) + return FALSE; + if (!_cert_verify_property(priv->phase2_ca_cert, + NM_SETTING_802_1X_PHASE2_CA_CERT, + priv->phase2_ca_cert_password, + NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, + error)) + return FALSE; + + if (!_cert_verify_property(priv->client_cert, + NM_SETTING_802_1X_CLIENT_CERT, + priv->client_cert_password, + NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, + error)) + return FALSE; + if (!_cert_verify_property(priv->phase2_client_cert, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + priv->phase2_client_cert_password, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, + error)) + return FALSE; + + if (!_cert_verify_property(priv->private_key, NM_SETTING_802_1X_PRIVATE_KEY, NULL, NULL, error)) + return FALSE; + if (!_cert_verify_property(priv->phase2_private_key, + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + NULL, + NULL, + error)) + return FALSE; + + return TRUE; +} + +/*****************************************************************************/ + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + NMSetting8021x * self = NM_SETTING_802_1X(setting); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + GSList * iter; + GPtrArray * secrets; + gboolean eap_method_found = FALSE; + + secrets = g_ptr_array_sized_new(4); + + /* Ask each configured EAP method if it needs secrets */ + for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next(iter)) { + const char *method = (const char *) iter->data; + int i; + + for (i = 0; eap_methods_table[i].method; i++) { + if (eap_methods_table[i].ns_func == NULL) + continue; + if (!strcmp(eap_methods_table[i].method, method)) { + (*eap_methods_table[i].ns_func)(self, secrets, FALSE); + + /* Only break out of the outer loop if this EAP method + * needed secrets. + */ + if (secrets->len > 0) + eap_method_found = TRUE; + break; + } + } + } + + if (secrets->len == 0) { + g_ptr_array_free(secrets, TRUE); + return NULL; + } + + return secrets; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSetting8021x * setting = NM_SETTING_802_1X(object); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_EAP: + g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->eap, TRUE)); + break; + case PROP_IDENTITY: + g_value_set_string(value, priv->identity); + break; + case PROP_ANONYMOUS_IDENTITY: + g_value_set_string(value, priv->anonymous_identity); + break; + case PROP_PAC_FILE: + g_value_set_string(value, priv->pac_file); + break; + case PROP_CA_CERT: + g_value_set_boxed(value, priv->ca_cert); + break; + case PROP_CA_CERT_PASSWORD: + g_value_set_string(value, priv->ca_cert_password); + break; + case PROP_CA_CERT_PASSWORD_FLAGS: + g_value_set_flags(value, priv->ca_cert_password_flags); + break; + case PROP_CA_PATH: + g_value_set_string(value, priv->ca_path); + break; + case PROP_SUBJECT_MATCH: + g_value_set_string(value, priv->subject_match); + break; + case PROP_ALTSUBJECT_MATCHES: + g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->altsubject_matches, TRUE)); + break; + case PROP_DOMAIN_SUFFIX_MATCH: + g_value_set_string(value, priv->domain_suffix_match); + break; + case PROP_DOMAIN_MATCH: + g_value_set_string(value, priv->domain_match); + break; + case PROP_CLIENT_CERT: + g_value_set_boxed(value, priv->client_cert); + break; + case PROP_CLIENT_CERT_PASSWORD: + g_value_set_string(value, priv->client_cert_password); + break; + case PROP_CLIENT_CERT_PASSWORD_FLAGS: + g_value_set_flags(value, priv->client_cert_password_flags); + break; + case PROP_PHASE1_PEAPVER: + g_value_set_string(value, priv->phase1_peapver); + break; + case PROP_PHASE1_PEAPLABEL: + g_value_set_string(value, priv->phase1_peaplabel); + break; + case PROP_PHASE1_FAST_PROVISIONING: + g_value_set_string(value, priv->phase1_fast_provisioning); + break; + case PROP_PHASE1_AUTH_FLAGS: + g_value_set_uint(value, priv->phase1_auth_flags); + break; + case PROP_PHASE2_AUTH: + g_value_set_string(value, priv->phase2_auth); + break; + case PROP_PHASE2_AUTHEAP: + g_value_set_string(value, priv->phase2_autheap); + break; + case PROP_PHASE2_CA_CERT: + g_value_set_boxed(value, priv->phase2_ca_cert); + break; + case PROP_PHASE2_CA_CERT_PASSWORD: + g_value_set_string(value, priv->phase2_ca_cert_password); + break; + case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS: + g_value_set_flags(value, priv->phase2_ca_cert_password_flags); + break; + case PROP_PHASE2_CA_PATH: + g_value_set_string(value, priv->phase2_ca_path); + break; + case PROP_PHASE2_SUBJECT_MATCH: + g_value_set_string(value, priv->phase2_subject_match); + break; + case PROP_PHASE2_ALTSUBJECT_MATCHES: + g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->phase2_altsubject_matches, TRUE)); + break; + case PROP_PHASE2_DOMAIN_SUFFIX_MATCH: + g_value_set_string(value, priv->phase2_domain_suffix_match); + break; + case PROP_PHASE2_DOMAIN_MATCH: + g_value_set_string(value, priv->phase2_domain_match); + break; + case PROP_PHASE2_CLIENT_CERT: + g_value_set_boxed(value, priv->phase2_client_cert); + break; + case PROP_PHASE2_CLIENT_CERT_PASSWORD: + g_value_set_string(value, priv->phase2_client_cert_password); + break; + case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS: + g_value_set_flags(value, priv->phase2_client_cert_password_flags); + break; + case PROP_PASSWORD: + g_value_set_string(value, priv->password); + break; + case PROP_PASSWORD_FLAGS: + g_value_set_flags(value, priv->password_flags); + break; + case PROP_PASSWORD_RAW: + g_value_set_boxed(value, priv->password_raw); + break; + case PROP_PASSWORD_RAW_FLAGS: + g_value_set_flags(value, priv->password_raw_flags); + break; + case PROP_PRIVATE_KEY: + g_value_set_boxed(value, priv->private_key); + break; + case PROP_PRIVATE_KEY_PASSWORD: + g_value_set_string(value, priv->private_key_password); + break; + case PROP_PRIVATE_KEY_PASSWORD_FLAGS: + g_value_set_flags(value, priv->private_key_password_flags); + break; + case PROP_PHASE2_PRIVATE_KEY: + g_value_set_boxed(value, priv->phase2_private_key); + break; + case PROP_PHASE2_PRIVATE_KEY_PASSWORD: + g_value_set_string(value, priv->phase2_private_key_password); + break; + case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS: + g_value_set_flags(value, priv->phase2_private_key_password_flags); + break; + case PROP_PIN: + g_value_set_string(value, priv->pin); + break; + case PROP_PIN_FLAGS: + g_value_set_flags(value, priv->pin_flags); + break; + case PROP_SYSTEM_CA_CERTS: + g_value_set_boolean(value, priv->system_ca_certs); + break; + case PROP_AUTH_TIMEOUT: + g_value_set_int(value, priv->auth_timeout); + break; + case PROP_OPTIONAL: + g_value_set_boolean(value, priv->optional); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSetting8021x * setting = NM_SETTING_802_1X(object); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_EAP: + g_slist_free_full(priv->eap, g_free); + priv->eap = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); + break; + case PROP_IDENTITY: + g_free(priv->identity); + priv->identity = g_value_dup_string(value); + break; + case PROP_ANONYMOUS_IDENTITY: + g_free(priv->anonymous_identity); + priv->anonymous_identity = g_value_dup_string(value); + break; + case PROP_PAC_FILE: + g_free(priv->pac_file); + priv->pac_file = g_value_dup_string(value); + break; + case PROP_CA_CERT: + g_bytes_unref(priv->ca_cert); + priv->ca_cert = g_value_dup_boxed(value); + break; + case PROP_CA_CERT_PASSWORD: + g_free(priv->ca_cert_password); + priv->ca_cert_password = g_value_dup_string(value); + break; + case PROP_CA_CERT_PASSWORD_FLAGS: + priv->ca_cert_password_flags = g_value_get_flags(value); + break; + case PROP_CA_PATH: + g_free(priv->ca_path); + priv->ca_path = g_value_dup_string(value); + break; + case PROP_SUBJECT_MATCH: + g_free(priv->subject_match); + priv->subject_match = nm_strdup_not_empty(g_value_get_string(value)); + break; + case PROP_ALTSUBJECT_MATCHES: + g_slist_free_full(priv->altsubject_matches, g_free); + priv->altsubject_matches = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); + break; + case PROP_DOMAIN_SUFFIX_MATCH: + g_free(priv->domain_suffix_match); + priv->domain_suffix_match = nm_strdup_not_empty(g_value_get_string(value)); + break; + case PROP_DOMAIN_MATCH: + g_free(priv->domain_match); + priv->domain_match = nm_strdup_not_empty(g_value_get_string(value)); + break; + case PROP_CLIENT_CERT: + g_bytes_unref(priv->client_cert); + priv->client_cert = g_value_dup_boxed(value); + break; + case PROP_CLIENT_CERT_PASSWORD: + g_free(priv->client_cert_password); + priv->client_cert_password = g_value_dup_string(value); + break; + case PROP_CLIENT_CERT_PASSWORD_FLAGS: + priv->client_cert_password_flags = g_value_get_flags(value); + break; + case PROP_PHASE1_PEAPVER: + g_free(priv->phase1_peapver); + priv->phase1_peapver = g_value_dup_string(value); + break; + case PROP_PHASE1_PEAPLABEL: + g_free(priv->phase1_peaplabel); + priv->phase1_peaplabel = g_value_dup_string(value); + break; + case PROP_PHASE1_FAST_PROVISIONING: + g_free(priv->phase1_fast_provisioning); + priv->phase1_fast_provisioning = g_value_dup_string(value); + break; + case PROP_PHASE1_AUTH_FLAGS: + priv->phase1_auth_flags = g_value_get_uint(value); + break; + case PROP_PHASE2_AUTH: + g_free(priv->phase2_auth); + priv->phase2_auth = g_value_dup_string(value); + break; + case PROP_PHASE2_AUTHEAP: + g_free(priv->phase2_autheap); + priv->phase2_autheap = g_value_dup_string(value); + break; + case PROP_PHASE2_CA_CERT: + g_bytes_unref(priv->phase2_ca_cert); + priv->phase2_ca_cert = g_value_dup_boxed(value); + break; + case PROP_PHASE2_CA_CERT_PASSWORD: + g_free(priv->phase2_ca_cert_password); + priv->phase2_ca_cert_password = g_value_dup_string(value); + break; + case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS: + priv->phase2_ca_cert_password_flags = g_value_get_flags(value); + break; + case PROP_PHASE2_CA_PATH: + g_free(priv->phase2_ca_path); + priv->phase2_ca_path = g_value_dup_string(value); + break; + case PROP_PHASE2_SUBJECT_MATCH: + g_free(priv->phase2_subject_match); + priv->phase2_subject_match = nm_strdup_not_empty(g_value_get_string(value)); + break; + case PROP_PHASE2_ALTSUBJECT_MATCHES: + g_slist_free_full(priv->phase2_altsubject_matches, g_free); + priv->phase2_altsubject_matches = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); + break; + case PROP_PHASE2_DOMAIN_SUFFIX_MATCH: + g_free(priv->phase2_domain_suffix_match); + priv->phase2_domain_suffix_match = nm_strdup_not_empty(g_value_get_string(value)); + break; + case PROP_PHASE2_DOMAIN_MATCH: + g_free(priv->phase2_domain_match); + priv->phase2_domain_match = nm_strdup_not_empty(g_value_get_string(value)); + break; + case PROP_PHASE2_CLIENT_CERT: + g_bytes_unref(priv->phase2_client_cert); + priv->phase2_client_cert = g_value_dup_boxed(value); + break; + case PROP_PHASE2_CLIENT_CERT_PASSWORD: + g_free(priv->phase2_client_cert_password); + priv->phase2_client_cert_password = g_value_dup_string(value); + break; + case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS: + priv->phase2_client_cert_password_flags = g_value_get_flags(value); + break; + case PROP_PASSWORD: + g_free(priv->password); + priv->password = g_value_dup_string(value); + break; + case PROP_PASSWORD_FLAGS: + priv->password_flags = g_value_get_flags(value); + break; + case PROP_PASSWORD_RAW: + g_bytes_unref(priv->password_raw); + priv->password_raw = g_value_dup_boxed(value); + break; + case PROP_PASSWORD_RAW_FLAGS: + priv->password_raw_flags = g_value_get_flags(value); + break; + case PROP_PRIVATE_KEY: + g_bytes_unref(priv->private_key); + priv->private_key = g_value_dup_boxed(value); + break; + case PROP_PRIVATE_KEY_PASSWORD: + nm_free_secret(priv->private_key_password); + priv->private_key_password = g_value_dup_string(value); + break; + case PROP_PRIVATE_KEY_PASSWORD_FLAGS: + priv->private_key_password_flags = g_value_get_flags(value); + break; + case PROP_PHASE2_PRIVATE_KEY: + g_bytes_unref(priv->phase2_private_key); + priv->phase2_private_key = g_value_dup_boxed(value); + break; + case PROP_PHASE2_PRIVATE_KEY_PASSWORD: + nm_free_secret(priv->phase2_private_key_password); + priv->phase2_private_key_password = g_value_dup_string(value); + break; + case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS: + priv->phase2_private_key_password_flags = g_value_get_flags(value); + break; + case PROP_PIN: + g_free(priv->pin); + priv->pin = g_value_dup_string(value); + break; + case PROP_PIN_FLAGS: + priv->pin_flags = g_value_get_flags(value); + break; + case PROP_SYSTEM_CA_CERTS: + priv->system_ca_certs = g_value_get_boolean(value); + break; + case PROP_AUTH_TIMEOUT: + priv->auth_timeout = g_value_get_int(value); + break; + case PROP_OPTIONAL: + priv->optional = g_value_get_boolean(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_802_1x_init(NMSetting8021x *setting) +{} + +/** + * nm_setting_802_1x_new: + * + * Creates a new #NMSetting8021x object with default values. + * + * Returns: the new empty #NMSetting8021x object + **/ +NMSetting * +nm_setting_802_1x_new(void) +{ + return g_object_new(NM_TYPE_SETTING_802_1X, NULL); +} + +static void +finalize(GObject *object) +{ + NMSetting8021x * self = NM_SETTING_802_1X(object); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); + + g_free(priv->identity); + g_free(priv->anonymous_identity); + g_free(priv->ca_path); + g_free(priv->subject_match); + g_free(priv->domain_suffix_match); + g_free(priv->phase1_peapver); + g_free(priv->phase1_peaplabel); + g_free(priv->phase1_fast_provisioning); + g_free(priv->phase2_auth); + g_free(priv->phase2_autheap); + g_free(priv->phase2_ca_path); + g_free(priv->phase2_subject_match); + g_free(priv->phase2_domain_suffix_match); + g_free(priv->password); + g_bytes_unref(priv->password_raw); + g_free(priv->pin); + + g_slist_free_full(priv->eap, g_free); + g_slist_free_full(priv->altsubject_matches, g_free); + g_slist_free_full(priv->phase2_altsubject_matches, g_free); + + g_bytes_unref(priv->ca_cert); + g_free(priv->ca_cert_password); + g_bytes_unref(priv->client_cert); + g_free(priv->client_cert_password); + g_bytes_unref(priv->private_key); + nm_free_secret(priv->private_key_password); + g_bytes_unref(priv->phase2_ca_cert); + g_free(priv->phase2_ca_cert_password); + g_bytes_unref(priv->phase2_client_cert); + g_free(priv->phase2_client_cert_password); + g_bytes_unref(priv->phase2_private_key); + nm_free_secret(priv->phase2_private_key_password); + + G_OBJECT_CLASS(nm_setting_802_1x_parent_class)->finalize(object); +} + +static void +nm_setting_802_1x_class_init(NMSetting8021xClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSetting8021xPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; + + /** + * NMSetting8021x:eap: + * + * The allowed EAP method to be used when authenticating to the network with + * 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd", + * and "fast". Each method requires different configuration using the + * properties of this setting; refer to wpa_supplicant documentation for the + * allowed combinations. + **/ + /* ---ifcfg-rh--- + * property: eap + * variable: IEEE_8021X_EAP_METHODS(+) + * values: "LEAP", "PWD", "TLS", "PEAP", "TTLS", "FAST" + * description: EAP method for 802.1X authentication. + * example: IEEE_8021X_EAP_METHODS=PEAP + * ---end--- + */ + obj_properties[PROP_EAP] = g_param_spec_boxed(NM_SETTING_802_1X_EAP, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:identity: + * + * Identity string for EAP authentication methods. Often the user's user or + * login name. + **/ + /* ---ifcfg-rh--- + * property: identity + * variable: IEEE_8021X_IDENTITY(+) + * description: Identity for EAP authentication methods. + * example: IEEE_8021X_IDENTITY=itsme + * ---end--- + */ + obj_properties[PROP_IDENTITY] = g_param_spec_string(NM_SETTING_802_1X_IDENTITY, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:anonymous-identity: + * + * Anonymous identity string for EAP authentication methods. Used as the + * unencrypted identity with EAP types that support different tunneled + * identity like EAP-TTLS. + **/ + /* ---ifcfg-rh--- + * property: anonymous-identity + * variable: IEEE_8021X_ANON_IDENTITY(+) + * description: Anonymous identity for EAP authentication methods. + * ---end--- + */ + obj_properties[PROP_ANONYMOUS_IDENTITY] = + g_param_spec_string(NM_SETTING_802_1X_ANONYMOUS_IDENTITY, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:pac-file: + * + * UTF-8 encoded file path containing PAC for EAP-FAST. + **/ + /* ---ifcfg-rh--- + * property: pac-file + * variable: IEEE_8021X_PAC_FILE(+) + * description: File with PAC (Protected Access Credential) for EAP-FAST. + * example: IEEE_8021X_PAC_FILE=/home/joe/my-fast.pac + * ---end--- + */ + obj_properties[PROP_PAC_FILE] = g_param_spec_string(NM_SETTING_802_1X_PAC_FILE, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:ca-cert: + * + * Contains the CA certificate if used by the EAP method specified in the + * #NMSetting8021x:eap property. + * + * Certificate data is specified using a "scheme"; three are currently + * supported: blob, path and pkcs#11 URL. When using the blob scheme this property + * should be set to the certificate's DER encoded data. When using the path + * scheme, this property should be set to the full UTF-8 encoded path of the + * certificate, prefixed with the string "file://" and ending with a terminating + * NUL byte. + * This property can be unset even if the EAP method supports CA certificates, + * but this allows man-in-the-middle attacks and is NOT recommended. + * + * Note that enabling NMSetting8021x:system-ca-certs will override this + * setting to use the built-in path, if the built-in path is not a directory. + * + * Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_ca_cert() function instead. + **/ + /* ---ifcfg-rh--- + * property: ca-cert + * variable: IEEE_8021X_CA_CERT(+) + * description: CA certificate for EAP. + * example: IEEE_8021X_CA_CERT=/home/joe/cacert.crt + * ---end--- + */ + obj_properties[PROP_CA_CERT] = g_param_spec_boxed(NM_SETTING_802_1X_CA_CERT, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:ca-cert-password: + * + * The password used to access the CA certificate stored in + * #NMSetting8021x:ca-cert property. Only makes sense if the certificate + * is stored on a PKCS#11 token that requires a login. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * ---end--- + */ + obj_properties[PROP_CA_CERT_PASSWORD] = + g_param_spec_string(NM_SETTING_802_1X_CA_CERT_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:ca-cert-password-flags: + * + * Flags indicating how to handle the #NMSetting8021x:ca-cert-password property. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * ---end--- + */ + obj_properties[PROP_CA_CERT_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:ca-path: + * + * UTF-8 encoded path to a directory containing PEM or DER formatted + * certificates to be added to the verification chain in addition to the + * certificate specified in the #NMSetting8021x:ca-cert property. + * + * If NMSetting8021x:system-ca-certs is enabled and the built-in CA + * path is an existing directory, then this setting is ignored. + **/ + /* ---ifcfg-rh--- + * property: ca-path + * variable: IEEE_8021X_CA_PATH(+) + * description: The search path for the certificate. + * ---end--- + */ + obj_properties[PROP_CA_PATH] = g_param_spec_string(NM_SETTING_802_1X_CA_PATH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:subject-match: + * + * Substring to be matched against the subject of the certificate presented + * by the authentication server. When unset, no verification of the + * authentication server certificate's subject is performed. This property + * provides little security, if any, and its use is deprecated in favor of + * NMSetting8021x:domain-suffix-match. + **/ + /* ---ifcfg-rh--- + * property: subject-match + * variable: IEEE_8021X_SUBJECT_MATCH(+) + * description: Substring to match subject of server certificate against. + * example: IEEE_8021X_SUBJECT_MATCH="Red Hat" + * ---end--- + */ + obj_properties[PROP_SUBJECT_MATCH] = + g_param_spec_string(NM_SETTING_802_1X_SUBJECT_MATCH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:altsubject-matches: + * + * List of strings to be matched against the altSubjectName of the + * certificate presented by the authentication server. If the list is empty, + * no verification of the server certificate's altSubjectName is performed. + **/ + /* ---ifcfg-rh--- + * property: altsubject-matches + * variable: IEEE_8021X_ALTSUBJECT_MATCHES(+) + * description: List of strings to be matched against the altSubjectName. + * example: IEEE_8021X_ALTSUBJECT_MATCHES="s1.domain.cc" + * ---end--- + */ + obj_properties[PROP_ALTSUBJECT_MATCHES] = + g_param_spec_boxed(NM_SETTING_802_1X_ALTSUBJECT_MATCHES, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:domain-suffix-match: + * + * Constraint for server domain name. If set, this FQDN is used as a suffix + * match requirement for dNSName element(s) of the certificate presented by + * the authentication server. If a matching dNSName is found, this + * constraint is met. If no dNSName values are present, this constraint is + * matched against SubjectName CN using same suffix match comparison. + * Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited + * list. + * + * Since: 1.2 + **/ + /* ---ifcfg-rh--- + * property: domain-suffix-match + * description: Suffix to match domain of server certificate against. + * variable: IEEE_8021X_DOMAIN_SUFFIX_MATCH(+) + * ---end--- + */ + obj_properties[PROP_DOMAIN_SUFFIX_MATCH] = + g_param_spec_string(NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:domain-match: + * + * Constraint for server domain name. If set, this list of FQDNs is used as + * a match requirement for dNSName element(s) of the certificate presented + * by the authentication server. If a matching dNSName is found, this + * constraint is met. If no dNSName values are present, this constraint is + * matched against SubjectName CN using the same comparison. + * Multiple valid FQDNs can be passed as a ";" delimited list. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: domain-match + * description: Value to match domain of server certificate against. + * variable: IEEE_8021X_DOMAIN_MATCH(+) + * ---end--- + */ + obj_properties[PROP_DOMAIN_MATCH] = + g_param_spec_string(NM_SETTING_802_1X_DOMAIN_MATCH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:client-cert: + * + * Contains the client certificate if used by the EAP method specified in + * the #NMSetting8021x:eap property. + * + * Certificate data is specified using a "scheme"; two are currently + * supported: blob and path. When using the blob scheme (which is backwards + * compatible with NM 0.7.x) this property should be set to the + * certificate's DER encoded data. When using the path scheme, this property + * should be set to the full UTF-8 encoded path of the certificate, prefixed + * with the string "file://" and ending with a terminating NUL byte. + * + * Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_client_cert() function instead. + **/ + /* ---ifcfg-rh--- + * property: client-cert + * variable: IEEE_8021X_CLIENT_CERT(+) + * description: Client certificate for EAP. + * example: IEEE_8021X_CLIENT_CERT=/home/joe/mycert.crt + * ---end--- + */ + obj_properties[PROP_CLIENT_CERT] = + g_param_spec_boxed(NM_SETTING_802_1X_CLIENT_CERT, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:client-cert-password: + * + * The password used to access the client certificate stored in + * #NMSetting8021x:client-cert property. Only makes sense if the certificate + * is stored on a PKCS#11 token that requires a login. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * ---end--- + */ + obj_properties[PROP_CLIENT_CERT_PASSWORD] = + g_param_spec_string(NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:client-cert-password-flags: + * + * Flags indicating how to handle the #NMSetting8021x:client-cert-password property. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * ---end--- + */ + obj_properties[PROP_CLIENT_CERT_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase1-peapver: + * + * Forces which PEAP version is used when PEAP is set as the EAP method in + * the #NMSetting8021x:eap property. When unset, the version reported by + * the server will be used. Sometimes when using older RADIUS servers, it + * is necessary to force the client to use a particular PEAP version. To do + * so, this property may be set to "0" or "1" to force that specific PEAP + * version. + **/ + /* ---ifcfg-rh--- + * property: phase1-peapver + * variable: IEEE_8021X_PEAP_VERSION(+) + * values: 0, 1 + * description: Use to force a specific PEAP version. + * ---end--- + */ + obj_properties[PROP_PHASE1_PEAPVER] = + g_param_spec_string(NM_SETTING_802_1X_PHASE1_PEAPVER, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase1-peaplabel: + * + * Forces use of the new PEAP label during key derivation. Some RADIUS + * servers may require forcing the new PEAP label to interoperate with + * PEAPv1. Set to "1" to force use of the new PEAP label. See the + * wpa_supplicant documentation for more details. + **/ + /* ---ifcfg-rh--- + * property: phase1-peaplabel + * variable: IEEE_8021X_PEAP_FORCE_NEW_LABEL(+) + * values: yes, no + * default: no + * description: Use to force the new PEAP label during key derivation. + * ---end--- + */ + obj_properties[PROP_PHASE1_PEAPLABEL] = + g_param_spec_string(NM_SETTING_802_1X_PHASE1_PEAPLABEL, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase1-fast-provisioning: + * + * Enables or disables in-line provisioning of EAP-FAST credentials when + * FAST is specified as the EAP method in the #NMSetting8021x:eap property. + * Recognized values are "0" (disabled), "1" (allow unauthenticated + * provisioning), "2" (allow authenticated provisioning), and "3" (allow + * both authenticated and unauthenticated provisioning). See the + * wpa_supplicant documentation for more details. + **/ + /* ---ifcfg-rh--- + * property: phase1-fast-provisioning + * variable: IEEE_8021X_FAST_PROVISIONING(+) + * values: space-separated list of these values [allow-auth, allow-unauth] + * description: Enable in-line provisioning of EAP-FAST credentials. + * example: IEEE_8021X_FAST_PROVISIONING="allow-auth allow-unauth" + * ---end--- + */ + obj_properties[PROP_PHASE1_FAST_PROVISIONING] = + g_param_spec_string(NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase1-auth-flags: + * + * Specifies authentication flags to use in "phase 1" outer + * authentication using #NMSetting8021xAuthFlags options. + * The individual TLS versions can be explicitly disabled. If a certain + * TLS disable flag is not set, it is up to the supplicant to allow + * or forbid it. The TLS options map to tls_disable_tlsv1_x settings. + * See the wpa_supplicant documentation for more details. + * + * Since: 1.8 + */ + /* ---ifcfg-rh--- + * property: phase1-auth-flags + * variable: IEEE_8021X_PHASE1_AUTH_FLAGS(+) + * values: space-separated list of authentication flags names + * description: Authentication flags for the supplicant + * example: IEEE_8021X_PHASE1_AUTH_FLAGS="tls-1-0-disable tls-1-1-disable" + * ---end--- + */ + obj_properties[PROP_PHASE1_AUTH_FLAGS] = + g_param_spec_uint(NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, + "", + "", + 0, + G_MAXUINT32, + NM_SETTING_802_1X_AUTH_FLAGS_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-auth: + * + * Specifies the allowed "phase 2" inner authentication method when an EAP + * method that uses an inner TLS tunnel is specified in the #NMSetting8021x:eap + * property. For TTLS this property selects one of the supported non-EAP + * inner methods: "pap", "chap", "mschap", "mschapv2" while + * #NMSetting8021x:phase2-autheap selects an EAP inner method. For PEAP + * this selects an inner EAP method, one of: "gtc", "otp", "md5" and "tls". + * Each "phase 2" inner method requires specific parameters for successful + * authentication; see the wpa_supplicant documentation for more details. + * Both #NMSetting8021x:phase2-auth and #NMSetting8021x:phase2-autheap cannot + * be specified. + **/ + /* ---ifcfg-rh--- + * property: phase2-auth + * variable: IEEE_8021X_INNER_AUTH_METHODS(+) + * values: "PAP", "CHAP", "MSCHAP", "MSCHAPV2", "GTC", "OTP", "MD5" and "TLS" + * description: Inner non-EAP authentication methods for TTLS or the inner EAP + * authentication method for PEAP. IEEE_8021X_INNER_AUTH_METHODS can contain + * values both for 'phase2-auth' and 'phase2-autheap' properties. + * example: IEEE_8021X_INNER_AUTH_METHODS=PAP + * ---end--- + */ + obj_properties[PROP_PHASE2_AUTH] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_AUTH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-autheap: + * + * Specifies the allowed "phase 2" inner EAP-based authentication method + * when TTLS is specified in the #NMSetting8021x:eap property. Recognized + * EAP-based "phase 2" methods are "md5", "mschapv2", "otp", "gtc", and + * "tls". Each "phase 2" inner method requires specific parameters for + * successful authentication; see the wpa_supplicant documentation for + * more details. + **/ + /* ---ifcfg-rh--- + * property: phase2-autheap + * variable: IEEE_8021X_INNER_AUTH_METHODS(+) + * values: "EAP-MD5", "EAP-MSCHAPV2", "EAP-GTC", "EAP-OTP" and "EAP-TLS" + * description: Inner EAP-based authentication methods. Note that + * IEEE_8021X_INNER_AUTH_METHODS is also used for 'phase2-auth' values. + * example: IEEE_8021X_INNER_AUTH_METHODS="MSCHAPV2 EAP-TLS" + * ---end--- + */ + obj_properties[PROP_PHASE2_AUTHEAP] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_AUTHEAP, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-ca-cert: + * + * Contains the "phase 2" CA certificate if used by the EAP method specified + * in the #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap + * properties. + * + * Certificate data is specified using a "scheme"; three are currently + * supported: blob, path and pkcs#11 URL. When using the blob scheme this property + * should be set to the certificate's DER encoded data. When using the path + * scheme, this property should be set to the full UTF-8 encoded path of the + * certificate, prefixed with the string "file://" and ending with a terminating + * NUL byte. + * This property can be unset even if the EAP method supports CA certificates, + * but this allows man-in-the-middle attacks and is NOT recommended. + * + * Note that enabling NMSetting8021x:system-ca-certs will override this + * setting to use the built-in path, if the built-in path is not a directory. + * + * Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_phase2_ca_cert() function instead. + **/ + obj_properties[PROP_PHASE2_CA_CERT] = + g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_CA_CERT, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-ca-cert-password: + * + * The password used to access the "phase2" CA certificate stored in + * #NMSetting8021x:phase2-ca-cert property. Only makes sense if the certificate + * is stored on a PKCS#11 token that requires a login. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * ---end--- + */ + obj_properties[PROP_PHASE2_CA_CERT_PASSWORD] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-ca-cert-password-flags: + * + * Flags indicating how to handle the #NMSetting8021x:phase2-ca-cert-password property. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * ---end--- + */ + obj_properties[PROP_PHASE2_CA_CERT_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-ca-path: + * + * UTF-8 encoded path to a directory containing PEM or DER formatted + * certificates to be added to the verification chain in addition to the + * certificate specified in the #NMSetting8021x:phase2-ca-cert property. + * + * If NMSetting8021x:system-ca-certs is enabled and the built-in CA + * path is an existing directory, then this setting is ignored. + **/ + /* ---ifcfg-rh--- + * property: phase2-ca-path + * variable: IEEE_8021X_PHASE2_CA_PATH(+) + * description: The search path for the certificate. + * ---end--- + */ + obj_properties[PROP_PHASE2_CA_PATH] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_CA_PATH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-subject-match: + * + * Substring to be matched against the subject of the certificate presented + * by the authentication server during the inner "phase 2" + * authentication. When unset, no verification of the authentication server + * certificate's subject is performed. This property provides little security, + * if any, and its use is deprecated in favor of + * NMSetting8021x:phase2-domain-suffix-match. + **/ + /* ---ifcfg-rh--- + * property: phase2-subject-match + * variable: IEEE_8021X_PHASE2_SUBJECT_MATCH(+) + * description: Substring to match subject of server certificate against. + * example: IEEE_8021X_PHASE2_SUBJECT_MATCH="Red Hat" + * ---end--- + */ + obj_properties[PROP_PHASE2_SUBJECT_MATCH] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-altsubject-matches: + * + * List of strings to be matched against the altSubjectName of the + * certificate presented by the authentication server during the inner + * "phase 2" authentication. If the list is empty, no verification of the + * server certificate's altSubjectName is performed. + **/ + /* ---ifcfg-rh--- + * property: phase2-altsubject-matches + * variable: IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES(+) + * ---end--- + */ + obj_properties[PROP_PHASE2_ALTSUBJECT_MATCHES] = + g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-domain-suffix-match: + * + * Constraint for server domain name. If set, this FQDN is used as a suffix + * match requirement for dNSName element(s) of the certificate presented by + * the authentication server during the inner "phase 2" authentication. If + * a matching dNSName is found, this constraint is met. If no dNSName + * values are present, this constraint is matched against SubjectName CN + * using same suffix match comparison. + * Since version 1.24, multiple valid FQDNs can be passed as a ";" delimited + * list. + * + * Since: 1.2 + **/ + /* ---ifcfg-rh--- + * property: phase2-domain-suffix-match + * description: Suffix to match domain of server certificate for phase 2 against. + * variable: IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH(+) + * ---end--- + */ + obj_properties[PROP_PHASE2_DOMAIN_SUFFIX_MATCH] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-domain-match: + * + * Constraint for server domain name. If set, this list of FQDNs is used as + * a match requirement for dNSName element(s) of the certificate presented + * by the authentication server during the inner "phase 2" authentication. + * If a matching dNSName is found, this constraint is met. If no dNSName + * values are present, this constraint is matched against SubjectName CN + * using the same comparison. + * Multiple valid FQDNs can be passed as a ";" delimited list. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: phase2-domain-match + * description: Value to match domain of server certificate for phase 2 against. + * variable: IEEE_8021X_PHASE2_DOMAIN_MATCH(+) + * ---end--- + */ + obj_properties[PROP_PHASE2_DOMAIN_MATCH] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-client-cert: + * + * Contains the "phase 2" client certificate if used by the EAP method + * specified in the #NMSetting8021x:phase2-auth or + * #NMSetting8021x:phase2-autheap properties. + * + * Certificate data is specified using a "scheme"; two are currently + * supported: blob and path. When using the blob scheme (which is backwards + * compatible with NM 0.7.x) this property should be set to the + * certificate's DER encoded data. When using the path scheme, this property + * should be set to the full UTF-8 encoded path of the certificate, prefixed + * with the string "file://" and ending with a terminating NUL byte. This + * property can be unset even if the EAP method supports CA certificates, + * but this allows man-in-the-middle attacks and is NOT recommended. + * + * Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_phase2_client_cert() function instead. + **/ + /* ---ifcfg-rh--- + * property: phase2-client-cert + * variable: IEEE_8021X_INNER_CLIENT_CERT(+) + * description: Client certificate for inner EAP method. + * example: IEEE_8021X_INNER_CLIENT_CERT=/home/joe/mycert.crt + * ---end--- + */ + obj_properties[PROP_PHASE2_CLIENT_CERT] = + g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-client-cert-password: + * + * The password used to access the "phase2" client certificate stored in + * #NMSetting8021x:phase2-client-cert property. Only makes sense if the certificate + * is stored on a PKCS#11 token that requires a login. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * ---end--- + */ + obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-client-cert-password-flags: + * + * Flags indicating how to handle the #NMSetting8021x:phase2-client-cert-password property. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * ---end--- + */ + obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:password: + * + * UTF-8 encoded password used for EAP authentication methods. If both the + * #NMSetting8021x:password property and the #NMSetting8021x:password-raw + * property are specified, #NMSetting8021x:password is preferred. + **/ + /* ---ifcfg-rh--- + * property: password + * variable: IEEE_8021X_PASSWORD(+) + * description: UTF-8 encoded password used for EAP. It can also go to "key-" + * lookaside file, or it can be owned by a secret agent. + * ---end--- + */ + obj_properties[PROP_PASSWORD] = + g_param_spec_string(NM_SETTING_802_1X_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:password-flags: + * + * Flags indicating how to handle the #NMSetting8021x:password property. + **/ + /* ---ifcfg-rh--- + * property: password-flags + * variable: IEEE_8021X_PASSWORD_FLAGS(+) + * format: NMSettingSecretFlags + * description: Password flags for IEEE_8021X_PASSWORD password. + * ---end--- + */ + obj_properties[PROP_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_802_1X_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:password-raw: + * + * Password used for EAP authentication methods, given as a byte array to + * allow passwords in other encodings than UTF-8 to be used. If both the + * #NMSetting8021x:password property and the #NMSetting8021x:password-raw + * property are specified, #NMSetting8021x:password is preferred. + **/ + /* ---ifcfg-rh--- + * property: password-raw + * variable: IEEE_8021X_PASSWORD_RAW(+) + * description: password used for EAP, encoded as a hexadecimal string. It + * can also go to "key-" lookaside file. + * example: IEEE_8021X_PASSWORD_RAW=041c8320083aa4bf + * ---end--- + */ + obj_properties[PROP_PASSWORD_RAW] = + g_param_spec_boxed(NM_SETTING_802_1X_PASSWORD_RAW, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:password-raw-flags: + * + * Flags indicating how to handle the #NMSetting8021x:password-raw property. + **/ + /* ---ifcfg-rh--- + * property: password-raw-flags + * variable: IEEE_8021X_PASSWORD_RAW_FLAGS(+) + * description: The secret flags for password-raw. + * ---end--- + */ + obj_properties[PROP_PASSWORD_RAW_FLAGS] = + g_param_spec_flags(NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:private-key: + * + * Contains the private key when the #NMSetting8021x:eap property is set to + * "tls". + * + * Key data is specified using a "scheme"; two are currently supported: blob + * and path. When using the blob scheme and private keys, this property + * should be set to the key's encrypted PEM encoded data. When using private + * keys with the path scheme, this property should be set to the full UTF-8 + * encoded path of the key, prefixed with the string "file://" and ending + * with a terminating NUL byte. When using PKCS#12 format private + * keys and the blob scheme, this property should be set to the + * PKCS#12 data and the #NMSetting8021x:private-key-password + * property must be set to password used to decrypt the PKCS#12 + * certificate and key. When using PKCS#12 files and the path + * scheme, this property should be set to the full UTF-8 encoded path of the + * key, prefixed with the string "file://" and ending with a terminating + * NUL byte, and as with the blob scheme the "private-key-password" property + * must be set to the password used to decode the PKCS#12 private + * key and certificate. + * + * Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_private_key() function instead. + * + * WARNING: #NMSetting8021x:private-key is not a "secret" property, and thus + * unencrypted private key data using the BLOB scheme may be readable by + * unprivileged users. Private keys should always be encrypted with a + * private key password to prevent unauthorized access to unencrypted + * private key data. + **/ + /* ---ifcfg-rh--- + * property: private-key + * variable: IEEE_8021X_PRIVATE_KEY(+) + * description: Private key for EAP-TLS. + * example: IEEE_8021X_PRIVATE_KEY=/home/joe/mykey.p12 + * ---end--- + */ + obj_properties[PROP_PRIVATE_KEY] = + g_param_spec_boxed(NM_SETTING_802_1X_PRIVATE_KEY, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:private-key-password: + * + * The password used to decrypt the private key specified in the + * #NMSetting8021x:private-key property when the private key either uses the + * path scheme, or if the private key is a PKCS#12 format key. Setting this + * property directly is not generally necessary except when returning + * secrets to NetworkManager; it is generally set automatically when setting + * the private key by the nm_setting_802_1x_set_private_key() function. + **/ + /* ---ifcfg-rh--- + * property: private-key-password + * variable: IEEE_8021X_PRIVATE_KEY_PASSWORD(+) + * description: Password for IEEE_8021X_PRIVATE_KEY. It can also go to "key-" + * lookaside file, or it can be owned by a secret agent. + * ---end--- + */ + obj_properties[PROP_PRIVATE_KEY_PASSWORD] = + g_param_spec_string(NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:private-key-password-flags: + * + * Flags indicating how to handle the #NMSetting8021x:private-key-password + * property. + **/ + /* ---ifcfg-rh--- + * property: private-key-password-flags + * variable: IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS(+) + * format: NMSettingSecretFlags + * description: Password flags for IEEE_8021X_PRIVATE_KEY_PASSWORD password. + * ---end--- + */ + obj_properties[PROP_PRIVATE_KEY_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-private-key: + * + * Contains the "phase 2" inner private key when the + * #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap property is + * set to "tls". + * + * Key data is specified using a "scheme"; two are currently supported: blob + * and path. When using the blob scheme and private keys, this property + * should be set to the key's encrypted PEM encoded data. When using private + * keys with the path scheme, this property should be set to the full UTF-8 + * encoded path of the key, prefixed with the string "file://" and ending + * with a terminating NUL byte. When using PKCS#12 format private + * keys and the blob scheme, this property should be set to the + * PKCS#12 data and the #NMSetting8021x:phase2-private-key-password + * property must be set to password used to decrypt the PKCS#12 + * certificate and key. When using PKCS#12 files and the path + * scheme, this property should be set to the full UTF-8 encoded path of the + * key, prefixed with the string "file://" and ending with a terminating + * NUL byte, and as with the blob scheme the + * #NMSetting8021x:phase2-private-key-password property must be set to the + * password used to decode the PKCS#12 private key and certificate. + * + * Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_phase2_private_key() function instead. + **/ + /* ---ifcfg-rh--- + * property: phase2-private-key + * variable: IEEE_8021X_INNER_PRIVATE_KEY(+) + * description: Private key for inner authentication method for EAP-TLS. + * ---end--- + */ + obj_properties[PROP_PHASE2_PRIVATE_KEY] = + g_param_spec_boxed(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-private-key-password: + * + * The password used to decrypt the "phase 2" private key specified in the + * #NMSetting8021x:phase2-private-key property when the private key either + * uses the path scheme, or is a PKCS#12 format key. Setting this + * property directly is not generally necessary except when returning + * secrets to NetworkManager; it is generally set automatically when setting + * the private key by the nm_setting_802_1x_set_phase2_private_key() + * function. + **/ + /* ---ifcfg-rh--- + * property: phase2-private-key-password + * variable: IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD(+) + * description: Password for IEEE_8021X_INNER_PRIVATE_KEY. It can also go to "key-" + * lookaside file, or it can be owned by a secret agent. + * ---end--- + */ + obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD] = + g_param_spec_string(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:phase2-private-key-password-flags: + * + * Flags indicating how to handle the + * #NMSetting8021x:phase2-private-key-password property. + **/ + /* ---ifcfg-rh--- + * property: phase2-private-key-password-flags + * variable: IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS(+) + * format: NMSettingSecretFlags + * description: Password flags for IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD password. + * ---end--- + */ + obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:pin: + * + * PIN used for EAP authentication methods. + **/ + /* ---ifcfg-rh--- + * property: pin + * variable: IEEE_8021X_PIN(+) + * description: The pin secret used for EAP authentication methods. + * ---end--- + */ + obj_properties[PROP_PIN] = + g_param_spec_string(NM_SETTING_802_1X_PIN, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:pin-flags: + * + * Flags indicating how to handle the #NMSetting8021x:pin property. + **/ + /* ---ifcfg-rh--- + * property: pin-flags + * variable: IEEE_8021X_PIN_FLAGS(+) + * description: The secret flags for the pin property. + * ---end--- + */ + obj_properties[PROP_PIN_FLAGS] = g_param_spec_flags(NM_SETTING_802_1X_PIN_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:system-ca-certs: + * + * When %TRUE, overrides the #NMSetting8021x:ca-path and + * #NMSetting8021x:phase2-ca-path properties using the system CA directory + * specified at configure time with the --system-ca-path switch. The + * certificates in this directory are added to the verification chain in + * addition to any certificates specified by the #NMSetting8021x:ca-cert and + * #NMSetting8021x:phase2-ca-cert properties. If the path provided with + * --system-ca-path is rather a file name (bundle of trusted CA certificates), + * it overrides #NMSetting8021x:ca-cert and #NMSetting8021x:phase2-ca-cert + * properties instead (sets ca_cert/ca_cert2 options for wpa_supplicant). + **/ + /* ---ifcfg-rh--- + * property: system-ca-certs + * variable: IEEE_8021X_SYSTEM_CA_CERTS(+) + * description: a boolean value. + * ---end--- + */ + obj_properties[PROP_SYSTEM_CA_CERTS] = + g_param_spec_boolean(NM_SETTING_802_1X_SYSTEM_CA_CERTS, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:auth-timeout: + * + * A timeout for the authentication. Zero means the global default; if the + * global default is not set, the authentication timeout is 25 seconds. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * property: auth-timeout + * variable: IEEE_8021X_AUTH_TIMEOUT(+) + * default: 0 + * description: Timeout in seconds for the 802.1X authentication. Zero means the global default or 25. + * ---end--- + */ + obj_properties[PROP_AUTH_TIMEOUT] = g_param_spec_int( + NM_SETTING_802_1X_AUTH_TIMEOUT, + "", + "", + 0, + G_MAXINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSetting8021x:optional: + * + * Whether the 802.1X authentication is optional. If %TRUE, the activation + * will continue even after a timeout or an authentication failure. Setting + * the property to %TRUE is currently allowed only for Ethernet connections. + * If set to %FALSE, the activation can continue only after a successful + * authentication. + * + * Since: 1.22 + **/ + /* ---ifcfg-rh--- + * property: optional + * variable: IEEE_8021X_OPTIONAL(+) + * default=no + * description: whether the 802.1X authentication is optional + * ---end--- + */ + obj_properties[PROP_OPTIONAL] = + g_param_spec_boolean(NM_SETTING_802_1X_OPTIONAL, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_802_1X); +} diff --git a/src/libnm-core-impl/nm-setting-adsl.c b/src/libnm-core-impl/nm-setting-adsl.c new file mode 100644 index 0000000000..5b1afab69f --- /dev/null +++ b/src/libnm-core-impl/nm-setting-adsl.c @@ -0,0 +1,439 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2013 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-adsl.h" + +#include "nm-setting-ppp.h" +#include "nm-setting-private.h" +#include "nm-utils.h" +#include "nm-core-enum-types.h" + +/** + * SECTION:nm-setting-adsl + * @short_description: Describes ADSL-based properties + * + * The #NMSettingAdsl object is a #NMSetting subclass that describes + * properties of ADSL connections. + */ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_USERNAME, + PROP_PASSWORD, + PROP_PASSWORD_FLAGS, + PROP_PROTOCOL, + PROP_ENCAPSULATION, + PROP_VPI, + PROP_VCI, ); + +typedef struct { + char * username; + char * password; + NMSettingSecretFlags password_flags; + char * protocol; + char * encapsulation; + guint32 vpi; + guint32 vci; +} NMSettingAdslPrivate; + +G_DEFINE_TYPE(NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING) + +#define NM_SETTING_ADSL_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_ADSL, NMSettingAdslPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_adsl_get_username: + * @setting: the #NMSettingAdsl + * + * Returns: the #NMSettingAdsl:username property of the setting + **/ +const char * +nm_setting_adsl_get_username(NMSettingAdsl *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NULL); + + return NM_SETTING_ADSL_GET_PRIVATE(setting)->username; +} + +/** + * nm_setting_adsl_get_password: + * @setting: the #NMSettingAdsl + * + * Returns: the #NMSettingAdsl:password property of the setting + **/ +const char * +nm_setting_adsl_get_password(NMSettingAdsl *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NULL); + + return NM_SETTING_ADSL_GET_PRIVATE(setting)->password; +} + +/** + * nm_setting_adsl_get_password_flags: + * @setting: the #NMSettingAdsl + * + * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingAdsl:password + **/ +NMSettingSecretFlags +nm_setting_adsl_get_password_flags(NMSettingAdsl *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_ADSL_GET_PRIVATE(setting)->password_flags; +} + +/** + * nm_setting_adsl_get_protocol: + * @setting: the #NMSettingAdsl + * + * Returns: the #NMSettingAdsl:protocol property of the setting + **/ +const char * +nm_setting_adsl_get_protocol(NMSettingAdsl *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NULL); + + return NM_SETTING_ADSL_GET_PRIVATE(setting)->protocol; +} + +/** + * nm_setting_adsl_get_encapsulation: + * @setting: the #NMSettingAdsl + * + * Returns: the #NMSettingAdsl:encapsulation property of the setting + **/ +const char * +nm_setting_adsl_get_encapsulation(NMSettingAdsl *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), NULL); + + return NM_SETTING_ADSL_GET_PRIVATE(setting)->encapsulation; +} + +/** + * nm_setting_adsl_get_vpi: + * @setting: the #NMSettingAdsl + * + * Returns: the #NMSettingAdsl:vpi property of the setting + **/ +guint32 +nm_setting_adsl_get_vpi(NMSettingAdsl *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), 0); + + return NM_SETTING_ADSL_GET_PRIVATE(setting)->vpi; +} + +/** + * nm_setting_adsl_get_vci: + * @setting: the #NMSettingAdsl + * + * Returns: the #NMSettingAdsl:vci property of the setting + **/ +guint32 +nm_setting_adsl_get_vci(NMSettingAdsl *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_ADSL(setting), 0); + + return NM_SETTING_ADSL_GET_PRIVATE(setting)->vci; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(setting); + + if (!priv->username) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME); + return FALSE; + } + if (!priv->username[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME); + return FALSE; + } + + if (!NM_IN_STRSET(priv->protocol, + NM_SETTING_ADSL_PROTOCOL_PPPOA, + NM_SETTING_ADSL_PROTOCOL_PPPOE, + NM_SETTING_ADSL_PROTOCOL_IPOATM)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + priv->protocol ?: "(null)"); + g_prefix_error(error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_PROTOCOL); + return FALSE; + } + + if (!NM_IN_STRSET(priv->encapsulation, + NULL, + NM_SETTING_ADSL_ENCAPSULATION_VCMUX, + NM_SETTING_ADSL_ENCAPSULATION_LLC)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + priv->encapsulation); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_ADSL_SETTING_NAME, + NM_SETTING_ADSL_ENCAPSULATION); + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) +{ + return _nm_setting_verify_secret_string(NM_SETTING_ADSL_GET_PRIVATE(setting)->password, + NM_SETTING_ADSL_SETTING_NAME, + NM_SETTING_ADSL_PASSWORD, + error); +} + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(setting); + GPtrArray * secrets = NULL; + + if (priv->password && *priv->password) + return NULL; + + if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { + secrets = g_ptr_array_sized_new(1); + g_ptr_array_add(secrets, NM_SETTING_ADSL_PASSWORD); + } + + return secrets; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingAdsl *setting = NM_SETTING_ADSL(object); + + switch (prop_id) { + case PROP_USERNAME: + g_value_set_string(value, nm_setting_adsl_get_username(setting)); + break; + case PROP_PASSWORD: + g_value_set_string(value, nm_setting_adsl_get_password(setting)); + break; + case PROP_PASSWORD_FLAGS: + g_value_set_flags(value, nm_setting_adsl_get_password_flags(setting)); + break; + case PROP_PROTOCOL: + g_value_set_string(value, nm_setting_adsl_get_protocol(setting)); + break; + case PROP_ENCAPSULATION: + g_value_set_string(value, nm_setting_adsl_get_encapsulation(setting)); + break; + case PROP_VPI: + g_value_set_uint(value, nm_setting_adsl_get_vpi(setting)); + break; + case PROP_VCI: + g_value_set_uint(value, nm_setting_adsl_get_vci(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(object); + const char * str; + + switch (prop_id) { + case PROP_USERNAME: + g_free(priv->username); + priv->username = g_value_dup_string(value); + break; + case PROP_PASSWORD: + g_free(priv->password); + priv->password = g_value_dup_string(value); + break; + case PROP_PASSWORD_FLAGS: + priv->password_flags = g_value_get_flags(value); + break; + case PROP_PROTOCOL: + g_free(priv->protocol); + str = g_value_get_string(value); + priv->protocol = str ? g_ascii_strdown(str, -1) : NULL; + break; + case PROP_ENCAPSULATION: + g_free(priv->encapsulation); + str = g_value_get_string(value); + priv->encapsulation = str ? g_ascii_strdown(str, -1) : NULL; + break; + case PROP_VPI: + priv->vpi = g_value_get_uint(value); + break; + case PROP_VCI: + priv->vci = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_adsl_init(NMSettingAdsl *setting) +{} + +/** + * nm_setting_adsl_new: + * + * Creates a new #NMSettingAdsl object with default values. + * + * Returns: the new empty #NMSettingAdsl object + **/ +NMSetting * +nm_setting_adsl_new(void) +{ + return g_object_new(NM_TYPE_SETTING_ADSL, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(object); + + g_free(priv->username); + g_free(priv->password); + g_free(priv->protocol); + g_free(priv->encapsulation); + + G_OBJECT_CLASS(nm_setting_adsl_parent_class)->finalize(object); +} + +static void +nm_setting_adsl_class_init(NMSettingAdslClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingAdslPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; + + /** + * NMSettingAdsl:username: + * + * Username used to authenticate with the ADSL service. + **/ + obj_properties[PROP_USERNAME] = g_param_spec_string(NM_SETTING_ADSL_USERNAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingAdsl:password: + * + * Password used to authenticate with the ADSL service. + **/ + obj_properties[PROP_PASSWORD] = + g_param_spec_string(NM_SETTING_ADSL_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingAdsl:password-flags: + * + * Flags indicating how to handle the #NMSettingAdsl:password property. + **/ + obj_properties[PROP_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_ADSL_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingAdsl:protocol: + * + * ADSL connection protocol. Can be "pppoa", "pppoe" or "ipoatm". + **/ + obj_properties[PROP_PROTOCOL] = g_param_spec_string(NM_SETTING_ADSL_PROTOCOL, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingAdsl:encapsulation: + * + * Encapsulation of ADSL connection. Can be "vcmux" or "llc". + **/ + obj_properties[PROP_ENCAPSULATION] = + g_param_spec_string(NM_SETTING_ADSL_ENCAPSULATION, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingAdsl:vpi: + * + * VPI of ADSL connection + **/ + obj_properties[PROP_VPI] = g_param_spec_uint(NM_SETTING_ADSL_VPI, + "", + "", + 0, + 65536, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingAdsl:vci: + * + * VCI of ADSL connection + **/ + obj_properties[PROP_VCI] = g_param_spec_uint(NM_SETTING_ADSL_VCI, + "", + "", + 0, + 65536, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_ADSL); +} diff --git a/src/libnm-core-impl/nm-setting-bluetooth.c b/src/libnm-core-impl/nm-setting-bluetooth.c new file mode 100644 index 0000000000..18d08487e1 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-bluetooth.c @@ -0,0 +1,332 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-bluetooth.h" + +#include + +#include "nm-connection-private.h" +#include "nm-setting-cdma.h" +#include "nm-setting-gsm.h" +#include "nm-setting-private.h" +#include "nm-utils.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-bluetooth + * @short_description: Describes Bluetooth connection properties + * + * The #NMSettingBluetooth object is a #NMSetting subclass that describes + * properties necessary for connection to devices that provide network + * connections via the Bluetooth Dial-Up Networking (DUN) and Network Access + * Point (NAP) profiles. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_BDADDR, PROP_TYPE, ); + +typedef struct { + char *bdaddr; + char *type; +} NMSettingBluetoothPrivate; + +G_DEFINE_TYPE(NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING) + +#define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_bluetooth_get_connection_type: + * @setting: the #NMSettingBluetooth + * + * Returns the connection method for communicating with the remote device (i.e. + * either DUN to a DUN-capable device or PANU to a NAP-capable device). + * + * Returns: the type, either %NM_SETTING_BLUETOOTH_TYPE_PANU, + * %NM_SETTING_BLUETOOTH_TYPE_NAP or %NM_SETTING_BLUETOOTH_TYPE_DUN + **/ +const char * +nm_setting_bluetooth_get_connection_type(NMSettingBluetooth *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BLUETOOTH(setting), NULL); + + return NM_SETTING_BLUETOOTH_GET_PRIVATE(setting)->type; +} + +/** + * nm_setting_bluetooth_get_bdaddr: + * @setting: the #NMSettingBluetooth + * + * Gets the Bluetooth address of the remote device which this setting + * describes a connection to. + * + * Returns: the Bluetooth address + **/ +const char * +nm_setting_bluetooth_get_bdaddr(NMSettingBluetooth *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BLUETOOTH(setting), NULL); + + return NM_SETTING_BLUETOOTH_GET_PRIVATE(setting)->bdaddr; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE(setting); + const char * type; + gboolean missing_nap_bridge = FALSE; + + if (priv->bdaddr && !nm_utils_hwaddr_valid(priv->bdaddr, ETH_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BLUETOOTH_SETTING_NAME, + NM_SETTING_BLUETOOTH_BDADDR); + return FALSE; + } + + type = priv->type; + if (!type) { + if (connection) { + /* We may infer the type from the (non-)existence of gsm/cdma/bridge settings. */ + type = _nm_connection_detect_bluetooth_type(connection); + } + if (!type) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BLUETOOTH_SETTING_NAME, + NM_SETTING_BLUETOOTH_TYPE); + return FALSE; + } + } + + if (!NM_IN_STRSET(type, + NM_SETTING_BLUETOOTH_TYPE_DUN, + NM_SETTING_BLUETOOTH_TYPE_NAP, + NM_SETTING_BLUETOOTH_TYPE_PANU)) { + nm_assert(priv->type == type); + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BLUETOOTH_SETTING_NAME, + NM_SETTING_BLUETOOTH_TYPE); + return FALSE; + } + + /* Make sure the corresponding 'type' setting is present */ + if (connection && nm_streq(type, NM_SETTING_BLUETOOTH_TYPE_DUN)) { + gboolean gsm = FALSE, cdma = FALSE; + + gsm = !!nm_connection_get_setting_gsm(connection); + cdma = !!nm_connection_get_setting_cdma(connection); + + if (!gsm && !cdma) { + /* We can't return MISSING_SETTING here, because we don't know + * whether to prefix the message with NM_SETTING_GSM_SETTING_NAME or + * NM_SETTING_CDMA_SETTING_NAME. + */ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("'%s' connection requires '%s' or '%s' setting"), + NM_SETTING_BLUETOOTH_TYPE_DUN, + NM_SETTING_GSM_SETTING_NAME, + NM_SETTING_CDMA_SETTING_NAME); + g_prefix_error(error, "%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME); + return FALSE; + } + } + /* PANU doesn't need a 'type' setting since no further configuration + * is required at the interface level. + */ + + /* NAP mode needs a bridge setting, and a bridge needs a name. */ + if (nm_streq(type, NM_SETTING_BLUETOOTH_TYPE_NAP)) { + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + if (connection && !nm_connection_get_setting_bridge(connection)) + missing_nap_bridge = TRUE; + } else { + if (!priv->bdaddr) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BLUETOOTH_SETTING_NAME, + NM_SETTING_BLUETOOTH_BDADDR); + return FALSE; + } + } + + /* errors form here are normalizable. */ + + if (!priv->type) { + /* as determined above, we can detect the bluetooth type. */ + nm_assert(!missing_nap_bridge); + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BLUETOOTH_SETTING_NAME, + NM_SETTING_BLUETOOTH_TYPE); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + if (missing_nap_bridge) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("'%s' connection requires '%s' setting"), + NM_SETTING_BLUETOOTH_TYPE_NAP, + NM_SETTING_BRIDGE_SETTING_NAME); + g_prefix_error(error, "%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingBluetooth *setting = NM_SETTING_BLUETOOTH(object); + + switch (prop_id) { + case PROP_BDADDR: + g_value_set_string(value, nm_setting_bluetooth_get_bdaddr(setting)); + break; + case PROP_TYPE: + g_value_set_string(value, nm_setting_bluetooth_get_connection_type(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_BDADDR: + g_free(priv->bdaddr); + priv->bdaddr = g_value_dup_string(value); + break; + case PROP_TYPE: + g_free(priv->type); + priv->type = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_bluetooth_init(NMSettingBluetooth *setting) +{} + +/** + * nm_setting_bluetooth_new: + * + * Creates a new #NMSettingBluetooth object with default values. + * + * Returns: (transfer full): the new empty #NMSettingBluetooth object + **/ +NMSetting * +nm_setting_bluetooth_new(void) +{ + return g_object_new(NM_TYPE_SETTING_BLUETOOTH, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE(object); + + g_free(priv->bdaddr); + g_free(priv->type); + + G_OBJECT_CLASS(nm_setting_bluetooth_parent_class)->finalize(object); +} + +static void +nm_setting_bluetooth_class_init(NMSettingBluetoothClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingBluetoothPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingBluetooth:bdaddr: + * + * The Bluetooth address of the device. + **/ + obj_properties[PROP_BDADDR] = g_param_spec_string( + NM_SETTING_BLUETOOTH_BDADDR, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_BDADDR], + &nm_sett_info_propert_type_mac_address); + + /** + * NMSettingBluetooth:type: + * + * Either "dun" for Dial-Up Networking connections or "panu" for Personal + * Area Networking connections to devices supporting the NAP profile. + **/ + obj_properties[PROP_TYPE] = g_param_spec_string(NM_SETTING_BLUETOOTH_TYPE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_BLUETOOTH, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-bond.c b/src/libnm-core-impl/nm-setting-bond.c new file mode 100644 index 0000000000..69bf49a4e4 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-bond.c @@ -0,0 +1,1185 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2013 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-bond.h" + +#include +#include +#include +#include + +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-connection-private.h" +#include "nm-setting-infiniband.h" +#include "libnm-core-intern/nm-core-internal.h" + +/*****************************************************************************/ + +/** + * SECTION:nm-setting-bond + * @short_description: Describes connection properties for bonds + * + * The #NMSettingBond object is a #NMSetting subclass that describes properties + * necessary for bond connections. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingBond, PROP_OPTIONS, ); + +typedef struct { + GHashTable * options; + NMUtilsNamedValue *options_idx_cache; +} NMSettingBondPrivate; + +G_DEFINE_TYPE(NMSettingBond, nm_setting_bond, NM_TYPE_SETTING) + +#define NM_SETTING_BOND_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_BOND, NMSettingBondPrivate)) + +/*****************************************************************************/ + +static const char *const valid_options_lst[] = { + /* mode must be the first element. nm-device-bond.c relies on that. */ + NM_SETTING_BOND_OPTION_MODE, + NM_SETTING_BOND_OPTION_MIIMON, + NM_SETTING_BOND_OPTION_DOWNDELAY, + NM_SETTING_BOND_OPTION_UPDELAY, + NM_SETTING_BOND_OPTION_ARP_INTERVAL, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + NM_SETTING_BOND_OPTION_ARP_VALIDATE, + NM_SETTING_BOND_OPTION_PRIMARY, + NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, + NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, + NM_SETTING_BOND_OPTION_USE_CARRIER, + NM_SETTING_BOND_OPTION_AD_SELECT, + NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, + NM_SETTING_BOND_OPTION_RESEND_IGMP, + NM_SETTING_BOND_OPTION_LACP_RATE, + NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, + NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, + NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, + NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, + NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, + NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, + NM_SETTING_BOND_OPTION_MIN_LINKS, + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, + NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, + NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, + NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, + NM_SETTING_BOND_OPTION_LP_INTERVAL, + NULL, +}; + +typedef struct { + const char * val; + NMBondOptionType opt_type; + guint min; + guint max; + const char *const *list; +} OptionMeta; + +static gboolean +_nm_assert_bond_meta(const OptionMeta *option_meta) +{ + nm_assert(option_meta); + + switch (option_meta->opt_type) { + case NM_BOND_OPTION_TYPE_BOTH: + nm_assert(option_meta->val); + nm_assert(option_meta->list); + nm_assert(option_meta->list[0]); + nm_assert(option_meta->min == 0); + nm_assert(option_meta->max == NM_PTRARRAY_LEN(option_meta->list) - 1); + nm_assert(g_strv_contains(option_meta->list, option_meta->val)); + return TRUE; + case NM_BOND_OPTION_TYPE_INT: + nm_assert(option_meta->val); + nm_assert(!option_meta->list); + nm_assert(option_meta->min < option_meta->max); + nm_assert(NM_STRCHAR_ALL(option_meta->val, ch, g_ascii_isdigit(ch))); + nm_assert(NM_STRCHAR_ALL(option_meta->val, ch, g_ascii_isdigit(ch))); + nm_assert(({ + _nm_utils_ascii_str_to_uint64(option_meta->val, + 10, + option_meta->min, + option_meta->max, + 0); + errno == 0; + })); + return TRUE; + case NM_BOND_OPTION_TYPE_IP: + nm_assert(option_meta->val); + /* fall-through */ + case NM_BOND_OPTION_TYPE_IFNAME: + case NM_BOND_OPTION_TYPE_MAC: + nm_assert(!option_meta->list); + nm_assert(option_meta->min == 0); + nm_assert(option_meta->max == 0); + return TRUE; + } + + nm_assert_not_reached(); + return FALSE; +} + +static char const *const _option_default_strv_ad_select[] = + NM_MAKE_STRV("stable", "bandwidth", "count"); +static char const *const _option_default_strv_arp_all_targets[] = NM_MAKE_STRV("any", "all"); +static char const *const _option_default_strv_arp_validate[] = + NM_MAKE_STRV("none", "active", "backup", "all", "filter", "filter_active", "filter_backup"); +static char const *const _option_default_strv_fail_over_mac[] = + NM_MAKE_STRV("none", "active", "follow"); +static char const *const _option_default_strv_lacp_rate[] = NM_MAKE_STRV("slow", "fast"); +static char const *const _option_default_strv_mode[] = NM_MAKE_STRV("balance-rr", + "active-backup", + "balance-xor", + "broadcast", + "802.3ad", + "balance-tlb", + "balance-alb"); +static char const *const _option_default_strv_primary_reselect[] = + NM_MAKE_STRV("always", "better", "failure"); +static char const *const _option_default_strv_xmit_hash_policy[] = + NM_MAKE_STRV("layer2", "layer3+4", "layer2+3", "encap2+3", "encap3+4", "vlan+srcmac"); + +static NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE( + _get_option_meta, + OptionMeta, + { + G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(LIST) == G_N_ELEMENTS(valid_options_lst) - 1); + + if (NM_MORE_ASSERT_ONCE(5)) { + int i; + + nm_assert(G_N_ELEMENTS(LIST) == NM_PTRARRAY_LEN(valid_options_lst)); + for (i = 0; i < G_N_ELEMENTS(LIST); i++) + _nm_assert_bond_meta(&LIST[i].value); + nm_assert(nm_streq(valid_options_lst[0], NM_SETTING_BOND_OPTION_MODE)); + } + }, + { return NULL; }, + {NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, {NULL, NM_BOND_OPTION_TYPE_IFNAME}}, + {NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, {"65535", NM_BOND_OPTION_TYPE_INT, 1, 65535}}, + {NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, {NULL, NM_BOND_OPTION_TYPE_MAC}}, + {NM_SETTING_BOND_OPTION_AD_SELECT, + {"stable", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_ad_select}}, + {NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, {"0", NM_BOND_OPTION_TYPE_INT, 0, 1023}}, + {NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, {"0", NM_BOND_OPTION_TYPE_INT, 0, 1}}, + {NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, + {"any", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_arp_all_targets}}, + {NM_SETTING_BOND_OPTION_ARP_INTERVAL, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, + {NM_SETTING_BOND_OPTION_ARP_IP_TARGET, {"", NM_BOND_OPTION_TYPE_IP}}, + {NM_SETTING_BOND_OPTION_ARP_VALIDATE, + {"none", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_arp_validate}}, + {NM_SETTING_BOND_OPTION_DOWNDELAY, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, + {NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, + {"none", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_fail_over_mac}}, + {NM_SETTING_BOND_OPTION_LACP_RATE, + {"slow", NM_BOND_OPTION_TYPE_BOTH, 0, 1, _option_default_strv_lacp_rate}}, + {NM_SETTING_BOND_OPTION_LP_INTERVAL, {"1", NM_BOND_OPTION_TYPE_INT, 1, G_MAXINT}}, + {NM_SETTING_BOND_OPTION_MIIMON, {"100", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, + {NM_SETTING_BOND_OPTION_MIN_LINKS, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, + {NM_SETTING_BOND_OPTION_MODE, + {"balance-rr", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_mode}}, + {NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, {"1", NM_BOND_OPTION_TYPE_INT, 0, 255}}, + {NM_SETTING_BOND_OPTION_NUM_UNSOL_NA, {"1", NM_BOND_OPTION_TYPE_INT, 0, 255}}, + {NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, {"1", NM_BOND_OPTION_TYPE_INT, 0, 65535}}, + {NM_SETTING_BOND_OPTION_PRIMARY, {"", NM_BOND_OPTION_TYPE_IFNAME}}, + {NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, + {"always", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_primary_reselect}}, + {NM_SETTING_BOND_OPTION_RESEND_IGMP, {"1", NM_BOND_OPTION_TYPE_INT, 0, 255}}, + {NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, {"1", NM_BOND_OPTION_TYPE_INT, 0, 1}}, + {NM_SETTING_BOND_OPTION_UPDELAY, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, + {NM_SETTING_BOND_OPTION_USE_CARRIER, {"1", NM_BOND_OPTION_TYPE_INT, 0, 1}}, + {NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, + {"layer2", NM_BOND_OPTION_TYPE_BOTH, 0, 5, _option_default_strv_xmit_hash_policy}}, ); + +/*****************************************************************************/ + +#define BIT(x) (((guint32) 1) << (x)) + +static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( + _bond_option_unsupp_mode, + guint32, + { ; }, + { return 0; }, + {NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, + ~(BIT(NM_BOND_MODE_ACTIVEBACKUP) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, + {NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, ~(BIT(NM_BOND_MODE_8023AD))}, + {NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, ~(BIT(NM_BOND_MODE_8023AD))}, + {NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, ~(BIT(NM_BOND_MODE_8023AD))}, + {NM_SETTING_BOND_OPTION_ARP_INTERVAL, + (BIT(NM_BOND_MODE_8023AD) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, + {NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + (BIT(NM_BOND_MODE_8023AD) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, + {NM_SETTING_BOND_OPTION_ARP_VALIDATE, + (BIT(NM_BOND_MODE_8023AD) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, + {NM_SETTING_BOND_OPTION_LACP_RATE, ~(BIT(NM_BOND_MODE_8023AD))}, + {NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, ~(BIT(NM_BOND_MODE_ROUNDROBIN))}, + {NM_SETTING_BOND_OPTION_PRIMARY, + ~(BIT(NM_BOND_MODE_ACTIVEBACKUP) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, + {NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, ~(BIT(NM_BOND_MODE_TLB))}, ); + +gboolean +_nm_setting_bond_option_supported(const char *option, NMBondMode mode) +{ + nm_assert(option); + nm_assert(mode != NM_BOND_MODE_UNKNOWN); + nm_assert(_NM_INT_NOT_NEGATIVE(mode) && mode < 32); + + return !NM_FLAGS_ANY(_bond_option_unsupp_mode(option), BIT(mode)); +} + +static const char * +_bond_get_option(NMSettingBond *self, const char *option) +{ + g_return_val_if_fail(NM_IS_SETTING_BOND(self), NULL); + g_return_val_if_fail(option, NULL); + + return g_hash_table_lookup(NM_SETTING_BOND_GET_PRIVATE(self)->options, option); +} + +static const char * +_bond_get_option_default(NMSettingBond *self, const char *option) +{ + const OptionMeta *option_meta; + + g_return_val_if_fail(NM_IS_SETTING_BOND(self), NULL); + + option_meta = _get_option_meta(option); + + g_return_val_if_fail(option_meta, NULL); + + return option_meta->val; +} + +static const char * +_bond_get_option_or_default(NMSettingBond *self, const char *option) +{ + return _bond_get_option(self, option) ?: _bond_get_option_default(self, option); +} + +static const char * +_bond_get_option_normalized(NMSettingBond *self, const char *option, gboolean get_default_only) +{ + const char *mode_str; + NMBondMode mode; + const char *value = NULL; + + g_return_val_if_fail(NM_IS_SETTING_BOND(self), NULL); + g_return_val_if_fail(option, NULL); + + mode_str = _bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_MODE); + mode = _nm_setting_bond_mode_from_string(mode_str); + + if (mode == NM_BOND_MODE_UNKNOWN) { + /* the mode is unknown, consequently, there is no normalized/default + * value either. */ + return NULL; + } + + if (!_nm_setting_bond_option_supported(option, mode)) + return NULL; + + /* Apply custom NetworkManager policies here */ + if (!get_default_only) { + if (NM_IN_STRSET(option, + NM_SETTING_BOND_OPTION_ARP_INTERVAL, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) { + int miimon; + + /* if arp_interval is explicitly set and miimon is not, then disable miimon + * (and related updelay and downdelay) as recommended by the kernel docs */ + miimon = + _nm_utils_ascii_str_to_int64(_bond_get_option(self, NM_SETTING_BOND_OPTION_MIIMON), + 10, + 0, + G_MAXINT, + 0); + if (miimon != 0) { + /* miimon is enabled. arp_interval values are unset. */ + if (nm_streq(option, NM_SETTING_BOND_OPTION_ARP_INTERVAL)) + return "0"; + return ""; + } + value = _bond_get_option(self, option); + } else if (NM_IN_STRSET(option, + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, + NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)) { + /* just get one of the 2, at kernel level they're the same bond option */ + value = _bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); + if (!value) + value = _bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); + } else if (NM_IN_STRSET(option, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE)) { + /* "active_slave" is deprecated, and an alias for "primary". The property + * itself always normalizes to %NULL. */ + value = NULL; + } else if (NM_IN_STRSET(option, NM_SETTING_BOND_OPTION_PRIMARY)) { + /* "active_slave" is deprecated, and an alias for "primary". */ + value = _bond_get_option(self, NM_SETTING_BOND_OPTION_PRIMARY); + if (!value) + value = _bond_get_option(self, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE); + } else + value = _bond_get_option(self, option); + + if (value) + return value; + } + + /* Apply rules that change the default value of an option */ + if (nm_streq(option, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) { + /* The default value depends on the current mode */ + if (mode == NM_BOND_MODE_8023AD) + return "00:00:00:00:00:00"; + return ""; + } + + return _bond_get_option_or_default(self, option); +} + +const char * +nm_setting_bond_get_option_or_default(NMSettingBond *self, const char *option) +{ + g_return_val_if_fail(NM_IS_SETTING_BOND(self), NULL); + g_return_val_if_fail(option, NULL); + + return _bond_get_option_normalized(self, option, FALSE); +} + +static int +_atoi(const char *value) +{ + int v; + + v = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXINT, -1); + nm_assert(v >= 0); + return v; +}; + +/** + * nm_setting_bond_get_num_options: + * @setting: the #NMSettingBond + * + * Returns the number of options that should be set for this bond when it + * is activated. This can be used to retrieve each option individually + * using nm_setting_bond_get_option(). + * + * Returns: the number of bonding options + **/ +guint32 +nm_setting_bond_get_num_options(NMSettingBond *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BOND(setting), 0); + + return g_hash_table_size(NM_SETTING_BOND_GET_PRIVATE(setting)->options); +} + +static int +_get_option_sort(gconstpointer p_a, gconstpointer p_b, gpointer _unused) +{ + const char *a = *((const char *const *) p_a); + const char *b = *((const char *const *) p_b); + + NM_CMP_DIRECT(nm_streq(b, NM_SETTING_BOND_OPTION_MODE), + nm_streq(a, NM_SETTING_BOND_OPTION_MODE)); + NM_CMP_DIRECT_STRCMP(a, b); + nm_assert_not_reached(); + return 0; +} + +static void +_ensure_options_idx_cache(NMSettingBondPrivate *priv) +{ + if (!G_UNLIKELY(priv->options_idx_cache)) + priv->options_idx_cache = nm_utils_named_values_from_strdict_full(priv->options, + NULL, + _get_option_sort, + NULL, + NULL, + 0, + NULL); +} + +/** + * nm_setting_bond_get_option: + * @setting: the #NMSettingBond + * @idx: index of the desired option, from 0 to + * nm_setting_bond_get_num_options() - 1 + * @out_name: (out) (transfer none): on return, the name of the bonding option; + * this value is owned by the setting and should not be modified + * @out_value: (out) (transfer none): on return, the value of the name of the + * bonding option; this value is owned by the setting and should not be + * modified + * + * Given an index, return the value of the bonding option at that index. Indexes + * are *not* guaranteed to be static across modifications to options done by + * nm_setting_bond_add_option() and nm_setting_bond_remove_option(), + * and should not be used to refer to options except for short periods of time + * such as during option iteration. + * + * Returns: %TRUE on success if the index was valid and an option was found, + * %FALSE if the index was invalid (ie, greater than the number of options + * currently held by the setting) + **/ +gboolean +nm_setting_bond_get_option(NMSettingBond *setting, + guint32 idx, + const char ** out_name, + const char ** out_value) +{ + NMSettingBondPrivate *priv; + guint len; + + g_return_val_if_fail(NM_IS_SETTING_BOND(setting), FALSE); + + priv = NM_SETTING_BOND_GET_PRIVATE(setting); + + len = g_hash_table_size(priv->options); + if (idx >= len) + return FALSE; + + _ensure_options_idx_cache(priv); + + NM_SET_OUT(out_name, priv->options_idx_cache[idx].name); + NM_SET_OUT(out_value, priv->options_idx_cache[idx].value_str); + return TRUE; +} + +static gboolean +validate_int(const char *name, const char *value, const OptionMeta *option_meta) +{ + guint64 num; + + if (!NM_STRCHAR_ALL(value, ch, g_ascii_isdigit(ch))) + return FALSE; + + num = _nm_utils_ascii_str_to_uint64(value, 10, option_meta->min, option_meta->max, G_MAXUINT64); + if (num == G_MAXUINT64 && errno != 0) + return FALSE; + + return TRUE; +} + +static gboolean +validate_list(const char *name, const char *value, const OptionMeta *option_meta) +{ + int i; + + nm_assert(option_meta->list); + + for (i = 0; option_meta->list[i]; i++) { + if (nm_streq(option_meta->list[i], value)) + return TRUE; + } + return FALSE; +} + +static gboolean +validate_ip(const char *name, const char *value, GError **error) +{ + gs_free const char **addrs = NULL; + gsize i; + + addrs = nm_utils_bond_option_arp_ip_targets_split(value); + if (!addrs) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option is empty"), + name); + return FALSE; + } + for (i = 0; addrs[i]; i++) { + if (!nm_utils_parse_inaddr_bin(AF_INET, addrs[i], NULL, NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IPv4 address for '%s' option"), + addrs[i], + name); + return FALSE; + } + } + return TRUE; +} + +static gboolean +validate_ifname(const char *name, const char *value) +{ + return nm_utils_ifname_valid_kernel(value, NULL); +} + +gboolean +_nm_setting_bond_validate_option(const char *name, const char *value, GError **error) +{ + const OptionMeta *option_meta; + gboolean success; + + option_meta = _get_option_meta(name); + if (!option_meta) { + if (!name) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("missing option name")); + } else { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid option '%s'"), + name); + } + return FALSE; + } + + if (!value) + return TRUE; + + switch (option_meta->opt_type) { + case NM_BOND_OPTION_TYPE_INT: + success = validate_int(name, value, option_meta); + goto handle_error; + case NM_BOND_OPTION_TYPE_BOTH: + success = + (validate_int(name, value, option_meta) || validate_list(name, value, option_meta)); + goto handle_error; + case NM_BOND_OPTION_TYPE_IP: + nm_assert(nm_streq0(name, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)); + return validate_ip(name, value, error); + case NM_BOND_OPTION_TYPE_MAC: + success = nm_utils_hwaddr_valid(value, ETH_ALEN); + goto handle_error; + case NM_BOND_OPTION_TYPE_IFNAME: + success = validate_ifname(name, value); + goto handle_error; + } + + nm_assert_not_reached(); + success = FALSE; + +handle_error: + if (!success) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid value '%s' for option '%s'"), + value, + name); + } + return success; +} + +/** + * nm_setting_bond_validate_option: + * @name: the name of the option to validate + * @value (allow-none): the value of the option to validate. + * + * Checks whether @name is a valid bond option and @value is a valid value for + * the @name. If @value is %NULL, the function only validates the option name. + * + * Returns: %TRUE, if the @value is valid for the given name. + * If the @name is not a valid option, %FALSE will be returned. + **/ +gboolean +nm_setting_bond_validate_option(const char *name, const char *value) +{ + return _nm_setting_bond_validate_option(name, value, NULL); +} + +/** + * nm_setting_bond_get_option_by_name: + * @setting: the #NMSettingBond + * @name: the option name for which to retrieve the value + * + * Returns the value associated with the bonding option specified by + * @name, if it exists. + * + * Returns: the value, or %NULL if the key/value pair was never added to the + * setting; the value is owned by the setting and must not be modified + **/ +const char * +nm_setting_bond_get_option_by_name(NMSettingBond *setting, const char *name) +{ + g_return_val_if_fail(NM_IS_SETTING_BOND(setting), NULL); + + return _bond_get_option(setting, name); +} + +/** + * nm_setting_bond_add_option: + * @setting: the #NMSettingBond + * @name: name for the option + * @value: value for the option + * + * Add an option to the table. Adding a new name replaces any existing name/value pair + * that may already exist. + * + * Returns: returns %FALSE if either @name or @value is %NULL, in that case + * the option is not set. Otherwise, the function does not fail and does not validate + * the arguments. All validation happens via nm_connection_verify() or do basic validation + * yourself with nm_setting_bond_validate_option(). + * + * Note: Before 1.30, libnm would perform basic validation of the name and the value + * via nm_setting_bond_validate_option() and reject the request by returning FALSE. + * Since 1.30, libnm no longer rejects any values as the setter is not supposed + * to perform validation. + **/ +gboolean +nm_setting_bond_add_option(NMSettingBond *setting, const char *name, const char *value) +{ + NMSettingBondPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_BOND(setting), FALSE); + + if (!name) + return FALSE; + if (!value) + return FALSE; + + priv = NM_SETTING_BOND_GET_PRIVATE(setting); + + nm_clear_g_free(&priv->options_idx_cache); + g_hash_table_insert(priv->options, g_strdup(name), g_strdup(value)); + _notify(setting, PROP_OPTIONS); + return TRUE; +} + +/** + * nm_setting_bond_remove_option: + * @setting: the #NMSettingBond + * @name: name of the option to remove + * + * Remove the bonding option referenced by @name from the internal option + * list. + * + * Returns: %TRUE if the option was found and removed from the internal option + * list, %FALSE if it was not. + **/ +gboolean +nm_setting_bond_remove_option(NMSettingBond *setting, const char *name) +{ + NMSettingBondPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_BOND(setting), FALSE); + + priv = NM_SETTING_BOND_GET_PRIVATE(setting); + + if (!g_hash_table_remove(priv->options, name)) + return FALSE; + + nm_clear_g_free(&priv->options_idx_cache); + _notify(setting, PROP_OPTIONS); + return TRUE; +} + +/** + * nm_setting_bond_get_valid_options: + * @setting: (allow-none): the #NMSettingBond + * + * Returns a list of valid bond options. + * + * The @setting argument is unused and may be passed as %NULL. + * + * Returns: (transfer none): a %NULL-terminated array of strings of valid bond options. + **/ +const char ** +nm_setting_bond_get_valid_options(NMSettingBond *setting) +{ + return (const char **) valid_options_lst; +} + +/** + * nm_setting_bond_get_option_default: + * @setting: the #NMSettingBond + * @name: the name of the option + * + * Returns: the value of the bond option if not overridden by an entry in + * the #NMSettingBond:options property. + **/ +const char * +nm_setting_bond_get_option_default(NMSettingBond *setting, const char *name) +{ + g_return_val_if_fail(NM_IS_SETTING_BOND(setting), NULL); + + if (!name) + return NULL; + + return _bond_get_option_normalized(setting, name, TRUE); +} + +/** + * nm_setting_bond_get_option_normalized: + * @setting: the #NMSettingBond + * @name: the name of the option + * + * Since: 1.24 + * + * Returns: the value of the bond option after normalization, which is what NetworkManager + * will actually apply when activating the connection. %NULL if the option won't be applied + * to the connection. + **/ +const char * +nm_setting_bond_get_option_normalized(NMSettingBond *setting, const char *name) +{ + g_return_val_if_fail(NM_IS_SETTING_BOND(setting), NULL); + g_return_val_if_fail(name, NULL); + + return _bond_get_option_normalized(setting, name, FALSE); +} + +/** + * nm_setting_bond_get_option_type: + * @setting: the #NMSettingBond + * @name: the name of the option + * + * Returns: the type of the bond option. + **/ +NMBondOptionType +_nm_setting_bond_get_option_type(NMSettingBond *setting, const char *name) +{ + const OptionMeta *option_meta; + + g_return_val_if_fail(NM_IS_SETTING_BOND(setting), NM_BOND_OPTION_TYPE_INT); + + option_meta = _get_option_meta(name); + + g_return_val_if_fail(option_meta, NM_BOND_OPTION_TYPE_INT); + + return option_meta->opt_type; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingBond * self = NM_SETTING_BOND(setting); + NMSettingBondPrivate * priv = NM_SETTING_BOND_GET_PRIVATE(setting); + int miimon; + int arp_interval; + int num_grat_arp; + int num_unsol_na; + const char * mode_str; + const char * arp_ip_target = NULL; + const char * lacp_rate; + const char * primary; + NMBondMode bond_mode; + guint i; + const NMUtilsNamedValue *n; + + _ensure_options_idx_cache(priv); + + if (priv->options_idx_cache) { + for (i = 0; priv->options_idx_cache[i].name; i++) { + n = &priv->options_idx_cache[i]; + + if (!n->value_str || !_nm_setting_bond_validate_option(n->name, n->value_str, error)) { + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BOND_OPTIONS); + return FALSE; + } + } + } + + miimon = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_MIIMON)); + arp_interval = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_ARP_INTERVAL)); + num_grat_arp = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP)); + num_unsol_na = _atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)); + + /* Option restrictions: + * + * arp_interval conflicts [ alb, tlb ] + * arp_interval needs arp_ip_target + * arp_validate does not work with [ BOND_MODE_8023AD, BOND_MODE_TLB, BOND_MODE_ALB ] + * downdelay needs miimon + * updelay needs miimon + * primary needs [ active-backup, tlb, alb ] + */ + + /* Verify bond mode */ + mode_str = _bond_get_option(self, NM_SETTING_BOND_OPTION_MODE); + if (!mode_str) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("mandatory option '%s' is missing"), + NM_SETTING_BOND_OPTION_MODE); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + bond_mode = _nm_setting_bond_mode_from_string(mode_str); + if (bond_mode == NM_BOND_MODE_UNKNOWN) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for '%s'"), + mode_str, + NM_SETTING_BOND_OPTION_MODE); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + + /* Make sure mode is compatible with other settings */ + if (NM_IN_SET(bond_mode, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB)) { + if (arp_interval > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s=%s' is incompatible with '%s > 0'"), + NM_SETTING_BOND_OPTION_MODE, + mode_str, + NM_SETTING_BOND_OPTION_ARP_INTERVAL); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + } + + primary = _bond_get_option(self, NM_SETTING_BOND_OPTION_PRIMARY); + if (NM_IN_SET(bond_mode, NM_BOND_MODE_ACTIVEBACKUP, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB)) { + GError *tmp_error = NULL; + + if (primary && !nm_utils_ifname_valid_kernel(primary, &tmp_error)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not valid for the '%s' option: %s"), + primary, + NM_SETTING_BOND_OPTION_PRIMARY, + tmp_error->message); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + g_error_free(tmp_error); + return FALSE; + } + } else if (primary) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option is only valid for '%s=%s'"), + NM_SETTING_BOND_OPTION_PRIMARY, + NM_SETTING_BOND_OPTION_MODE, + "active-backup"); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + + if (connection && nm_connection_get_setting_infiniband(connection)) { + if (bond_mode != NM_BOND_MODE_ACTIVEBACKUP) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s=%s' is not a valid configuration for '%s'"), + NM_SETTING_BOND_OPTION_MODE, + mode_str, + NM_SETTING_INFINIBAND_SETTING_NAME); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + } + + if (miimon == 0) { + /* updelay and downdelay need miimon to be enabled to be valid */ + if (_atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_UPDELAY))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option requires '%s' option to be enabled"), + NM_SETTING_BOND_OPTION_UPDELAY, + NM_SETTING_BOND_OPTION_MIIMON); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + + if (_atoi(_bond_get_option_or_default(self, NM_SETTING_BOND_OPTION_DOWNDELAY))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option requires '%s' option to be enabled"), + NM_SETTING_BOND_OPTION_DOWNDELAY, + NM_SETTING_BOND_OPTION_MIIMON); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + } + + /* arp_ip_target can only be used with arp_interval, and must + * contain a comma-separated list of IPv4 addresses. + */ + arp_ip_target = _bond_get_option(self, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + if (arp_interval > 0) { + if (!arp_ip_target) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option requires '%s' option to be set"), + NM_SETTING_BOND_OPTION_ARP_INTERVAL, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + } else { + if (arp_ip_target) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option requires '%s' option to be set"), + NM_SETTING_BOND_OPTION_ARP_IP_TARGET, + NM_SETTING_BOND_OPTION_ARP_INTERVAL); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + } + + lacp_rate = _bond_get_option(self, NM_SETTING_BOND_OPTION_LACP_RATE); + if (lacp_rate && bond_mode != NM_BOND_MODE_8023AD && !NM_IN_STRSET(lacp_rate, "0", "slow")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option is only valid with mode '%s'"), + NM_SETTING_BOND_OPTION_LACP_RATE, + "802.3ad"); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + + if (_bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP) + && _bond_get_option(self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA) + && num_grat_arp != num_unsol_na) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' and '%s' cannot have different values"), + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, + NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ + + if (!NM_IN_STRSET(mode_str, + "802.3ad", + "active-backup", + "balance-rr", + "balance-alb", + "balance-tlb", + "balance-xor", + "broadcast")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option should be string"), + NM_SETTING_BOND_OPTION_MODE); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + /* normalize unsupported options for the current mode */ + for (i = 0; priv->options_idx_cache[i].name; i++) { + n = &priv->options_idx_cache[i]; + if (!_nm_setting_bond_option_supported(n->name, bond_mode)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option is not valid with mode '%s'"), + n->name, + mode_str); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + } + + return TRUE; +} + +/*****************************************************************************/ + +static gboolean +options_equal_asym(NMSettingBond *s_bond, NMSettingBond *s_bond2, NMSettingCompareFlags flags) +{ + GHashTableIter iter; + const char * key, *value; + + g_hash_table_iter_init(&iter, NM_SETTING_BOND_GET_PRIVATE(s_bond)->options); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) { + /* when doing an inferrable match, the active-slave should be ignored + * as it might be differ from the setting in the connection. + * + * Also, the fail_over_mac setting can change, see for example + * https://bugzilla.redhat.com/show_bug.cgi?id=1375558#c8 */ + if (NM_IN_STRSET(key, "fail_over_mac", "active_slave")) + continue; + } + + if (!nm_streq0(value, _bond_get_option(s_bond2, key))) + return FALSE; + } + + return TRUE; +} + +static gboolean +options_equal(NMSettingBond *s_bond, NMSettingBond *s_bond2, NMSettingCompareFlags flags) +{ + return options_equal_asym(s_bond, s_bond2, flags) && options_equal_asym(s_bond2, s_bond, flags); +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_BOND_OPTIONS)) { + return (!set_b || options_equal(NM_SETTING_BOND(set_a), NM_SETTING_BOND(set_b), flags)); + } + + return NM_SETTING_CLASS(nm_setting_bond_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_OPTIONS: + g_value_take_boxed(value, _nm_utils_copy_strdict(priv->options)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_OPTIONS: + nm_clear_g_free(&priv->options_idx_cache); + g_hash_table_unref(priv->options); + priv->options = _nm_utils_copy_strdict(g_value_get_boxed(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_bond_init(NMSettingBond *setting) +{ + NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(setting); + + priv->options = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); + + /* Default values: */ + nm_setting_bond_add_option(setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr"); +} + +/** + * nm_setting_bond_new: + * + * Creates a new #NMSettingBond object with default values. + * + * Returns: (transfer full): the new empty #NMSettingBond object + **/ +NMSetting * +nm_setting_bond_new(void) +{ + return g_object_new(NM_TYPE_SETTING_BOND, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE(object); + + nm_clear_g_free(&priv->options_idx_cache); + g_hash_table_destroy(priv->options); + + G_OBJECT_CLASS(nm_setting_bond_parent_class)->finalize(object); +} + +static void +nm_setting_bond_class_init(NMSettingBondClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingBondPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->compare_property = compare_property; + + /** + * NMSettingBond:options: (type GHashTable(utf8,utf8)): + * + * Dictionary of key/value pairs of bonding options. Both keys and values + * must be strings. Option names must contain only alphanumeric characters + * (ie, [a-zA-Z0-9]). + **/ + /* ---ifcfg-rh--- + * property: options + * variable: BONDING_OPTS + * description: Bonding options. + * example: BONDING_OPTS="miimon=100 mode=broadcast" + * ---end--- + */ + obj_properties[PROP_OPTIONS] = g_param_spec_boxed( + NM_SETTING_BOND_OPTIONS, + "", + "", + G_TYPE_HASH_TABLE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_OPTIONS], + &nm_sett_info_propert_type_strdict); + + /* ---dbus--- + * property: interface-name + * format: string + * description: Deprecated in favor of connection.interface-name, but can + * be used for backward-compatibility with older daemons, to set the + * bond's interface name. + * ---end--- + */ + _nm_properties_override_dbus(properties_override, + "interface-name", + &nm_sett_info_propert_type_deprecated_interface_name); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_BOND, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-bridge-port.c b/src/libnm-core-impl/nm-setting-bridge-port.c new file mode 100644 index 0000000000..9d1ff25986 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-bridge-port.c @@ -0,0 +1,589 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2012 - 2013 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-bridge-port.h" + +#include +#include + +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-bridge.h" + +/** + * SECTION:nm-setting-bridge-port + * @short_description: Describes connection properties for bridge ports + * + * The #NMSettingBridgePort object is a #NMSetting subclass that describes + * optional properties that apply to bridge ports. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingBridgePort, + PROP_PRIORITY, + PROP_PATH_COST, + PROP_HAIRPIN_MODE, + PROP_VLANS, ); + +typedef struct { + GPtrArray *vlans; + guint16 priority; + guint16 path_cost; + bool hairpin_mode : 1; +} NMSettingBridgePortPrivate; + +G_DEFINE_TYPE(NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING) + +#define NM_SETTING_BRIDGE_PORT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortPrivate)) + +static int +vlan_ptr_cmp(gconstpointer a, gconstpointer b) +{ + const NMBridgeVlan *vlan_a = *(const NMBridgeVlan **) a; + const NMBridgeVlan *vlan_b = *(const NMBridgeVlan **) b; + + return nm_bridge_vlan_cmp(vlan_a, vlan_b); +} + +gboolean +_nm_setting_bridge_port_sort_vlans(NMSettingBridgePort *setting) +{ + NMSettingBridgePortPrivate *priv; + gboolean need_sort = FALSE; + guint i; + + priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + for (i = 1; i < priv->vlans->len; i++) { + NMBridgeVlan *vlan_prev = priv->vlans->pdata[i - 1]; + NMBridgeVlan *vlan = priv->vlans->pdata[i]; + + if (nm_bridge_vlan_cmp(vlan_prev, vlan) > 0) { + need_sort = TRUE; + break; + } + } + + if (need_sort) { + g_ptr_array_sort(priv->vlans, vlan_ptr_cmp); + _notify(setting, PROP_VLANS); + } + + return need_sort; +} + +/*****************************************************************************/ + +/** + * nm_setting_bridge_port_get_priority: + * @setting: the #NMSettingBridgePort + * + * Returns: the #NMSettingBridgePort:priority property of the setting + **/ +guint16 +nm_setting_bridge_port_get_priority(NMSettingBridgePort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), 0); + + return NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting)->priority; +} + +/** + * nm_setting_bridge_port_get_path_cost: + * @setting: the #NMSettingBridgePort + * + * Returns: the #NMSettingBridgePort:path-cost property of the setting + **/ +guint16 +nm_setting_bridge_port_get_path_cost(NMSettingBridgePort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), 0); + + return NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting)->path_cost; +} + +/** + * nm_setting_bridge_port_get_hairpin_mode: + * @setting: the #NMSettingBridgePort + * + * Returns: the #NMSettingBridgePort:hairpin-mode property of the setting + **/ +gboolean +nm_setting_bridge_port_get_hairpin_mode(NMSettingBridgePort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), FALSE); + + return NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting)->hairpin_mode; +} + +/** + * nm_setting_bridge_port_add_vlan: + * @setting: the #NMSettingBridgePort + * @vlan: the vlan to add + * + * Appends a new vlan and associated information to the setting. The + * given vlan gets sealed and a reference to it is added. + * + * Since: 1.18 + **/ +void +nm_setting_bridge_port_add_vlan(NMSettingBridgePort *setting, NMBridgeVlan *vlan) +{ + NMSettingBridgePortPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting)); + g_return_if_fail(vlan); + + priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + nm_bridge_vlan_seal(vlan); + nm_bridge_vlan_ref(vlan); + + g_ptr_array_add(priv->vlans, vlan); + _notify(setting, PROP_VLANS); +} + +/** + * nm_setting_bridge_port_get_num_vlans: + * @setting: the #NMSettingBridgePort + * + * Returns: the number of VLANs + * + * Since: 1.18 + **/ +guint +nm_setting_bridge_port_get_num_vlans(NMSettingBridgePort *setting) +{ + NMSettingBridgePortPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), 0); + priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + return priv->vlans->len; +} + +/** + * nm_setting_bridge_port_get_vlan: + * @setting: the #NMSettingBridgePort + * @idx: index number of the VLAN to return + * + * Returns: (transfer none): the VLAN at index @idx + * + * Since: 1.18 + **/ +NMBridgeVlan * +nm_setting_bridge_port_get_vlan(NMSettingBridgePort *setting, guint idx) +{ + NMSettingBridgePortPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), NULL); + priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + g_return_val_if_fail(idx < priv->vlans->len, NULL); + + return priv->vlans->pdata[idx]; +} + +/** + * nm_setting_bridge_port_remove_vlan: + * @setting: the #NMSettingBridgePort + * @idx: index number of the VLAN. + * + * Removes the vlan at index @idx. + * + * Since: 1.18 + **/ +void +nm_setting_bridge_port_remove_vlan(NMSettingBridgePort *setting, guint idx) +{ + NMSettingBridgePortPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting)); + priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + g_return_if_fail(idx < priv->vlans->len); + + g_ptr_array_remove_index(priv->vlans, idx); + _notify(setting, PROP_VLANS); +} + +/** + * nm_setting_bridge_port_remove_vlan_by_vid: + * @setting: the #NMSettingBridgePort + * @vid_start: the vlan start index + * @vid_end: the vlan end index + * + * Remove the VLAN with range @vid_start to @vid_end. + * If @vid_end is zero, it is assumed to be equal to @vid_start + * and so the single-id VLAN with id @vid_start is removed. + * + * Returns: %TRUE if the vlan was found and removed; %FALSE otherwise + * + * Since: 1.18 + **/ +gboolean +nm_setting_bridge_port_remove_vlan_by_vid(NMSettingBridgePort *setting, + guint16 vid_start, + guint16 vid_end) +{ + NMSettingBridgePortPrivate *priv; + guint i; + + if (vid_end == 0) + vid_end = vid_start; + + g_return_val_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting), FALSE); + + priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + for (i = 0; i < priv->vlans->len; i++) { + NMBridgeVlan *vlan = priv->vlans->pdata[i]; + guint16 v_start = 0; + guint16 v_end = 0; + + nm_bridge_vlan_get_vid_range(vlan, &v_start, &v_end); + if (v_start == vid_start && v_end == vid_end) { + g_ptr_array_remove_index(priv->vlans, i); + _notify(setting, PROP_VLANS); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_bridge_port_clear_vlans: + * @setting: the #NMSettingBridgePort + * + * Removes all configured VLANs. + * + * Since: 1.18 + **/ +void +nm_setting_bridge_port_clear_vlans(NMSettingBridgePort *setting) +{ + NMSettingBridgePortPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_BRIDGE_PORT(setting)); + priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + if (priv->vlans->len != 0) { + g_ptr_array_set_size(priv->vlans, 0); + _notify(setting, PROP_VLANS); + } +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingBridgePortPrivate *priv; + + priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + if (connection) { + NMSettingConnection *s_con; + const char * slave_type; + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + slave_type = nm_setting_connection_get_slave_type(s_con); + if (slave_type && strcmp(slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have the slave-type set to '%s'. " + "Instead it is '%s'"), + NM_SETTING_BRIDGE_PORT_SETTING_NAME, + NM_SETTING_BRIDGE_SETTING_NAME, + slave_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + } + + if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, + FALSE, + error, + NM_SETTING_BRIDGE_PORT_SETTING_NAME, + NM_SETTING_BRIDGE_PORT_VLANS)) + return FALSE; + + /* Failures from here on are NORMALIZABLE... */ + + if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, + TRUE, + error, + NM_SETTING_BRIDGE_PORT_SETTING_NAME, + NM_SETTING_BRIDGE_PORT_VLANS)) + return NM_SETTING_VERIFY_NORMALIZABLE; + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingBridgePortPrivate *priv_a; + NMSettingBridgePortPrivate *priv_b; + guint i; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_BRIDGE_PORT_VLANS)) { + if (set_b) { + priv_a = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(set_a); + priv_b = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(set_b); + + if (priv_a->vlans->len != priv_b->vlans->len) + return FALSE; + for (i = 0; i < priv_a->vlans->len; i++) { + if (nm_bridge_vlan_cmp(priv_a->vlans->pdata[i], priv_b->vlans->pdata[i])) + return FALSE; + } + } + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_bridge_port_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_PRIORITY: + g_value_set_uint(value, priv->priority); + break; + case PROP_PATH_COST: + g_value_set_uint(value, priv->path_cost); + break; + case PROP_HAIRPIN_MODE: + g_value_set_boolean(value, priv->hairpin_mode); + break; + case PROP_VLANS: + g_value_take_boxed(value, + _nm_utils_copy_array(priv->vlans, + (NMUtilsCopyFunc) nm_bridge_vlan_ref, + (GDestroyNotify) nm_bridge_vlan_unref)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_PRIORITY: + priv->priority = g_value_get_uint(value); + break; + case PROP_PATH_COST: + priv->path_cost = g_value_get_uint(value); + break; + case PROP_HAIRPIN_MODE: + priv->hairpin_mode = g_value_get_boolean(value); + break; + case PROP_VLANS: + g_ptr_array_unref(priv->vlans); + priv->vlans = _nm_utils_copy_array(g_value_get_boxed(value), + (NMUtilsCopyFunc) _nm_bridge_vlan_dup_and_seal, + (GDestroyNotify) nm_bridge_vlan_unref); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_bridge_port_init(NMSettingBridgePort *setting) +{ + NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(setting); + + priv->vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); + + priv->priority = NM_BRIDGE_PORT_PRIORITY_DEF; + priv->path_cost = NM_BRIDGE_PORT_PATH_COST_DEF; +} + +/** + * nm_setting_bridge_port_new: + * + * Creates a new #NMSettingBridgePort object with default values. + * + * Returns: (transfer full): the new empty #NMSettingBridgePort object + **/ +NMSetting * +nm_setting_bridge_port_new(void) +{ + return g_object_new(NM_TYPE_SETTING_BRIDGE_PORT, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE(object); + + g_ptr_array_unref(priv->vlans); + + G_OBJECT_CLASS(nm_setting_bridge_port_parent_class)->finalize(object); +} + +static void +nm_setting_bridge_port_class_init(NMSettingBridgePortClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingBridgePortPrivate)); + + object_class->finalize = finalize; + object_class->get_property = get_property; + object_class->set_property = set_property; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + + /** + * NMSettingBridgePort:priority: + * + * The Spanning Tree Protocol (STP) priority of this bridge port. + **/ + /* ---ifcfg-rh--- + * property: priority + * variable: BRIDGING_OPTS: priority= + * values: 0 - 63 + * default: 32 + * description: STP priority. + * ---end--- + */ + obj_properties[PROP_PRIORITY] = + g_param_spec_uint(NM_SETTING_BRIDGE_PORT_PRIORITY, + "", + "", + NM_BRIDGE_PORT_PRIORITY_MIN, + NM_BRIDGE_PORT_PRIORITY_MAX, + NM_BRIDGE_PORT_PRIORITY_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridgePort:path-cost: + * + * The Spanning Tree Protocol (STP) port cost for destinations via this + * port. + **/ + /* ---ifcfg-rh--- + * property: path-cost + * variable: BRIDGING_OPTS: path_cost= + * values: 1 - 65535 + * default: 100 + * description: STP cost. + * ---end--- + */ + obj_properties[PROP_PATH_COST] = g_param_spec_uint(NM_SETTING_BRIDGE_PORT_PATH_COST, + "", + "", + NM_BRIDGE_PORT_PATH_COST_MIN, + NM_BRIDGE_PORT_PATH_COST_MAX, + NM_BRIDGE_PORT_PATH_COST_DEF, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridgePort:hairpin-mode: + * + * Enables or disables "hairpin mode" for the port, which allows frames to + * be sent back out through the port the frame was received on. + **/ + /* ---ifcfg-rh--- + * property: hairpin-mode + * variable: BRIDGING_OPTS: hairpin_mode= + * default: yes + * description: Hairpin mode of the bridge port. + * ---end--- + */ + obj_properties[PROP_HAIRPIN_MODE] = g_param_spec_boolean( + NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridgePort:vlans: (type GPtrArray(NMBridgeVlan)) + * + * Array of bridge VLAN objects. In addition to the VLANs + * specified here, the port will also have the default-pvid + * VLAN configured on the bridge by the bridge.vlan-default-pvid + * property. + * + * In nmcli the VLAN list can be specified with the following + * syntax: + * + * $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... + * + * where $vid is either a single id between 1 and 4094 or a + * range, represented as a couple of ids separated by a dash. + * + * Since: 1.18 + **/ + /* ---ifcfg-rh--- + * property: vlans + * variable: BRIDGE_PORT_VLANS + * description: List of VLANs on the bridge port + * example: BRIDGE_PORT_VLANS="1 pvid untagged,20,300-400 untagged" + * ---end--- + */ + obj_properties[PROP_VLANS] = g_param_spec_boxed(NM_SETTING_BRIDGE_PORT_VLANS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_VLANS], + &nm_sett_info_propert_type_bridge_vlans); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_BRIDGE_PORT, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-bridge.c b/src/libnm-core-impl/nm-setting-bridge.c new file mode 100644 index 0000000000..95ae5bfbcc --- /dev/null +++ b/src/libnm-core-impl/nm-setting-bridge.c @@ -0,0 +1,2292 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-bridge.h" + +#include +#include +#include + +#include "nm-glib-aux/nm-str-buf.h" +#include "nm-connection-private.h" +#include "nm-utils.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-bridge + * @short_description: Describes connection properties for bridges + * + * The #NMSettingBridge object is a #NMSetting subclass that describes properties + * necessary for bridging connections. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingBridge, + PROP_MAC_ADDRESS, + PROP_STP, + PROP_PRIORITY, + PROP_FORWARD_DELAY, + PROP_HELLO_TIME, + PROP_MAX_AGE, + PROP_AGEING_TIME, + PROP_GROUP_ADDRESS, + PROP_GROUP_FORWARD_MASK, + PROP_MULTICAST_HASH_MAX, + PROP_MULTICAST_LAST_MEMBER_COUNT, + PROP_MULTICAST_LAST_MEMBER_INTERVAL, + PROP_MULTICAST_MEMBERSHIP_INTERVAL, + PROP_MULTICAST_ROUTER, + PROP_MULTICAST_QUERIER, + PROP_MULTICAST_QUERIER_INTERVAL, + PROP_MULTICAST_QUERY_INTERVAL, + PROP_MULTICAST_QUERY_RESPONSE_INTERVAL, + PROP_MULTICAST_QUERY_USE_IFADDR, + PROP_MULTICAST_SNOOPING, + PROP_MULTICAST_STARTUP_QUERY_COUNT, + PROP_MULTICAST_STARTUP_QUERY_INTERVAL, + PROP_VLAN_FILTERING, + PROP_VLAN_DEFAULT_PVID, + PROP_VLAN_PROTOCOL, + PROP_VLAN_STATS_ENABLED, + PROP_VLANS, ); + +typedef struct { + GPtrArray *vlans; + char * mac_address; + char * multicast_router; + char * group_address; + char * vlan_protocol; + guint64 multicast_last_member_interval; + guint64 multicast_membership_interval; + guint64 multicast_querier_interval; + guint64 multicast_query_interval; + guint64 multicast_query_response_interval; + guint64 multicast_startup_query_interval; + guint32 ageing_time; + guint32 multicast_hash_max; + guint32 multicast_last_member_count; + guint32 multicast_startup_query_count; + guint16 priority; + guint16 forward_delay; + guint16 hello_time; + guint16 max_age; + guint16 vlan_default_pvid; + guint16 group_forward_mask; + bool multicast_snooping : 1; + bool vlan_filtering : 1; + bool stp : 1; + bool vlan_stats_enabled : 1; + bool multicast_query_use_ifaddr : 1; + bool multicast_querier : 1; +} NMSettingBridgePrivate; + +/** + * NMSettingBridge: + * + * Bridging Settings + */ +struct _NMSettingBridge { + NMSetting parent; + NMSettingBridgePrivate _priv; +}; + +struct _NMSettingBridgeClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING) + +#define NM_SETTING_BRIDGE_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingBridge, NM_IS_SETTING_BRIDGE, NMSetting) + +/*****************************************************************************/ + +G_DEFINE_BOXED_TYPE(NMBridgeVlan, nm_bridge_vlan, _nm_bridge_vlan_dup, nm_bridge_vlan_unref) + +struct _NMBridgeVlan { + guint refcount; + guint16 vid_start; + guint16 vid_end; + bool untagged : 1; + bool pvid : 1; + bool sealed : 1; +}; + +static gboolean +NM_IS_BRIDGE_VLAN(const NMBridgeVlan *self, gboolean also_sealed) +{ + return self && self->refcount > 0 && (also_sealed || !self->sealed); +} + +/** + * nm_bridge_vlan_new: + * @vid_start: the start VLAN id, must be between 1 and 4094. + * @vid_end: the end VLAN id, must be 0 or between @vid_start and 4094. + * + * Creates a new #NMBridgeVlan object for the given VLAN id range. + * Setting @vid_end to 0 is equivalent to setting it to @vid_start + * and creates a single-id VLAN. + * + * Returns: (transfer full): the new #NMBridgeVlan object. + * + * Since: 1.18 + **/ +NMBridgeVlan * +nm_bridge_vlan_new(guint16 vid_start, guint16 vid_end) +{ + NMBridgeVlan *vlan; + + if (vid_end == 0) + vid_end = vid_start; + + g_return_val_if_fail(vid_start >= NM_BRIDGE_VLAN_VID_MIN, NULL); + g_return_val_if_fail(vid_end <= NM_BRIDGE_VLAN_VID_MAX, NULL); + g_return_val_if_fail(vid_start <= vid_end, NULL); + + vlan = g_slice_new0(NMBridgeVlan); + vlan->refcount = 1; + vlan->vid_start = vid_start; + vlan->vid_end = vid_end; + + return vlan; +} + +/** + * nm_bridge_vlan_ref: + * @vlan: the #NMBridgeVlan + * + * Increases the reference count of the object. + * + * Returns: the input argument @vlan object. + * + * Since: 1.18 + **/ +NMBridgeVlan * +nm_bridge_vlan_ref(NMBridgeVlan *vlan) +{ + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); + + nm_assert(vlan->refcount < G_MAXUINT); + + vlan->refcount++; + return vlan; +} + +/** + * nm_bridge_vlan_unref: + * @vlan: the #NMBridgeVlan + * + * Decreases the reference count of the object. If the reference count + * reaches zero the object will be destroyed. + * + * Since: 1.18 + **/ +void +nm_bridge_vlan_unref(NMBridgeVlan *vlan) +{ + g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE)); + + if (--vlan->refcount == 0) + g_slice_free(NMBridgeVlan, vlan); +} + +/** + * nm_bridge_vlan_cmp: + * @a: a #NMBridgeVlan + * @b: another #NMBridgeVlan + * + * Compare two bridge VLAN objects. + * + * Returns: zero of the two instances are equivalent or + * a non-zero integer otherwise. This defines a total ordering + * over the VLANs. Whether a VLAN is sealed or not does not + * affect the comparison. + * + * Since: 1.18 + **/ +int +nm_bridge_vlan_cmp(const NMBridgeVlan *a, const NMBridgeVlan *b) +{ + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(a, TRUE), 0); + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(b, TRUE), 0); + + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, vid_start); + NM_CMP_FIELD(a, b, vid_end); + NM_CMP_FIELD_BOOL(a, b, untagged); + NM_CMP_FIELD_BOOL(a, b, pvid); + + return 0; +} + +NMBridgeVlan * +_nm_bridge_vlan_dup(const NMBridgeVlan *vlan) +{ + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); + + if (vlan->sealed) { + nm_bridge_vlan_ref((NMBridgeVlan *) vlan); + return (NMBridgeVlan *) vlan; + } + + return nm_bridge_vlan_new_clone(vlan); +} + +NMBridgeVlan * +_nm_bridge_vlan_dup_and_seal(const NMBridgeVlan *vlan) +{ + NMBridgeVlan *new; + + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); + + new = _nm_bridge_vlan_dup(vlan); + nm_bridge_vlan_seal(new); + + return new; +} + +/** + * nm_bridge_vlan_get_vid_range: + * @vlan: the #NMBridgeVlan + * @vid_start: (out): location to store the VLAN id range start. + * @vid_end: (out): location to store the VLAN id range end + * + * Gets the VLAN id range. + * + * Returns: %TRUE is the VLAN specifies a range, %FALSE if it is + * a single-id VLAN. + * + * Since: 1.18 + **/ +gboolean +nm_bridge_vlan_get_vid_range(const NMBridgeVlan *vlan, guint16 *vid_start, guint16 *vid_end) +{ + /* with LTO and optimization, the compiler complains that the + * output variables are not initialized. In practice, the function + * only sets the output on success. But make the compiler happy. + */ + NM_SET_OUT(vid_start, 0); + NM_SET_OUT(vid_end, 0); + + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), 0); + + NM_SET_OUT(vid_start, vlan->vid_start); + NM_SET_OUT(vid_end, vlan->vid_end); + + return vlan->vid_start != vlan->vid_end; +} + +/** + * nm_bridge_vlan_is_untagged: + * @vlan: the #NMBridgeVlan + * + * Returns whether the VLAN is untagged. + * + * Returns: %TRUE if the VLAN is untagged, %FALSE otherwise + * + * Since: 1.18 + **/ +gboolean +nm_bridge_vlan_is_untagged(const NMBridgeVlan *vlan) +{ + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); + + return vlan->untagged; +} + +/** + * nm_bridge_vlan_is_pvid: + * @vlan: the #NMBridgeVlan + * + * Returns whether the VLAN is the PVID for the port. + * + * Returns: %TRUE if the VLAN is the PVID + * + * Since: 1.18 + **/ +gboolean +nm_bridge_vlan_is_pvid(const NMBridgeVlan *vlan) +{ + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); + + return vlan->pvid; +} + +/** + * nm_bridge_vlan_set_untagged: + * @vlan: the #NMBridgeVlan + * @value: the new value + * + * Change the value of the untagged property of the VLAN. + * + * Since: 1.18 + **/ +void +nm_bridge_vlan_set_untagged(NMBridgeVlan *vlan, gboolean value) +{ + g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, FALSE)); + + vlan->untagged = value; +} + +/** + * nm_bridge_vlan_set_pvid: + * @vlan: the #NMBridgeVlan + * @value: the new value + * + * Change the value of the PVID property of the VLAN. It + * is invalid to set the value to %TRUE for non-single-id + * VLANs. + * + * Since: 1.18 + **/ +void +nm_bridge_vlan_set_pvid(NMBridgeVlan *vlan, gboolean value) +{ + g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, FALSE)); + g_return_if_fail(!value || vlan->vid_start == vlan->vid_end); + + vlan->pvid = value; +} + +/** + * nm_bridge_vlan_is_sealed: + * @vlan: the #NMBridgeVlan instance + * + * Returns: whether @self is sealed or not. + * + * Since: 1.18 + */ +gboolean +nm_bridge_vlan_is_sealed(const NMBridgeVlan *vlan) +{ + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); + + return vlan->sealed; +} + +/** + * nm_bridge_vlan_seal: + * @vlan: the #NMBridgeVlan instance + * + * Seal the #NMBridgeVlan instance. Afterwards, it is a bug + * to call all functions that modify the instance (except ref/unref). + * A sealed instance cannot be unsealed again, but you can create + * an unsealed copy with nm_bridge_vlan_new_clone(). + * + * Since: 1.18 + */ +void +nm_bridge_vlan_seal(NMBridgeVlan *vlan) +{ + g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE)); + + vlan->sealed = TRUE; +} + +/** + * nm_bridge_vlan_new_clone: + * @vlan: the #NMBridgeVlan instance to copy + * + * Returns: (transfer full): a clone of @vlan. This instance + * is always unsealed. + * + * Since: 1.18 + */ +NMBridgeVlan * +nm_bridge_vlan_new_clone(const NMBridgeVlan *vlan) +{ + NMBridgeVlan *copy; + + g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); + + copy = nm_bridge_vlan_new(vlan->vid_start, vlan->vid_end); + copy->untagged = vlan->untagged; + copy->pvid = vlan->pvid; + + return copy; +} + +/** + * nm_bridge_vlan_to_str: + * @vlan: the %NMBridgeVlan + * @error: location of the error + * + * Convert a %NMBridgeVlan to a string. + * + * Returns: formatted string or %NULL + * + * Since: 1.18 + */ +char * +nm_bridge_vlan_to_str(const NMBridgeVlan *vlan, GError **error) +{ + NMStrBuf string; + + g_return_val_if_fail(vlan, NULL); + g_return_val_if_fail(!error || !*error, NULL); + + /* The function never fails at the moment, but it might in the + * future if more parameters are added to the object that could + * make it invalid. */ + + nm_str_buf_init(&string, NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE); + + if (vlan->vid_start == vlan->vid_end) + nm_str_buf_append_printf(&string, "%u", vlan->vid_start); + else + nm_str_buf_append_printf(&string, "%u-%u", vlan->vid_start, vlan->vid_end); + + if (nm_bridge_vlan_is_pvid(vlan)) + nm_str_buf_append(&string, " pvid"); + if (nm_bridge_vlan_is_untagged(vlan)) + nm_str_buf_append(&string, " untagged"); + + return nm_str_buf_finalize(&string, NULL); +} + +/** + * nm_bridge_vlan_from_str: + * @str: the string representation of a bridge VLAN + * @error: location of the error + * + * Parses the string representation of the queueing + * discipline to a %NMBridgeVlan instance. + * + * Returns: the %NMBridgeVlan or %NULL + * + * Since: 1.18 + */ +NMBridgeVlan * +nm_bridge_vlan_from_str(const char *str, GError **error) +{ + NMBridgeVlan * vlan = NULL; + gs_free const char **tokens = NULL; + guint i, vid_start, vid_end = 0; + gboolean pvid = FALSE; + gboolean untagged = FALSE; + char * c; + + g_return_val_if_fail(str, NULL); + g_return_val_if_fail(!error || !*error, NULL); + + tokens = nm_utils_escaped_tokens_split(str, NM_ASCII_SPACES); + if (!tokens || !tokens[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "missing VLAN id"); + return NULL; + } + + c = strchr(tokens[0], '-'); + if (c) + *c = '\0'; + + vid_start = _nm_utils_ascii_str_to_uint64(tokens[0], + 10, + NM_BRIDGE_VLAN_VID_MIN, + NM_BRIDGE_VLAN_VID_MAX, + G_MAXUINT); + if (vid_start == G_MAXUINT) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VLAN id range start '%s', must be in [1,4094]", + tokens[0]); + return NULL; + } + + if (c) { + vid_end = _nm_utils_ascii_str_to_uint64(c + 1, + 10, + NM_BRIDGE_VLAN_VID_MIN, + NM_BRIDGE_VLAN_VID_MAX, + G_MAXUINT); + if (vid_end == G_MAXUINT) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VLAN id range end '%s', must be in [1,4094]", + c + 1); + return NULL; + } + if (vid_end < vid_start) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VLAN id range %u-%u, start VLAN id must be less than end VLAN id", + vid_start, + vid_end); + return NULL; + } + } else + vid_end = vid_start; + + for (i = 1; tokens[i]; i++) { + if (nm_streq(tokens[i], "pvid")) { + if (vid_start != vid_end) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "a VLAN range can't be a PVID"); + return NULL; + } + pvid = TRUE; + } else if (nm_streq(tokens[i], "untagged")) + untagged = TRUE; + else { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid option '%s'", + tokens[i]); + return NULL; + } + } + + vlan = nm_bridge_vlan_new(vid_start, vid_end); + nm_bridge_vlan_set_pvid(vlan, pvid); + nm_bridge_vlan_set_untagged(vlan, untagged); + + return vlan; +} + +/*****************************************************************************/ + +static int +vlan_ptr_cmp(gconstpointer a, gconstpointer b) +{ + const NMBridgeVlan *vlan_a = *(const NMBridgeVlan **) a; + const NMBridgeVlan *vlan_b = *(const NMBridgeVlan **) b; + + return nm_bridge_vlan_cmp(vlan_a, vlan_b); +} + +gboolean +_nm_setting_bridge_sort_vlans(NMSettingBridge *setting) +{ + NMSettingBridgePrivate *priv; + gboolean need_sort = FALSE; + guint i; + + priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + for (i = 1; i < priv->vlans->len; i++) { + NMBridgeVlan *vlan_prev = priv->vlans->pdata[i - 1]; + NMBridgeVlan *vlan = priv->vlans->pdata[i]; + + if (nm_bridge_vlan_cmp(vlan_prev, vlan) > 0) { + need_sort = TRUE; + break; + } + } + + if (need_sort) { + g_ptr_array_sort(priv->vlans, vlan_ptr_cmp); + _notify(setting, PROP_VLANS); + } + + return need_sort; +} + +/*****************************************************************************/ + +/** + * nm_setting_bridge_get_mac_address: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:mac-address property of the setting + **/ +const char * +nm_setting_bridge_get_mac_address(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->mac_address; +} + +/** + * nm_setting_bridge_get_stp: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:stp property of the setting + **/ +gboolean +nm_setting_bridge_get_stp(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->stp; +} + +/** + * nm_setting_bridge_get_priority: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:priority property of the setting + **/ +guint16 +nm_setting_bridge_get_priority(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->priority; +} + +/** + * nm_setting_bridge_get_forward_delay: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:forward-delay property of the setting + **/ +guint16 +nm_setting_bridge_get_forward_delay(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->forward_delay; +} + +/** + * nm_setting_bridge_get_hello_time: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:hello-time property of the setting + **/ +guint16 +nm_setting_bridge_get_hello_time(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->hello_time; +} + +/** + * nm_setting_bridge_get_max_age: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:max-age property of the setting + **/ +guint16 +nm_setting_bridge_get_max_age(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->max_age; +} + +/** + * nm_setting_bridge_get_ageing_time: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:ageing-time property of the setting + **/ +guint +nm_setting_bridge_get_ageing_time(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->ageing_time; +} + +/** + * nm_setting_bridge_get_group_forward_mask: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:group-forward-mask property of the setting + * + * Since: 1.10 + **/ +guint16 +nm_setting_bridge_get_group_forward_mask(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->group_forward_mask; +} + +/** + * nm_setting_bridge_get_multicast_snooping: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-snooping property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_bridge_get_multicast_snooping(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_snooping; +} + +/** + * nm_setting_bridge_get_vlan_filtering: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:vlan-filtering property of the setting + * + * Since: 1.18 + **/ +gboolean +nm_setting_bridge_get_vlan_filtering(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_filtering; +} + +/** + * nm_setting_bridge_get_vlan_default_pvid: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:vlan-default-pvid property of the setting + * + * Since: 1.18 + **/ +guint16 +nm_setting_bridge_get_vlan_default_pvid(NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 1); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_default_pvid; +} + +/** + * nm_setting_bridge_add_vlan: + * @setting: the #NMSettingBridge + * @vlan: the vlan to add + * + * Appends a new vlan and associated information to the setting. The + * given vlan gets sealed and a reference to it is added. + * + * Since: 1.18 + **/ +void +nm_setting_bridge_add_vlan(NMSettingBridge *setting, NMBridgeVlan *vlan) +{ + NMSettingBridgePrivate *priv; + + g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); + g_return_if_fail(vlan); + + priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + nm_bridge_vlan_seal(vlan); + nm_bridge_vlan_ref(vlan); + + g_ptr_array_add(priv->vlans, vlan); + _notify(setting, PROP_VLANS); +} + +/** + * nm_setting_bridge_get_num_vlans: + * @setting: the #NMSettingBridge + * + * Returns: the number of VLANs + * + * Since: 1.18 + **/ +guint +nm_setting_bridge_get_num_vlans(NMSettingBridge *setting) +{ + NMSettingBridgePrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + return priv->vlans->len; +} + +/** + * nm_setting_bridge_get_vlan: + * @setting: the #NMSettingBridge + * @idx: index number of the VLAN to return + * + * Returns: (transfer none): the VLAN at index @idx + * + * Since: 1.18 + **/ +NMBridgeVlan * +nm_setting_bridge_get_vlan(NMSettingBridge *setting, guint idx) +{ + NMSettingBridgePrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); + priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + g_return_val_if_fail(idx < priv->vlans->len, NULL); + + return priv->vlans->pdata[idx]; +} + +/** + * nm_setting_bridge_remove_vlan: + * @setting: the #NMSettingBridge + * @idx: index number of the VLAN. + * + * Removes the vlan at index @idx. + * + * Since: 1.18 + **/ +void +nm_setting_bridge_remove_vlan(NMSettingBridge *setting, guint idx) +{ + NMSettingBridgePrivate *priv; + + g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); + priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + g_return_if_fail(idx < priv->vlans->len); + + g_ptr_array_remove_index(priv->vlans, idx); + _notify(setting, PROP_VLANS); +} + +/** + * nm_setting_bridge_remove_vlan_by_vid: + * @setting: the #NMSettingBridge + * @vid_start: the vlan start index + * @vid_end: the vlan end index + * + * Remove the VLAN with range @vid_start to @vid_end. + * If @vid_end is zero, it is assumed to be equal to @vid_start + * and so the single-id VLAN with id @vid_start is removed. + * + * Returns: %TRUE if the vlan was found and removed; %FALSE otherwise + * + * Since: 1.18 + **/ +gboolean +nm_setting_bridge_remove_vlan_by_vid(NMSettingBridge *setting, guint16 vid_start, guint16 vid_end) +{ + NMSettingBridgePrivate *priv; + NMBridgeVlan * vlan; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); + priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + if (vid_end == 0) + vid_end = vid_start; + + for (i = 0; i < priv->vlans->len; i++) { + vlan = (NMBridgeVlan *) priv->vlans->pdata[i]; + if (vlan->vid_start == vid_start && vlan->vid_end == vid_end) { + g_ptr_array_remove_index(priv->vlans, i); + _notify(setting, PROP_VLANS); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_bridge_clear_vlans: + * @setting: the #NMSettingBridge + * + * Removes all configured VLANs. + * + * Since: 1.18 + **/ +void +nm_setting_bridge_clear_vlans(NMSettingBridge *setting) +{ + NMSettingBridgePrivate *priv; + + g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); + priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + if (priv->vlans->len != 0) { + g_ptr_array_set_size(priv->vlans, 0); + _notify(setting, PROP_VLANS); + } +} + +/** + * nm_setting_bridge_get_group_address: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:group-address property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_group_address(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->group_address; +} + +/** + * nm_setting_bridge_get_vlan_protocol: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:vlan-protocol property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_vlan_protocol(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_protocol; +} + +/** + * nm_setting_bridge_get_vlan_stats_enabled: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:vlan-stats-enabled property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_vlan_stats_enabled(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_stats_enabled; +} + +/** + * nm_setting_bridge_get_multicast_router: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-router property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_multicast_router(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_router; +} + +/** + * nm_setting_bridge_get_multicast_query_use_ifaddr: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-query-use-ifaddr property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_multicast_query_use_ifaddr(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_use_ifaddr; +} + +/** + * nm_setting_bridge_get_multicast_querier: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-querier property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_multicast_querier(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_querier; +} + +/** + * nm_setting_bridge_get_multicast_hash_max: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-hash-max property of the setting + * + * Since 1.26 + **/ +guint32 +nm_setting_bridge_get_multicast_hash_max(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_hash_max; +} + +/** + * nm_setting_bridge_get_multicast_last_member_count: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-last-member-count property of the setting + * + * Since 1.26 + **/ +guint32 +nm_setting_bridge_get_multicast_last_member_count(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_last_member_count; +} + +/** + * nm_setting_bridge_get_multicast_last_member_interval: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-last-member-interval property of the setting + * + * Since 1.26 + **/ +guint64 +nm_setting_bridge_get_multicast_last_member_interval(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_last_member_interval; +} + +/** + * nm_setting_bridge_get_multicast_membership_interval: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-membership-interval property of the setting + * + * Since 1.26 + **/ +guint64 +nm_setting_bridge_get_multicast_membership_interval(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_membership_interval; +} + +/** + * nm_setting_bridge_get_multicast_querier_interval: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-querier-interval property of the setting + * + * Since 1.26 + **/ +guint64 +nm_setting_bridge_get_multicast_querier_interval(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_querier_interval; +} + +/** + * nm_setting_bridge_get_multicast_query_interval: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-query-interval property of the setting + * + * Since 1.26 + **/ +guint64 +nm_setting_bridge_get_multicast_query_interval(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_interval; +} + +/** + * nm_setting_bridge_get_multicast_query_response_interval: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-query-response-interval property of the setting + * + * Since 1.26 + **/ +guint64 +nm_setting_bridge_get_multicast_query_response_interval(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_response_interval; +} + +/** + * nm_setting_bridge_get_multicast_startup_query_count: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-query-response-interval property of the setting + * + * Since 1.26 + **/ +guint32 +nm_setting_bridge_get_multicast_startup_query_count(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_startup_query_count; +} + +/** + * nm_setting_bridge_get_multicast_startup_query_interval: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-startup-query-interval property of the setting + * + * Since 1.26 + **/ +guint64 +nm_setting_bridge_get_multicast_startup_query_interval(const NMSettingBridge *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_startup_query_interval; +} + +/*****************************************************************************/ + +static gboolean +check_range(guint32 val, guint32 min, guint32 max, gboolean zero, const char *prop, GError **error) +{ + if (zero && val == 0) + return TRUE; + + if (val < min || val > max) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value '%d' is out of range <%d-%d>"), + val, + min, + max); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, prop); + return FALSE; + } + return TRUE; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, ETH_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid MAC address")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_BRIDGE_MAC_ADDRESS); + return FALSE; + } + + if (!check_range(priv->forward_delay, + NM_BRIDGE_FORWARD_DELAY_MIN, + NM_BRIDGE_FORWARD_DELAY_MAX, + !priv->stp, + NM_SETTING_BRIDGE_FORWARD_DELAY, + error)) + return FALSE; + + if (!check_range(priv->hello_time, + NM_BRIDGE_HELLO_TIME_MIN, + NM_BRIDGE_HELLO_TIME_MAX, + !priv->stp, + NM_SETTING_BRIDGE_HELLO_TIME, + error)) + return FALSE; + + if (!check_range(priv->max_age, + NM_BRIDGE_MAX_AGE_MIN, + NM_BRIDGE_MAX_AGE_MAX, + !priv->stp, + NM_SETTING_BRIDGE_MAX_AGE, + error)) + return FALSE; + + if (!check_range(priv->ageing_time, + NM_BRIDGE_AGEING_TIME_MIN, + NM_BRIDGE_AGEING_TIME_MAX, + !priv->stp, + NM_SETTING_BRIDGE_AGEING_TIME, + error)) + return FALSE; + + if (priv->group_forward_mask & 7) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the mask can't contain bits 0 (STP), 1 (MAC) or 2 (LACP)")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_BRIDGE_GROUP_FORWARD_MASK); + return FALSE; + } + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, + FALSE, + error, + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_BRIDGE_VLANS)) + return FALSE; + + if (priv->group_address && !_nm_utils_hwaddr_link_local_valid(priv->group_address)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid link local MAC address")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_BRIDGE_GROUP_ADDRESS); + return FALSE; + } + + if (priv->vlan_protocol && !NM_IN_STRSET(priv->vlan_protocol, "802.1Q", "802.1ad")) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid VLAN filtering protocol")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_BRIDGE_VLAN_PROTOCOL); + return FALSE; + } + + if (!NM_IN_STRSET(priv->multicast_router, NULL, "auto", "enabled", "disabled")) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid option")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_BRIDGE_MULTICAST_ROUTER); + return FALSE; + } + + if (!nm_utils_is_power_of_two(priv->multicast_hash_max)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option must be a power of 2"), + NM_SETTING_BRIDGE_MULTICAST_HASH_MAX); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_BRIDGE_MULTICAST_HASH_MAX); + return FALSE; + } + + /* Failures from here on are NORMALIZABLE... */ + + if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, + TRUE, + error, + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_BRIDGE_VLANS)) + return NM_SETTING_VERIFY_NORMALIZABLE; + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingBridgePrivate *priv_a; + NMSettingBridgePrivate *priv_b; + guint i; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_BRIDGE_VLANS)) { + if (set_b) { + priv_a = NM_SETTING_BRIDGE_GET_PRIVATE(set_a); + priv_b = NM_SETTING_BRIDGE_GET_PRIVATE(set_b); + + if (priv_a->vlans->len != priv_b->vlans->len) + return FALSE; + for (i = 0; i < priv_a->vlans->len; i++) { + if (nm_bridge_vlan_cmp(priv_a->vlans->pdata[i], priv_b->vlans->pdata[i])) + return FALSE; + } + } + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_bridge_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); + NMSettingBridge * setting = NM_SETTING_BRIDGE(object); + + switch (prop_id) { + case PROP_MAC_ADDRESS: + g_value_set_string(value, nm_setting_bridge_get_mac_address(setting)); + break; + case PROP_STP: + g_value_set_boolean(value, priv->stp); + break; + case PROP_PRIORITY: + g_value_set_uint(value, priv->priority); + break; + case PROP_FORWARD_DELAY: + g_value_set_uint(value, priv->forward_delay); + break; + case PROP_HELLO_TIME: + g_value_set_uint(value, priv->hello_time); + break; + case PROP_MAX_AGE: + g_value_set_uint(value, priv->max_age); + break; + case PROP_AGEING_TIME: + g_value_set_uint(value, priv->ageing_time); + break; + case PROP_GROUP_ADDRESS: + g_value_set_string(value, priv->group_address); + break; + case PROP_GROUP_FORWARD_MASK: + g_value_set_uint(value, priv->group_forward_mask); + break; + case PROP_MULTICAST_HASH_MAX: + g_value_set_uint(value, priv->multicast_hash_max); + break; + case PROP_MULTICAST_LAST_MEMBER_COUNT: + g_value_set_uint(value, priv->multicast_last_member_count); + break; + case PROP_MULTICAST_LAST_MEMBER_INTERVAL: + g_value_set_uint64(value, priv->multicast_last_member_interval); + break; + case PROP_MULTICAST_MEMBERSHIP_INTERVAL: + g_value_set_uint64(value, priv->multicast_membership_interval); + break; + case PROP_MULTICAST_SNOOPING: + g_value_set_boolean(value, priv->multicast_snooping); + break; + case PROP_MULTICAST_ROUTER: + g_value_set_string(value, priv->multicast_router); + break; + case PROP_MULTICAST_QUERIER: + g_value_set_boolean(value, priv->multicast_querier); + break; + case PROP_MULTICAST_QUERIER_INTERVAL: + g_value_set_uint64(value, priv->multicast_querier_interval); + break; + case PROP_MULTICAST_QUERY_INTERVAL: + g_value_set_uint64(value, priv->multicast_query_interval); + break; + case PROP_MULTICAST_QUERY_RESPONSE_INTERVAL: + g_value_set_uint64(value, priv->multicast_query_response_interval); + break; + case PROP_MULTICAST_QUERY_USE_IFADDR: + g_value_set_boolean(value, priv->multicast_query_use_ifaddr); + break; + case PROP_MULTICAST_STARTUP_QUERY_COUNT: + g_value_set_uint(value, priv->multicast_startup_query_count); + break; + case PROP_MULTICAST_STARTUP_QUERY_INTERVAL: + g_value_set_uint64(value, priv->multicast_startup_query_interval); + break; + case PROP_VLAN_FILTERING: + g_value_set_boolean(value, priv->vlan_filtering); + break; + case PROP_VLAN_DEFAULT_PVID: + g_value_set_uint(value, priv->vlan_default_pvid); + break; + case PROP_VLAN_PROTOCOL: + g_value_set_string(value, priv->vlan_protocol); + break; + case PROP_VLAN_STATS_ENABLED: + g_value_set_boolean(value, priv->vlan_stats_enabled); + break; + case PROP_VLANS: + g_value_take_boxed(value, + _nm_utils_copy_array(priv->vlans, + (NMUtilsCopyFunc) nm_bridge_vlan_ref, + (GDestroyNotify) nm_bridge_vlan_unref)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_MAC_ADDRESS: + g_free(priv->mac_address); + priv->mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); + break; + case PROP_STP: + priv->stp = g_value_get_boolean(value); + break; + case PROP_PRIORITY: + priv->priority = (guint16) g_value_get_uint(value); + break; + case PROP_FORWARD_DELAY: + priv->forward_delay = (guint16) g_value_get_uint(value); + break; + case PROP_HELLO_TIME: + priv->hello_time = (guint16) g_value_get_uint(value); + break; + case PROP_MAX_AGE: + priv->max_age = (guint16) g_value_get_uint(value); + break; + case PROP_AGEING_TIME: + priv->ageing_time = g_value_get_uint(value); + break; + case PROP_GROUP_ADDRESS: + g_free(priv->group_address); + priv->group_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); + break; + case PROP_GROUP_FORWARD_MASK: + priv->group_forward_mask = (guint16) g_value_get_uint(value); + break; + case PROP_MULTICAST_HASH_MAX: + priv->multicast_hash_max = g_value_get_uint(value); + break; + case PROP_MULTICAST_LAST_MEMBER_COUNT: + priv->multicast_last_member_count = g_value_get_uint(value); + break; + case PROP_MULTICAST_LAST_MEMBER_INTERVAL: + priv->multicast_last_member_interval = g_value_get_uint64(value); + break; + case PROP_MULTICAST_MEMBERSHIP_INTERVAL: + priv->multicast_membership_interval = g_value_get_uint64(value); + break; + case PROP_MULTICAST_SNOOPING: + priv->multicast_snooping = g_value_get_boolean(value); + break; + case PROP_MULTICAST_ROUTER: + g_free(priv->multicast_router); + priv->multicast_router = g_value_dup_string(value); + break; + case PROP_MULTICAST_QUERIER: + priv->multicast_querier = g_value_get_boolean(value); + break; + case PROP_MULTICAST_QUERIER_INTERVAL: + priv->multicast_querier_interval = g_value_get_uint64(value); + break; + case PROP_MULTICAST_QUERY_INTERVAL: + priv->multicast_query_interval = g_value_get_uint64(value); + break; + case PROP_MULTICAST_QUERY_RESPONSE_INTERVAL: + priv->multicast_query_response_interval = g_value_get_uint64(value); + break; + case PROP_MULTICAST_QUERY_USE_IFADDR: + priv->multicast_query_use_ifaddr = g_value_get_boolean(value); + break; + case PROP_MULTICAST_STARTUP_QUERY_COUNT: + priv->multicast_startup_query_count = g_value_get_uint(value); + break; + case PROP_MULTICAST_STARTUP_QUERY_INTERVAL: + priv->multicast_startup_query_interval = g_value_get_uint64(value); + break; + case PROP_VLAN_FILTERING: + priv->vlan_filtering = g_value_get_boolean(value); + break; + case PROP_VLAN_DEFAULT_PVID: + priv->vlan_default_pvid = g_value_get_uint(value); + break; + case PROP_VLAN_PROTOCOL: + g_free(priv->vlan_protocol); + priv->vlan_protocol = g_value_dup_string(value); + break; + case PROP_VLAN_STATS_ENABLED: + priv->vlan_stats_enabled = g_value_get_boolean(value); + break; + case PROP_VLANS: + g_ptr_array_unref(priv->vlans); + priv->vlans = _nm_utils_copy_array(g_value_get_boxed(value), + (NMUtilsCopyFunc) _nm_bridge_vlan_dup_and_seal, + (GDestroyNotify) nm_bridge_vlan_unref); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_bridge_init(NMSettingBridge *setting) +{ + NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); + + priv->vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); + + priv->ageing_time = NM_BRIDGE_AGEING_TIME_DEF; + priv->forward_delay = NM_BRIDGE_FORWARD_DELAY_DEF; + priv->hello_time = NM_BRIDGE_HELLO_TIME_DEF; + priv->max_age = NM_BRIDGE_MAX_AGE_DEF; + priv->multicast_last_member_count = NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF; + priv->multicast_last_member_interval = NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF; + priv->multicast_membership_interval = NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF; + priv->multicast_hash_max = NM_BRIDGE_MULTICAST_HASH_MAX_DEF; + priv->multicast_snooping = NM_BRIDGE_MULTICAST_SNOOPING_DEF; + priv->priority = NM_BRIDGE_PRIORITY_DEF; + priv->stp = NM_BRIDGE_STP_DEF; + priv->vlan_default_pvid = NM_BRIDGE_VLAN_DEFAULT_PVID_DEF; + priv->multicast_query_interval = NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF; + priv->multicast_query_response_interval = NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF; + priv->multicast_querier_interval = NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF; + priv->multicast_startup_query_count = NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF; + priv->multicast_startup_query_interval = NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF; + + nm_assert(priv->multicast_querier == NM_BRIDGE_MULTICAST_QUERIER_DEF); + nm_assert(priv->multicast_query_use_ifaddr == NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF); + nm_assert(priv->vlan_stats_enabled == NM_BRIDGE_VLAN_STATS_ENABLED_DEF); +} + +/** + * nm_setting_bridge_new: + * + * Creates a new #NMSettingBridge object with default values. + * + * Returns: (transfer full): the new empty #NMSettingBridge object + **/ +NMSetting * +nm_setting_bridge_new(void) +{ + return g_object_new(NM_TYPE_SETTING_BRIDGE, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); + + g_free(priv->mac_address); + g_free(priv->multicast_router); + g_free(priv->group_address); + g_free(priv->vlan_protocol); + g_ptr_array_unref(priv->vlans); + + G_OBJECT_CLASS(nm_setting_bridge_parent_class)->finalize(object); +} + +static void +nm_setting_bridge_class_init(NMSettingBridgeClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + + /** + * NMSettingBridge:mac-address: + * + * If specified, the MAC address of bridge. When creating a new bridge, this + * MAC address will be set. + * + * If this field is left unspecified, the "ethernet.cloned-mac-address" is + * referred instead to generate the initial MAC address. Note that setting + * "ethernet.cloned-mac-address" anyway overwrites the MAC address of + * the bridge later while activating the bridge. Hence, this property + * is deprecated. + * + * Deprecated: 1.12: Use the ethernet.cloned-mac-address property instead. + **/ + /* ---keyfile--- + * property: mac-address + * format: usual hex-digits-and-colons notation + * description: MAC address in traditional hex-digits-and-colons notation, + * or semicolon separated list of 6 decimal bytes (obsolete) + * example: mac-address=00:22:68:12:79:A2 + * mac-address=0;34;104;18;121;162; + * ---end--- + * ---ifcfg-rh--- + * property: mac-address + * variable: BRIDGE_MACADDR(+) + * description: MAC address of the bridge. Note that this requires a recent + * kernel support, originally introduced in 3.15 upstream kernel) + * BRIDGE_MACADDR for bridges is an NM extension. + * ---end--- + */ + obj_properties[PROP_MAC_ADDRESS] = g_param_spec_string( + NM_SETTING_BRIDGE_MAC_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_MAC_ADDRESS], + &nm_sett_info_propert_type_mac_address); + + /** + * NMSettingBridge:stp: + * + * Controls whether Spanning Tree Protocol (STP) is enabled for this bridge. + **/ + /* ---ifcfg-rh--- + * property: stp + * variable: STP + * default: no + * description: Span tree protocol participation. + * ---end--- + */ + obj_properties[PROP_STP] = g_param_spec_boolean(NM_SETTING_BRIDGE_STP, + "", + "", + NM_BRIDGE_STP_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:priority: + * + * Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower + * values are "better"; the lowest priority bridge will be elected the root + * bridge. + **/ + /* ---ifcfg-rh--- + * property: priority + * variable: BRIDGING_OPTS: priority= + * values: 0 - 32768 + * default: 32768 + * description: STP priority. + * ---end--- + */ + obj_properties[PROP_PRIORITY] = + g_param_spec_uint(NM_SETTING_BRIDGE_PRIORITY, + "", + "", + NM_BRIDGE_PRIORITY_MIN, + NM_BRIDGE_PRIORITY_MAX, + NM_BRIDGE_PRIORITY_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:forward-delay: + * + * The Spanning Tree Protocol (STP) forwarding delay, in seconds. + **/ + /* ---ifcfg-rh--- + * property: forward-delay + * variable: DELAY + * values: 2 - 30 + * default: 15 + * description: STP forwarding delay. + * ---end--- + */ + obj_properties[PROP_FORWARD_DELAY] = + g_param_spec_uint(NM_SETTING_BRIDGE_FORWARD_DELAY, + "", + "", + 0, + NM_BRIDGE_FORWARD_DELAY_MAX, + NM_BRIDGE_FORWARD_DELAY_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:hello-time: + * + * The Spanning Tree Protocol (STP) hello time, in seconds. + **/ + /* ---ifcfg-rh--- + * property: hello-time + * variable: BRIDGING_OPTS: hello_time= + * values: 1 - 10 + * default: 2 + * description: STP hello time. + * ---end--- + */ + obj_properties[PROP_HELLO_TIME] = + g_param_spec_uint(NM_SETTING_BRIDGE_HELLO_TIME, + "", + "", + 0, + NM_BRIDGE_HELLO_TIME_MAX, + NM_BRIDGE_HELLO_TIME_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:max-age: + * + * The Spanning Tree Protocol (STP) maximum message age, in seconds. + **/ + /* ---ifcfg-rh--- + * property: max-age + * variable: BRIDGING_OPTS: max_age= + * values: 6 - 40 + * default: 20 + * description: STP maximum message age. + * ---end--- + */ + obj_properties[PROP_MAX_AGE] = + g_param_spec_uint(NM_SETTING_BRIDGE_MAX_AGE, + "", + "", + 0, + NM_BRIDGE_MAX_AGE_MAX, + NM_BRIDGE_MAX_AGE_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:ageing-time: + * + * The Ethernet MAC address aging time, in seconds. + **/ + /* ---ifcfg-rh--- + * property: ageing-time + * variable: BRIDGING_OPTS: ageing_time= + * values: 0 - 1000000 + * default: 300 + * description: Ethernet MAC ageing time. + * ---end--- + */ + obj_properties[PROP_AGEING_TIME] = + g_param_spec_uint(NM_SETTING_BRIDGE_AGEING_TIME, + "", + "", + NM_BRIDGE_AGEING_TIME_MIN, + NM_BRIDGE_AGEING_TIME_MAX, + NM_BRIDGE_AGEING_TIME_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:group-forward-mask: + * + * A mask of group addresses to forward. Usually, group addresses in + * the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not + * forwarded according to standards. This property is a mask of 16 bits, + * each corresponding to a group address in that range that must be + * forwarded. The mask can't have bits 0, 1 or 2 set because they are + * used for STP, MAC pause frames and LACP. + * + * Since: 1.10 + **/ + obj_properties[PROP_GROUP_FORWARD_MASK] = + g_param_spec_uint(NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, + "", + "", + 0, + 0xFFFF, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-snooping: + * + * Controls whether IGMP snooping is enabled for this bridge. + * Note that if snooping was automatically disabled due to hash collisions, + * the system may refuse to enable the feature until the collisions are + * resolved. + * + * Since: 1.2 + **/ + /* ---ifcfg-rh--- + * property: multicast-snooping + * variable: BRIDGING_OPTS: multicast_snooping= + * values: 0 or 1 + * default: 1 + * description: IGMP snooping support. + * ---end--- + */ + obj_properties[PROP_MULTICAST_SNOOPING] = g_param_spec_boolean( + NM_SETTING_BRIDGE_MULTICAST_SNOOPING, + "", + "", + NM_BRIDGE_MULTICAST_SNOOPING_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:vlan-filtering: + * + * Control whether VLAN filtering is enabled on the bridge. + * + * Since: 1.18 + **/ + /* ---ifcfg-rh--- + * property: vlan-filtering + * variable: BRIDGING_OPTS: vlan_filtering= + * values: 0 or 1 + * default: 0 + * description: VLAN filtering support. + * ---end--- + */ + obj_properties[PROP_VLAN_FILTERING] = g_param_spec_boolean( + NM_SETTING_BRIDGE_VLAN_FILTERING, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:vlan-default-pvid: + * + * The default PVID for the ports of the bridge, that is the VLAN id + * assigned to incoming untagged frames. + * + * Since: 1.18 + **/ + /* ---ifcfg-rh--- + * property: vlan-default-pvid + * variable: BRIDGING_OPTS: default_pvid= + * values: 0 - 4094 + * default: 1 + * description: default VLAN PVID. + * ---end--- + */ + obj_properties[PROP_VLAN_DEFAULT_PVID] = + g_param_spec_uint(NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, + "", + "", + 0, + NM_BRIDGE_VLAN_VID_MAX, + NM_BRIDGE_VLAN_DEFAULT_PVID_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:vlans: (type GPtrArray(NMBridgeVlan)) + * + * Array of bridge VLAN objects. In addition to the VLANs + * specified here, the bridge will also have the default-pvid + * VLAN configured by the bridge.vlan-default-pvid property. + * + * In nmcli the VLAN list can be specified with the following + * syntax: + * + * $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... + * + * where $vid is either a single id between 1 and 4094 or a + * range, represented as a couple of ids separated by a dash. + * + * Since: 1.18 + **/ + /* ---ifcfg-rh--- + * property: vlans + * variable: BRIDGE_VLANS + * description: List of VLANs on the bridge + * example: BRIDGE_VLANS="1 pvid untagged,20,300-400 untagged" + * ---end--- + */ + obj_properties[PROP_VLANS] = g_param_spec_boxed(NM_SETTING_BRIDGE_VLANS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_VLANS], + &nm_sett_info_propert_type_bridge_vlans); + + /* ---dbus--- + * property: interface-name + * format: string + * description: Deprecated in favor of connection.interface-name, but can + * be used for backward-compatibility with older daemons, to set the + * bridge's interface name. + * ---end--- + */ + _nm_properties_override_dbus(properties_override, + "interface-name", + &nm_sett_info_propert_type_deprecated_interface_name); + + /** + * NMSettingBridge:group-address: + * + * If specified, The MAC address of the multicast group this bridge uses for STP. + * + * The address must be a link-local address in standard Ethernet MAC address format, + * ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. + * If not specified the default value is 01:80:C2:00:00:00. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: group-address + * variable: BRIDGING_OPTS: group_address= + * description: STP group address. + * example: BRIDGING_OPTS="group_address=01:80:C2:00:00:0A" + * ---end--- + */ + obj_properties[PROP_GROUP_ADDRESS] = g_param_spec_string( + NM_SETTING_BRIDGE_GROUP_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_GROUP_ADDRESS], + &nm_sett_info_propert_type_mac_address); + + /** + * NMSettingBridge:vlan-protocol: + * + * If specified, the protocol used for VLAN filtering. + * + * Supported values are: '802.1Q', '802.1ad'. + * If not specified the default value is '802.1Q'. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: vlan-protocol + * variable: BRIDGING_OPTS: vlan_protocol= + * description: VLAN filtering protocol. + * example: BRIDGING_OPTS="vlan_protocol=802.1Q" + * ---end--- + * + * Since: 1.24 + */ + obj_properties[PROP_VLAN_PROTOCOL] = g_param_spec_string( + NM_SETTING_BRIDGE_VLAN_PROTOCOL, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:vlan-stats-enabled: + * + * Controls whether per-VLAN stats accounting is enabled. + **/ + /* ---ifcfg-rh--- + * property: vlan-stats-enabled + * variable: BRIDGING_OPTS: vlan_stats_enabled= + * default: 0 + * example: BRIDGING_OPTS="vlan_stats_enabled=1" + * ---end--- + * + * Since: 1.24 + */ + obj_properties[PROP_VLAN_STATS_ENABLED] = g_param_spec_boolean( + NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, + "", + "", + NM_BRIDGE_VLAN_STATS_ENABLED_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-router: + * + * Sets bridge's multicast router. Multicast-snooping must be enabled + * for this option to work. + * + * Supported values are: 'auto', 'disabled', 'enabled' to which kernel + * assigns the numbers 1, 0, and 2, respectively. + * If not specified the default value is 'auto' (1). + **/ + /* ---ifcfg-rh--- + * property: multicast-router + * variable: BRIDGING_OPTS: multicast_router= + * values: auto, enabled, disabled + * default: auto + * example: BRIDGING_OPTS="multicast_router=enabled" + * ---end--- + * + * Since: 1.24 + */ + obj_properties[PROP_MULTICAST_ROUTER] = g_param_spec_string( + NM_SETTING_BRIDGE_MULTICAST_ROUTER, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-query-use-ifaddr: + * + * If enabled the bridge's own IP address is used as + * the source address for IGMP queries otherwise + * the default of 0.0.0.0 is used. + **/ + /* ---ifcfg-rh--- + * property: multicast-query-use-ifaddr + * variable: BRIDGING_OPTS: multicast_query_use_ifaddr= + * default: 0 + * example: BRIDGING_OPTS="multicast_query-use_ifaddr=1" + * ---end--- + * + * Since: 1.24 + */ + obj_properties[PROP_MULTICAST_QUERY_USE_IFADDR] = g_param_spec_boolean( + NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, + "", + "", + NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-querier: + * + * Enable or disable sending of multicast queries by the bridge. + * If not specified the option is disabled. + **/ + /* ---ifcfg-rh--- + * property: multicast-querier + * variable: BRIDGING_OPTS: multicast_querier= + * default: 0 + * example: BRIDGING_OPTS="multicast_querier=1" + * ---end--- + * + * Since: 1.24 + */ + obj_properties[PROP_MULTICAST_QUERIER] = g_param_spec_boolean( + NM_SETTING_BRIDGE_MULTICAST_QUERIER, + "", + "", + NM_BRIDGE_MULTICAST_QUERIER_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-hash-max: + * + * Set maximum size of multicast hash table (value must be a power of 2). + **/ + /* ---ifcfg-rh--- + * property: multicast-hash-max + * variable: BRIDGING_OPTS: multicast_hash_max= + * default: 4096 + * example: BRIDGING_OPTS="multicast_hash_max=8192" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_HASH_MAX] = + g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_HASH_MAX, + "", + "", + NM_BRIDGE_MULTICAST_HASH_MAX_MIN, + NM_BRIDGE_MULTICAST_HASH_MAX_MAX, + NM_BRIDGE_MULTICAST_HASH_MAX_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-last-member-count: + * + * Set the number of queries the bridge will send before + * stopping forwarding a multicast group after a "leave" + * message has been received. + **/ + /* ---ifcfg-rh--- + * property: multicast-last-member-count + * variable: BRIDGING_OPTS: multicast_last_member_count= + * default: 2 + * example: BRIDGING_OPTS="multicast_last_member_count=4" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_LAST_MEMBER_COUNT] = + g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_COUNT, + "", + "", + NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MIN, + NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MAX, + NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-last-member-interval: + * + * Set interval (in deciseconds) between queries to find remaining + * members of a group, after a "leave" message is received. + **/ + /* ---ifcfg-rh--- + * property: multicast-last-member-interval + * variable: BRIDGING_OPTS: multicast_last_member_interval= + * default: 100 + * example: BRIDGING_OPTS="multicast_last_member_interval=200" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_LAST_MEMBER_INTERVAL] = g_param_spec_uint64( + NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL, + "", + "", + NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MIN, + NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MAX, + NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-membership-interval: + * + * Set delay (in deciseconds) after which the bridge will + * leave a group, if no membership reports for this + * group are received. + **/ + /* ---ifcfg-rh--- + * property: multicast-membership-interval + * variable: BRIDGING_OPTS: multicast_membership_interval= + * default: 26000 + * example: BRIDGING_OPTS="multicast_membership_interval=16000" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_MEMBERSHIP_INTERVAL] = g_param_spec_uint64( + NM_SETTING_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL, + "", + "", + NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MIN, + NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MAX, + NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-querier-interval: + * + * If no queries are seen after this delay (in deciseconds) has passed, + * the bridge will start to send its own queries. + **/ + /* ---ifcfg-rh--- + * property: multicast-querier-interval + * variable: BRIDGING_OPTS: multicast_querier_interval= + * default: 25500 + * example: BRIDGING_OPTS="multicast_querier_interval=20000" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_QUERIER_INTERVAL] = g_param_spec_uint64( + NM_SETTING_BRIDGE_MULTICAST_QUERIER_INTERVAL, + "", + "", + NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MIN, + NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MAX, + NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-query-interval: + * + * Interval (in deciseconds) between queries sent + * by the bridge after the end of the startup phase. + **/ + /* ---ifcfg-rh--- + * property: multicast-query-interval + * variable: BRIDGING_OPTS: multicast_query_interval= + * default: 12500 + * example: BRIDGING_OPTS="multicast_query_interval=22500" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_QUERY_INTERVAL] = g_param_spec_uint64( + NM_SETTING_BRIDGE_MULTICAST_QUERY_INTERVAL, + "", + "", + NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MIN, + NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MAX, + NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-query-response-interval: + * + * Set the Max Response Time/Max Response Delay + * (in deciseconds) for IGMP/MLD queries sent by the bridge. + **/ + /* ---ifcfg-rh--- + * property: multicast-query-response-interval + * variable: BRIDGING_OPTS: multicast_query_response_interval= + * default: 1000 + * example: BRIDGING_OPTS="multicast_query_response_interval=2000" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_QUERY_RESPONSE_INTERVAL] = g_param_spec_uint64( + NM_SETTING_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL, + "", + "", + NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MIN, + NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MAX, + NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-startup-query-count: + * + * Set the number of IGMP queries to send during startup phase. + **/ + /* ---ifcfg-rh--- + * property: multicast-startup-query-count + * variable: BRIDGING_OPTS: multicast_startup_query_count= + * default: 2 + * example: BRIDGING_OPTS="multicast_startup_query_count=4" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_STARTUP_QUERY_COUNT] = + g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT, + "", + "", + NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MIN, + NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MAX, + NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingBridge:multicast-startup-query-interval: + * + * Sets the time (in deciseconds) between queries sent out + * at startup to determine membership information. + **/ + /* ---ifcfg-rh--- + * property: multicast-startup-query-interval + * variable: BRIDGING_OPTS: multicast_startup_query_interval= + * default: 3125 + * example: BRIDGING_OPTS="multicast_startup_query_interval=4000" + * ---end--- + * + * Since: 1.26 + */ + obj_properties[PROP_MULTICAST_STARTUP_QUERY_INTERVAL] = g_param_spec_uint64( + NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL, + "", + "", + NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MIN, + NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MAX, + NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_BRIDGE, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-cdma.c b/src/libnm-core-impl/nm-setting-cdma.c new file mode 100644 index 0000000000..bb30d10425 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-cdma.c @@ -0,0 +1,358 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-cdma.h" + +#include "nm-utils.h" +#include "nm-setting-private.h" +#include "nm-core-enum-types.h" + +/** + * SECTION:nm-setting-cdma + * @short_description: Describes CDMA-based mobile broadband properties + * + * The #NMSettingCdma object is a #NMSetting subclass that describes + * properties that allow connections to IS-95-based mobile broadband + * networks, including those using CDMA2000/EVDO technology. + */ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_NUMBER, + PROP_USERNAME, + PROP_PASSWORD, + PROP_PASSWORD_FLAGS, + PROP_MTU, ); + +typedef struct { + char * number; /* For dialing, duh */ + char * username; + char * password; + guint32 mtu; + NMSettingSecretFlags password_flags; +} NMSettingCdmaPrivate; + +G_DEFINE_TYPE(NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING) + +#define NM_SETTING_CDMA_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_CDMA, NMSettingCdmaPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_cdma_get_number: + * @setting: the #NMSettingCdma + * + * Returns: the #NMSettingCdma:number property of the setting + **/ +const char * +nm_setting_cdma_get_number(NMSettingCdma *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), NULL); + + return NM_SETTING_CDMA_GET_PRIVATE(setting)->number; +} + +/** + * nm_setting_cdma_get_username: + * @setting: the #NMSettingCdma + * + * Returns: the #NMSettingCdma:username property of the setting + **/ +const char * +nm_setting_cdma_get_username(NMSettingCdma *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), NULL); + + return NM_SETTING_CDMA_GET_PRIVATE(setting)->username; +} + +/** + * nm_setting_cdma_get_password: + * @setting: the #NMSettingCdma + * + * Returns: the #NMSettingCdma:password property of the setting + **/ +const char * +nm_setting_cdma_get_password(NMSettingCdma *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), NULL); + + return NM_SETTING_CDMA_GET_PRIVATE(setting)->password; +} + +/** + * nm_setting_cdma_get_password_flags: + * @setting: the #NMSettingCdma + * + * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingCdma:password + **/ +NMSettingSecretFlags +nm_setting_cdma_get_password_flags(NMSettingCdma *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_CDMA_GET_PRIVATE(setting)->password_flags; +} + +/** + * nm_setting_cdma_get_mtu: + * @setting: the #NMSettingCdma + * + * Returns: the #NMSettingCdma:mtu property of the setting + * + * Since: 1.8 + **/ +guint32 +nm_setting_cdma_get_mtu(NMSettingCdma *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CDMA(setting), 0); + + return NM_SETTING_CDMA_GET_PRIVATE(setting)->mtu; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(setting); + + if (!priv->number) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_NUMBER); + return FALSE; + } else if (!strlen(priv->number)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_NUMBER); + return FALSE; + } + + if (priv->username && !strlen(priv->username)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_USERNAME); + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) +{ + return _nm_setting_verify_secret_string(NM_SETTING_CDMA_GET_PRIVATE(setting)->password, + NM_SETTING_CDMA_SETTING_NAME, + NM_SETTING_CDMA_PASSWORD, + error); +} + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(setting); + GPtrArray * secrets = NULL; + + if (priv->password && *priv->password) + return NULL; + + if (priv->username) { + if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { + secrets = g_ptr_array_sized_new(1); + g_ptr_array_add(secrets, NM_SETTING_CDMA_PASSWORD); + } + } + + return secrets; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingCdma *setting = NM_SETTING_CDMA(object); + + switch (prop_id) { + case PROP_NUMBER: + g_value_set_string(value, nm_setting_cdma_get_number(setting)); + break; + case PROP_USERNAME: + g_value_set_string(value, nm_setting_cdma_get_username(setting)); + break; + case PROP_PASSWORD: + g_value_set_string(value, nm_setting_cdma_get_password(setting)); + break; + case PROP_PASSWORD_FLAGS: + g_value_set_flags(value, nm_setting_cdma_get_password_flags(setting)); + break; + case PROP_MTU: + g_value_set_uint(value, nm_setting_cdma_get_mtu(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_NUMBER: + g_free(priv->number); + priv->number = g_value_dup_string(value); + break; + case PROP_USERNAME: + g_free(priv->username); + priv->username = g_value_dup_string(value); + break; + case PROP_PASSWORD: + g_free(priv->password); + priv->password = g_value_dup_string(value); + break; + case PROP_PASSWORD_FLAGS: + priv->password_flags = g_value_get_flags(value); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_cdma_init(NMSettingCdma *setting) +{} + +/** + * nm_setting_cdma_new: + * + * Creates a new #NMSettingCdma object with default values. + * + * Returns: the new empty #NMSettingCdma object + **/ +NMSetting * +nm_setting_cdma_new(void) +{ + return g_object_new(NM_TYPE_SETTING_CDMA, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(object); + + g_free(priv->number); + g_free(priv->username); + g_free(priv->password); + + G_OBJECT_CLASS(nm_setting_cdma_parent_class)->finalize(object); +} + +static void +nm_setting_cdma_class_init(NMSettingCdmaClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingCdmaPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; + + /** + * NMSettingCdma:number: + * + * The number to dial to establish the connection to the CDMA-based mobile + * broadband network, if any. If not specified, the default number (#777) + * is used when required. + **/ + obj_properties[PROP_NUMBER] = g_param_spec_string(NM_SETTING_CDMA_NUMBER, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingCdma:username: + * + * The username used to authenticate with the network, if required. Many + * providers do not require a username, or accept any username. But if a + * username is required, it is specified here. + **/ + obj_properties[PROP_USERNAME] = g_param_spec_string(NM_SETTING_CDMA_USERNAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingCdma:password: + * + * The password used to authenticate with the network, if required. Many + * providers do not require a password, or accept any password. But if a + * password is required, it is specified here. + **/ + obj_properties[PROP_PASSWORD] = + g_param_spec_string(NM_SETTING_CDMA_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingCdma:password-flags: + * + * Flags indicating how to handle the #NMSettingCdma:password property. + **/ + obj_properties[PROP_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_CDMA_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingCdma:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple frames. + * + * Since: 1.8 + **/ + obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_CDMA_MTU, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_CDMA); +} diff --git a/src/libnm-core-impl/nm-setting-connection.c b/src/libnm-core-impl/nm-setting-connection.c new file mode 100644 index 0000000000..38ba6663fb --- /dev/null +++ b/src/libnm-core-impl/nm-setting-connection.c @@ -0,0 +1,2529 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-connection.h" + +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-core-enum-types.h" +#include "nm-connection-private.h" +#include "nm-setting-bond.h" +#include "nm-setting-bridge.h" +#include "nm-setting-team.h" +#include "nm-setting-vlan.h" +#include "systemd/nm-sd-utils-shared.h" + +/** + * SECTION:nm-setting-connection + * @short_description: Describes general connection properties + * + * The #NMSettingConnection object is a #NMSetting subclass that describes + * properties that apply to all #NMConnection objects, regardless of what type + * of network connection they describe. Each #NMConnection object must contain + * a #NMSettingConnection setting. + **/ + +/*****************************************************************************/ + +typedef enum _nm_packed { + PERM_TYPE_INVALID, + PERM_TYPE_USER, +} PermType; + +typedef struct { + PermType ptype; + char * item; +} Permission; + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingConnection, + PROP_ID, + PROP_UUID, + PROP_INTERFACE_NAME, + PROP_TYPE, + PROP_PERMISSIONS, + PROP_AUTOCONNECT, + PROP_AUTOCONNECT_PRIORITY, + PROP_AUTOCONNECT_RETRIES, + PROP_MULTI_CONNECT, + PROP_TIMESTAMP, + PROP_READ_ONLY, + PROP_ZONE, + PROP_MASTER, + PROP_SLAVE_TYPE, + PROP_AUTOCONNECT_SLAVES, + PROP_SECONDARIES, + PROP_GATEWAY_PING_TIMEOUT, + PROP_METERED, + PROP_LLDP, + PROP_MDNS, + PROP_LLMNR, + PROP_STABLE_ID, + PROP_AUTH_RETRIES, + PROP_WAIT_DEVICE_TIMEOUT, + PROP_MUD_URL, ); + +typedef struct { + GArray *permissions; + GSList *secondaries; /* secondary connections to activate with the base connection */ + char * id; + char * uuid; + char * stable_id; + char * interface_name; + char * type; + char * master; + char * slave_type; + char * zone; + char * mud_url; + guint64 timestamp; + int autoconnect_priority; + int autoconnect_retries; + int multi_connect; + int auth_retries; + int mdns; + int llmnr; + int wait_device_timeout; + guint gateway_ping_timeout; + NMSettingConnectionAutoconnectSlaves autoconnect_slaves; + NMMetered metered; + NMSettingConnectionLldp lldp; + bool read_only : 1; + bool autoconnect : 1; +} NMSettingConnectionPrivate; + +G_DEFINE_TYPE(NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING) + +#define NM_SETTING_CONNECTION_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate)) + +/*****************************************************************************/ + +static void +_permission_set_stale(Permission *permission, PermType ptype, char *item_take) +{ + nm_assert(permission); + nm_assert(NM_IN_SET(ptype, PERM_TYPE_INVALID, PERM_TYPE_USER)); + nm_assert(ptype != PERM_TYPE_USER + || nm_settings_connection_validate_permission_user(item_take, -1)); + + /* we don't inspect (clear) permission before setting. It takes a + * stale instance. */ + *permission = (Permission){ + .ptype = ptype, + .item = item_take, + }; +} + +static void +_permission_clear_stale(Permission *permission) +{ + g_free(permission->item); + /* We leave the permission instance with dangling pointers. + * It is "stale". */ +} + +static gboolean +_permission_set_stale_parse(Permission *permission, const char *str) +{ + const char *str0 = str; + const char *last_colon; + gsize ulen; + + nm_assert(str); + + if (!str) + goto invalid; + + if (!NM_STR_HAS_PREFIX(str, NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX)) + goto invalid; + + str += NM_STRLEN(NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX); + + last_colon = strrchr(str, ':'); + if (last_colon) { + /* Reject :[detail] for now */ + if (last_colon[1] != '\0') + goto invalid; + ulen = last_colon - str; + } else + ulen = strlen(str); + + if (!nm_settings_connection_validate_permission_user(str, ulen)) + goto invalid; + + /* Yay, valid... create the new permission */ + if (permission) + _permission_set_stale(permission, PERM_TYPE_USER, g_strndup(str, ulen)); + return TRUE; + +invalid: + if (permission) + _permission_set_stale(permission, PERM_TYPE_INVALID, g_strdup(str0)); + return FALSE; +} + +static char * +_permission_to_string(Permission *permission) +{ + nm_assert(permission); + + switch (permission->ptype) { + case PERM_TYPE_USER: + return g_strdup_printf(NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX "%s:", + permission->item); + case PERM_TYPE_INVALID: + nm_assert(permission->item); + return g_strdup(permission->item); + } + nm_assert_not_reached(); + return g_strdup(permission->item ?: ""); +} + +/*****************************************************************************/ + +/** + * nm_setting_connection_get_id: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:id property of the connection. + * + * Returns: the connection ID + **/ +const char * +nm_setting_connection_get_id(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->id; +} + +/** + * nm_setting_connection_get_uuid: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:uuid property of the connection. + * + * Returns: the connection UUID + **/ +const char * +nm_setting_connection_get_uuid(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->uuid; +} + +/** + * nm_setting_connection_get_stable_id: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:stable_id property of the connection. + * + * Returns: the stable-id for the connection + * + * Since: 1.4 + **/ +const char * +nm_setting_connection_get_stable_id(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->stable_id; +} + +/** + * nm_setting_connection_get_interface_name: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:interface-name property of the connection. + * + * Returns: the connection's interface name + **/ +const char * +nm_setting_connection_get_interface_name(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->interface_name; +} + +/** + * nm_setting_connection_get_connection_type: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:type property of the connection. + * + * Returns: the connection type + **/ +const char * +nm_setting_connection_get_connection_type(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->type; +} + +/** + * nm_setting_connection_get_num_permissions: + * @setting: the #NMSettingConnection + * + * Returns the number of entries in the #NMSettingConnection:permissions + * property of this setting. + * + * Returns: the number of permissions entries + */ +guint32 +nm_setting_connection_get_num_permissions(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); + + return nm_g_array_len(NM_SETTING_CONNECTION_GET_PRIVATE(setting)->permissions); +} + +/** + * nm_setting_connection_get_permission: + * @setting: the #NMSettingConnection + * @idx: the zero-based index of the permissions entry + * @out_ptype: on return, the permission type. This is currently always "user", + * unless the entry is invalid, in which case it returns "invalid". + * @out_pitem: on return, the permission item (formatted according to @ptype, see + * #NMSettingConnection:permissions for more detail + * @out_detail: on return, the permission detail (at this time, always %NULL) + * + * Retrieve one of the entries of the #NMSettingConnection:permissions property + * of this setting. + * + * Returns: %TRUE if a permission was returned, %FALSE if @idx was invalid + */ +gboolean +nm_setting_connection_get_permission(NMSettingConnection *setting, + guint32 idx, + const char ** out_ptype, + const char ** out_pitem, + const char ** out_detail) +{ + NMSettingConnectionPrivate *priv; + Permission * permission; + + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + + g_return_val_if_fail(idx < nm_g_array_len(priv->permissions), FALSE); + + permission = &g_array_index(priv->permissions, Permission, idx); + switch (permission->ptype) { + case PERM_TYPE_USER: + NM_SET_OUT(out_ptype, NM_SETTINGS_CONNECTION_PERMISSION_USER); + NM_SET_OUT(out_pitem, permission->item); + NM_SET_OUT(out_detail, NULL); + return TRUE; + case PERM_TYPE_INVALID: + goto invalid; + } + nm_assert_not_reached(); +invalid: + NM_SET_OUT(out_ptype, "invalid"); + NM_SET_OUT(out_pitem, permission->item); + NM_SET_OUT(out_detail, NULL); + return TRUE; +} + +/** + * nm_setting_connection_permissions_user_allowed: + * @setting: the #NMSettingConnection + * @uname: the user name to check permissions for + * + * Checks whether the given username is allowed to view/access this connection. + * + * Returns: %TRUE if the requested user is allowed to view this connection, + * %FALSE if the given user is not allowed to view this connection + */ +gboolean +nm_setting_connection_permissions_user_allowed(NMSettingConnection *setting, const char *uname) +{ + NMSettingConnectionPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); + g_return_val_if_fail(uname != NULL, FALSE); + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + + if (nm_g_array_len(priv->permissions) == 0) { + /* If no permissions, visible to all */ + return TRUE; + } + + for (i = 0; i < priv->permissions->len; i++) { + const Permission *permission = &g_array_index(priv->permissions, Permission, i); + + if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, uname)) + return TRUE; + } + + return FALSE; +} + +/** + * nm_setting_connection_add_permission: + * @setting: the #NMSettingConnection + * @ptype: the permission type; at this time only "user" is supported + * @pitem: the permission item formatted as required for @ptype + * @detail: (allow-none): unused at this time; must be %NULL + * + * Adds a permission to the connection's permission list. At this time, only + * the "user" permission type is supported, and @pitem must be a username. See + * #NMSettingConnection:permissions: for more details. + * + * Returns: %TRUE if the permission was unique and was successfully added to the + * list, %FALSE if @ptype or @pitem was invalid. + * If the permission was already present in the list, it will not be added + * a second time but %TRUE will be returned. Note that before 1.28, in this + * case %FALSE would be returned. + */ +gboolean +nm_setting_connection_add_permission(NMSettingConnection *setting, + const char * ptype, + const char * pitem, + const char * detail) +{ + NMSettingConnectionPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); + g_return_val_if_fail(ptype, FALSE); + g_return_val_if_fail(pitem, FALSE); + + if (!nm_streq0(ptype, NM_SETTINGS_CONNECTION_PERMISSION_USER)) + return FALSE; + + if (!nm_settings_connection_validate_permission_user(pitem, -1)) + return FALSE; + + if (detail) + return FALSE; + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + + if (!priv->permissions) { + priv->permissions = g_array_sized_new(FALSE, FALSE, sizeof(Permission), 1); + g_array_set_clear_func(priv->permissions, (GDestroyNotify) _permission_clear_stale); + } + + for (i = 0; i < priv->permissions->len; i++) { + const Permission *permission = &g_array_index(priv->permissions, Permission, i); + + if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, pitem)) + return TRUE; + } + + _permission_set_stale(nm_g_array_append_new(priv->permissions, Permission), + PERM_TYPE_USER, + g_strdup(pitem)); + _notify(setting, PROP_PERMISSIONS); + return TRUE; +} + +/** + * nm_setting_connection_remove_permission: + * @setting: the #NMSettingConnection + * @idx: the zero-based index of the permission to remove + * + * Removes the permission at index @idx from the connection. + */ +void +nm_setting_connection_remove_permission(NMSettingConnection *setting, guint32 idx) +{ + NMSettingConnectionPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_CONNECTION(setting)); + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + + g_return_if_fail(idx < nm_g_array_len(priv->permissions)); + + g_array_remove_index(priv->permissions, idx); + + _notify(setting, PROP_PERMISSIONS); +} + +/** + * nm_setting_connection_remove_permission_by_value: + * @setting: the #NMSettingConnection + * @ptype: the permission type; at this time only "user" is supported + * @pitem: the permission item formatted as required for @ptype + * @detail: (allow-none): unused at this time; must be %NULL + * + * Removes the permission from the connection. + * At this time, only the "user" permission type is supported, and @pitem must + * be a username. See #NMSettingConnection:permissions: for more details. + * + * Returns: %TRUE if the permission was found and removed; %FALSE if it was not. + */ +gboolean +nm_setting_connection_remove_permission_by_value(NMSettingConnection *setting, + const char * ptype, + const char * pitem, + const char * detail) +{ + NMSettingConnectionPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); + g_return_val_if_fail(ptype, FALSE); + g_return_val_if_fail(pitem, FALSE); + + if (!nm_streq0(ptype, NM_SETTINGS_CONNECTION_PERMISSION_USER)) + return FALSE; + + if (detail) + return FALSE; + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + if (priv->permissions) { + for (i = 0; i < priv->permissions->len; i++) { + const Permission *permission = &g_array_index(priv->permissions, Permission, i); + + if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, pitem)) { + g_array_remove_index(priv->permissions, i); + _notify(setting, PROP_PERMISSIONS); + return TRUE; + } + } + } + return FALSE; +} + +/** + * nm_setting_connection_get_autoconnect: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:autoconnect property of the connection. + * + * Returns: the connection's autoconnect behavior + **/ +gboolean +nm_setting_connection_get_autoconnect(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->autoconnect; +} + +/** + * nm_setting_connection_get_autoconnect_priority: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:autoconnect-priority property of the connection. + * The higher number, the higher priority. + * + * Returns: the connection's autoconnect priority + **/ +int +nm_setting_connection_get_autoconnect_priority(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->autoconnect_priority; +} + +/** + * nm_setting_connection_get_autoconnect_retries: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:autoconnect-retries property of the connection. + * Zero means infinite, -1 means the global default value. + * + * Returns: the connection's autoconnect retries + * + * Since: 1.6 + **/ +int +nm_setting_connection_get_autoconnect_retries(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), -1); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->autoconnect_retries; +} + +/** + * nm_setting_connection_get_multi_connect: + * @setting: the #NMSettingConnection + * + * Returns: the #NMSettingConnection:multi-connect property of the connection. + * + * Since: 1.14 + **/ +NMConnectionMultiConnect +nm_setting_connection_get_multi_connect(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), -1); + + return (NMConnectionMultiConnect) NM_SETTING_CONNECTION_GET_PRIVATE(setting)->multi_connect; +} + +/** + * nm_setting_connection_get_auth_retries: + * @setting: the #NMSettingConnection + * + * Returns the value contained in the #NMSettingConnection:auth-retries property. + * + * Returns: the configured authentication retries. Zero means + * infinity and -1 means a global default value. + * + * Since: 1.10 + **/ +int +nm_setting_connection_get_auth_retries(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), -1); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->auth_retries; +} + +/** + * nm_setting_connection_get_timestamp: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:timestamp property of the connection. + * + * Returns: the connection's timestamp + **/ +guint64 +nm_setting_connection_get_timestamp(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->timestamp; +} + +static GVariant * +_to_dbus_fcn_timestamp(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + guint64 v; + + v = options && options->timestamp.has ? options->timestamp.val + : NM_SETTING_CONNECTION_GET_PRIVATE(setting)->timestamp; + + if (v == 0u) + return NULL; + + return g_variant_new_uint64(v); +} + +/** + * nm_setting_connection_get_read_only: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:read-only property of the connection. + * + * Returns: %TRUE if the connection is read-only, %FALSE if it is not + **/ +gboolean +nm_setting_connection_get_read_only(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), TRUE); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->read_only; +} + +/** + * nm_setting_connection_get_zone: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:zone property of the connection. + * + * Returns: the trust level of a connection + **/ +const char * +nm_setting_connection_get_zone(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->zone; +} + +/** + * nm_setting_connection_get_master: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:master property of the connection. + * + * Returns: interface name of the master device or UUID of the master + * connection. + */ +const char * +nm_setting_connection_get_master(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->master; +} + +/** + * nm_setting_connection_get_slave_type: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:slave-type property of the connection. + * + * Returns: the type of slave this connection is, if any + */ +const char * +nm_setting_connection_get_slave_type(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->slave_type; +} + +/** + * nm_setting_connection_is_slave_type: + * @setting: the #NMSettingConnection + * @type: the setting name (ie #NM_SETTING_BOND_SETTING_NAME) to be matched + * against @setting's slave type + * + * Returns: %TRUE if connection is of the given slave @type + */ +gboolean +nm_setting_connection_is_slave_type(NMSettingConnection *setting, const char *type) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); + + return !g_strcmp0(NM_SETTING_CONNECTION_GET_PRIVATE(setting)->slave_type, type); +} + +/** + * nm_setting_connection_get_wait_device_timeout: + * @setting: the #NMSettingConnection + * + * Returns: the %NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT property with + * the timeout in milliseconds. -1 is the default. + * + * Since: 1.20 + */ +gint32 +nm_setting_connection_get_wait_device_timeout(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), -1); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->wait_device_timeout; +} + +/** + * nm_setting_connection_get_autoconnect_slaves: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:autoconnect-slaves property of the connection. + * + * Returns: whether slaves of the connection should be activated together + * with the connection. + * + * Since: 1.2 + **/ +NMSettingConnectionAutoconnectSlaves +nm_setting_connection_get_autoconnect_slaves(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), + NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->autoconnect_slaves; +} + +/** + * nm_setting_connection_get_num_secondaries: + * @setting: the #NMSettingConnection + * + * Returns: the number of configured secondary connection UUIDs + **/ +guint32 +nm_setting_connection_get_num_secondaries(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); + + return g_slist_length(NM_SETTING_CONNECTION_GET_PRIVATE(setting)->secondaries); +} + +/** + * nm_setting_connection_get_secondary: + * @setting: the #NMSettingConnection + * @idx: the zero-based index of the secondary connection UUID entry + * + * Returns: the secondary connection UUID at index @idx + **/ +const char * +nm_setting_connection_get_secondary(NMSettingConnection *setting, guint32 idx) +{ + NMSettingConnectionPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + g_return_val_if_fail(idx <= g_slist_length(priv->secondaries), NULL); + + return (const char *) g_slist_nth_data(priv->secondaries, idx); +} + +/** + * nm_setting_connection_get_mud_url: + * @setting: the #NMSettingConnection + * + * Returns the value contained in the #NMSettingConnection:mud-url + * property. + * + * Since: 1.26 + **/ +const char * +nm_setting_connection_get_mud_url(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->mud_url; +} + +/** + * nm_setting_connection_add_secondary: + * @setting: the #NMSettingConnection + * @sec_uuid: the secondary connection UUID to add + * + * Adds a new secondary connection UUID to the setting. + * + * Returns: %TRUE if the secondary connection UUID was added; %FALSE if the UUID + * was already present + **/ +gboolean +nm_setting_connection_add_secondary(NMSettingConnection *setting, const char *sec_uuid) +{ + NMSettingConnectionPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); + g_return_val_if_fail(sec_uuid != NULL, FALSE); + g_return_val_if_fail(sec_uuid[0] != '\0', FALSE); + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + for (iter = priv->secondaries; iter; iter = g_slist_next(iter)) { + if (!strcmp(sec_uuid, (char *) iter->data)) + return FALSE; + } + + priv->secondaries = g_slist_append(priv->secondaries, g_strdup(sec_uuid)); + _notify(setting, PROP_SECONDARIES); + return TRUE; +} + +/** + * nm_setting_connection_remove_secondary: + * @setting: the #NMSettingConnection + * @idx: index number of the secondary connection UUID + * + * Removes the secondary connection UUID at index @idx. + **/ +void +nm_setting_connection_remove_secondary(NMSettingConnection *setting, guint32 idx) +{ + NMSettingConnectionPrivate *priv; + GSList * elt; + + g_return_if_fail(NM_IS_SETTING_CONNECTION(setting)); + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + elt = g_slist_nth(priv->secondaries, idx); + g_return_if_fail(elt != NULL); + + g_free(elt->data); + priv->secondaries = g_slist_delete_link(priv->secondaries, elt); + _notify(setting, PROP_SECONDARIES); +} + +/** + * nm_setting_connection_remove_secondary_by_value: + * @setting: the #NMSettingConnection + * @sec_uuid: the secondary connection UUID to remove + * + * Removes the secondary connection UUID @sec_uuid. + * + * Returns: %TRUE if the secondary connection UUID was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_connection_remove_secondary_by_value(NMSettingConnection *setting, const char *sec_uuid) +{ + NMSettingConnectionPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), FALSE); + g_return_val_if_fail(sec_uuid != NULL, FALSE); + g_return_val_if_fail(sec_uuid[0] != '\0', FALSE); + + priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + for (iter = priv->secondaries; iter; iter = g_slist_next(iter)) { + if (!strcmp(sec_uuid, (char *) iter->data)) { + priv->secondaries = g_slist_delete_link(priv->secondaries, iter); + _notify(setting, PROP_SECONDARIES); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_connection_get_gateway_ping_timeout: + * @setting: the #NMSettingConnection + * + * Returns: the value contained in the #NMSettingConnection:gateway-ping-timeout + * property. + **/ +guint32 +nm_setting_connection_get_gateway_ping_timeout(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), 0); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->gateway_ping_timeout; +} + +/** + * nm_setting_connection_get_metered: + * @setting: the #NMSettingConnection + * + * Returns: the #NMSettingConnection:metered property of the setting. + * + * Since: 1.2 + **/ +NMMetered +nm_setting_connection_get_metered(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NM_METERED_UNKNOWN); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->metered; +} + +/** + * nm_setting_connection_get_lldp: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:lldp property of the connection. + * + * Returns: a %NMSettingConnectionLldp which indicates whether LLDP must be + * enabled for the connection. + * + * Since: 1.2 + **/ +NMSettingConnectionLldp +nm_setting_connection_get_lldp(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NM_SETTING_CONNECTION_LLDP_DEFAULT); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->lldp; +} + +/** + * nm_setting_connection_get_mdns: + * @setting: the #NMSettingConnection + * + * Returns: the #NMSettingConnection:mdns property of the setting. + * + * Since: 1.12 + **/ +NMSettingConnectionMdns +nm_setting_connection_get_mdns(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NM_SETTING_CONNECTION_MDNS_DEFAULT); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->mdns; +} + +/** + * nm_setting_connection_get_llmnr: + * @setting: the #NMSettingConnection + * + * Returns: the #NMSettingConnection:llmnr property of the setting. + * + * Since: 1.14 + **/ +NMSettingConnectionLlmnr +nm_setting_connection_get_llmnr(NMSettingConnection *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_CONNECTION(setting), NM_SETTING_CONNECTION_LLMNR_DEFAULT); + + return NM_SETTING_CONNECTION_GET_PRIVATE(setting)->llmnr; +} + +static void +_set_error_missing_base_setting(GError **error, const char *type) +{ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("setting required for connection of type '%s'"), + type); + g_prefix_error(error, "%s: ", type); +} + +gboolean +_nm_connection_detect_slave_type_full(NMSettingConnection *s_con, + NMConnection * connection, + const char ** out_slave_type, + const char ** out_normerr_slave_setting_type, + const char ** out_normerr_missing_slave_type, + const char ** out_normerr_missing_slave_type_port, + GError ** error) +{ + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(s_con); + gboolean is_slave; + const char * slave_setting_type; + const char * slave_type; + const char * normerr_slave_setting_type = NULL; + const char * normerr_missing_slave_type = NULL; + const char * normerr_missing_slave_type_port = NULL; + + is_slave = FALSE; + slave_setting_type = NULL; + slave_type = priv->slave_type; + if (slave_type) { + is_slave = _nm_setting_slave_type_is_valid(slave_type, &slave_setting_type); + if (!is_slave) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Unknown slave type '%s'"), + slave_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + } + + if (is_slave) { + if (!priv->master) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("Slave connections need a valid '%s' property"), + NM_SETTING_CONNECTION_MASTER); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_MASTER); + return FALSE; + } + if (slave_setting_type && connection + && !nm_connection_get_setting_by_name(connection, slave_setting_type)) + normerr_slave_setting_type = slave_setting_type; + } else { + nm_assert(!slave_type); + if (priv->master) { + NMSetting *s_port; + + if (connection + && (slave_type = _nm_connection_detect_slave_type(connection, &s_port))) { + normerr_missing_slave_type = slave_type; + normerr_missing_slave_type_port = nm_setting_get_name(s_port); + } else { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("Cannot set '%s' without '%s'"), + NM_SETTING_CONNECTION_MASTER, + NM_SETTING_CONNECTION_SLAVE_TYPE); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + } + } + + NM_SET_OUT(out_slave_type, slave_type); + NM_SET_OUT(out_normerr_slave_setting_type, normerr_slave_setting_type); + NM_SET_OUT(out_normerr_missing_slave_type, normerr_missing_slave_type); + NM_SET_OUT(out_normerr_missing_slave_type_port, normerr_missing_slave_type_port); + return TRUE; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingConnection * self = NM_SETTING_CONNECTION(setting); + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(self); + NMSetting * normerr_base_type = NULL; + const char * type; + const char * slave_type; + const char * normerr_slave_setting_type = NULL; + const char * normerr_missing_slave_type = NULL; + const char * normerr_missing_slave_type_port = NULL; + gboolean normerr_base_setting = FALSE; + + if (!priv->id) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + return FALSE; + } else if (!priv->id[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + return FALSE; + } + + if (priv->uuid && !nm_utils_is_uuid(priv->uuid)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid UUID"), + priv->uuid); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_UUID); + return FALSE; + } + + type = priv->type; + if (!type) { + if (!connection + || !(normerr_base_type = _nm_connection_find_base_type_setting(connection))) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TYPE); + return FALSE; + } + type = nm_setting_get_name(normerr_base_type); + } else { + GType base_type; + + if (!type[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TYPE); + return FALSE; + } + + base_type = nm_setting_lookup_type(type); + if (base_type == G_TYPE_INVALID + || _nm_setting_type_get_base_type_priority(base_type) == NM_SETTING_PRIORITY_INVALID) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("connection type '%s' is not valid"), + type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TYPE); + return FALSE; + } + + /* Make sure the corresponding 'type' item is present */ + if (connection && !nm_connection_get_setting_by_name(connection, type)) { + NMSetting * s_base; + NMConnection *connection2; + + s_base = g_object_new(base_type, NULL); + connection2 = nm_simple_connection_new_clone(connection); + nm_connection_add_setting(connection2, s_base); + + normerr_base_setting = nm_setting_verify(s_base, connection2, NULL); + + g_object_unref(connection2); + + if (!normerr_base_setting) { + _set_error_missing_base_setting(error, type); + return FALSE; + } + } + } + + if (priv->interface_name) { + GError * tmp_error = NULL; + NMUtilsIfaceType iface_type; + + if (NM_IN_STRSET(type, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME)) + iface_type = NMU_IFACE_OVS; + else if (nm_streq(type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) { + NMSettingOvsInterface *s_ovs_iface = NULL; + const char * ovs_iface_type; + + if (connection) + s_ovs_iface = nm_connection_get_setting_ovs_interface(connection); + _nm_setting_ovs_interface_verify_interface_type( + s_ovs_iface, + s_ovs_iface ? nm_setting_ovs_interface_get_interface_type(s_ovs_iface) : NULL, + connection, + FALSE, + NULL, + &ovs_iface_type, + NULL); + if (!ovs_iface_type) { + /* We cannot determine to OVS interface type. Consequently, we cannot + * fully validate the interface name. + * + * If we have a connection (and we do a full validation anyway), skip the + * check. The connection will fail validation when we validate the OVS setting. + * + * Otherwise, do the most basic validation. + */ + if (connection) + goto after_interface_name; + iface_type = NMU_IFACE_ANY; + } else if (NM_IN_STRSET(ovs_iface_type, "patch")) { + /* this interface type is internal to OVS. */ + iface_type = NMU_IFACE_OVS; + } else { + /* This interface type also requires a netdev. We need to validate + * for both OVS and KERNEL. */ + nm_assert(NM_IN_STRSET(ovs_iface_type, "internal", "system", "dpdk")); + iface_type = NMU_IFACE_OVS_AND_KERNEL; + } + } else + iface_type = NMU_IFACE_KERNEL; + + if (!nm_utils_ifname_valid(priv->interface_name, iface_type, &tmp_error)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "'%s': %s", + priv->interface_name, + tmp_error->message); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME); + g_error_free(tmp_error); + return FALSE; + } + } +after_interface_name: + + if (!_nm_connection_detect_slave_type_full(self, + connection, + &slave_type, + &normerr_slave_setting_type, + &normerr_missing_slave_type, + &normerr_missing_slave_type_port, + error)) + return FALSE; + + if (nm_streq(type, NM_SETTING_OVS_PORT_SETTING_NAME) && slave_type + && !nm_streq(slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("'%s' connections must be enslaved to '%s', not '%s'"), + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + slave_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + + if (priv->metered != NM_METERED_UNKNOWN && priv->metered != NM_METERED_YES + && priv->metered != NM_METERED_NO) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("metered value %d is not valid"), + priv->metered); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_METERED); + return FALSE; + } + + if (priv->mdns < (int) NM_SETTING_CONNECTION_MDNS_DEFAULT + || priv->mdns > (int) NM_SETTING_CONNECTION_MDNS_YES) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value %d is not valid"), + priv->mdns); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_MDNS); + return FALSE; + } + + if (priv->llmnr < (int) NM_SETTING_CONNECTION_LLMNR_DEFAULT + || priv->llmnr > (int) NM_SETTING_CONNECTION_LLMNR_YES) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value %d is not valid"), + priv->llmnr); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_LLMNR); + return FALSE; + } + + if (!NM_IN_SET(priv->multi_connect, + (int) NM_CONNECTION_MULTI_CONNECT_DEFAULT, + (int) NM_CONNECTION_MULTI_CONNECT_SINGLE, + (int) NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE, + (int) NM_CONNECTION_MULTI_CONNECT_MULTIPLE)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value %d is not valid"), + priv->multi_connect); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_MULTI_CONNECT); + return FALSE; + } + + if (priv->mud_url) { + if (!priv->mud_url[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_CONNECTION_MUD_URL); + return FALSE; + } + if (nm_streq(priv->mud_url, NM_CONNECTION_MUD_URL_NONE)) { + /* pass */ + } else { + if (strlen(priv->mud_url) > 255) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("DHCP option cannot be longer than 255 characters")); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_CONNECTION_MUD_URL); + return FALSE; + } + if (!nm_sd_http_url_is_valid_https(priv->mud_url)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("MUD URL is not a valid URL")); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_CONNECTION_MUD_URL); + return FALSE; + } + } + } + + if (priv->permissions) { + guint i; + + for (i = 0; i < priv->permissions->len; i++) { + const Permission *permissions = &g_array_index(priv->permissions, Permission, i); + + if (permissions->ptype != PERM_TYPE_USER) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid permissions not in format \"user:$UNAME[:]\"")); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_CONNECTION_PERMISSIONS); + return FALSE; + } + nm_assert(nm_settings_connection_validate_permission_user(permissions->item, -1)); + } + } + + /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ + + if (!priv->uuid) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_UUID); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + if (normerr_base_type) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property type should be set to '%s'"), + nm_setting_get_name(normerr_base_type)); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TYPE); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + if (normerr_base_setting) { + _set_error_missing_base_setting(error, priv->type); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + if (normerr_slave_setting_type) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("slave-type '%s' requires a '%s' setting in the connection"), + priv->slave_type, + normerr_slave_setting_type); + g_prefix_error(error, "%s: ", normerr_slave_setting_type); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + if (normerr_missing_slave_type) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("Detect a slave connection with '%s' set and a port type '%s'. '%s' should " + "be set to '%s'"), + NM_SETTING_CONNECTION_MASTER, + normerr_missing_slave_type_port, + NM_SETTING_CONNECTION_SLAVE_TYPE, + normerr_missing_slave_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + if (connection) { + gboolean has_bridge_port = FALSE; + + if ((!nm_streq0(priv->slave_type, NM_SETTING_BRIDGE_SETTING_NAME) + && (has_bridge_port = + !!nm_connection_get_setting_by_name(connection, + NM_SETTING_BRIDGE_PORT_SETTING_NAME))) + || (!nm_streq0(priv->slave_type, NM_SETTING_TEAM_SETTING_NAME) + && nm_connection_get_setting_by_name(connection, + NM_SETTING_TEAM_PORT_SETTING_NAME))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("A slave connection with '%s' set to '%s' cannot have a '%s' setting"), + NM_SETTING_CONNECTION_SLAVE_TYPE, + priv->slave_type ?: "", + has_bridge_port ? NM_SETTING_BRIDGE_PORT_SETTING_NAME + : NM_SETTING_TEAM_PORT_SETTING_NAME); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + } + + return TRUE; +} + +static const char * +find_virtual_interface_name(GVariant *connection_dict, GVariant **variant_to_free) +{ + GVariant * setting_dict; + const char *interface_name; + + nm_assert(variant_to_free && !*variant_to_free); + + setting_dict = g_variant_lookup_value(connection_dict, + NM_SETTING_BOND_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + if (!setting_dict) + setting_dict = g_variant_lookup_value(connection_dict, + NM_SETTING_BRIDGE_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + if (!setting_dict) + setting_dict = g_variant_lookup_value(connection_dict, + NM_SETTING_TEAM_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + if (!setting_dict) + setting_dict = g_variant_lookup_value(connection_dict, + NM_SETTING_VLAN_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + + if (!setting_dict) + return NULL; + + *variant_to_free = setting_dict; + + /* All of the deprecated virtual interface name properties were named "interface-name". */ + if (!g_variant_lookup(setting_dict, "interface-name", "&s", &interface_name)) + interface_name = NULL; + + return interface_name; +} + +static gboolean +nm_setting_connection_no_interface_name(NMSetting * setting, + GVariant * connection_dict, + const char * property, + NMSettingParseFlags parse_flags, + GError ** error) +{ + const char * virtual_interface_name; + gs_unref_variant GVariant *variant_to_free = NULL; + + virtual_interface_name = find_virtual_interface_name(connection_dict, &variant_to_free); + g_object_set(G_OBJECT(setting), + NM_SETTING_CONNECTION_INTERFACE_NAME, + virtual_interface_name, + NULL); + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_ID) + && nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_CONNECTION_ID)) + return NM_TERNARY_DEFAULT; + + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP) + && nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_CONNECTION_TIMESTAMP)) + return NM_TERNARY_DEFAULT; + + return NM_SETTING_CLASS(nm_setting_connection_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingConnection * setting = NM_SETTING_CONNECTION(object); + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_ID: + g_value_set_string(value, nm_setting_connection_get_id(setting)); + break; + case PROP_UUID: + g_value_set_string(value, nm_setting_connection_get_uuid(setting)); + break; + case PROP_STABLE_ID: + g_value_set_string(value, nm_setting_connection_get_stable_id(setting)); + break; + case PROP_INTERFACE_NAME: + g_value_set_string(value, nm_setting_connection_get_interface_name(setting)); + break; + case PROP_TYPE: + g_value_set_string(value, nm_setting_connection_get_connection_type(setting)); + break; + case PROP_PERMISSIONS: + { + char **strv; + gsize i, l; + + l = nm_g_array_len(priv->permissions); + strv = g_new(char *, l + 1u); + + for (i = 0; i < l; i++) + strv[i] = _permission_to_string(&g_array_index(priv->permissions, Permission, i)); + strv[i] = NULL; + + g_value_take_boxed(value, strv); + break; + } + case PROP_AUTOCONNECT: + g_value_set_boolean(value, nm_setting_connection_get_autoconnect(setting)); + break; + case PROP_AUTOCONNECT_PRIORITY: + g_value_set_int(value, nm_setting_connection_get_autoconnect_priority(setting)); + break; + case PROP_AUTOCONNECT_RETRIES: + g_value_set_int(value, nm_setting_connection_get_autoconnect_retries(setting)); + break; + case PROP_MULTI_CONNECT: + g_value_set_int(value, priv->multi_connect); + break; + case PROP_TIMESTAMP: + g_value_set_uint64(value, nm_setting_connection_get_timestamp(setting)); + break; + case PROP_READ_ONLY: + g_value_set_boolean(value, nm_setting_connection_get_read_only(setting)); + break; + case PROP_ZONE: + g_value_set_string(value, nm_setting_connection_get_zone(setting)); + break; + case PROP_MASTER: + g_value_set_string(value, nm_setting_connection_get_master(setting)); + break; + case PROP_SLAVE_TYPE: + g_value_set_string(value, nm_setting_connection_get_slave_type(setting)); + break; + case PROP_AUTOCONNECT_SLAVES: + g_value_set_enum(value, nm_setting_connection_get_autoconnect_slaves(setting)); + break; + case PROP_SECONDARIES: + g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->secondaries, TRUE)); + break; + case PROP_GATEWAY_PING_TIMEOUT: + g_value_set_uint(value, priv->gateway_ping_timeout); + break; + case PROP_METERED: + g_value_set_enum(value, priv->metered); + break; + case PROP_LLDP: + g_value_set_int(value, priv->lldp); + break; + case PROP_AUTH_RETRIES: + g_value_set_int(value, priv->auth_retries); + break; + case PROP_MDNS: + g_value_set_int(value, priv->mdns); + break; + case PROP_LLMNR: + g_value_set_int(value, priv->llmnr); + break; + case PROP_WAIT_DEVICE_TIMEOUT: + g_value_set_int(value, priv->wait_device_timeout); + break; + case PROP_MUD_URL: + g_value_set_string(value, priv->mud_url); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_ID: + g_free(priv->id); + priv->id = g_value_dup_string(value); + break; + case PROP_UUID: + g_free(priv->uuid); + priv->uuid = g_value_dup_string(value); + break; + case PROP_STABLE_ID: + g_free(priv->stable_id); + priv->stable_id = g_value_dup_string(value); + break; + case PROP_INTERFACE_NAME: + g_free(priv->interface_name); + priv->interface_name = g_value_dup_string(value); + break; + case PROP_TYPE: + g_free(priv->type); + priv->type = g_value_dup_string(value); + break; + case PROP_PERMISSIONS: + { + const char *const *strv; + guint i; + + nm_clear_pointer(&priv->permissions, g_array_unref); + strv = g_value_get_boxed(value); + if (strv && strv[0]) { + priv->permissions = + g_array_sized_new(FALSE, FALSE, sizeof(Permission), NM_PTRARRAY_LEN(strv)); + g_array_set_clear_func(priv->permissions, (GDestroyNotify) _permission_clear_stale); + + for (i = 0; strv[i]; i++) { + Permission *permission = nm_g_array_append_new(priv->permissions, Permission); + + _permission_set_stale_parse(permission, strv[i]); + } + } + break; + } + case PROP_AUTOCONNECT: + priv->autoconnect = g_value_get_boolean(value); + break; + case PROP_AUTOCONNECT_PRIORITY: + priv->autoconnect_priority = g_value_get_int(value); + break; + case PROP_AUTOCONNECT_RETRIES: + priv->autoconnect_retries = g_value_get_int(value); + break; + case PROP_MULTI_CONNECT: + priv->multi_connect = g_value_get_int(value); + break; + case PROP_TIMESTAMP: + priv->timestamp = g_value_get_uint64(value); + break; + case PROP_READ_ONLY: + priv->read_only = g_value_get_boolean(value); + break; + case PROP_ZONE: + g_free(priv->zone); + priv->zone = g_value_dup_string(value); + break; + case PROP_MASTER: + g_free(priv->master); + priv->master = g_value_dup_string(value); + break; + case PROP_SLAVE_TYPE: + g_free(priv->slave_type); + priv->slave_type = g_value_dup_string(value); + break; + case PROP_AUTOCONNECT_SLAVES: + priv->autoconnect_slaves = g_value_get_enum(value); + break; + case PROP_SECONDARIES: + g_slist_free_full(priv->secondaries, g_free); + priv->secondaries = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); + break; + case PROP_GATEWAY_PING_TIMEOUT: + priv->gateway_ping_timeout = g_value_get_uint(value); + break; + case PROP_METERED: + priv->metered = g_value_get_enum(value); + break; + case PROP_LLDP: + priv->lldp = g_value_get_int(value); + break; + case PROP_AUTH_RETRIES: + priv->auth_retries = g_value_get_int(value); + break; + case PROP_MDNS: + priv->mdns = g_value_get_int(value); + break; + case PROP_LLMNR: + priv->llmnr = g_value_get_int(value); + break; + case PROP_WAIT_DEVICE_TIMEOUT: + priv->wait_device_timeout = g_value_get_int(value); + break; + case PROP_MUD_URL: + g_free(priv->mud_url); + priv->mud_url = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_connection_init(NMSettingConnection *setting) +{ + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); + + priv->auth_retries = -1; + priv->autoconnect = TRUE; + priv->autoconnect_priority = NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT; + priv->autoconnect_retries = -1; + priv->autoconnect_slaves = NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT; + priv->lldp = NM_SETTING_CONNECTION_LLDP_DEFAULT; + priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; + priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; + priv->wait_device_timeout = -1; +} + +/** + * nm_setting_connection_new: + * + * Creates a new #NMSettingConnection object with default values. + * + * Returns: the new empty #NMSettingConnection object + **/ +NMSetting * +nm_setting_connection_new(void) +{ + return g_object_new(NM_TYPE_SETTING_CONNECTION, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE(object); + + g_free(priv->id); + g_free(priv->uuid); + g_free(priv->stable_id); + g_free(priv->interface_name); + g_free(priv->type); + g_free(priv->zone); + g_free(priv->master); + g_free(priv->slave_type); + g_free(priv->mud_url); + nm_clear_pointer(&priv->permissions, g_array_unref); + g_slist_free_full(priv->secondaries, g_free); + + G_OBJECT_CLASS(nm_setting_connection_parent_class)->finalize(object); +} + +static void +nm_setting_connection_class_init(NMSettingConnectionClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingConnectionPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->compare_property = compare_property; + + /** + * NMSettingConnection:id: + * + * A human readable unique identifier for the connection, like "Work Wi-Fi" + * or "T-Mobile 3G". + **/ + /* ---ifcfg-rh--- + * property: id + * variable: NAME(+) + * description: User friendly name for the connection profile. + * ---end--- + */ + obj_properties[PROP_ID] = g_param_spec_string(NM_SETTING_CONNECTION_ID, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:uuid: + * + * A universally unique identifier for the connection, for example generated + * with libuuid. It should be assigned when the connection is created, and + * never changed as long as the connection still applies to the same + * network. For example, it should not be changed when the + * #NMSettingConnection:id property or #NMSettingIP4Config changes, but + * might need to be re-created when the Wi-Fi SSID, mobile broadband network + * provider, or #NMSettingConnection:type property changes. + * + * The UUID must be in the format "2815492f-7e56-435e-b2e9-246bd7cdc664" + * (ie, contains only hexadecimal characters and "-"). A suitable UUID may + * be generated by nm_utils_uuid_generate() or + * nm_utils_uuid_generate_from_string(). + **/ + /* ---ifcfg-rh--- + * property: uuid + * variable: UUID(+) + * description: UUID for the connection profile. When missing, NetworkManager + * creates the UUID itself (by hashing the filename). + * ---end--- + */ + obj_properties[PROP_UUID] = g_param_spec_string( + NM_SETTING_CONNECTION_UUID, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:stable-id: + * + * This represents the identity of the connection used for various purposes. + * It allows to configure multiple profiles to share the identity. Also, + * the stable-id can contain placeholders that are substituted dynamically and + * deterministically depending on the context. + * + * The stable-id is used for generating IPv6 stable private addresses + * with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the + * generated cloned MAC address for ethernet.cloned-mac-address=stable + * and wifi.cloned-mac-address=stable. It is also used as DHCP client + * identifier with ipv4.dhcp-client-id=stable and to derive the DHCP + * DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. + * + * Note that depending on the context where it is used, other parameters are + * also seeded into the generation algorithm. For example, a per-host key + * is commonly also included, so that different systems end up generating + * different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's + * name is included, so that different interfaces yield different addresses. + * The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret-key. + * + * The '$' character is treated special to perform dynamic substitutions + * at runtime. Currently, supported are "${CONNECTION}", "${DEVICE}", "${MAC}", + * "${BOOT}", "${RANDOM}". + * These effectively create unique IDs per-connection, per-device, per-boot, + * or every time. Note that "${DEVICE}" corresponds to the interface name of the + * device and "${MAC}" is the permanent MAC address of the device. + * Any unrecognized patterns following '$' are treated verbatim, however + * are reserved for future use. You are thus advised to avoid '$' or + * escape it as "$$". + * For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to create a unique id for + * this connection that changes with every reboot and differs depending on the + * interface where the profile activates. + * + * If the value is unset, a global connection default is consulted. If the + * value is still unset, the default is similar to "${CONNECTION}" and uses + * a unique, fixed ID for the connection. + * + * Since: 1.4 + **/ + /* ---ifcfg-rh--- + * property: stable-id + * variable: STABLE_ID(+) + * description: Token to generate stable IDs. + * ---end--- + */ + obj_properties[PROP_STABLE_ID] = g_param_spec_string( + NM_SETTING_CONNECTION_STABLE_ID, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:interface-name: + * + * The name of the network interface this connection is bound to. If not + * set, then the connection can be attached to any interface of the + * appropriate type (subject to restrictions imposed by other settings). + * + * For software devices this specifies the name of the created device. + * + * For connection types where interface names cannot easily be made + * persistent (e.g. mobile broadband or USB Ethernet), this property should + * not be used. Setting this property restricts the interfaces a connection + * can be used with, and if interface names change or are reordered the + * connection may be applied to the wrong interface. + **/ + /* ---ifcfg-rh--- + * property: interface-name + * variable: DEVICE + * description: Interface name of the device this profile is bound to. The variable + * can be left out when the profile should apply for more devices. Note that DEVICE + * can be required for some connection types. + * ---end--- + */ + obj_properties[PROP_INTERFACE_NAME] = g_param_spec_string( + NM_SETTING_CONNECTION_INTERFACE_NAME, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_INTERFACE_NAME], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING, + .missing_from_dbus_fcn = + nm_setting_connection_no_interface_name, )); + + /** + * NMSettingConnection:type: + * + * Base type of the connection. For hardware-dependent connections, should + * contain the setting name of the hardware-type specific setting (ie, + * "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for + * non-hardware dependent connections like VPN or otherwise, should contain + * the setting name of that setting type (ie, "vpn" or "bridge", etc). + **/ + /* ---ifcfg-rh--- + * property: type + * variable: TYPE (DEVICETYPE, DEVICE) + * values: Ethernet, Wireless, InfiniBand, Bridge, Bond, Vlan, Team, TeamPort + * description: Base type of the connection. DEVICETYPE is used for teaming + * connections. + * example: TYPE=Ethernet; TYPE=Bond; TYPE=Bridge; DEVICETYPE=TeamPort + * ---end--- + */ + obj_properties[PROP_TYPE] = g_param_spec_string(NM_SETTING_CONNECTION_TYPE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:permissions: + * + * An array of strings defining what access a given user has to this + * connection. If this is %NULL or empty, all users are allowed to access + * this connection; otherwise users are allowed if and only if they are in + * this list. When this is not empty, the connection can be active only when + * one of the specified users is logged into an active session. Each entry + * is of the form "[type]:[id]:[reserved]"; for example, "user:dcbw:blah". + * + * At this time only the "user" [type] is allowed. Any other values are + * ignored and reserved for future use. [id] is the username that this + * permission refers to, which may not contain the ":" character. Any + * [reserved] information present must be ignored and is reserved for future + * use. All of [type], [id], and [reserved] must be valid UTF-8. + */ + /* ---ifcfg-rh--- + * property: permissions + * variable: USERS(+) + * description: Restrict to certain users the access to this connection, and + * allow the connection to be active only when at least one of the + * specified users is logged into an active session. + * example: USERS="joe bob" + * ---end--- + */ + obj_properties[PROP_PERMISSIONS] = + g_param_spec_boxed(NM_SETTING_CONNECTION_PERMISSIONS, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:autoconnect: + * + * Whether or not the connection should be automatically connected by + * NetworkManager when the resources for the connection are available. + * %TRUE to automatically activate the connection, %FALSE to require manual + * intervention to activate the connection. + * + * Note that autoconnect is not implemented for VPN profiles. See + * #NMSettingConnection:secondaries as an alternative to automatically + * connect VPN profiles. + **/ + /* ---ifcfg-rh--- + * property: autoconnect + * variable: ONBOOT + * default: yes + * description: Whether the connection should be autoconnected (not only while booting). + * ---end--- + */ + obj_properties[PROP_AUTOCONNECT] = g_param_spec_boolean( + NM_SETTING_CONNECTION_AUTOCONNECT, + "", + "", + TRUE, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:autoconnect-priority: + * + * The autoconnect priority. If the connection is set to autoconnect, + * connections with higher priority will be preferred. Defaults to 0. + * The higher number means higher priority. + **/ + /* ---ifcfg-rh--- + * property: autoconnect-priority + * variable: AUTOCONNECT_PRIORITY(+) + * values: -999 to 999 + * default: 0 + * description: Connection priority for automatic activation. Connections with + * higher numbers are preferred when selecting profiles for automatic activation. + * example: AUTOCONNECT_PRIORITY=20 + * ---end--- + */ + obj_properties[PROP_AUTOCONNECT_PRIORITY] = g_param_spec_int( + NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, + "", + "", + NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN, + NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX, + NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:autoconnect-retries: + * + * The number of times a connection should be tried when autoactivating before + * giving up. Zero means forever, -1 means the global default (4 times if not + * overridden). Setting this to 1 means to try activation only once before + * blocking autoconnect. Note that after a timeout, NetworkManager will try + * to autoconnect again. + */ + /* ---ifcfg-rh--- + * property: autoconnect-retries + * variable: AUTOCONNECT_RETRIES(+) + * description: The number of times a connection should be autoactivated + * before giving up and switching to the next one. + * values: -1 (use global default), 0 (forever) or a positive value + * example: AUTOCONNECT_RETRIES=1 + * ---end--- + */ + obj_properties[PROP_AUTOCONNECT_RETRIES] = g_param_spec_int( + NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, + "", + "", + -1, + G_MAXINT32, + -1, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:multi-connect: + * + * Specifies whether the profile can be active multiple times at a particular + * moment. The value is of type #NMConnectionMultiConnect. + * + * Since: 1.14 + */ + /* ---ifcfg-rh--- + * property: multi-connect + * variable: MULTI_CONNECT(+) + * description: whether the profile can be active on multiple devices at a given + * moment. The values are numbers corresponding to #NMConnectionMultiConnect enum. + * example: MULTI_CONNECT=3 + * ---end--- + */ + obj_properties[PROP_MULTI_CONNECT] = g_param_spec_int( + NM_SETTING_CONNECTION_MULTI_CONNECT, + "", + "", + G_MININT32, + G_MAXINT32, + NM_CONNECTION_MULTI_CONNECT_DEFAULT, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:timestamp: + * + * The time, in seconds since the Unix Epoch, that the connection was last + * _successfully_ fully activated. + * + * NetworkManager updates the connection timestamp periodically when the + * connection is active to ensure that an active connection has the latest + * timestamp. The property is only meant for reading (changes to this + * property will not be preserved). + **/ + obj_properties[PROP_TIMESTAMP] = g_param_spec_uint64( + NM_SETTING_CONNECTION_TIMESTAMP, + "", + "", + 0, + G_MAXUINT64, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_TIMESTAMP], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT64, + .to_dbus_fcn = _to_dbus_fcn_timestamp, )); + + /** + * NMSettingConnection:read-only: + * + * %FALSE if the connection can be modified using the provided settings + * service's D-Bus interface with the right privileges, or %TRUE if the + * connection is read-only and cannot be modified. + **/ + obj_properties[PROP_READ_ONLY] = g_param_spec_boolean( + NM_SETTING_CONNECTION_READ_ONLY, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:zone: + * + * The trust level of a the connection. Free form case-insensitive string + * (for example "Home", "Work", "Public"). %NULL or unspecified zone means + * the connection will be placed in the default zone as defined by the + * firewall. + * + * When updating this property on a currently activated connection, + * the change takes effect immediately. + **/ + /* ---ifcfg-rh--- + * property: zone + * variable: ZONE(+) + * description: Trust level of this connection. The string is usually used + * for a firewall. + * example: ZONE=Work + * ---end--- + */ + obj_properties[PROP_ZONE] = + g_param_spec_string(NM_SETTING_CONNECTION_ZONE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:master: + * + * Interface name of the master device or UUID of the master connection. + **/ + /* ---ifcfg-rh--- + * property: master + * variable: MASTER, MASTER_UUID, TEAM_MASTER, TEAM_MASTER_UUID, BRIDGE, BRIDGE_UUID + * description: Reference to master connection. The variable used depends on + * the connection type and the value. In general, if the *_UUID variant is present, + * the variant without *_UUID is ignored. NetworkManager attempts to write both + * for compatibility with legacy tooling. + * ---end--- + */ + obj_properties[PROP_MASTER] = + g_param_spec_string(NM_SETTING_CONNECTION_MASTER, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:slave-type: + * + * Setting name of the device type of this slave's master connection (eg, + * %NM_SETTING_BOND_SETTING_NAME), or %NULL if this connection is not a + * slave. + **/ + /* ---ifcfg-rh--- + * property: slave-type + * variable: MASTER, MASTER_UUID, TEAM_MASTER, TEAM_MASTER_UUID, DEVICETYPE, + * BRIDGE, BRIDGE_UUID + * description: Slave type doesn't map directly to a variable, but it is + * recognized using different variables. MASTER and MASTER_UUID for bonding, + * TEAM_MASTER, TEAM_MASTER_UUID and DEVICETYPE for teaming, BRIDGE + * and BRIDGE_UUID for bridging. + * ---end--- + */ + obj_properties[PROP_SLAVE_TYPE] = + g_param_spec_string(NM_SETTING_CONNECTION_SLAVE_TYPE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:autoconnect-slaves: + * + * Whether or not slaves of this connection should be automatically brought up + * when NetworkManager activates this connection. This only has a real effect + * for master connections. The properties #NMSettingConnection:autoconnect, + * #NMSettingConnection:autoconnect-priority and #NMSettingConnection:autoconnect-retries + * are unrelated to this setting. + * The permitted values are: 0: leave slave connections untouched, + * 1: activate all the slave connections with this connection, -1: default. + * If -1 (default) is set, global connection.autoconnect-slaves is read to + * determine the real value. If it is default as well, this fallbacks to 0. + * + * Since: 1.2 + **/ + /* ---ifcfg-rh--- + * property: autoconnect-slaves + * variable: AUTOCONNECT_SLAVES(+) + * default: missing variable means global default + * description: Whether slaves of this connection should be auto-connected + * when this connection is activated. + * ---end--- + */ + obj_properties[PROP_AUTOCONNECT_SLAVES] = g_param_spec_enum( + NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, + "", + "", + NM_TYPE_SETTING_CONNECTION_AUTOCONNECT_SLAVES, + NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:secondaries: + * + * List of connection UUIDs that should be activated when the base + * connection itself is activated. Currently, only VPN connections are + * supported. + **/ + /* ---ifcfg-rh--- + * property: secondaries + * variable: SECONDARY_UUIDS(+) + * description: UUID of VPN connections that should be activated + * together with this connection. + * ---end--- + */ + obj_properties[PROP_SECONDARIES] = g_param_spec_boxed( + NM_SETTING_CONNECTION_SECONDARIES, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:gateway-ping-timeout: + * + * If greater than zero, delay success of IP addressing until either the + * timeout is reached, or an IP gateway replies to a ping. + **/ + /* ---ifcfg-rh--- + * property: gateway-ping-timeout + * variable: GATEWAY_PING_TIMEOUT(+) + * default: 0 + * description: If greater than zero, the IP connectivity will be checked by + * pinging the gateway and waiting for the specified timeout (in seconds). + * example: GATEWAY_PING_TIMEOUT=5 + * ---end--- + */ + obj_properties[PROP_GATEWAY_PING_TIMEOUT] = + g_param_spec_uint(NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, + "", + "", + 0, + 600, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:metered: + * + * Whether the connection is metered. + * + * When updating this property on a currently activated connection, + * the change takes effect immediately. + * + * Since: 1.2 + **/ + /* ---ifcfg-rh--- + * property: metered + * variable: CONNECTION_METERED(+) + * values: yes,no,unknown + * description: Whether the device is metered + * example: CONNECTION_METERED=yes + * ---end--- + */ + obj_properties[PROP_METERED] = g_param_spec_enum( + NM_SETTING_CONNECTION_METERED, + "", + "", + NM_TYPE_METERED, + NM_METERED_UNKNOWN, + G_PARAM_READWRITE | NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:lldp: + * + * Whether LLDP is enabled for the connection. + * + * Since: 1.2 + **/ + /* ---ifcfg-rh--- + * property: lldp + * variable: LLDP(+) + * values: boolean value or 'rx' + * default: missing variable means global default + * description: whether LLDP is enabled for the connection + * example: LLDP=no + * ---end--- + */ + obj_properties[PROP_LLDP] = g_param_spec_int(NM_SETTING_CONNECTION_LLDP, + "", + "", + G_MININT32, + G_MAXINT32, + NM_SETTING_CONNECTION_LLDP_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:auth-retries: + * + * The number of retries for the authentication. Zero means to try indefinitely; -1 means + * to use a global default. If the global default is not set, the authentication + * retries for 3 times before failing the connection. + * + * Currently, this only applies to 802-1x authentication. + * + * Since: 1.10 + **/ + /* ---ifcfg-rh--- + * property: auth-retries + * variable: AUTH_RETRIES(+) + * default: 0 + * description: Number of retries for authentication. + * ---end--- + */ + obj_properties[PROP_AUTH_RETRIES] = g_param_spec_int( + NM_SETTING_CONNECTION_AUTH_RETRIES, + "", + "", + -1, + G_MAXINT32, + -1, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:mdns: + * + * Whether mDNS is enabled for the connection. + * + * The permitted values are: "yes" (2) register hostname and resolving + * for the connection, "no" (0) disable mDNS for the interface, "resolve" + * (1) do not register hostname but allow resolving of mDNS host names + * and "default" (-1) to allow lookup of a global default in NetworkManager.conf. + * If unspecified, "default" ultimately depends on the DNS plugin (which + * for systemd-resolved currently means "no"). + * + * This feature requires a plugin which supports mDNS. Otherwise, the + * setting has no effect. One such plugin is dns-systemd-resolved. +* + * Since: 1.12 + **/ + /* ---ifcfg-rh--- + * property: mdns + * variable: MDNS(+) + * values: yes,no,resolve + * default: missing variable means global default + * description: Whether or not mDNS is enabled for the connection + * example: MDNS=yes + * ---end--- + */ + obj_properties[PROP_MDNS] = g_param_spec_int(NM_SETTING_CONNECTION_MDNS, + "", + "", + G_MININT32, + G_MAXINT32, + NM_SETTING_CONNECTION_MDNS_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:llmnr: + * + * Whether Link-Local Multicast Name Resolution (LLMNR) is enabled + * for the connection. LLMNR is a protocol based on the Domain Name + * System (DNS) packet format that allows both IPv4 and IPv6 hosts + * to perform name resolution for hosts on the same local link. + * + * The permitted values are: "yes" (2) register hostname and resolving + * for the connection, "no" (0) disable LLMNR for the interface, "resolve" + * (1) do not register hostname but allow resolving of LLMNR host names + * If unspecified, "default" ultimately depends on the DNS plugin (which + * for systemd-resolved currently means "yes"). + * + * This feature requires a plugin which supports LLMNR. Otherwise, the + * setting has no effect. One such plugin is dns-systemd-resolved. + * + * Since: 1.14 + **/ + /* ---ifcfg-rh--- + * property: llmnr + * variable: LLMNR(+) + * values: yes,no,resolve + * default: missing variable means global default + * description: Whether or not LLMNR is enabled for the connection + * example: LLMNR=yes + * ---end--- + */ + obj_properties[PROP_LLMNR] = g_param_spec_int(NM_SETTING_CONNECTION_LLMNR, + "", + "", + G_MININT32, + G_MAXINT32, + NM_SETTING_CONNECTION_LLMNR_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:wait-device-timeout: + * + * Timeout in milliseconds to wait for device at startup. + * During boot, devices may take a while to be detected by the driver. + * This property will cause to delay NetworkManager-wait-online.service + * and nm-online to give the device a chance to appear. This works by + * waiting for the given timeout until a compatible device for the + * profile is available and managed. + * + * The value 0 means no wait time. The default value is -1, which + * currently has the same meaning as no wait time. + * + * Since: 1.20 + **/ + /* ---ifcfg-rh--- + * property: wait-device-timeout + * variable: DEVTIMEOUT(+) + * values: timeout in seconds. + * description: for initscripts compatibility, this variable must be + * a whole integer. If necessary, NetworkManager stores also a fractional + * component for the milliseconds. + * example: DEVTIMEOUT=5 + * ---end--- + */ + obj_properties[PROP_WAIT_DEVICE_TIMEOUT] = + g_param_spec_int(NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, + "", + "", + -1, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingConnection:mud-url: + * + * If configured, set to a Manufacturer Usage Description (MUD) URL that points + * to manufacturer-recommended network policies for IoT devices. It is transmitted + * as a DHCPv4 or DHCPv6 option. The value must be a valid URL starting with "https://". + * + * The special value "none" is allowed to indicate that no MUD URL is used. + * + * If the per-profile value is unspecified (the default), a global connection default gets + * consulted. If still unspecified, the ultimate default is "none". + * + * Since: 1.26 + **/ + /* ---ifcfg-rh--- + * property: mud-url + * variable: MUD_URL + * values: a valid URL that points to recommended policy for this device + * description: MUD_URL to be sent by device (See RFC 8520). + * example: https://yourdevice.example.com/model.json + * ---end--- + */ + obj_properties[PROP_MUD_URL] = g_param_spec_string(NM_SETTING_CONNECTION_MUD_URL, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_CONNECTION, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-dcb.c b/src/libnm-core-impl/nm-setting-dcb.c new file mode 100644 index 0000000000..695953d14e --- /dev/null +++ b/src/libnm-core-impl/nm-setting-dcb.c @@ -0,0 +1,1281 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2013 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-dcb.h" + +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" +#include "nm-core-enum-types.h" + +/** + * SECTION:nm-setting-dcb + * @short_description: Connection properties for Data Center Bridging + * + * The #NMSettingDcb object is a #NMSetting subclass that describes properties + * for enabling and using Data Center Bridging (DCB) on Ethernet networks. + * DCB is a set of protocols (including 802.1Qbb, 802.1Qaz, 802.1Qau, and + * 802.1AB) to eliminate packet loss in Ethernet networks and support the use + * of storage technologies like Fibre Channel over Ethernet (FCoE) and iSCSI. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingDcb, + + PROP_APP_FCOE_FLAGS, + PROP_APP_FCOE_PRIORITY, + PROP_APP_FCOE_MODE, + + PROP_APP_ISCSI_FLAGS, + PROP_APP_ISCSI_PRIORITY, + + PROP_APP_FIP_FLAGS, + PROP_APP_FIP_PRIORITY, + + PROP_PFC_FLAGS, + PROP_PRIORITY_FLOW_CONTROL, + + PROP_PRIORITY_GROUP_FLAGS, + PROP_PRIORITY_GROUP_ID, + PROP_PRIORITY_GROUP_BANDWIDTH, + PROP_PRIORITY_BANDWIDTH, + PROP_PRIORITY_STRICT_BANDWIDTH, + PROP_PRIORITY_TRAFFIC_CLASS, ); + +typedef struct { + char * app_fcoe_mode; + guint pfc[8]; + guint priority_group_id[8]; + guint priority_group_bandwidth[8]; + guint priority_bandwidth[8]; + guint priority_strict[8]; + guint priority_traffic_class[8]; + int app_fcoe_priority; + int app_iscsi_priority; + int app_fip_priority; + NMSettingDcbFlags app_fcoe_flags; + NMSettingDcbFlags app_iscsi_flags; + NMSettingDcbFlags app_fip_flags; + NMSettingDcbFlags pfc_flags; + NMSettingDcbFlags priority_group_flags; +} NMSettingDcbPrivate; + +G_DEFINE_TYPE(NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING) + +#define NM_SETTING_DCB_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_DCB, NMSettingDcbPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_dcb_get_app_fcoe_flags: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:app-fcoe-flags property of the setting + **/ +NMSettingDcbFlags +nm_setting_dcb_get_app_fcoe_flags(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fcoe_flags; +} + +/** + * nm_setting_dcb_get_app_fcoe_priority: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:app-fcoe-priority property of the setting + **/ +int +nm_setting_dcb_get_app_fcoe_priority(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fcoe_priority; +} + +/** + * nm_setting_dcb_get_app_fcoe_mode: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:app-fcoe-mode property of the setting + **/ +const char * +nm_setting_dcb_get_app_fcoe_mode(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), NULL); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fcoe_mode; +} + +/** + * nm_setting_dcb_get_app_iscsi_flags: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:app-iscsi-flags property of the setting + **/ +NMSettingDcbFlags +nm_setting_dcb_get_app_iscsi_flags(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->app_iscsi_flags; +} + +/** + * nm_setting_dcb_get_app_iscsi_priority: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:app-iscsi-priority property of the setting + **/ +int +nm_setting_dcb_get_app_iscsi_priority(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->app_iscsi_priority; +} + +/** + * nm_setting_dcb_get_app_fip_flags: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:app-fip-flags property of the setting + **/ +NMSettingDcbFlags +nm_setting_dcb_get_app_fip_flags(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fip_flags; +} + +/** + * nm_setting_dcb_get_app_fip_priority: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:app-fip-priority property of the setting + **/ +int +nm_setting_dcb_get_app_fip_priority(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->app_fip_priority; +} + +/** + * nm_setting_dcb_get_priority_flow_control_flags: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:priority-flow-control-flags property of the setting + **/ +NMSettingDcbFlags +nm_setting_dcb_get_priority_flow_control_flags(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->pfc_flags; +} + +/** + * nm_setting_dcb_get_priority_flow_control: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to retrieve flow control for + * + * Returns: %TRUE if flow control is enabled for the given @user_priority, + * %FALSE if not enabled + **/ +gboolean +nm_setting_dcb_get_priority_flow_control(NMSettingDcb *setting, guint user_priority) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), FALSE); + g_return_val_if_fail(user_priority <= 7, FALSE); + + return !!NM_SETTING_DCB_GET_PRIVATE(setting)->pfc[user_priority]; +} + +/** + * nm_setting_dcb_set_priority_flow_control: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to set flow control for + * @enabled: %TRUE to enable flow control for this priority, %FALSE to disable it + * + * These values are only valid when #NMSettingDcb:priority-flow-control includes + * the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +void +nm_setting_dcb_set_priority_flow_control(NMSettingDcb *setting, + guint user_priority, + gboolean enabled) +{ + NMSettingDcbPrivate *priv; + guint uint_enabled = enabled ? 1 : 0; + + g_return_if_fail(NM_IS_SETTING_DCB(setting)); + g_return_if_fail(user_priority <= 7); + + priv = NM_SETTING_DCB_GET_PRIVATE(setting); + if (priv->pfc[user_priority] != uint_enabled) { + priv->pfc[user_priority] = uint_enabled; + _notify(setting, PROP_PRIORITY_FLOW_CONTROL); + } +} + +/** + * nm_setting_dcb_get_priority_group_flags: + * @setting: the #NMSettingDcb + * + * Returns: the #NMSettingDcb:priority-group-flags property of the setting + **/ +NMSettingDcbFlags +nm_setting_dcb_get_priority_group_flags(NMSettingDcb *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_group_flags; +} + +/** + * nm_setting_dcb_get_priority_group_id: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to retrieve the group ID for + * + * Returns: the group number @user_priority is assigned to. These values are + * only valid when #NMSettingDcb:priority-group-flags includes the + * %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +guint +nm_setting_dcb_get_priority_group_id(NMSettingDcb *setting, guint user_priority) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + g_return_val_if_fail(user_priority <= 7, 0); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_group_id[user_priority]; +} + +/** + * nm_setting_dcb_set_priority_group_id: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to set flow control for + * @group_id: the group (0 - 7) to assign @user_priority to, or 15 for the + * unrestricted group. + * + * These values are only valid when #NMSettingDcb:priority-group-flags includes + * the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +void +nm_setting_dcb_set_priority_group_id(NMSettingDcb *setting, guint user_priority, guint group_id) +{ + NMSettingDcbPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_DCB(setting)); + g_return_if_fail(user_priority <= 7); + g_return_if_fail(group_id <= 7 || group_id == 15); + + priv = NM_SETTING_DCB_GET_PRIVATE(setting); + if (priv->priority_group_id[user_priority] != group_id) { + priv->priority_group_id[user_priority] = group_id; + _notify(setting, PROP_PRIORITY_GROUP_ID); + } +} + +/** + * nm_setting_dcb_get_priority_group_bandwidth: + * @setting: the #NMSettingDcb + * @group_id: the priority group (0 - 7) to retrieve the bandwidth percentage for + * + * Returns: the bandwidth percentage assigned to @group_id. These values are + * only valid when #NMSettingDcb:priority-group-flags includes the + * %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +guint +nm_setting_dcb_get_priority_group_bandwidth(NMSettingDcb *setting, guint group_id) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + g_return_val_if_fail(group_id <= 7, FALSE); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_group_bandwidth[group_id]; +} + +/** + * nm_setting_dcb_set_priority_group_bandwidth: + * @setting: the #NMSettingDcb + * @group_id: the priority group (0 - 7) to set the bandwidth percentage for + * @bandwidth_percent: the bandwidth percentage (0 - 100) to assign to @group_id to + * + * These values are only valid when #NMSettingDcb:priority-group-flags includes + * the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +void +nm_setting_dcb_set_priority_group_bandwidth(NMSettingDcb *setting, + guint group_id, + guint bandwidth_percent) +{ + NMSettingDcbPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_DCB(setting)); + g_return_if_fail(group_id <= 7); + g_return_if_fail(bandwidth_percent <= 100); + + priv = NM_SETTING_DCB_GET_PRIVATE(setting); + if (priv->priority_group_bandwidth[group_id] != bandwidth_percent) { + priv->priority_group_bandwidth[group_id] = bandwidth_percent; + _notify(setting, PROP_PRIORITY_GROUP_BANDWIDTH); + } +} + +/** + * nm_setting_dcb_get_priority_bandwidth: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to retrieve the group bandwidth percentage for + * + * Returns: the allowed bandwidth percentage of @user_priority in its priority group. + * These values are only valid when #NMSettingDcb:priority-group-flags includes the + * %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +guint +nm_setting_dcb_get_priority_bandwidth(NMSettingDcb *setting, guint user_priority) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + g_return_val_if_fail(user_priority <= 7, FALSE); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_bandwidth[user_priority]; +} + +/** + * nm_setting_dcb_set_priority_bandwidth: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for + * @bandwidth_percent: the bandwidth percentage (0 - 100) that @user_priority is + * allowed to use within its priority group + * + * These values are only valid when #NMSettingDcb:priority-group-flags includes + * the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +void +nm_setting_dcb_set_priority_bandwidth(NMSettingDcb *setting, + guint user_priority, + guint bandwidth_percent) +{ + NMSettingDcbPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_DCB(setting)); + g_return_if_fail(user_priority <= 7); + g_return_if_fail(bandwidth_percent <= 100); + + priv = NM_SETTING_DCB_GET_PRIVATE(setting); + if (priv->priority_bandwidth[user_priority] != bandwidth_percent) { + priv->priority_bandwidth[user_priority] = bandwidth_percent; + _notify(setting, PROP_PRIORITY_BANDWIDTH); + } +} + +/** + * nm_setting_dcb_get_priority_strict_bandwidth: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to retrieve strict bandwidth for + * + * Returns: %TRUE if @user_priority may use all of the bandwidth allocated to its + * assigned group, or %FALSE if not. These values are only valid when + * #NMSettingDcb:priority-group-flags includes the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +gboolean +nm_setting_dcb_get_priority_strict_bandwidth(NMSettingDcb *setting, guint user_priority) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + g_return_val_if_fail(user_priority <= 7, FALSE); + + return !!NM_SETTING_DCB_GET_PRIVATE(setting)->priority_strict[user_priority]; +} + +/** + * nm_setting_dcb_set_priority_strict_bandwidth: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to set strict bandwidth for + * @strict: %TRUE to allow @user_priority to use all the bandwidth allocated to + * its priority group, or %FALSE if not + * + * These values are only valid when #NMSettingDcb:priority-group-flags includes + * the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +void +nm_setting_dcb_set_priority_strict_bandwidth(NMSettingDcb *setting, + guint user_priority, + gboolean strict) +{ + NMSettingDcbPrivate *priv; + guint uint_strict = strict ? 1 : 0; + + g_return_if_fail(NM_IS_SETTING_DCB(setting)); + g_return_if_fail(user_priority <= 7); + + priv = NM_SETTING_DCB_GET_PRIVATE(setting); + if (priv->priority_strict[user_priority] != uint_strict) { + priv->priority_strict[user_priority] = uint_strict; + _notify(setting, PROP_PRIORITY_STRICT_BANDWIDTH); + } +} + +/** + * nm_setting_dcb_get_priority_traffic_class: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to retrieve the traffic class for + * + * Returns: the traffic class assigned to @user_priority. These values are only + * valid when #NMSettingDcb:priority-group-flags includes the + * %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +guint +nm_setting_dcb_get_priority_traffic_class(NMSettingDcb *setting, guint user_priority) +{ + g_return_val_if_fail(NM_IS_SETTING_DCB(setting), 0); + g_return_val_if_fail(user_priority <= 7, FALSE); + + return NM_SETTING_DCB_GET_PRIVATE(setting)->priority_traffic_class[user_priority]; +} + +/** + * nm_setting_dcb_set_priority_traffic_clas: + * @setting: the #NMSettingDcb + * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for + * @traffic_class: the traffic_class (0 - 7) that @user_priority should map to + * + * These values are only valid when #NMSettingDcb:priority-group-flags includes + * the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ +void +nm_setting_dcb_set_priority_traffic_class(NMSettingDcb *setting, + guint user_priority, + guint traffic_class) +{ + NMSettingDcbPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_DCB(setting)); + g_return_if_fail(user_priority <= 7); + g_return_if_fail(traffic_class <= 7); + + priv = NM_SETTING_DCB_GET_PRIVATE(setting); + if (priv->priority_traffic_class[user_priority] != traffic_class) { + priv->priority_traffic_class[user_priority] = traffic_class; + _notify(setting, PROP_PRIORITY_TRAFFIC_CLASS); + } +} + +/*****************************************************************************/ + +#define DCB_FLAGS_ALL \ + (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + +static gboolean +check_dcb_flags(NMSettingDcbFlags flags, const char *prop_name, GError **error) +{ + if (flags & ~DCB_FLAGS_ALL) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("flags invalid")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); + return FALSE; + } + + if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (flags & ~NM_SETTING_DCB_FLAG_ENABLE)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("flags invalid - disabled")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); + return FALSE; + } + + return TRUE; +} + +static gboolean +check_uint_array(const guint * array, + guint len, + NMSettingDcbFlags flags, + guint max, + guint extra, + gboolean sum_pct, + const char * prop_name, + GError ** error) +{ + guint i, sum = 0; + + /* Ensure each element is <= to max or equals extra */ + for (i = 0; i < len; i++) { + if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && array[i]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property invalid (not enabled)")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); + return FALSE; + } + + if ((array[i] > max) && (array[i] != extra)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("element invalid")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); + return FALSE; + } + sum += array[i]; + } + + /* Verify sum of percentages */ + if (sum_pct) { + if (flags & NM_SETTING_DCB_FLAG_ENABLE) { + /* If the feature is enabled, sum must equal 100% */ + if (sum != 100) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("sum not 100%")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); + return FALSE; + } + } else { + /* If the feature is disabled, sum must equal 0%, which was checked + * by the for() loop above. + */ + g_assert_cmpint(sum, ==, 0); + } + } + + return TRUE; +} + +static gboolean +check_priority(int val, NMSettingDcbFlags flags, const char *prop_name, GError **error) +{ + if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (val >= 0)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property invalid (not enabled)")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); + return FALSE; + } + + if (val < -1 || val > 7) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property invalid")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name); + return FALSE; + } + return TRUE; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(setting); + + if (!check_dcb_flags(priv->app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_FLAGS, error)) + return FALSE; + + if (!check_priority(priv->app_fcoe_priority, + priv->app_fcoe_flags, + NM_SETTING_DCB_APP_FCOE_PRIORITY, + error)) + return FALSE; + + if (!priv->app_fcoe_mode) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property missing")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE); + return FALSE; + } + + if (strcmp(priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_FABRIC) + && strcmp(priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_VN2VN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property invalid")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE); + return FALSE; + } + + if (!check_dcb_flags(priv->app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_FLAGS, error)) + return FALSE; + + if (!check_priority(priv->app_iscsi_priority, + priv->app_iscsi_flags, + NM_SETTING_DCB_APP_ISCSI_PRIORITY, + error)) + return FALSE; + + if (!check_dcb_flags(priv->app_fip_flags, NM_SETTING_DCB_APP_FIP_FLAGS, error)) + return FALSE; + + if (!check_priority(priv->app_fip_priority, + priv->app_fip_flags, + NM_SETTING_DCB_APP_FIP_PRIORITY, + error)) + return FALSE; + + if (!check_dcb_flags(priv->pfc_flags, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, error)) + return FALSE; + + if (!check_uint_array(priv->pfc, + G_N_ELEMENTS(priv->pfc), + priv->pfc_flags, + 1, + 0, + FALSE, + NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, + error)) + return FALSE; + + if (!check_dcb_flags(priv->priority_group_flags, NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, error)) + return FALSE; + + if (!check_uint_array(priv->priority_group_id, + G_N_ELEMENTS(priv->priority_group_id), + priv->priority_group_flags, + 7, + 15, + FALSE, + NM_SETTING_DCB_PRIORITY_GROUP_ID, + error)) + return FALSE; + + if (!check_uint_array(priv->priority_group_bandwidth, + G_N_ELEMENTS(priv->priority_group_bandwidth), + priv->priority_group_flags, + 100, + 0, + TRUE, + NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, + error)) + return FALSE; + + /* FIXME: sum bandwidths in each group */ + if (!check_uint_array(priv->priority_bandwidth, + G_N_ELEMENTS(priv->priority_bandwidth), + priv->priority_group_flags, + 100, + 0, + FALSE, + NM_SETTING_DCB_PRIORITY_BANDWIDTH, + error)) + return FALSE; + + if (!check_uint_array(priv->priority_strict, + G_N_ELEMENTS(priv->priority_strict), + priv->priority_group_flags, + 1, + 0, + FALSE, + NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, + error)) + return FALSE; + + if (!check_uint_array(priv->priority_traffic_class, + G_N_ELEMENTS(priv->priority_traffic_class), + priv->priority_group_flags, + 7, + 0, + FALSE, + NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS, + error)) + return FALSE; + + return TRUE; +} + +/*****************************************************************************/ + +G_STATIC_ASSERT(sizeof(guint) == sizeof(gboolean)); + +static void +set_array_from_gvalue(const GValue *v, uint *a, size_t len) +{ + GArray * src = g_value_get_boxed(v); + const guint total_len = len * sizeof(a[0]); + + memset(a, 0, total_len); + if (src) { + g_return_if_fail(g_array_get_element_size(src) == sizeof(a[0])); + g_return_if_fail(src->len == len); + memcpy(a, src->data, total_len); + } +} +#define SET_ARRAY_FROM_GVALUE(v, a) set_array_from_gvalue(v, a, G_N_ELEMENTS(a)) + +static void +set_gvalue_from_array(GValue *v, uint *a, size_t len) +{ + GArray *src = g_array_sized_new(FALSE, TRUE, sizeof(guint), len); + + g_array_append_vals(src, a, len); + g_value_take_boxed(v, src); +} + +#define SET_GVALUE_FROM_ARRAY(v, a) set_gvalue_from_array(v, a, G_N_ELEMENTS(a)) + +static GVariant * +_nm_setting_dcb_uint_array_to_dbus(const GValue *prop_value) +{ + GArray *src = g_value_get_boxed(prop_value); + + return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, src->data, src->len, sizeof(guint32)); +} + +static void +_nm_setting_dcb_uint_array_from_dbus(GVariant *dbus_value, GValue *prop_value) +{ + gconstpointer array; + gsize length; + + array = g_variant_get_fixed_array(dbus_value, &length, sizeof(guint32)); + set_gvalue_from_array(prop_value, (guint *) array, length); +} + +static const NMSettInfoPropertType nm_sett_info_propert_type_dcb_au = { + .dbus_type = NM_G_VARIANT_TYPE("au"), + .gprop_to_dbus_fcn = _nm_setting_dcb_uint_array_to_dbus, + .gprop_from_dbus_fcn = _nm_setting_dcb_uint_array_from_dbus, +}; + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingDcb * setting = NM_SETTING_DCB(object); + NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_APP_FCOE_FLAGS: + g_value_set_flags(value, priv->app_fcoe_flags); + break; + case PROP_APP_FCOE_PRIORITY: + g_value_set_int(value, priv->app_fcoe_priority); + break; + case PROP_APP_FCOE_MODE: + g_value_set_string(value, priv->app_fcoe_mode); + break; + case PROP_APP_ISCSI_FLAGS: + g_value_set_flags(value, priv->app_iscsi_flags); + break; + case PROP_APP_ISCSI_PRIORITY: + g_value_set_int(value, priv->app_iscsi_priority); + break; + case PROP_APP_FIP_FLAGS: + g_value_set_flags(value, priv->app_fip_flags); + break; + case PROP_APP_FIP_PRIORITY: + g_value_set_int(value, priv->app_fip_priority); + break; + case PROP_PFC_FLAGS: + g_value_set_flags(value, priv->pfc_flags); + break; + case PROP_PRIORITY_FLOW_CONTROL: + SET_GVALUE_FROM_ARRAY(value, priv->pfc); + break; + case PROP_PRIORITY_GROUP_FLAGS: + g_value_set_flags(value, priv->priority_group_flags); + break; + case PROP_PRIORITY_GROUP_ID: + SET_GVALUE_FROM_ARRAY(value, priv->priority_group_id); + break; + case PROP_PRIORITY_GROUP_BANDWIDTH: + SET_GVALUE_FROM_ARRAY(value, priv->priority_group_bandwidth); + break; + case PROP_PRIORITY_BANDWIDTH: + SET_GVALUE_FROM_ARRAY(value, priv->priority_bandwidth); + break; + case PROP_PRIORITY_STRICT_BANDWIDTH: + SET_GVALUE_FROM_ARRAY(value, priv->priority_strict); + break; + case PROP_PRIORITY_TRAFFIC_CLASS: + SET_GVALUE_FROM_ARRAY(value, priv->priority_traffic_class); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_APP_FCOE_FLAGS: + priv->app_fcoe_flags = g_value_get_flags(value); + break; + case PROP_APP_FCOE_PRIORITY: + priv->app_fcoe_priority = g_value_get_int(value); + break; + case PROP_APP_FCOE_MODE: + g_free(priv->app_fcoe_mode); + priv->app_fcoe_mode = g_value_dup_string(value); + break; + case PROP_APP_ISCSI_FLAGS: + priv->app_iscsi_flags = g_value_get_flags(value); + break; + case PROP_APP_ISCSI_PRIORITY: + priv->app_iscsi_priority = g_value_get_int(value); + break; + case PROP_APP_FIP_FLAGS: + priv->app_fip_flags = g_value_get_flags(value); + break; + case PROP_APP_FIP_PRIORITY: + priv->app_fip_priority = g_value_get_int(value); + break; + case PROP_PFC_FLAGS: + priv->pfc_flags = g_value_get_flags(value); + break; + case PROP_PRIORITY_FLOW_CONTROL: + SET_ARRAY_FROM_GVALUE(value, priv->pfc); + break; + case PROP_PRIORITY_GROUP_FLAGS: + priv->priority_group_flags = g_value_get_flags(value); + break; + case PROP_PRIORITY_GROUP_ID: + SET_ARRAY_FROM_GVALUE(value, priv->priority_group_id); + break; + case PROP_PRIORITY_GROUP_BANDWIDTH: + SET_ARRAY_FROM_GVALUE(value, priv->priority_group_bandwidth); + break; + case PROP_PRIORITY_BANDWIDTH: + SET_ARRAY_FROM_GVALUE(value, priv->priority_bandwidth); + break; + case PROP_PRIORITY_STRICT_BANDWIDTH: + SET_ARRAY_FROM_GVALUE(value, priv->priority_strict); + break; + case PROP_PRIORITY_TRAFFIC_CLASS: + SET_ARRAY_FROM_GVALUE(value, priv->priority_traffic_class); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_dcb_init(NMSettingDcb *self) +{ + NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(self); + + priv->app_fcoe_mode = g_strdup(NM_SETTING_DCB_FCOE_MODE_FABRIC); + priv->app_fcoe_priority = -1; + priv->app_fip_priority = -1; + priv->app_iscsi_priority = -1; +} + +/** + * nm_setting_dcb_new: + * + * Creates a new #NMSettingDcb object with default values. + * + * Returns: (transfer full): the new empty #NMSettingDcb object + **/ +NMSetting * +nm_setting_dcb_new(void) +{ + return g_object_new(NM_TYPE_SETTING_DCB, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE(object); + + g_free(priv->app_fcoe_mode); + + G_OBJECT_CLASS(nm_setting_dcb_parent_class)->finalize(object); +} + +static void +nm_setting_dcb_class_init(NMSettingDcbClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingDcbPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingDcb:app-fcoe-flags: + * + * Specifies the #NMSettingDcbFlags for the DCB FCoE application. Flags may + * be any combination of %NM_SETTING_DCB_FLAG_ENABLE, + * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. + **/ + /* ---ifcfg-rh--- + * property: app-fcoe-flags + * variable: DCB_APP_FCOE_ENABLE, DCB_APP_FCOE_ADVERTISE, DCB_APP_FCOE_WILLING + * description: FCOE flags. + * default: no + * example: DCB_APP_FCOE_ENABLE=yes DCB_APP_FCOE_ADVERTISE=yes + * ---end--- + */ + obj_properties[PROP_APP_FCOE_FLAGS] = + g_param_spec_flags(NM_SETTING_DCB_APP_FCOE_FLAGS, + "", + "", + NM_TYPE_SETTING_DCB_FLAGS, + NM_SETTING_DCB_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:app-fcoe-priority: + * + * The highest User Priority (0 - 7) which FCoE frames should use, or -1 for + * default priority. Only used when the #NMSettingDcb:app-fcoe-flags + * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ + /* ---ifcfg-rh--- + * property: app-fcoe-priority + * variable: DCB_APP_FCOE_PRIORITY + * values: 0 - 7 + * description: Priority of FCoE frames. + * ---end--- + */ + obj_properties[PROP_APP_FCOE_PRIORITY] = + g_param_spec_int(NM_SETTING_DCB_APP_FCOE_PRIORITY, + "", + "", + -1, + 7, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:app-fcoe-mode: + * + * The FCoE controller mode; either %NM_SETTING_DCB_FCOE_MODE_FABRIC + * (default) or %NM_SETTING_DCB_FCOE_MODE_VN2VN. + **/ + /* ---ifcfg-rh--- + * property: app-fcoe-mode + * variable: DCB_APP_FCOE_MODE + * values: fabric, vn2vn + * default: fabric + * description: FCoE controller mode. + * ---end--- + */ + obj_properties[PROP_APP_FCOE_MODE] = + g_param_spec_string(NM_SETTING_DCB_APP_FCOE_MODE, + "", + "", + NM_SETTING_DCB_FCOE_MODE_FABRIC, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:app-iscsi-flags: + * + * Specifies the #NMSettingDcbFlags for the DCB iSCSI application. Flags + * may be any combination of %NM_SETTING_DCB_FLAG_ENABLE, + * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. + **/ + /* ---ifcfg-rh--- + * property: app-iscsi-flags + * variable: DCB_APP_ISCSI_ENABLE, DCB_APP_ISCSI_ADVERTISE, DCB_APP_ISCSI_WILLING + * default: no + * description: iSCSI flags. + * ---end--- + */ + obj_properties[PROP_APP_ISCSI_FLAGS] = + g_param_spec_flags(NM_SETTING_DCB_APP_ISCSI_FLAGS, + "", + "", + NM_TYPE_SETTING_DCB_FLAGS, + NM_SETTING_DCB_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:app-iscsi-priority: + * + * The highest User Priority (0 - 7) which iSCSI frames should use, or -1 + * for default priority. Only used when the #NMSettingDcb:app-iscsi-flags + * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ + /* ---ifcfg-rh--- + * property: app-iscsi-priority + * variable: DCB_APP_ISCSI_PRIORITY + * values: 0 - 7 + * description: Priority of iSCSI frames. + * ---end--- + */ + obj_properties[PROP_APP_ISCSI_PRIORITY] = + g_param_spec_int(NM_SETTING_DCB_APP_ISCSI_PRIORITY, + "", + "", + -1, + 7, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:app-fip-flags: + * + * Specifies the #NMSettingDcbFlags for the DCB FIP application. Flags may + * be any combination of %NM_SETTING_DCB_FLAG_ENABLE, + * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. + **/ + /* ---ifcfg-rh--- + * property: app-fip-flags + * variable: DCB_APP_FIP_ENABLE, DCB_APP_FIP_ADVERTISE, DCB_APP_FIP_WILLING + * default: no + * description: FIP flags. + * ---end--- + */ + obj_properties[PROP_APP_FIP_FLAGS] = + g_param_spec_flags(NM_SETTING_DCB_APP_FIP_FLAGS, + "", + "", + NM_TYPE_SETTING_DCB_FLAGS, + NM_SETTING_DCB_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:app-fip-priority: + * + * The highest User Priority (0 - 7) which FIP frames should use, or -1 for + * default priority. Only used when the #NMSettingDcb:app-fip-flags + * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag. + **/ + /* ---ifcfg-rh--- + * property: app-fip-priority + * variable: DCB_APP_FIP_PRIORITY + * values: 0 - 7 + * description: Priority of FIP frames. + * ---end--- + */ + obj_properties[PROP_APP_FIP_PRIORITY] = + g_param_spec_int(NM_SETTING_DCB_APP_FIP_PRIORITY, + "", + "", + -1, + 7, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:priority-flow-control-flags: + * + * Specifies the #NMSettingDcbFlags for DCB Priority Flow Control (PFC). + * Flags may be any combination of %NM_SETTING_DCB_FLAG_ENABLE, + * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. + **/ + /* ---ifcfg-rh--- + * property: priority-flow-control-flags + * variable: DCB_PFC_ENABLE, DCB_PFC_ADVERTISE, DCB_PFC_WILLING + * default: no + * description: Priority flow control flags. + * ---end--- + */ + obj_properties[PROP_PFC_FLAGS] = g_param_spec_flags(NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, + "", + "", + NM_TYPE_SETTING_DCB_FLAGS, + NM_SETTING_DCB_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:priority-flow-control: (type GArray(gboolean)) + * + * An array of 8 boolean values, where the array index corresponds to the User + * Priority (0 - 7) and the value indicates whether or not the corresponding + * priority should transmit priority pause. + **/ + /* ---ifcfg-rh--- + * property: priority-flow-control + * variable: DCB_PFC_UP + * description: Priority flow control values. String of 8 "0" and "1", where "0". + * means "do not transmit priority pause", "1" means "transmit pause". + * example: DCB_PFC_UP=01101110 + * ---end--- + */ + obj_properties[PROP_PRIORITY_FLOW_CONTROL] = + g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, + "", + "", + G_TYPE_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_PRIORITY_FLOW_CONTROL], + &nm_sett_info_propert_type_dcb_au); + + /** + * NMSettingDcb:priority-group-flags: + * + * Specifies the #NMSettingDcbFlags for DCB Priority Groups. Flags may be + * any combination of %NM_SETTING_DCB_FLAG_ENABLE, + * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING. + **/ + /* ---ifcfg-rh--- + * property: priority-group-flags + * variable: DCB_PG_ENABLE, DCB_PG_ADVERTISE, DCB_PG_WILLING + * default: no + * description: Priority groups flags. + * ---end--- + */ + obj_properties[PROP_PRIORITY_GROUP_FLAGS] = + g_param_spec_flags(NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, + "", + "", + NM_TYPE_SETTING_DCB_FLAGS, + NM_SETTING_DCB_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingDcb:priority-group-id: (type GArray(guint)) + * + * An array of 8 uint values, where the array index corresponds to the User + * Priority (0 - 7) and the value indicates the Priority Group ID. Allowed + * Priority Group ID values are 0 - 7 or 15 for the unrestricted group. + **/ + /* ---ifcfg-rh--- + * property: priority-group-id + * variable: DCB_PG_ID + * description: Priority groups values. String of eight priorities (0 - 7) or "f" + * (unrestricted). + * example: DCB_PG_ID=1205f173 + * ---end--- + */ + obj_properties[PROP_PRIORITY_GROUP_ID] = + g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_GROUP_ID, + "", + "", + G_TYPE_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_PRIORITY_GROUP_ID], + &nm_sett_info_propert_type_dcb_au); + + /** + * NMSettingDcb:priority-group-bandwidth: (type GArray(guint)) + * + * An array of 8 uint values, where the array index corresponds to the + * Priority Group ID (0 - 7) and the value indicates the percentage of link + * bandwidth allocated to that group. Allowed values are 0 - 100, and the + * sum of all values must total 100 percents. + **/ + /* ---ifcfg-rh--- + * property: priority-group-bandwidth + * variable: DCB_PG_PCT + * description: Priority groups values. Eight bandwidths (in percent), separated with commas. + * example: DCB_PG_PCT=10,5,10,15,10,10,10,30 + * ---end--- + */ + obj_properties[PROP_PRIORITY_GROUP_BANDWIDTH] = + g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, + "", + "", + G_TYPE_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_PRIORITY_GROUP_BANDWIDTH], + &nm_sett_info_propert_type_dcb_au); + + /** + * NMSettingDcb:priority-bandwidth: (type GArray(guint)) + * + * An array of 8 uint values, where the array index corresponds to the User + * Priority (0 - 7) and the value indicates the percentage of bandwidth of + * the priority's assigned group that the priority may use. The sum of all + * percentages for priorities which belong to the same group must total 100 + * percents. + **/ + /* ---ifcfg-rh--- + * property: priority-bandwidth + * variable: DCB_PG_UPPCT + * description: Priority values. Eight bandwidths (in percent), separated with commas. + * The sum of the numbers must be 100. + * example: DCB_PG_UPPCT=7,13,10,10,15,15,10,20 + * ---end--- + */ + obj_properties[PROP_PRIORITY_BANDWIDTH] = + g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_BANDWIDTH, + "", + "", + G_TYPE_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_PRIORITY_BANDWIDTH], + &nm_sett_info_propert_type_dcb_au); + + /** + * NMSettingDcb:priority-strict-bandwidth: (type GArray(gboolean)) + * + * An array of 8 boolean values, where the array index corresponds to the User + * Priority (0 - 7) and the value indicates whether or not the priority may + * use all of the bandwidth allocated to its assigned group. + **/ + /* ---ifcfg-rh--- + * property: priority-strict-bandwidth + * variable: DCB_PG_STRICT + * description: Priority values. String of eight "0" or "1", where "0" means + * "may not utilize all bandwidth", "1" means "may utilize all bandwidth". + * example: DCB_PG_STRICT=01101110 + * ---end--- + */ + obj_properties[PROP_PRIORITY_STRICT_BANDWIDTH] = + g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, + "", + "", + G_TYPE_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_PRIORITY_STRICT_BANDWIDTH], + &nm_sett_info_propert_type_dcb_au); + + /** + * NMSettingDcb:priority-traffic-class: (type GArray(guint)) + * + * An array of 8 uint values, where the array index corresponds to the User + * Priority (0 - 7) and the value indicates the traffic class (0 - 7) to + * which the priority is mapped. + **/ + /* ---ifcfg-rh--- + * property: priority-traffic-class + * variable: DCB_PG_UP2TC + * description: Priority values. String of eight traffic class values (0 - 7). + * example: DCB_PG_UP2TC=01623701 + * ---end--- + */ + obj_properties[PROP_PRIORITY_TRAFFIC_CLASS] = + g_param_spec_boxed(NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS, + "", + "", + G_TYPE_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_PRIORITY_TRAFFIC_CLASS], + &nm_sett_info_propert_type_dcb_au); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_DCB, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-dummy.c b/src/libnm-core-impl/nm-setting-dummy.c new file mode 100644 index 0000000000..f2b479b883 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-dummy.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-dummy.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-dummy + * @short_description: Describes connection properties for dummy interfaces + * + * The #NMSettingDummy object is a #NMSetting subclass that describes properties + * necessary for connection to dummy devices + **/ + +/*****************************************************************************/ + +G_DEFINE_TYPE(NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING) + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + return TRUE; +} + +/*****************************************************************************/ + +static void +nm_setting_dummy_init(NMSettingDummy *setting) +{} + +/** + * nm_setting_dummy_new: + * + * Creates a new #NMSettingDummy object with default values. + * + * Returns: (transfer full): the new empty #NMSettingDummy object + * + * Since: 1.8 + **/ +NMSetting * +nm_setting_dummy_new(void) +{ + return g_object_new(NM_TYPE_SETTING_DUMMY, NULL); +} + +static void +nm_setting_dummy_class_init(NMSettingDummyClass *klass) +{ + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + setting_class->verify = verify; + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_DUMMY); +} diff --git a/src/libnm-core-impl/nm-setting-ethtool.c b/src/libnm-core-impl/nm-setting-ethtool.c new file mode 100644 index 0000000000..db459697db --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ethtool.c @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ethtool.h" + +#include "nm-setting-private.h" +#include "nm-base/nm-ethtool-base.h" + +/*****************************************************************************/ + +/** + * SECTION:nm-setting-ethtool + * @short_description: Describes connection properties for ethtool related options + * + * The #NMSettingEthtool object is a #NMSetting subclass that describes properties + * to control network driver and hardware settings. + **/ + +/*****************************************************************************/ + +static const GVariantType * +get_variant_type_from_ethtool_id(NMEthtoolID ethtool_id) +{ + if (nm_ethtool_id_is_feature(ethtool_id)) + return G_VARIANT_TYPE_BOOLEAN; + + if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id)) + return G_VARIANT_TYPE_UINT32; + + return NULL; +} + +/*****************************************************************************/ + +/** + * nm_ethtool_optname_is_feature: + * @optname: (allow-none): the option name to check + * + * Checks whether @optname is a valid option name for an offload feature. + * + * %Returns: %TRUE, if @optname is valid + * + * Since: 1.20 + * + * Note that nm_ethtool_optname_is_feature() was first added to the libnm header files + * in 1.14.0 but forgot to actually add to the library. This happened belatedly in 1.20.0 and + * the stable versions 1.18.2, 1.16.4 and 1.14.8 (with linker version "libnm_1_14_8"). + */ +gboolean +nm_ethtool_optname_is_feature(const char *optname) +{ + return optname && nm_ethtool_id_is_feature(nm_ethtool_id_get_by_name(optname)); +} + +/** + * nm_ethtool_optname_is_coalesce: + * @optname: (allow-none): the option name to check + * + * Checks whether @optname is a valid option name for a coalesce setting. + * + * %Returns: %TRUE, if @optname is valid + * + * Since: 1.26 + */ +gboolean +nm_ethtool_optname_is_coalesce(const char *optname) +{ + return optname && nm_ethtool_id_is_coalesce(nm_ethtool_id_get_by_name(optname)); +} + +/** + * nm_ethtool_optname_is_ring: + * @optname: (allow-none): the option name to check + * + * Checks whether @optname is a valid option name for a ring setting. + * + * %Returns: %TRUE, if @optname is valid + * + * Since: 1.26 + */ +gboolean +nm_ethtool_optname_is_ring(const char *optname) +{ + return optname && nm_ethtool_id_is_ring(nm_ethtool_id_get_by_name(optname)); +} + +/*****************************************************************************/ + +/** + * NMSettingEthtool: + * + * Ethtool Ethernet Settings + * + * Since: 1.14 + */ +struct _NMSettingEthtool { + NMSetting parent; +}; + +struct _NMSettingEthtoolClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingEthtool, nm_setting_ethtool, NM_TYPE_SETTING) + +#define NM_SETTING_ETHTOOL_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingEthtool, NM_IS_SETTING_ETHTOOL, NMSetting) + +/*****************************************************************************/ + +/** + * nm_setting_ethtool_get_feature: + * @setting: the #NMSettingEthtool + * @optname: option name of the offload feature to get + * + * Gets and offload feature setting. Returns %NM_TERNARY_DEFAULT if the + * feature is not set. + * + * Note that @optname must be a valid name for a feature, according to + * nm_ethtool_optname_is_feature(). + * + * Returns: a #NMTernary value indicating whether the offload feature + * is enabled, disabled, or left untouched. + * + * Since: 1.14 + * + * Deprecated: 1.26: use nm_setting_option_get_boolean() instead. + */ +NMTernary +nm_setting_ethtool_get_feature(NMSettingEthtool *setting, const char *optname) +{ + gboolean v; + + g_return_val_if_fail(NM_IS_SETTING_ETHTOOL(setting), NM_TERNARY_DEFAULT); + g_return_val_if_fail(optname && nm_ethtool_optname_is_feature(optname), NM_TERNARY_DEFAULT); + + if (!nm_setting_option_get_boolean(NM_SETTING(setting), optname, &v)) + return NM_TERNARY_DEFAULT; + return v ? NM_TERNARY_TRUE : NM_TERNARY_FALSE; +} + +/** + * nm_setting_ethtool_set_feature: + * @setting: the #NMSettingEthtool + * @optname: option name of the offload feature to get + * @value: the new value to set. The special value %NM_TERNARY_DEFAULT + * means to clear the offload feature setting. + * + * Sets and offload feature setting. + * + * Note that @optname must be a valid name for a feature, according to + * nm_ethtool_optname_is_feature(). + * + * Since: 1.14 + * + * Deprecated: 1.26: use nm_setting_option_set() or nm_setting_option_set_boolean() instead. + */ +void +nm_setting_ethtool_set_feature(NMSettingEthtool *setting, const char *optname, NMTernary value) +{ + g_return_if_fail(NM_IS_SETTING_ETHTOOL(setting)); + g_return_if_fail(optname && nm_ethtool_optname_is_feature(optname)); + g_return_if_fail(NM_IN_SET(value, NM_TERNARY_DEFAULT, NM_TERNARY_FALSE, NM_TERNARY_TRUE)); + + if (value == NM_TERNARY_DEFAULT) + nm_setting_option_set(NM_SETTING(setting), optname, NULL); + else + nm_setting_option_set_boolean(NM_SETTING(setting), optname, (value != NM_TERNARY_FALSE)); +} + +/** + * nm_setting_ethtool_clear_features: + * @setting: the #NMSettingEthtool + * + * Clears all offload features settings + * + * Since: 1.14 + * + * Deprecated: 1.26: use nm_setting_option_clear_by_name() with nm_ethtool_optname_is_feature() predicate instead. + */ +void +nm_setting_ethtool_clear_features(NMSettingEthtool *setting) +{ + g_return_if_fail(NM_IS_SETTING_ETHTOOL(setting)); + + nm_setting_option_clear_by_name(NM_SETTING(setting), nm_ethtool_optname_is_feature); +} + +/*****************************************************************************/ + +guint +nm_setting_ethtool_init_features( + NMSettingEthtool *setting, + NMOptionBool * requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */) +{ + GHashTable * hash; + GHashTableIter iter; + guint i; + guint n_req = 0; + const char * name; + GVariant * variant; + + nm_assert(NM_IS_SETTING_ETHTOOL(setting)); + nm_assert(requested); + + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) + requested[i] = NM_OPTION_BOOL_DEFAULT; + + hash = _nm_setting_option_hash(NM_SETTING(setting), FALSE); + if (!hash) + return 0; + + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) { + NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name(name); + + if (!nm_ethtool_id_is_feature(ethtool_id)) + continue; + if (!g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) + continue; + + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(ethtool_id)] = + g_variant_get_boolean(variant) ? NM_OPTION_BOOL_TRUE : NM_OPTION_BOOL_FALSE; + n_req++; + } + + return n_req; +} + +/*****************************************************************************/ + +/** + * nm_setting_ethtool_get_optnames: + * @setting: the #NMSettingEthtool instance. + * @out_length: (out) (optional): return location for the number of keys returned, or %NULL + * + * This returns all options names that are set. This includes the feature names + * like %NM_ETHTOOL_OPTNAME_FEATURE_GRO. See nm_ethtool_optname_is_feature() to + * check whether the option name is valid for offload features. + * + * Returns: (array zero-terminated=1) (transfer container): list of set option + * names or %NULL if no options are set. The option names are still owned by + * @setting and may get invalidated when @setting gets modified. + * + * Since: 1.20 + * + * Deprecated: 1.26: use nm_setting_option_get_all_names() instead. + */ +const char ** +nm_setting_ethtool_get_optnames(NMSettingEthtool *setting, guint *out_length) +{ + const char *const *names; + guint len = 0; + + g_return_val_if_fail(NM_IS_SETTING_ETHTOOL(setting), NULL); + + names = nm_setting_option_get_all_names(NM_SETTING(setting), &len); + NM_SET_OUT(out_length, len); + return len > 0 ? nm_memdup(names, sizeof(names[0]) * (((gsize) len) + 1u)) : NULL; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + const char *const *optnames; + GVariant *const * variants; + guint len; + guint i; + + len = _nm_setting_option_get_all(setting, &optnames, &variants); + + for (i = 0; i < len; i++) { + const char * optname = optnames[i]; + GVariant * variant = variants[i]; + const GVariantType *variant_type; + NMEthtoolID ethtool_id; + + ethtool_id = nm_ethtool_id_get_by_name(optname); + variant_type = get_variant_type_from_ethtool_id(ethtool_id); + + if (!variant_type) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unsupported ethtool setting")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); + return FALSE; + } + + if (!g_variant_is_of_type(variant, variant_type)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("setting has invalid variant type")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); + return FALSE; + } + + if (NM_IN_SET(ethtool_id, + NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX, + NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)) { + if (!NM_IN_SET(g_variant_get_uint32(variant), 0, 1)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("coalesce option must be either 0 or 1")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); + return FALSE; + } + } + } + + return TRUE; +} + +/*****************************************************************************/ + +static const GVariantType * +get_variant_type(const NMSettInfoSetting *sett_info, const char *name, GError **error) +{ + const GVariantType *variant_type; + + variant_type = get_variant_type_from_ethtool_id(nm_ethtool_id_get_by_name(name)); + + if (!variant_type) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unknown ethtool option '%s'"), + name); + return NULL; + } + + return variant_type; +} + +/*****************************************************************************/ + +static void +nm_setting_ethtool_init(NMSettingEthtool *setting) +{} + +/** + * nm_setting_ethtool_new: + * + * Creates a new #NMSettingEthtool object with default values. + * + * Returns: (transfer full): the new empty #NMSettingEthtool object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_ethtool_new(void) +{ + return g_object_new(NM_TYPE_SETTING_ETHTOOL, NULL); +} + +static void +nm_setting_ethtool_class_init(NMSettingEthtoolClass *klass) +{ + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + setting_class->verify = verify; + + _nm_setting_class_commit_full( + setting_class, + NM_META_SETTING_TYPE_ETHTOOL, + NM_SETT_INFO_SETT_DETAIL(.gendata_info = + NM_SETT_INFO_SETT_GENDATA(.get_variant_type = + get_variant_type, ), ), + NULL); +} diff --git a/src/libnm-core-impl/nm-setting-generic.c b/src/libnm-core-impl/nm-setting-generic.c new file mode 100644 index 0000000000..70752c07eb --- /dev/null +++ b/src/libnm-core-impl/nm-setting-generic.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2013 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-generic.h" + +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-generic + * @short_description: Describes connection properties for generic devices + * + * The #NMSettingGeneric object is a #NMSetting subclass that describes + * optional properties that apply to "generic" devices (ie, devices that + * NetworkManager does not specifically recognize). + * + * There are currently no properties on this object; it exists only to be + * the "connection type" setting on #NMConnections for generic devices. + **/ + +/*****************************************************************************/ + +typedef struct { + int dummy; +} NMSettingGenericPrivate; + +G_DEFINE_TYPE(NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING) + +#define NM_SETTING_GENERIC_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_GENERIC, NMSettingGenericPrivate)) + +/*****************************************************************************/ + +static void +nm_setting_generic_init(NMSettingGeneric *setting) +{} + +/** + * nm_setting_generic_new: + * + * Creates a new #NMSettingGeneric object with default values. + * + * Returns: (transfer full): the new empty #NMSettingGeneric object + **/ +NMSetting * +nm_setting_generic_new(void) +{ + return g_object_new(NM_TYPE_SETTING_GENERIC, NULL); +} + +static void +nm_setting_generic_class_init(NMSettingGenericClass *klass) +{ + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingGenericPrivate)); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_GENERIC); +} diff --git a/src/libnm-core-impl/nm-setting-gsm.c b/src/libnm-core-impl/nm-setting-gsm.c new file mode 100644 index 0000000000..a148e139f6 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-gsm.c @@ -0,0 +1,868 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-gsm.h" + +#include "nm-utils.h" +#include "nm-setting-private.h" +#include "nm-core-enum-types.h" + +/** + * SECTION:nm-setting-gsm + * @short_description: Describes GSM/3GPP-based mobile broadband properties + * + * The #NMSettingGsm object is a #NMSetting subclass that describes + * properties that allow connections to 3GPP-based mobile broadband + * networks, including those using GPRS/EDGE and UMTS/HSPA technology. + */ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_AUTO_CONFIG, + PROP_NUMBER, + PROP_USERNAME, + PROP_PASSWORD, + PROP_PASSWORD_FLAGS, + PROP_APN, + PROP_NETWORK_ID, + PROP_PIN, + PROP_PIN_FLAGS, + PROP_HOME_ONLY, + PROP_DEVICE_ID, + PROP_SIM_ID, + PROP_SIM_OPERATOR_ID, + PROP_MTU, ); + +typedef struct { + char * number; /* For dialing, duh */ + char * username; + char * password; + char * device_id; + char * sim_id; + char * sim_operator_id; + char * apn; /* NULL for dynamic */ + char * network_id; /* for manual registration or NULL for automatic */ + char * pin; + NMSettingSecretFlags password_flags; + NMSettingSecretFlags pin_flags; + guint32 mtu; + bool auto_config : 1; + bool home_only : 1; +} NMSettingGsmPrivate; + +G_DEFINE_TYPE(NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING) + +#define NM_SETTING_GSM_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_GSM, NMSettingGsmPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_gsm_get_auto_config: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:auto-config property of the setting + * + * Since: 1.22 + **/ +gboolean +nm_setting_gsm_get_auto_config(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), FALSE); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->auto_config; +} + +/** + * nm_setting_gsm_get_number: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:number property of the setting + * + * Deprecated: 1.16: User-provided values for this setting are no longer used. + **/ +const char * +nm_setting_gsm_get_number(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->number; +} + +/** + * nm_setting_gsm_get_username: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:username property of the setting + **/ +const char * +nm_setting_gsm_get_username(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->username; +} + +/** + * nm_setting_gsm_get_password: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:password property of the setting + **/ +const char * +nm_setting_gsm_get_password(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->password; +} + +/** + * nm_setting_gsm_get_password_flags: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingGsm:password + **/ +NMSettingSecretFlags +nm_setting_gsm_get_password_flags(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->password_flags; +} + +/** + * nm_setting_gsm_get_apn: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:apn property of the setting + **/ +const char * +nm_setting_gsm_get_apn(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->apn; +} + +/** + * nm_setting_gsm_get_network_id: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:network-id property of the setting + **/ +const char * +nm_setting_gsm_get_network_id(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->network_id; +} + +/** + * nm_setting_gsm_get_pin: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:pin property of the setting + **/ +const char * +nm_setting_gsm_get_pin(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->pin; +} + +/** + * nm_setting_gsm_get_pin_flags: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingGsm:pin + **/ +NMSettingSecretFlags +nm_setting_gsm_get_pin_flags(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->pin_flags; +} + +/** + * nm_setting_gsm_get_home_only: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:home-only property of the setting + **/ +gboolean +nm_setting_gsm_get_home_only(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), FALSE); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->home_only; +} + +/** + * nm_setting_gsm_get_device_id: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:device-id property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_gsm_get_device_id(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->device_id; +} + +/** + * nm_setting_gsm_get_sim_id: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:sim-id property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_gsm_get_sim_id(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->sim_id; +} + +/** + * nm_setting_gsm_get_sim_operator_id: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:sim-operator-id property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_gsm_get_sim_operator_id(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->sim_operator_id; +} + +/** + * nm_setting_gsm_get_mtu: + * @setting: the #NMSettingGsm + * + * Returns: the #NMSettingGsm:mtu property of the setting + * + * Since: 1.8 + **/ +guint32 +nm_setting_gsm_get_mtu(NMSettingGsm *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GSM(setting), 0); + + return NM_SETTING_GSM_GET_PRIVATE(setting)->mtu; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(setting); + + if (priv->number && !priv->number[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_NUMBER); + return FALSE; + } + + if (priv->apn) { + gsize apn_len = strlen(priv->apn); + gsize i; + + if (apn_len > 64) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property value '%s' is empty or too long (>64)"), + priv->apn); + g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_APN); + return FALSE; + } + + /* APNs roughly follow the same rules as DNS domain names. Allowed + * characters are a-z, 0-9, . and -. GSM 03.03 Section 9.1 states: + * + * The syntax of the APN shall follow the Name Syntax defined in + * RFC 2181 [14] and RFC 1035 [15]. The APN consists of one or + * more labels. Each label is coded as one octet length field + * followed by that number of octets coded as 8 bit ASCII characters. + * Following RFC 1035 [15] the labels should consist only of the + * alphabetic characters (A-Z and a-z), digits (0-9) and the + * dash (-). The case of alphabetic characters is not significant. + * + * A dot (.) is commonly used to separate parts of the APN, and + * apparently the underscore (_) is used as well. RFC 2181 indicates + * that no restrictions of any kind are placed on DNS labels, and thus + * it would appear that none are placed on APNs either, but many modems + * and networks will fail to accept APNs that include odd characters + * like space ( ) and such. + */ + for (i = 0; i < apn_len; i++) { + if (!g_ascii_isalnum(priv->apn[i]) && (priv->apn[i] != '.') && (priv->apn[i] != '_') + && (priv->apn[i] != '-')) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' contains invalid char(s) (use [A-Za-z._-])"), + priv->apn); + g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_APN); + return FALSE; + } + } + } + + if (priv->username && priv->username[0] == '\0') { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_USERNAME); + return FALSE; + } + + if (priv->network_id) { + gsize nid_len = strlen(priv->network_id); + gsize i; + + /* Accept both 5 and 6 digit MCC/MNC codes */ + if ((nid_len < 5) || (nid_len > 6)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' length is invalid (should be 5 or 6 digits)"), + priv->network_id); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_GSM_SETTING_NAME, + NM_SETTING_GSM_NETWORK_ID); + return FALSE; + } + + for (i = 0; i < nid_len; i++) { + if (!g_ascii_isdigit(priv->network_id[i])) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a number"), + priv->network_id); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_GSM_SETTING_NAME, + NM_SETTING_GSM_NETWORK_ID); + return FALSE; + } + } + } + + if (priv->device_id && !priv->device_id[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_DEVICE_ID); + return FALSE; + } + + if (priv->sim_id && !priv->sim_id[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_SIM_ID); + return FALSE; + } + + if (priv->sim_operator_id) { + size_t len = strlen(priv->sim_operator_id); + const char *p = priv->sim_operator_id; + + if (len == 0 || (len != 5 && len != 6)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty or wrong size")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_GSM_SETTING_NAME, + NM_SETTING_GSM_SIM_OPERATOR_ID); + return FALSE; + } + + while (p && *p) { + if (!g_ascii_isdigit(*p++)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property must contain only digits")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_GSM_SETTING_NAME, + NM_SETTING_GSM_SIM_OPERATOR_ID); + return FALSE; + } + } + } + + if (priv->auto_config && (priv->apn || priv->username || priv->password)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can't be enabled when manual configuration is present")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_AUTO_CONFIG); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + return TRUE; +} + +static gboolean +verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) +{ + return _nm_setting_verify_secret_string(NM_SETTING_GSM_GET_PRIVATE(setting)->password, + NM_SETTING_GSM_SETTING_NAME, + NM_SETTING_GSM_PASSWORD, + error); +} + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(setting); + GPtrArray * secrets = NULL; + + if (priv->password && *priv->password) + return NULL; + + if (priv->username) { + if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { + secrets = g_ptr_array_sized_new(1); + g_ptr_array_add(secrets, NM_SETTING_GSM_PASSWORD); + } + } + + return secrets; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingGsm *setting = NM_SETTING_GSM(object); + + switch (prop_id) { + case PROP_AUTO_CONFIG: + g_value_set_boolean(value, nm_setting_gsm_get_auto_config(setting)); + break; + case PROP_NUMBER: + g_value_set_string(value, nm_setting_gsm_get_number(setting)); + break; + case PROP_USERNAME: + g_value_set_string(value, nm_setting_gsm_get_username(setting)); + break; + case PROP_PASSWORD: + g_value_set_string(value, nm_setting_gsm_get_password(setting)); + break; + case PROP_PASSWORD_FLAGS: + g_value_set_flags(value, nm_setting_gsm_get_password_flags(setting)); + break; + case PROP_APN: + g_value_set_string(value, nm_setting_gsm_get_apn(setting)); + break; + case PROP_NETWORK_ID: + g_value_set_string(value, nm_setting_gsm_get_network_id(setting)); + break; + case PROP_PIN: + g_value_set_string(value, nm_setting_gsm_get_pin(setting)); + break; + case PROP_PIN_FLAGS: + g_value_set_flags(value, nm_setting_gsm_get_pin_flags(setting)); + break; + case PROP_HOME_ONLY: + g_value_set_boolean(value, nm_setting_gsm_get_home_only(setting)); + break; + case PROP_DEVICE_ID: + g_value_set_string(value, nm_setting_gsm_get_device_id(setting)); + break; + case PROP_SIM_ID: + g_value_set_string(value, nm_setting_gsm_get_sim_id(setting)); + break; + case PROP_SIM_OPERATOR_ID: + g_value_set_string(value, nm_setting_gsm_get_sim_operator_id(setting)); + break; + case PROP_MTU: + g_value_set_uint(value, nm_setting_gsm_get_mtu(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(object); + char * tmp; + + switch (prop_id) { + case PROP_AUTO_CONFIG: + priv->auto_config = g_value_get_boolean(value); + break; + case PROP_NUMBER: + g_free(priv->number); + priv->number = g_value_dup_string(value); + break; + case PROP_USERNAME: + g_free(priv->username); + priv->username = g_value_dup_string(value); + break; + case PROP_PASSWORD: + g_free(priv->password); + priv->password = g_value_dup_string(value); + break; + case PROP_PASSWORD_FLAGS: + priv->password_flags = g_value_get_flags(value); + break; + case PROP_APN: + g_free(priv->apn); + priv->apn = NULL; + tmp = g_value_dup_string(value); + if (tmp) + priv->apn = g_strstrip(tmp); + break; + case PROP_NETWORK_ID: + g_free(priv->network_id); + priv->network_id = NULL; + tmp = g_value_dup_string(value); + if (tmp) + priv->network_id = g_strstrip(tmp); + break; + case PROP_PIN: + g_free(priv->pin); + priv->pin = g_value_dup_string(value); + break; + case PROP_PIN_FLAGS: + priv->pin_flags = g_value_get_flags(value); + break; + case PROP_HOME_ONLY: + priv->home_only = g_value_get_boolean(value); + break; + case PROP_DEVICE_ID: + g_free(priv->device_id); + priv->device_id = g_value_dup_string(value); + break; + case PROP_SIM_ID: + g_free(priv->sim_id); + priv->sim_id = g_value_dup_string(value); + break; + case PROP_SIM_OPERATOR_ID: + g_free(priv->sim_operator_id); + priv->sim_operator_id = g_value_dup_string(value); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_gsm_init(NMSettingGsm *setting) +{} + +/** + * nm_setting_gsm_new: + * + * Creates a new #NMSettingGsm object with default values. + * + * Returns: the new empty #NMSettingGsm object + **/ +NMSetting * +nm_setting_gsm_new(void) +{ + return g_object_new(NM_TYPE_SETTING_GSM, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(object); + + g_free(priv->number); + g_free(priv->username); + g_free(priv->password); + g_free(priv->apn); + g_free(priv->network_id); + g_free(priv->pin); + g_free(priv->device_id); + g_free(priv->sim_id); + g_free(priv->sim_operator_id); + + G_OBJECT_CLASS(nm_setting_gsm_parent_class)->finalize(object); +} + +static void +nm_setting_gsm_class_init(NMSettingGsmClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingGsmPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; + + /** + * NMSettingGsm:auto-config: + * + * When %TRUE, the settings such as APN, username, or password will + * default to values that match the network the modem will register + * to in the Mobile Broadband Provider database. + * + * Since: 1.22 + **/ + obj_properties[PROP_AUTO_CONFIG] = + g_param_spec_boolean(NM_SETTING_GSM_AUTO_CONFIG, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:number: + * + * Legacy setting that used to help establishing PPP data sessions for + * GSM-based modems. + * + * Deprecated: 1.16: User-provided values for this setting are no longer used. + **/ + obj_properties[PROP_NUMBER] = g_param_spec_string(NM_SETTING_GSM_NUMBER, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:username: + * + * The username used to authenticate with the network, if required. Many + * providers do not require a username, or accept any username. But if a + * username is required, it is specified here. + **/ + obj_properties[PROP_USERNAME] = g_param_spec_string(NM_SETTING_GSM_USERNAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:password: + * + * The password used to authenticate with the network, if required. Many + * providers do not require a password, or accept any password. But if a + * password is required, it is specified here. + **/ + obj_properties[PROP_PASSWORD] = + g_param_spec_string(NM_SETTING_GSM_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:password-flags: + * + * Flags indicating how to handle the #NMSettingGsm:password property. + **/ + obj_properties[PROP_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_GSM_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:apn: + * + * The GPRS Access Point Name specifying the APN used when establishing a + * data session with the GSM-based network. The APN often determines how + * the user will be billed for their network usage and whether the user has + * access to the Internet or just a provider-specific walled-garden, so it + * is important to use the correct APN for the user's mobile broadband plan. + * The APN may only be composed of the characters a-z, 0-9, ., and - per GSM + * 03.60 Section 14.9. + **/ + obj_properties[PROP_APN] = g_param_spec_string(NM_SETTING_GSM_APN, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:network-id: + * + * The Network ID (GSM LAI format, ie MCC-MNC) to force specific network + * registration. If the Network ID is specified, NetworkManager will + * attempt to force the device to register only on the specified network. + * This can be used to ensure that the device does not roam when direct + * roaming control of the device is not otherwise possible. + **/ + obj_properties[PROP_NETWORK_ID] = + g_param_spec_string(NM_SETTING_GSM_NETWORK_ID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:pin: + * + * If the SIM is locked with a PIN it must be unlocked before any other + * operations are requested. Specify the PIN here to allow operation of the + * device. + **/ + obj_properties[PROP_PIN] = + g_param_spec_string(NM_SETTING_GSM_PIN, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:pin-flags: + * + * Flags indicating how to handle the #NMSettingGsm:pin property. + **/ + obj_properties[PROP_PIN_FLAGS] = g_param_spec_flags(NM_SETTING_GSM_PIN_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:home-only: + * + * When %TRUE, only connections to the home network will be allowed. + * Connections to roaming networks will not be made. + **/ + obj_properties[PROP_HOME_ONLY] = + g_param_spec_boolean(NM_SETTING_GSM_HOME_ONLY, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:device-id: + * + * The device unique identifier (as given by the WWAN management service) + * which this connection applies to. If given, the connection will only + * apply to the specified device. + * + * Since: 1.2 + **/ + obj_properties[PROP_DEVICE_ID] = + g_param_spec_string(NM_SETTING_GSM_DEVICE_ID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:sim-id: + * + * The SIM card unique identifier (as given by the WWAN management service) + * which this connection applies to. If given, the connection will apply + * to any device also allowed by #NMSettingGsm:device-id which contains a + * SIM card matching the given identifier. + * + * Since: 1.2 + **/ + obj_properties[PROP_SIM_ID] = g_param_spec_string(NM_SETTING_GSM_SIM_ID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:sim-operator-id: + * + * A MCC/MNC string like "310260" or "21601" identifying the specific + * mobile network operator which this connection applies to. If given, + * the connection will apply to any device also allowed by + * #NMSettingGsm:device-id and #NMSettingGsm:sim-id which contains a SIM + * card provisioned by the given operator. + * + * Since: 1.2 + **/ + obj_properties[PROP_SIM_OPERATOR_ID] = + g_param_spec_string(NM_SETTING_GSM_SIM_OPERATOR_ID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingGsm:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple frames. + * + * Since: 1.8 + **/ + obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_GSM_MTU, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /* Ignore incoming deprecated properties */ + _nm_properties_override_dbus(properties_override, + "allowed-bands", + &nm_sett_info_propert_type_deprecated_ignore_u); + _nm_properties_override_dbus(properties_override, + "network-type", + &nm_sett_info_propert_type_deprecated_ignore_i); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_GSM, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-hostname.c b/src/libnm-core-impl/nm-setting-hostname.c new file mode 100644 index 0000000000..248ae556e3 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-hostname.c @@ -0,0 +1,339 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-hostname.h" + +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-hostname + * @short_description: Contains properties related to the hostname + * @include: nm-setting-hostname.h + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingHostname, + PROP_PRIORITY, + PROP_FROM_DHCP, + PROP_FROM_DNS_LOOKUP, + PROP_ONLY_FROM_DEFAULT, ); + +/** + * NMSettingHostname: + * + * Hostname settings + * + * Since: 1.30 + */ +struct _NMSettingHostname { + NMSetting parent; + int priority; + NMTernary from_dhcp; + NMTernary from_dns_lookup; + NMTernary only_from_default; +}; + +struct _NMSettingHostnameClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingHostname, nm_setting_hostname, NM_TYPE_SETTING) + +/** + * nm_setting_hostname_get_priority: + * @setting: the #NMSettingHostname + * + * Returns the value contained in the #NMSettingHostname:priority + * property. + * + * Returns: the 'priority' property value + * + * Since: 1.30 + **/ +int +nm_setting_hostname_get_priority(NMSettingHostname *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), 0); + + return setting->priority; +} + +/** + * nm_setting_hostname_get_from_dhcp: + * @setting: the #NMSettingHostname + * + * Returns the value contained in the #NMSettingHostname:from-dhcp + * property. + * + * Returns: the 'from-dhcp' property value + * + * Since: 1.30 + **/ +NMTernary +nm_setting_hostname_get_from_dhcp(NMSettingHostname *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT); + + return setting->from_dhcp; +} + +/** + * nm_setting_hostname_get_from_dns_lookup: + * @setting: the #NMSettingHostname + * + * Returns the value contained in the #NMSettingHostname:from-dns-lookup + * property. + * + * Returns: the 'from-dns-lookup' property value + * + * Since: 1.30 + **/ +NMTernary +nm_setting_hostname_get_from_dns_lookup(NMSettingHostname *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT); + + return setting->from_dns_lookup; +} + +/** + * nm_setting_hostname_get_only_from_default: + * @setting: the #NMSettingHostname + * + * Returns the value contained in the #NMSettingHostname:only-from-default + * property. + * + * Returns: the 'only-from-default' property value + * + * Since: 1.30 + **/ +NMTernary +nm_setting_hostname_get_only_from_default(NMSettingHostname *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT); + + return setting->only_from_default; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingHostname *self = NM_SETTING_HOSTNAME(object); + + switch (prop_id) { + case PROP_PRIORITY: + g_value_set_int(value, self->priority); + break; + case PROP_FROM_DHCP: + g_value_set_enum(value, self->from_dhcp); + break; + case PROP_FROM_DNS_LOOKUP: + g_value_set_enum(value, self->from_dns_lookup); + break; + case PROP_ONLY_FROM_DEFAULT: + g_value_set_enum(value, self->only_from_default); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingHostname *self = NM_SETTING_HOSTNAME(object); + + switch (prop_id) { + case PROP_PRIORITY: + self->priority = g_value_get_int(value); + break; + case PROP_FROM_DHCP: + self->from_dhcp = g_value_get_enum(value); + break; + case PROP_FROM_DNS_LOOKUP: + self->from_dns_lookup = g_value_get_enum(value); + break; + case PROP_ONLY_FROM_DEFAULT: + self->only_from_default = g_value_get_enum(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_hostname_init(NMSettingHostname *setting) +{ + setting->from_dhcp = NM_TERNARY_DEFAULT; + setting->from_dns_lookup = NM_TERNARY_DEFAULT; + setting->only_from_default = NM_TERNARY_DEFAULT; +} + +/** + * nm_setting_hostname_new: + * + * Creates a new #NMSettingHostname object with default values. + * + * Returns: (transfer full): the new empty #NMSettingHostname object + * + * Since: 1.30 + **/ +NMSetting * +nm_setting_hostname_new(void) +{ + return g_object_new(NM_TYPE_SETTING_HOSTNAME, NULL); +} + +static void +nm_setting_hostname_class_init(NMSettingHostnameClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + object_class->get_property = get_property; + object_class->set_property = set_property; + + /** + * NMSettingHostname:priority + * + * The relative priority of this connection to determine the + * system hostname. A lower numerical value is better (higher + * priority). A connection with higher priority is considered + * before connections with lower priority. + * + * If the value is zero, it can be overridden by a global value + * from NetworkManager configuration. If the property doesn't have + * a value in the global configuration, the value is assumed to be + * 100. + * + * Negative values have the special effect of excluding other + * connections with a greater numerical priority value; so in + * presence of at least one negative priority, only connections + * with the lowest priority value will be used to determine the + * hostname. + * + * Since: 1.30 + **/ + /* ---ifcfg-rh--- + * property: priority + * variable: HOSTNAME_PRIORITY(+) + * default: missing variable means global value or 100 + * description: hostname priority + * example: HOSTNAME_PRIORITY=50 + * ---end--- + */ + obj_properties[PROP_PRIORITY] = g_param_spec_int(NM_SETTING_HOSTNAME_PRIORITY, + "", + "", + G_MININT32, + G_MAXINT32, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingHostname:from-dhcp + * + * Whether the system hostname can be determined from DHCP on + * this connection. + * + * When set to %NM_TERNARY_DEFAULT, the value from global configuration + * is used. If the property doesn't have a value in the global + * configuration, NetworkManager assumes the value to be %NM_TERNARY_TRUE. + * + * Since: 1.30 + **/ + /* ---ifcfg-rh--- + * property: from-dhcp + * variable: HOSTNAME_FROM_DHCP(+) + * default: missing variable means global default or 1 + * description: whether the system hostname can be determined from DHCP + * example: HOSTNAME_FROM_DHCP=0,1 + * ---end--- + */ + obj_properties[PROP_FROM_DHCP] = g_param_spec_enum( + NM_SETTING_HOSTNAME_FROM_DHCP, + "", + "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingHostname:from-dns-lookup + * + * Whether the system hostname can be determined from reverse + * DNS lookup of addresses on this device. + * + * When set to %NM_TERNARY_DEFAULT, the value from global configuration + * is used. If the property doesn't have a value in the global + * configuration, NetworkManager assumes the value to be %NM_TERNARY_TRUE. + * + * Since: 1.30 + **/ + /* ---ifcfg-rh--- + * property: from-dhcp + * variable: HOSTNAME_FROM_DNS_LOOKUP(+) + * default: missing variable means global default or 1 + * description: whether the system hostname can be determined from reverse + * DNS lookup + * example: HOSTNAME_FROM_DNS_LOOKUP=0,1 + * ---end--- + */ + obj_properties[PROP_FROM_DNS_LOOKUP] = g_param_spec_enum( + NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP, + "", + "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingHostname:only-from-default + * + * If set to %NM_TERNARY_TRUE, NetworkManager attempts to get + * the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this + * device only when the device has the default route for the given + * address family (IPv4/IPv6). + * + * If set to %NM_TERNARY_FALSE, the hostname can be set from this + * device even if it doesn't have the default route. + * + * When set to %NM_TERNARY_DEFAULT, the value from global configuration + * is used. If the property doesn't have a value in the global + * configuration, NetworkManager assumes the value to be %NM_TERNARY_FALSE. + * + * Since: 1.30 + **/ + /* ---ifcfg-rh--- + * property: only-best-device + * variable: HOSTNAME_ONLY_FROM_DEFAULT(+) + * default: missing variable means global default or 1 + * description: whether the hostname can be determined only from + * devices with the default route + * example: HOSTNAME_ONLY_FROM_DEFAULT=0,1 + * ---end--- + */ + obj_properties[PROP_ONLY_FROM_DEFAULT] = g_param_spec_enum( + NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT, + "", + "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_HOSTNAME); +} diff --git a/src/libnm-core-impl/nm-setting-infiniband.c b/src/libnm-core-impl/nm-setting-infiniband.c new file mode 100644 index 0000000000..11485dda06 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-infiniband.c @@ -0,0 +1,521 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2013 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-infiniband.h" + +#include +#include + +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" +#include "nm-setting-connection.h" + +/** + * SECTION:nm-setting-infiniband + * @short_description: Describes connection properties for IP-over-InfiniBand networks + * + * The #NMSettingInfiniband object is a #NMSetting subclass that describes properties + * necessary for connection to IP-over-InfiniBand networks. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_MAC_ADDRESS, + PROP_MTU, + PROP_TRANSPORT_MODE, + PROP_P_KEY, + PROP_PARENT, ); + +typedef struct { + char * mac_address; + char * transport_mode; + char * parent; + char * virtual_iface_name; + int p_key; + guint32 mtu; +} NMSettingInfinibandPrivate; + +G_DEFINE_TYPE(NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING) + +#define NM_SETTING_INFINIBAND_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_infiniband_get_mac_address: + * @setting: the #NMSettingInfiniband + * + * Returns: the #NMSettingInfiniband:mac-address property of the setting + **/ +const char * +nm_setting_infiniband_get_mac_address(NMSettingInfiniband *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), NULL); + + return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->mac_address; +} + +/** + * nm_setting_infiniband_get_mtu: + * @setting: the #NMSettingInfiniband + * + * Returns: the #NMSettingInfiniband:mtu property of the setting + **/ +guint32 +nm_setting_infiniband_get_mtu(NMSettingInfiniband *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), 0); + + return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->mtu; +} + +/** + * nm_setting_infiniband_get_transport_mode: + * @setting: the #NMSettingInfiniband + * + * Returns the transport mode for this device. Either 'datagram' or + * 'connected'. + * + * Returns: the IPoIB transport mode + **/ +const char * +nm_setting_infiniband_get_transport_mode(NMSettingInfiniband *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), NULL); + + return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->transport_mode; +} + +/** + * nm_setting_infiniband_get_p_key: + * @setting: the #NMSettingInfiniband + * + * Returns the P_Key to use for this device. A value of -1 means to + * use the default P_Key (aka "the P_Key at index 0"). Otherwise, it is + * a 16-bit unsigned integer. + * + * Returns: the IPoIB P_Key + **/ +int +nm_setting_infiniband_get_p_key(NMSettingInfiniband *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), -1); + + return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->p_key; +} + +/** + * nm_setting_infiniband_get_parent: + * @setting: the #NMSettingInfiniband + * + * Returns the parent interface name for this device, if set. + * + * Returns: the parent interface name + **/ +const char * +nm_setting_infiniband_get_parent(NMSettingInfiniband *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_INFINIBAND(setting), NULL); + + return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->parent; +} + +/** + * nm_setting_infiniband_get_virtual_interface_name: + * @setting: the #NMSettingInfiniband + * + * Returns the interface name created by combining #NMSettingInfiniband:parent + * and #NMSettingInfiniband:p-key. (If either property is unset, this will + * return %NULL.) + * + * Returns: the interface name, or %NULL + **/ +const char * +nm_setting_infiniband_get_virtual_interface_name(NMSettingInfiniband *setting) +{ + NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(setting); + + if (priv->p_key == -1 || !priv->parent) + return NULL; + + if (!priv->virtual_iface_name) + priv->virtual_iface_name = g_strdup_printf("%s.%04x", priv->parent, priv->p_key); + + return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->virtual_iface_name; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingConnection * s_con = NULL; + NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(setting); + + if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, INFINIBAND_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_INFINIBAND_SETTING_NAME, + NM_SETTING_INFINIBAND_MAC_ADDRESS); + return FALSE; + } + + if (!NM_IN_STRSET(priv->transport_mode, "datagram", "connected")) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_INFINIBAND_SETTING_NAME, + NM_SETTING_INFINIBAND_TRANSPORT_MODE); + return FALSE; + } + + if (priv->parent) { + GError *tmp_error = NULL; + + if (!nm_utils_ifname_valid_kernel(priv->parent, &tmp_error)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "'%s': %s", + priv->parent, + tmp_error->message); + g_prefix_error(error, "%s: ", NM_SETTING_INFINIBAND_PARENT); + g_error_free(tmp_error); + return FALSE; + } + if (priv->p_key == -1) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Must specify a P_Key if specifying parent")); + g_prefix_error(error, "%s: ", NM_SETTING_INFINIBAND_PARENT); + } + } + + if (priv->p_key != -1) { + if (!priv->mac_address && !priv->parent) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("InfiniBand P_Key connection did not specify parent interface name")); + g_prefix_error(error, "%s: ", NM_SETTING_INFINIBAND_PARENT); + return FALSE; + } + } + + if (connection) + s_con = nm_connection_get_setting_connection(connection); + if (s_con) { + const char *interface_name = nm_setting_connection_get_interface_name(s_con); + + if (interface_name && priv->p_key != -1) { + if (!priv->virtual_iface_name) + priv->virtual_iface_name = g_strdup_printf("%s.%04x", priv->parent, priv->p_key); + + if (strcmp(interface_name, priv->virtual_iface_name) != 0) { + /* We don't support renaming software infiniband devices. Later we might, but + * for now just reject such connections. + **/ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("interface name of software infiniband device must be '%s' or unset " + "(instead it is '%s')"), + priv->virtual_iface_name, + interface_name); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME); + return FALSE; + } + } + } + + /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ + + if (priv->mtu > NM_INFINIBAND_MAX_MTU) { + /* Traditionally, MTU for "datagram" mode was limited to 2044 + * and for "connected" mode it was 65520. + * + * This is no longer the case, and both transport modes use the same + * maximum of 65520 (NM_INFINIBAND_MAX_MTU). + * + * Note that this is the MTU in the connection profile. Whether + * we will be able to configure large MTUs later (during activation) + * is unknown at this point. */ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("mtu can be at most %u but it is %u"), + NM_INFINIBAND_MAX_MTU, + priv->mtu); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_INFINIBAND_SETTING_NAME, + NM_SETTING_INFINIBAND_MTU); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingInfiniband *setting = NM_SETTING_INFINIBAND(object); + + switch (prop_id) { + case PROP_MAC_ADDRESS: + g_value_set_string(value, nm_setting_infiniband_get_mac_address(setting)); + break; + case PROP_MTU: + g_value_set_uint(value, nm_setting_infiniband_get_mtu(setting)); + break; + case PROP_TRANSPORT_MODE: + g_value_set_string(value, nm_setting_infiniband_get_transport_mode(setting)); + break; + case PROP_P_KEY: + g_value_set_int(value, nm_setting_infiniband_get_p_key(setting)); + break; + case PROP_PARENT: + g_value_set_string(value, nm_setting_infiniband_get_parent(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_MAC_ADDRESS: + g_free(priv->mac_address); + priv->mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), INFINIBAND_ALEN); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint(value); + break; + case PROP_TRANSPORT_MODE: + g_free(priv->transport_mode); + priv->transport_mode = g_value_dup_string(value); + break; + case PROP_P_KEY: + priv->p_key = g_value_get_int(value); + nm_clear_g_free(&priv->virtual_iface_name); + break; + case PROP_PARENT: + g_free(priv->parent); + priv->parent = g_value_dup_string(value); + nm_clear_g_free(&priv->virtual_iface_name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_infiniband_init(NMSettingInfiniband *self) +{ + NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(self); + + priv->p_key = -1; +} + +/** + * nm_setting_infiniband_new: + * + * Creates a new #NMSettingInfiniband object with default values. + * + * Returns: (transfer full): the new empty #NMSettingInfiniband object + **/ +NMSetting * +nm_setting_infiniband_new(void) +{ + return g_object_new(NM_TYPE_SETTING_INFINIBAND, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(object); + + g_free(priv->transport_mode); + g_free(priv->mac_address); + g_free(priv->parent); + g_free(priv->virtual_iface_name); + + G_OBJECT_CLASS(nm_setting_infiniband_parent_class)->finalize(object); +} + +static void +nm_setting_infiniband_class_init(NMSettingInfinibandClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingInfinibandPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingInfiniband:mac-address: + * + * If specified, this connection will only apply to the IPoIB device whose + * permanent MAC address matches. This property does not change the MAC + * address of the device (i.e. MAC spoofing). + **/ + /* ---keyfile--- + * property: mac-address + * format: usual hex-digits-and-colons notation + * description: MAC address in traditional hex-digits-and-colons notation, or + * or semicolon separated list of 20 decimal bytes (obsolete) + * example: mac-address= 80:00:00:6d:fe:80:00:00:00:00:00:00:00:02:55:00:70:33:cf:01 + * ---end--- + * ---ifcfg-rh--- + * property: mac-address + * variable: HWADDR + * description: IBoIP 20-byte hardware address of the device (in traditional + * hex-digits-and-colons notation). + * Note that for initscripts this is the current MAC address of the device as found + * during ifup. For NetworkManager this is the permanent MAC address. Or in case no + * permanent MAC address exists, the MAC address initially configured on the device. + * example: HWADDR=01:02:03:04:05:06:07:08:09:0A:01:02:03:04:05:06:07:08:09:11 + * ---end--- + */ + obj_properties[PROP_MAC_ADDRESS] = g_param_spec_string( + NM_SETTING_INFINIBAND_MAC_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_MAC_ADDRESS], + &nm_sett_info_propert_type_mac_address); + + /** + * NMSettingInfiniband:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple frames. + **/ + /* ---ifcfg-rh--- + * property: mtu + * variable: MTU + * description: MTU of the interface. + * ---end--- + */ + obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_INFINIBAND_MTU, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingInfiniband:transport-mode: + * + * The IP-over-InfiniBand transport mode. Either "datagram" or + * "connected". + **/ + /* ---ifcfg-rh--- + * property: transport-mode + * variable: CONNECTED_MODE + * default: CONNECTED_MODE=no + * description: CONNECTED_MODE=yes for "connected" mode, CONNECTED_MODE=no for + * "datagram" mode + * ---end--- + */ + obj_properties[PROP_TRANSPORT_MODE] = g_param_spec_string( + NM_SETTING_INFINIBAND_TRANSPORT_MODE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingInfiniband:p-key: + * + * The InfiniBand P_Key to use for this device. A value of -1 means to use + * the default P_Key (aka "the P_Key at index 0"). Otherwise, it is a 16-bit + * unsigned integer, whose high bit is set if it is a "full membership" + * P_Key. + **/ + /* ---ifcfg-rh--- + * property: p-key + * variable: PKEY_ID (and PKEY=yes) + * default: PKEY=no + * description: InfiniBand P_Key. The value can be a hex number prefixed with "0x" + * or a decimal number. + * When PKEY_ID is specified, PHYSDEV and DEVICE also must be specified. + * example: PKEY=yes PKEY_ID=2 PHYSDEV=mlx4_ib0 DEVICE=mlx4_ib0.8002 + * ---end--- + */ + obj_properties[PROP_P_KEY] = + g_param_spec_int(NM_SETTING_INFINIBAND_P_KEY, + "", + "", + -1, + 0xFFFF, + -1, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingInfiniband:parent: + * + * The interface name of the parent device of this device. Normally %NULL, + * but if the #NMSettingInfiniband:p_key property is set, then you must + * specify the base device by setting either this property or + * #NMSettingInfiniband:mac-address. + **/ + /* ---ifcfg-rh--- + * property: parent + * variable: PHYSDEV (PKEY=yes) + * default: PKEY=no + * description: InfiniBand parent device. + * example: PHYSDEV=ib0 + * ---end--- + */ + obj_properties[PROP_PARENT] = g_param_spec_string( + NM_SETTING_INFINIBAND_PARENT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_INFINIBAND, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c new file mode 100644 index 0000000000..d55ebbf78f --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -0,0 +1,6284 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2017 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ip-config.h" + +#include +#include + +#include "nm-glib-aux/nm-str-buf.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-utils.h" +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-ip-config + * @short_description: Abstract base class for IPv4 and IPv6 + * addressing, routing, and name service properties + * @include: nm-setting-ip-config.h + * @see_also: #NMSettingIP4Config, #NMSettingIP6Config + * + * #NMSettingIPConfig is the abstract base class of + * #NMSettingIP4Config and #NMSettingIP6Config, providing properties + * related to IP addressing, routing, and Domain Name Service. + **/ + +/*****************************************************************************/ + +const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[] = { + {NM_SETTING_DNS_OPTION_DEBUG, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_NDOTS, TRUE, FALSE}, + {NM_SETTING_DNS_OPTION_TIMEOUT, TRUE, FALSE}, + {NM_SETTING_DNS_OPTION_ATTEMPTS, TRUE, FALSE}, + {NM_SETTING_DNS_OPTION_ROTATE, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_NO_CHECK_NAMES, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_INET6, FALSE, TRUE}, + {NM_SETTING_DNS_OPTION_IP6_BYTESTRING, FALSE, TRUE}, + {NM_SETTING_DNS_OPTION_IP6_DOTINT, FALSE, TRUE}, + {NM_SETTING_DNS_OPTION_NO_IP6_DOTINT, FALSE, TRUE}, + {NM_SETTING_DNS_OPTION_EDNS0, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_SINGLE_REQUEST, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_SINGLE_REQUEST_REOPEN, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_NO_TLD_QUERY, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_USE_VC, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_NO_RELOAD, FALSE, FALSE}, + {NM_SETTING_DNS_OPTION_TRUST_AD, FALSE, FALSE}, + {NULL, FALSE, FALSE}}; + +static char * +canonicalize_ip(int family, const char *ip, gboolean null_any) +{ + guint8 addr_bytes[sizeof(struct in6_addr)]; + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + int ret; + + if (!ip) { + if (null_any) + return NULL; + if (family == AF_INET) + return g_strdup("0.0.0.0"); + if (family == AF_INET6) + return g_strdup("::"); + g_return_val_if_reached(NULL); + } + + ret = inet_pton(family, ip, addr_bytes); + g_return_val_if_fail(ret == 1, NULL); + + if (null_any) { + if (!memcmp(addr_bytes, &in6addr_any, nm_utils_addr_family_to_size(family))) + return NULL; + } + + return g_strdup(inet_ntop(family, addr_bytes, addr_str, sizeof(addr_str))); +} + +static char * +canonicalize_ip_binary(int family, gconstpointer ip, gboolean null_any) +{ + char string[NM_UTILS_INET_ADDRSTRLEN]; + + if (!ip) { + if (null_any) + return NULL; + if (family == AF_INET) + return g_strdup("0.0.0.0"); + if (family == AF_INET6) + return g_strdup("::"); + g_return_val_if_reached(NULL); + } + if (null_any) { + if (!memcmp(ip, &in6addr_any, nm_utils_addr_family_to_size(family))) + return NULL; + } + return g_strdup(inet_ntop(family, ip, string, sizeof(string))); +} + +static gboolean +valid_ip(int family, const char *ip, GError **error) +{ + if (!ip) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + family == AF_INET ? _("Missing IPv4 address") : _("Missing IPv6 address")); + return FALSE; + } + if (!nm_utils_ipaddr_is_valid(family, ip)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + family == AF_INET ? _("Invalid IPv4 address '%s'") + : _("Invalid IPv6 address '%s'"), + ip); + return FALSE; + } else + return TRUE; +} + +static gboolean +valid_prefix(int family, guint prefix, GError **error) +{ + if ((family == AF_INET && prefix <= 32) || (family == AF_INET6 && prefix <= 128)) + return TRUE; + + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + family == AF_INET ? _("Invalid IPv4 address prefix '%u'") + : _("Invalid IPv6 address prefix '%u'"), + prefix); + return FALSE; +} + +static gboolean +valid_metric(gint64 metric, GError **error) +{ + if (metric < -1 || metric > G_MAXUINT32) { + if (error) { + char buf[64]; + + /* We can't concatenate G_GINT64_FORMAT into a translatable string */ + g_snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT, metric); + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("Invalid routing metric '%s'"), + buf); + } + return FALSE; + } + + return TRUE; +} + +/***************************************************************************** + * NMIPAddress + *****************************************************************************/ + +G_DEFINE_BOXED_TYPE(NMIPAddress, nm_ip_address, nm_ip_address_dup, nm_ip_address_unref) + +struct NMIPAddress { + guint refcount; + + char *address; + int prefix, family; + + GHashTable *attributes; +}; + +/** + * nm_ip_address_new: + * @family: the IP address family (AF_INET or + * AF_INET6) + * @addr: the IP address + * @prefix: the address prefix length + * @error: location to store error, or %NULL + * + * Creates a new #NMIPAddress object. + * + * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error + **/ +NMIPAddress * +nm_ip_address_new(int family, const char *addr, guint prefix, GError **error) +{ + NMIPAddress *address; + + g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); + g_return_val_if_fail(addr != NULL, NULL); + + if (!valid_ip(family, addr, error)) + return NULL; + if (!valid_prefix(family, prefix, error)) + return NULL; + + address = g_slice_new0(NMIPAddress); + address->refcount = 1; + + address->family = family; + address->address = canonicalize_ip(family, addr, FALSE); + address->prefix = prefix; + + return address; +} + +/** + * nm_ip_address_new_binary: + * @family: the IP address family (AF_INET or + * AF_INET6) + * @addr: the IP address + * @prefix: the address prefix length + * @error: location to store error, or %NULL + * + * Creates a new #NMIPAddress object. @addr must point to a buffer of the + * correct size for @family. + * + * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error + **/ +NMIPAddress * +nm_ip_address_new_binary(int family, gconstpointer addr, guint prefix, GError **error) +{ + NMIPAddress *address; + char string[NM_UTILS_INET_ADDRSTRLEN]; + + g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); + g_return_val_if_fail(addr != NULL, NULL); + + if (!valid_prefix(family, prefix, error)) + return NULL; + + address = g_slice_new0(NMIPAddress); + address->refcount = 1; + + address->family = family; + address->address = g_strdup(inet_ntop(family, addr, string, sizeof(string))); + address->prefix = prefix; + + return address; +} + +/** + * nm_ip_address_ref: + * @address: the #NMIPAddress + * + * Increases the reference count of the object. + **/ +void +nm_ip_address_ref(NMIPAddress *address) +{ + g_return_if_fail(address != NULL); + g_return_if_fail(address->refcount > 0); + + address->refcount++; +} + +/** + * nm_ip_address_unref: + * @address: the #NMIPAddress + * + * Decreases the reference count of the object. If the reference count + * reaches zero, the object will be destroyed. + **/ +void +nm_ip_address_unref(NMIPAddress *address) +{ + g_return_if_fail(address != NULL); + g_return_if_fail(address->refcount > 0); + + address->refcount--; + if (address->refcount == 0) { + g_free(address->address); + if (address->attributes) + g_hash_table_unref(address->attributes); + g_slice_free(NMIPAddress, address); + } +} + +/** + * nm_ip_address_cmp_full: + * @a: the #NMIPAddress + * @b: the #NMIPAddress to compare @address to. + * @cmp_flags: the #NMIPAddressCmpFlags that indicate what to compare. + * + * Note that with @cmp_flags #NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS, there + * is no total order for comparing GVariant. That means, if the two addresses + * only differ by their attributes, the sort order is undefined and the return + * value only indicates equality. + * + * Returns: 0 if the two objects have the same values (according to their flags) + * or a integer indicating the compare order. + **/ +int +nm_ip_address_cmp_full(const NMIPAddress *a, const NMIPAddress *b, NMIPAddressCmpFlags cmp_flags) +{ + g_return_val_if_fail(!a || a->refcount > 0, 0); + g_return_val_if_fail(!b || b->refcount > 0, 0); + g_return_val_if_fail(!NM_FLAGS_ANY(cmp_flags, ~NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS), 0); + + NM_CMP_SELF(a, b); + + NM_CMP_FIELD(a, b, family); + NM_CMP_FIELD(a, b, prefix); + NM_CMP_FIELD_STR(a, b, address); + + if (NM_FLAGS_HAS(cmp_flags, NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS)) { + GHashTableIter iter; + const char * key; + GVariant * value, *value2; + guint n; + + n = a->attributes ? g_hash_table_size(a->attributes) : 0u; + NM_CMP_DIRECT(n, (b->attributes ? g_hash_table_size(b->attributes) : 0u)); + + if (n > 0) { + g_hash_table_iter_init(&iter, a->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { + value2 = g_hash_table_lookup(b->attributes, key); + /* We cannot really compare GVariants, because g_variant_compare() does + * not work in general. So, don't bother. NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS is + * documented to not provide a total order for the attribute contents. + * + * Theoretically, we can implement also a total order. However we should + * not do that by default because it would require us to sort the keys + * first. Most callers don't care about total order, so they shouldn't + * pay the overhead. */ + if (!value2) + return -2; + if (!g_variant_equal(value, value2)) + return -2; + } + } + } + + return 0; +} + +/** + * nm_ip_address_equal: + * @address: the #NMIPAddress + * @other: the #NMIPAddress to compare @address to. + * + * Determines if two #NMIPAddress objects contain the same address and prefix + * (attributes are not compared). + * + * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. + **/ +gboolean +nm_ip_address_equal(NMIPAddress *address, NMIPAddress *other) +{ + return nm_ip_address_cmp_full(address, other, NM_IP_ADDRESS_CMP_FLAGS_NONE) == 0; +} + +/** + * nm_ip_address_dup: + * @address: the #NMIPAddress + * + * Creates a copy of @address + * + * Returns: (transfer full): a copy of @address + **/ +NMIPAddress * +nm_ip_address_dup(NMIPAddress *address) +{ + NMIPAddress *copy; + + g_return_val_if_fail(address != NULL, NULL); + g_return_val_if_fail(address->refcount > 0, NULL); + + copy = nm_ip_address_new(address->family, address->address, address->prefix, NULL); + if (address->attributes) { + GHashTableIter iter; + const char * key; + GVariant * value; + + g_hash_table_iter_init(&iter, address->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) + nm_ip_address_set_attribute(copy, key, value); + } + + return copy; +} + +/** + * nm_ip_address_get_family: + * @address: the #NMIPAddress + * + * Gets the IP address family (eg, AF_INET) property of this address + * object. + * + * Returns: the IP address family + **/ +int +nm_ip_address_get_family(NMIPAddress *address) +{ + g_return_val_if_fail(address != NULL, 0); + g_return_val_if_fail(address->refcount > 0, 0); + + return address->family; +} + +/** + * nm_ip_address_get_address: + * @address: the #NMIPAddress + * + * Gets the IP address property of this address object. + * + * Returns: the IP address + **/ +const char * +nm_ip_address_get_address(NMIPAddress *address) +{ + g_return_val_if_fail(address != NULL, NULL); + g_return_val_if_fail(address->refcount > 0, NULL); + + return address->address; +} + +/** + * nm_ip_address_set_address: + * @address: the #NMIPAddress + * @addr: the IP address, as a string + * + * Sets the IP address property of this address object. + * + * @addr must be a valid address of @address's family. If you aren't sure you + * have a valid address, use nm_utils_ipaddr_valid() to check it. + **/ +void +nm_ip_address_set_address(NMIPAddress *address, const char *addr) +{ + g_return_if_fail(address != NULL); + g_return_if_fail(addr != NULL); + g_return_if_fail(nm_utils_ipaddr_is_valid(address->family, addr)); + + g_free(address->address); + address->address = canonicalize_ip(address->family, addr, FALSE); +} + +/** + * nm_ip_address_get_address_binary: (skip) + * @address: the #NMIPAddress + * @addr: a buffer in which to store the address in binary format. + * + * Gets the IP address property of this address object. + * + * @addr must point to a buffer that is the correct size for @address's family. + **/ +void +nm_ip_address_get_address_binary(NMIPAddress *address, gpointer addr) +{ + g_return_if_fail(address != NULL); + g_return_if_fail(addr != NULL); + + inet_pton(address->family, address->address, addr); +} + +/** + * nm_ip_address_set_address_binary: (skip) + * @address: the #NMIPAddress + * @addr: the address, in binary format + * + * Sets the IP address property of this address object. + * + * @addr must point to a buffer that is the correct size for @address's family. + **/ +void +nm_ip_address_set_address_binary(NMIPAddress *address, gconstpointer addr) +{ + char string[NM_UTILS_INET_ADDRSTRLEN]; + + g_return_if_fail(address != NULL); + g_return_if_fail(addr != NULL); + + g_free(address->address); + address->address = g_strdup(inet_ntop(address->family, addr, string, sizeof(string))); +} + +/** + * nm_ip_address_get_prefix: + * @address: the #NMIPAddress + * + * Gets the IP address prefix (ie "24" or "30" etc) property of this address + * object. + * + * Returns: the IP address prefix + **/ +guint +nm_ip_address_get_prefix(NMIPAddress *address) +{ + g_return_val_if_fail(address != NULL, 0); + g_return_val_if_fail(address->refcount > 0, 0); + + return address->prefix; +} + +/** + * nm_ip_address_set_prefix: + * @address: the #NMIPAddress + * @prefix: the IP address prefix + * + * Sets the IP address prefix property of this address object. + **/ +void +nm_ip_address_set_prefix(NMIPAddress *address, guint prefix) +{ + g_return_if_fail(address != NULL); + g_return_if_fail(valid_prefix(address->family, prefix, NULL)); + + address->prefix = prefix; +} + +const char ** +_nm_ip_address_get_attribute_names(const NMIPAddress *address, gboolean sorted, guint *out_length) +{ + nm_assert(address); + + return nm_utils_strdict_get_keys(address->attributes, sorted, out_length); +} + +/** + * nm_ip_address_get_attribute_names: + * @address: the #NMIPAddress + * + * Gets an array of attribute names defined on @address. + * + * Returns: (transfer full): a %NULL-terminated array of attribute names, + **/ +char ** +nm_ip_address_get_attribute_names(NMIPAddress *address) +{ + const char **names; + + g_return_val_if_fail(address, NULL); + + names = _nm_ip_address_get_attribute_names(address, TRUE, NULL); + return nm_utils_strv_make_deep_copied_nonnull(names); +} + +/** + * nm_ip_address_get_attribute: + * @address: the #NMIPAddress + * @name: the name of an address attribute + * + * Gets the value of the attribute with name @name on @address + * + * Returns: (transfer none): the value of the attribute with name @name on + * @address, or %NULL if @address has no such attribute. + **/ +GVariant * +nm_ip_address_get_attribute(NMIPAddress *address, const char *name) +{ + g_return_val_if_fail(address != NULL, NULL); + g_return_val_if_fail(name != NULL && *name != '\0', NULL); + + if (address->attributes) + return g_hash_table_lookup(address->attributes, name); + else + return NULL; +} + +/** + * nm_ip_address_set_attribute: + * @address: the #NMIPAddress + * @name: the name of an address attribute + * @value: (transfer none) (allow-none): the value + * + * Sets or clears the named attribute on @address to the given value. + **/ +void +nm_ip_address_set_attribute(NMIPAddress *address, const char *name, GVariant *value) +{ + g_return_if_fail(address != NULL); + g_return_if_fail(name != NULL && *name != '\0'); + g_return_if_fail(strcmp(name, "address") != 0 && strcmp(name, "prefix") != 0); + + if (!address->attributes) { + address->attributes = g_hash_table_new_full(nm_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_variant_unref); + } + + if (value) + g_hash_table_insert(address->attributes, g_strdup(name), g_variant_ref_sink(value)); + else + g_hash_table_remove(address->attributes, name); +} + +/***************************************************************************** + * NMIPRoute + *****************************************************************************/ + +G_DEFINE_BOXED_TYPE(NMIPRoute, nm_ip_route, nm_ip_route_dup, nm_ip_route_unref) + +struct NMIPRoute { + guint refcount; + + int family; + char * dest; + guint prefix; + char * next_hop; + gint64 metric; + + GHashTable *attributes; +}; + +/** + * nm_ip_route_new: + * @family: the IP address family (AF_INET or + * AF_INET6) + * @dest: the IP address of the route's destination + * @prefix: the address prefix length + * @next_hop: (allow-none): the IP address of the next hop (or %NULL) + * @metric: the route metric (or -1 for "default") + * @error: location to store error, or %NULL + * + * Creates a new #NMIPRoute object. + * + * Returns: (transfer full): the new #NMIPRoute object, or %NULL on error + **/ +NMIPRoute * +nm_ip_route_new(int family, + const char *dest, + guint prefix, + const char *next_hop, + gint64 metric, + GError ** error) +{ + NMIPRoute *route; + + g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); + g_return_val_if_fail(dest, NULL); + + if (!valid_ip(family, dest, error)) + return NULL; + if (!valid_prefix(family, prefix, error)) + return NULL; + if (next_hop && !valid_ip(family, next_hop, error)) + return NULL; + if (!valid_metric(metric, error)) + return NULL; + + route = g_slice_new0(NMIPRoute); + route->refcount = 1; + + route->family = family; + route->dest = canonicalize_ip(family, dest, FALSE); + route->prefix = prefix; + route->next_hop = canonicalize_ip(family, next_hop, TRUE); + route->metric = metric; + + return route; +} + +/** + * nm_ip_route_new_binary: + * @family: the IP address family (AF_INET or + * AF_INET6) + * @dest: the IP address of the route's destination + * @prefix: the address prefix length + * @next_hop: (allow-none): the IP address of the next hop (or %NULL) + * @metric: the route metric (or -1 for "default") + * @error: location to store error, or %NULL + * + * Creates a new #NMIPRoute object. @dest and @next_hop (if non-%NULL) must + * point to buffers of the correct size for @family. + * + * Returns: (transfer full): the new #NMIPRoute object, or %NULL on error + **/ +NMIPRoute * +nm_ip_route_new_binary(int family, + gconstpointer dest, + guint prefix, + gconstpointer next_hop, + gint64 metric, + GError ** error) +{ + NMIPRoute *route; + + g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); + g_return_val_if_fail(dest, NULL); + + if (!valid_prefix(family, prefix, error)) + return NULL; + if (!valid_metric(metric, error)) + return NULL; + + route = g_slice_new0(NMIPRoute); + route->refcount = 1; + + route->family = family; + route->dest = canonicalize_ip_binary(family, dest, FALSE); + route->prefix = prefix; + route->next_hop = canonicalize_ip_binary(family, next_hop, TRUE); + route->metric = metric; + + return route; +} + +/** + * nm_ip_route_ref: + * @route: the #NMIPRoute + * + * Increases the reference count of the object. + **/ +void +nm_ip_route_ref(NMIPRoute *route) +{ + g_return_if_fail(route != NULL); + g_return_if_fail(route->refcount > 0); + + route->refcount++; +} + +/** + * nm_ip_route_unref: + * @route: the #NMIPRoute + * + * Decreases the reference count of the object. If the reference count + * reaches zero, the object will be destroyed. + **/ +void +nm_ip_route_unref(NMIPRoute *route) +{ + g_return_if_fail(route != NULL); + g_return_if_fail(route->refcount > 0); + + route->refcount--; + if (route->refcount == 0) { + g_free(route->dest); + g_free(route->next_hop); + if (route->attributes) + g_hash_table_unref(route->attributes); + g_slice_free(NMIPRoute, route); + } +} + +/** + * nm_ip_route_equal_full: + * @route: the #NMIPRoute + * @other: the #NMIPRoute to compare @route to. + * @cmp_flags: tune how to compare attributes. Currently, only + * NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE (0) and NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS (1) + * is supported. + * + * Determines if two #NMIPRoute objects contain the same destination, prefix, + * next hop, and metric. + * + * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. + * + * Since: 1.10 + **/ +gboolean +nm_ip_route_equal_full(NMIPRoute *route, NMIPRoute *other, guint cmp_flags) +{ + g_return_val_if_fail(route != NULL, FALSE); + g_return_val_if_fail(route->refcount > 0, FALSE); + + g_return_val_if_fail(other != NULL, FALSE); + g_return_val_if_fail(other->refcount > 0, FALSE); + + g_return_val_if_fail(NM_IN_SET(cmp_flags, + NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE, + NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS), + FALSE); + + if (route->prefix != other->prefix || route->metric != other->metric + || strcmp(route->dest, other->dest) != 0 + || g_strcmp0(route->next_hop, other->next_hop) != 0) + return FALSE; + if (cmp_flags == NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS) { + GHashTableIter iter; + const char * key; + GVariant * value, *value2; + guint n; + + n = route->attributes ? g_hash_table_size(route->attributes) : 0u; + if (n != (other->attributes ? g_hash_table_size(other->attributes) : 0u)) + return FALSE; + if (n) { + g_hash_table_iter_init(&iter, route->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { + value2 = g_hash_table_lookup(other->attributes, key); + if (!value2) + return FALSE; + if (!g_variant_equal(value, value2)) + return FALSE; + } + } + } + return TRUE; +} + +/** + * nm_ip_route_equal: + * @route: the #NMIPRoute + * @other: the #NMIPRoute to compare @route to. + * + * Determines if two #NMIPRoute objects contain the same destination, prefix, + * next hop, and metric. (Attributes are not compared.) + * + * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. + **/ +gboolean +nm_ip_route_equal(NMIPRoute *route, NMIPRoute *other) +{ + return nm_ip_route_equal_full(route, other, NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE); +} + +/** + * nm_ip_route_dup: + * @route: the #NMIPRoute + * + * Creates a copy of @route + * + * Returns: (transfer full): a copy of @route + **/ +NMIPRoute * +nm_ip_route_dup(NMIPRoute *route) +{ + NMIPRoute *copy; + + g_return_val_if_fail(route != NULL, NULL); + g_return_val_if_fail(route->refcount > 0, NULL); + + copy = nm_ip_route_new(route->family, + route->dest, + route->prefix, + route->next_hop, + route->metric, + NULL); + if (route->attributes) { + GHashTableIter iter; + const char * key; + GVariant * value; + + g_hash_table_iter_init(&iter, route->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) + nm_ip_route_set_attribute(copy, key, value); + } + + return copy; +} + +/** + * nm_ip_route_get_family: + * @route: the #NMIPRoute + * + * Gets the IP address family (eg, AF_INET) property of this route + * object. + * + * Returns: the IP address family + **/ +int +nm_ip_route_get_family(NMIPRoute *route) +{ + g_return_val_if_fail(route != NULL, 0); + g_return_val_if_fail(route->refcount > 0, 0); + + return route->family; +} + +/** + * nm_ip_route_get_dest: + * @route: the #NMIPRoute + * + * Gets the IP destination address property of this route object. + * + * Returns: the IP address of the route's destination + **/ +const char * +nm_ip_route_get_dest(NMIPRoute *route) +{ + g_return_val_if_fail(route != NULL, NULL); + g_return_val_if_fail(route->refcount > 0, NULL); + + return route->dest; +} + +/** + * nm_ip_route_set_dest: + * @route: the #NMIPRoute + * @dest: the route's destination, as a string + * + * Sets the destination property of this route object. + * + * @dest must be a valid address of @route's family. If you aren't sure you + * have a valid address, use nm_utils_ipaddr_is_valid() to check it. + **/ +void +nm_ip_route_set_dest(NMIPRoute *route, const char *dest) +{ + g_return_if_fail(route != NULL); + g_return_if_fail(nm_utils_ipaddr_is_valid(route->family, dest)); + + g_free(route->dest); + route->dest = canonicalize_ip(route->family, dest, FALSE); +} + +/** + * nm_ip_route_get_dest_binary: (skip) + * @route: the #NMIPRoute + * @dest: a buffer in which to store the destination in binary format. + * + * Gets the destination property of this route object. + * + * @dest must point to a buffer that is the correct size for @route's family. + **/ +void +nm_ip_route_get_dest_binary(NMIPRoute *route, gpointer dest) +{ + g_return_if_fail(route != NULL); + g_return_if_fail(dest != NULL); + + inet_pton(route->family, route->dest, dest); +} + +/** + * nm_ip_route_set_dest_binary: (skip) + * @route: the #NMIPRoute + * @dest: the route's destination, in binary format + * + * Sets the destination property of this route object. + * + * @dest must point to a buffer that is the correct size for @route's family. + **/ +void +nm_ip_route_set_dest_binary(NMIPRoute *route, gconstpointer dest) +{ + char string[NM_UTILS_INET_ADDRSTRLEN]; + + g_return_if_fail(route != NULL); + g_return_if_fail(dest != NULL); + + g_free(route->dest); + route->dest = g_strdup(inet_ntop(route->family, dest, string, sizeof(string))); +} + +/** + * nm_ip_route_get_prefix: + * @route: the #NMIPRoute + * + * Gets the IP prefix (ie "24" or "30" etc) of this route. + * + * Returns: the IP prefix + **/ +guint +nm_ip_route_get_prefix(NMIPRoute *route) +{ + g_return_val_if_fail(route != NULL, 0); + g_return_val_if_fail(route->refcount > 0, 0); + + return route->prefix; +} + +/** + * nm_ip_route_set_prefix: + * @route: the #NMIPRoute + * @prefix: the route prefix + * + * Sets the prefix property of this route object. + **/ +void +nm_ip_route_set_prefix(NMIPRoute *route, guint prefix) +{ + g_return_if_fail(route != NULL); + g_return_if_fail(valid_prefix(route->family, prefix, NULL)); + + route->prefix = prefix; +} + +/** + * nm_ip_route_get_next_hop: + * @route: the #NMIPRoute + * + * Gets the IP address of the next hop of this route; this will be %NULL if the + * route has no next hop. + * + * Returns: the IP address of the next hop, or %NULL if this is a device route. + **/ +const char * +nm_ip_route_get_next_hop(NMIPRoute *route) +{ + g_return_val_if_fail(route != NULL, NULL); + g_return_val_if_fail(route->refcount > 0, NULL); + + return route->next_hop; +} + +/** + * nm_ip_route_set_next_hop: + * @route: the #NMIPRoute + * @next_hop: (allow-none): the route's next hop, as a string + * + * Sets the next-hop property of this route object. + * + * @next_hop (if non-%NULL) must be a valid address of @route's family. If you + * aren't sure you have a valid address, use nm_utils_ipaddr_valid() to check + * it. + **/ +void +nm_ip_route_set_next_hop(NMIPRoute *route, const char *next_hop) +{ + g_return_if_fail(route != NULL); + g_return_if_fail(!next_hop || nm_utils_ipaddr_is_valid(route->family, next_hop)); + + g_free(route->next_hop); + route->next_hop = canonicalize_ip(route->family, next_hop, TRUE); +} + +/** + * nm_ip_route_get_next_hop_binary: (skip) + * @route: the #NMIPRoute + * @next_hop: a buffer in which to store the next hop in binary format. + * + * Gets the next hop property of this route object. + * + * @next_hop must point to a buffer that is the correct size for @route's family. + * + * Returns: %TRUE if @route has a next hop, %FALSE if not (in which case + * @next_hop will be zeroed out) + **/ +gboolean +nm_ip_route_get_next_hop_binary(NMIPRoute *route, gpointer next_hop) +{ + g_return_val_if_fail(route != NULL, FALSE); + g_return_val_if_fail(next_hop != NULL, FALSE); + + if (route->next_hop) { + inet_pton(route->family, route->next_hop, next_hop); + return TRUE; + } else { + memset(next_hop, 0, nm_utils_addr_family_to_size(route->family)); + return FALSE; + } +} + +/** + * nm_ip_route_set_next_hop_binary: (skip) + * @route: the #NMIPRoute + * @next_hop: the route's next hop, in binary format + * + * Sets the destination property of this route object. + * + * @next_hop (if non-%NULL) must point to a buffer that is the correct size for + * @route's family. + **/ +void +nm_ip_route_set_next_hop_binary(NMIPRoute *route, gconstpointer next_hop) +{ + g_return_if_fail(route != NULL); + + g_free(route->next_hop); + route->next_hop = canonicalize_ip_binary(route->family, next_hop, TRUE); +} + +/** + * nm_ip_route_get_metric: + * @route: the #NMIPRoute + * + * Gets the route metric property of this route object; lower values + * indicate "better" or more preferred routes; -1 indicates "default" + * (meaning NetworkManager will set it appropriately). + * + * Returns: the route metric + **/ +gint64 +nm_ip_route_get_metric(NMIPRoute *route) +{ + g_return_val_if_fail(route != NULL, 0); + g_return_val_if_fail(route->refcount > 0, 0); + + return route->metric; +} + +/** + * nm_ip_route_set_metric: + * @route: the #NMIPRoute + * @metric: the route metric (or -1 for "default") + * + * Sets the metric property of this route object. + **/ +void +nm_ip_route_set_metric(NMIPRoute *route, gint64 metric) +{ + g_return_if_fail(route != NULL); + g_return_if_fail(valid_metric(metric, NULL)); + + route->metric = metric; +} + +GHashTable * +_nm_ip_route_get_attributes(NMIPRoute *route) +{ + nm_assert(route); + + return route->attributes; +} + +/** + * _nm_ip_route_get_attribute_names: + * @route: the #NMIPRoute + * @sorted: whether to sort the names. Otherwise, their order is + * undefined and unstable. + * @out_length: (allow-none) (out): the number of elements + * + * Gets an array of attribute names defined on @route. + * + * Returns: (array length=out_length) (transfer container): a %NULL-terminated array + * of attribute names or %NULL if there are no attributes. The order of the returned + * names depends on @sorted. + **/ +const char ** +_nm_ip_route_get_attribute_names(const NMIPRoute *route, gboolean sorted, guint *out_length) +{ + nm_assert(route); + + return nm_utils_strdict_get_keys(route->attributes, sorted, out_length); +} + +/** + * nm_ip_route_get_attribute_names: + * @route: the #NMIPRoute + * + * Gets an array of attribute names defined on @route. + * + * Returns: (transfer full): a %NULL-terminated array of attribute names + **/ +char ** +nm_ip_route_get_attribute_names(NMIPRoute *route) +{ + const char **names; + + g_return_val_if_fail(route != NULL, NULL); + + names = _nm_ip_route_get_attribute_names(route, TRUE, NULL); + return nm_utils_strv_make_deep_copied_nonnull(names); +} + +/** + * nm_ip_route_get_attribute: + * @route: the #NMIPRoute + * @name: the name of an route attribute + * + * Gets the value of the attribute with name @name on @route + * + * Returns: (transfer none): the value of the attribute with name @name on + * @route, or %NULL if @route has no such attribute. + **/ +GVariant * +nm_ip_route_get_attribute(NMIPRoute *route, const char *name) +{ + g_return_val_if_fail(route != NULL, NULL); + g_return_val_if_fail(name != NULL && *name != '\0', NULL); + + if (route->attributes) + return g_hash_table_lookup(route->attributes, name); + else + return NULL; +} + +/** + * nm_ip_route_set_attribute: + * @route: the #NMIPRoute + * @name: the name of a route attribute + * @value: (transfer none) (allow-none): the value + * + * Sets the named attribute on @route to the given value. + **/ +void +nm_ip_route_set_attribute(NMIPRoute *route, const char *name, GVariant *value) +{ + g_return_if_fail(route != NULL); + g_return_if_fail(name != NULL && *name != '\0'); + g_return_if_fail(strcmp(name, "dest") != 0 && strcmp(name, "prefix") != 0 + && strcmp(name, "next-hop") != 0 && strcmp(name, "metric") != 0); + + if (!route->attributes) { + route->attributes = g_hash_table_new_full(nm_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_variant_unref); + } + + if (value) + g_hash_table_insert(route->attributes, g_strdup(name), g_variant_ref_sink(value)); + else + g_hash_table_remove(route->attributes, name); +} + +static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_CWND, + G_VARIANT_TYPE_UINT32, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_FROM, + G_VARIANT_TYPE_STRING, + .v6 = TRUE, + .str_type = 'p', ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_INITCWND, + G_VARIANT_TYPE_UINT32, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_INITRWND, + G_VARIANT_TYPE_UINT32, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, + G_VARIANT_TYPE_BOOLEAN, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, + G_VARIANT_TYPE_BOOLEAN, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, + G_VARIANT_TYPE_BOOLEAN, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, + G_VARIANT_TYPE_BOOLEAN, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, + G_VARIANT_TYPE_BOOLEAN, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_MTU, + G_VARIANT_TYPE_UINT32, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_ONLINK, + G_VARIANT_TYPE_BOOLEAN, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_SCOPE, + G_VARIANT_TYPE_BYTE, + .v4 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_SRC, + G_VARIANT_TYPE_STRING, + .v4 = TRUE, + .v6 = TRUE, + .str_type = 'a', ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TABLE, + G_VARIANT_TYPE_UINT32, + .v4 = TRUE, + .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TYPE, + G_VARIANT_TYPE_STRING, + .v4 = TRUE, + .v6 = TRUE, + .str_type = 'T', ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_WINDOW, + G_VARIANT_TYPE_UINT32, + .v4 = TRUE, + .v6 = TRUE, ), + NULL, +}; + +/** + * nm_ip_route_get_variant_attribute_spec: + * + * Returns: the specifiers for route attributes + * + * Since: 1.8 + */ +const NMVariantAttributeSpec *const * +nm_ip_route_get_variant_attribute_spec(void) +{ + return ip_route_attribute_spec; +} + +/** + * nm_ip_route_attribute_validate: + * @name: the attribute name + * @value: the attribute value + * @family: IP address family of the route + * @known: (out): on return, whether the attribute name is a known one + * @error: (allow-none): return location for a #GError, or %NULL + * + * Validates a route attribute, i.e. checks that the attribute is a known one + * and the value is of the correct type and well-formed. + * + * Returns: %TRUE if the attribute is valid, %FALSE otherwise + * + * Since: 1.8 + */ +gboolean +nm_ip_route_attribute_validate(const char *name, + GVariant * value, + int family, + gboolean * known, + GError ** error) +{ + const NMVariantAttributeSpec *spec; + + g_return_val_if_fail(name, FALSE); + g_return_val_if_fail(value, FALSE); + g_return_val_if_fail(family == AF_INET || family == AF_INET6, FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + + spec = _nm_variant_attribute_spec_find_binary_search(ip_route_attribute_spec, + G_N_ELEMENTS(ip_route_attribute_spec) - 1, + name); + if (!spec) { + NM_SET_OUT(known, FALSE); + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("unknown attribute")); + return FALSE; + } + + NM_SET_OUT(known, TRUE); + + if (!g_variant_is_of_type(value, spec->type)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid attribute type '%s'"), + g_variant_get_type_string(value)); + return FALSE; + } + + if ((family == AF_INET && !spec->v4) || (family == AF_INET6 && !spec->v6)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + family == AF_INET ? _("attribute is not valid for a IPv4 route") + : _("attribute is not valid for a IPv6 route")); + return FALSE; + } + + if (g_variant_type_equal(spec->type, G_VARIANT_TYPE_STRING)) { + const char *string = g_variant_get_string(value, NULL); + + switch (spec->str_type) { + case 'a': /* IP address */ + if (!nm_utils_ipaddr_is_valid(family, string)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + family == AF_INET ? _("'%s' is not a valid IPv4 address") + : _("'%s' is not a valid IPv6 address"), + string); + return FALSE; + } + break; + case 'p': /* IP address + optional prefix */ + { + gs_free char *addr_free = NULL; + const char * addr = string; + const char * str; + + str = strchr(addr, '/'); + if (str) { + addr = nm_strndup_a(200, addr, str - addr, &addr_free); + str++; + if (_nm_utils_ascii_str_to_int64(str, 10, 0, family == AF_INET ? 32 : 128, -1) + < 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid prefix %s"), + str); + return FALSE; + } + } + if (!nm_utils_ipaddr_is_valid(family, addr)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + family == AF_INET ? _("'%s' is not a valid IPv4 address") + : _("'%s' is not a valid IPv6 address"), + string); + return FALSE; + } + break; + } + case 'T': /* route type. */ + if (!NM_IN_SET(nm_utils_route_type_by_name(string), RTN_UNICAST, RTN_LOCAL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%s is not a valid route type"), + string); + return FALSE; + } + break; + default: + break; + } + } + + return TRUE; +} + +gboolean +_nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error) +{ + NMUtilsNamedValue attrs_static[G_N_ELEMENTS(ip_route_attribute_spec)]; + gs_free NMUtilsNamedValue *attrs_free = NULL; + const NMUtilsNamedValue * attrs; + guint attrs_len; + GVariant * val; + guint i; + guint8 u8; + + g_return_val_if_fail(route, FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + + if (!route->attributes) + return TRUE; + + attrs = nm_utils_named_values_from_strdict(route->attributes, + &attrs_len, + attrs_static, + &attrs_free); + for (i = 0; i < attrs_len; i++) { + const char *key = attrs[i].name; + GVariant * val2 = attrs[i].value_ptr; + + if (!nm_ip_route_attribute_validate(key, val2, route->family, NULL, NULL)) + return FALSE; + } + + if ((val = g_hash_table_lookup(route->attributes, NM_IP_ROUTE_ATTRIBUTE_TYPE))) { + nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_STRING)); + u8 = nm_utils_route_type_by_name(g_variant_get_string(val, NULL)); + + if (u8 == RTN_LOCAL && route->family == AF_INET + && (val = g_hash_table_lookup(route->attributes, NM_IP_ROUTE_ATTRIBUTE_SCOPE))) { + nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_BYTE)); + u8 = g_variant_get_byte(val); + + if (!NM_IN_SET(u8, RT_SCOPE_HOST, RT_SCOPE_NOWHERE)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("route scope is invalid")); + return FALSE; + } + } + } + + return TRUE; +} + +/*****************************************************************************/ + +struct NMIPRoutingRule { + NMIPAddr from_bin; + NMIPAddr to_bin; + char * from_str; + char * to_str; + char * iifname; + char * oifname; + guint ref_count; + guint32 priority; + guint32 table; + gint32 suppress_prefixlength; + guint32 fwmark; + guint32 fwmask; + guint16 sport_start; + guint16 sport_end; + guint16 dport_start; + guint16 dport_end; + guint8 action; + guint8 from_len; + guint8 to_len; + guint8 tos; + guint8 ipproto; + bool is_v4 : 1; + bool sealed : 1; + bool priority_has : 1; + bool from_has : 1; + bool from_valid : 1; + bool to_has : 1; + bool to_valid : 1; + bool invert : 1; +}; + +static NMIPRoutingRule *_ip_routing_rule_dup(const NMIPRoutingRule *rule); + +G_DEFINE_BOXED_TYPE(NMIPRoutingRule, + nm_ip_routing_rule, + _ip_routing_rule_dup, + nm_ip_routing_rule_unref) + +static gboolean +NM_IS_IP_ROUTING_RULE(const NMIPRoutingRule *self, gboolean also_sealed) +{ + return self && self->ref_count > 0 && (also_sealed || !self->sealed); +} + +static int +_ip_routing_rule_get_addr_family(const NMIPRoutingRule *self) +{ + nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); + + return self->is_v4 ? AF_INET : AF_INET6; +} + +static int +_ip_routing_rule_get_addr_size(const NMIPRoutingRule *self) +{ + nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); + + return self->is_v4 ? sizeof(struct in_addr) : sizeof(struct in6_addr); +} + +static NMIPRoutingRule * +_ip_routing_rule_dup(const NMIPRoutingRule *rule) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), NULL); + + if (rule->sealed) + return nm_ip_routing_rule_ref((NMIPRoutingRule *) rule); + return nm_ip_routing_rule_new_clone(rule); +} + +/** + * nm_ip_routing_rule_new: + * @addr_family: the address family of the routing rule. Must be either + * %AF_INET (2) or %AF_INET6 (10). + * + * Returns: (transfer full): a newly created rule instance with the + * provided address family. The instance is unsealed. + * + * Since: 1.18 + */ +NMIPRoutingRule * +nm_ip_routing_rule_new(int addr_family) +{ + NMIPRoutingRule *self; + + g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NULL); + + self = g_slice_new(NMIPRoutingRule); + *self = (NMIPRoutingRule){ + .ref_count = 1, + .is_v4 = (addr_family == AF_INET), + .action = FR_ACT_TO_TBL, + .table = RT_TABLE_MAIN, + .suppress_prefixlength = -1, + }; + return self; +} + +/** + * nm_ip_routing_rule_new_clone: + * @rule: the #NMIPRoutingRule to clone. + * + * Returns: (transfer full): a newly created rule instance with + * the same settings as @rule. Note that the instance will + * always be unsealred. + * + * Since: 1.18 + */ +NMIPRoutingRule * +nm_ip_routing_rule_new_clone(const NMIPRoutingRule *rule) +{ + NMIPRoutingRule *self; + + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), NULL); + + self = g_slice_new(NMIPRoutingRule); + *self = (NMIPRoutingRule){ + .ref_count = 1, + .sealed = FALSE, + .is_v4 = rule->is_v4, + + .priority = rule->priority, + .priority_has = rule->priority_has, + + .invert = rule->invert, + + .tos = rule->tos, + + .fwmark = rule->fwmark, + .fwmask = rule->fwmask, + + .sport_start = rule->sport_start, + .sport_end = rule->sport_end, + .dport_start = rule->dport_start, + .dport_end = rule->dport_end, + + .ipproto = rule->ipproto, + + .from_len = rule->from_len, + .from_bin = rule->from_bin, + .from_str = (rule->from_has && !rule->from_valid) ? g_strdup(rule->from_str) : NULL, + .from_has = rule->from_has, + .from_valid = rule->from_valid, + + .to_len = rule->to_len, + .to_bin = rule->to_bin, + .to_str = (rule->to_has && !rule->to_valid) ? g_strdup(rule->to_str) : NULL, + .to_has = rule->to_has, + .to_valid = rule->to_valid, + + .iifname = g_strdup(rule->iifname), + .oifname = g_strdup(rule->oifname), + + .action = rule->action, + .table = rule->table, + + .suppress_prefixlength = rule->suppress_prefixlength, + }; + return self; +} + +/** + * nm_ip_routing_rule_ref: + * @self: (allow-none): the #NMIPRoutingRule instance + * + * Increases the reference count of the instance. + * This is not thread-safe. + * + * Returns: (transfer full): the @self argument with incremented + * reference count. + * + * Since: 1.18 + */ +NMIPRoutingRule * +nm_ip_routing_rule_ref(NMIPRoutingRule *self) +{ + if (!self) + return NULL; + + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + nm_assert(self->ref_count < G_MAXUINT); + self->ref_count++; + return self; +} + +/** + * nm_ip_routing_rule_unref: + * @self: (allow-none): the #NMIPRoutingRule instance + * + * Decreases the reference count of the instance and destroys + * the instance if the reference count reaches zero. + * This is not thread-safe. + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_unref(NMIPRoutingRule *self) +{ + if (!self) + return; + + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE)); + + if (--self->ref_count > 0) + return; + + g_free(self->from_str); + g_free(self->to_str); + g_free(self->iifname); + g_free(self->oifname); + + g_slice_free(NMIPRoutingRule, self); +} + +/** + * nm_ip_routing_rule_is_sealed: + * @self: the #NMIPRoutingRule instance + * + * Returns: whether @self is sealed. Once sealed, an instance + * cannot be modified nor unsealed. + * + * Since: 1.18 + */ +gboolean +nm_ip_routing_rule_is_sealed(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); + + return self->sealed; +} + +/** + * nm_ip_routing_rule_seal: + * @self: the #NMIPRoutingRule instance + * + * Seals the routing rule. Afterwards, the instance can no longer be + * modified, and it is a bug to call any of the accessors that would + * modify the rule. If @self was already sealed, this has no effect. + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_seal(NMIPRoutingRule *self) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE)); + + self->sealed = TRUE; +} + +/** + * nm_ip_routing_rule_get_addr_family: + * @self: the #NMIPRoutingRule instance + * + * Returns: the address family of the rule. Either %AF_INET or %AF_INET6. + * + * Since: 1.18 + */ +int +nm_ip_routing_rule_get_addr_family(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), AF_UNSPEC); + + return _ip_routing_rule_get_addr_family(self); +} + +/** + * nm_ip_routing_rule_get_priority: + * @self: the #NMIPRoutingRule instance + * + * Returns: the priority. A valid priority is in the range from + * 0 to %G_MAXUINT32. If unset, -1 is returned. + * + * Since: 1.18 + */ +gint64 +nm_ip_routing_rule_get_priority(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), -1); + + return self->priority_has ? (gint64) self->priority : (gint64) -1; +} + +/** + * nm_ip_routing_rule_set_priority: + * @self: the #NMIPRoutingRule instance + * @priority: the priority to set + * + * A valid priority ranges from 0 to %G_MAXUINT32. "-1" is also allowed + * to reset the priority. It is a bug calling this function with any + * other value. + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_priority(NMIPRoutingRule *self, gint64 priority) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + if (priority >= 0 && priority <= (gint64) G_MAXUINT32) { + self->priority = (guint32) priority; + self->priority_has = TRUE; + } else { + g_return_if_fail(priority == -1); + self->priority = 0; + self->priority_has = FALSE; + } +} + +/** + * nm_ip_routing_rule_get_invert: + * @self: the #NMIPRoutingRule instance + * + * Returns: the "invert" setting of the rule. + * + * Since: 1.18 + */ +gboolean +nm_ip_routing_rule_get_invert(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); + + return self->invert; +} + +/** + * nm_ip_routing_rule_set_invert: + * @self: the #NMIPRoutingRule instance + * @invert: the new value to set + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_invert(NMIPRoutingRule *self, gboolean invert) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->invert = invert; +} + +/** + * nm_ip_routing_rule_get_from_len: + * @self: the #NMIPRoutingRule instance + * + * Returns: the set prefix length for the from/src parameter. + * + * Since: 1.18 + */ +guint8 +nm_ip_routing_rule_get_from_len(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->from_len; +} + +/** + * nm_ip_routing_rule_get_from: + * @self: the #NMIPRoutingRule instance + * + * Returns: (transfer none): the set from/src parameter or + * %NULL, if no value is set. + * + * Since: 1.18 + */ +const char * +nm_ip_routing_rule_get_from(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + if (!self->from_has) + return NULL; + if (!self->from_str) { + nm_assert(self->from_valid); + ((NMIPRoutingRule *) self)->from_str = + nm_utils_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->from_bin); + } + return self->from_str; +} + +const NMIPAddr * +nm_ip_routing_rule_get_from_bin(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + return (self->from_has && self->from_valid) ? &self->from_bin : NULL; +} + +void +nm_ip_routing_rule_set_from_bin(NMIPRoutingRule *self, gconstpointer from, guint8 len) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + nm_clear_g_free(&self->from_str); + + if (!from) { + self->from_has = FALSE; + self->from_len = len; + return; + } + + self->from_has = TRUE; + self->from_len = len; + self->from_valid = TRUE; + nm_ip_addr_set(_ip_routing_rule_get_addr_family(self), &self->from_bin, from); +} + +/** + * nm_ip_routing_rule_set_from: + * @self: the #NMIPRoutingRule instance + * @from: (allow-none): the from/src address to set. + * The address family must match. + * @len: the corresponding prefix length of the address. + * + * Setting invalid values is accepted, but will later fail + * during nm_ip_routing_rule_validate(). + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_from(NMIPRoutingRule *self, const char *from, guint8 len) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + if (!from) { + nm_clear_g_free(&self->from_str); + self->from_has = FALSE; + self->from_len = len; + return; + } + + nm_clear_g_free(&self->from_str); + self->from_has = TRUE; + self->from_len = len; + self->from_valid = nm_utils_parse_inaddr_bin(_ip_routing_rule_get_addr_family(self), + from, + NULL, + &self->from_bin); + if (!self->from_valid) + self->from_str = g_strdup(from); +} + +/** + * nm_ip_routing_rule_get_to_len: + * @self: the #NMIPRoutingRule instance + * + * Returns: the set prefix length for the to/dst parameter. + * + * Since: 1.18 + */ +guint8 +nm_ip_routing_rule_get_to_len(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->to_len; +} + +/** + * nm_ip_routing_rule_get_to: + * @self: the #NMIPRoutingRule instance + * + * Returns: (transfer none): the set to/dst parameter or + * %NULL, if no value is set. + * + * Since: 1.18 + */ +const char * +nm_ip_routing_rule_get_to(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + if (!self->to_has) + return NULL; + if (!self->to_str) { + nm_assert(self->to_valid); + ((NMIPRoutingRule *) self)->to_str = + nm_utils_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->to_bin); + } + return self->to_str; +} + +const NMIPAddr * +nm_ip_routing_rule_get_to_bin(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + return (self->to_has && self->to_valid) ? &self->to_bin : NULL; +} + +void +nm_ip_routing_rule_set_to_bin(NMIPRoutingRule *self, gconstpointer to, guint8 len) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + nm_clear_g_free(&self->to_str); + + if (!to) { + self->to_has = FALSE; + self->to_len = len; + return; + } + + self->to_has = TRUE; + self->to_len = len; + self->to_valid = TRUE; + nm_ip_addr_set(_ip_routing_rule_get_addr_family(self), &self->to_bin, to); +} + +/** + * nm_ip_routing_rule_set_to: + * @self: the #NMIPRoutingRule instance + * @to: (allow-none): the to/dst address to set. + * The address family must match. + * @len: the corresponding prefix length of the address. + * If @to is %NULL, this valid is ignored. + * + * Setting invalid values is accepted, but will later fail + * during nm_ip_routing_rule_validate(). + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_to(NMIPRoutingRule *self, const char *to, guint8 len) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + if (!to) { + nm_clear_g_free(&self->to_str); + self->to_has = FALSE; + self->to_len = len; + return; + } + + nm_clear_g_free(&self->to_str); + self->to_has = TRUE; + self->to_len = len; + self->to_valid = + nm_utils_parse_inaddr_bin(_ip_routing_rule_get_addr_family(self), to, NULL, &self->to_bin); + if (!self->to_valid) + self->to_str = g_strdup(to); +} + +/** + * nm_ip_routing_rule_get_tos: + * @self: the #NMIPRoutingRule instance + * + * Returns: the tos of the rule. + * + * Since: 1.18 + */ +guint8 +nm_ip_routing_rule_get_tos(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->tos; +} + +/** + * nm_ip_routing_rule_set_tos: + * @self: the #NMIPRoutingRule instance + * @tos: the tos to set + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_tos(NMIPRoutingRule *self, guint8 tos) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->tos = tos; +} + +/** + * nm_ip_routing_rule_get_ipproto: + * @self: the #NMIPRoutingRule instance + * + * Returns: the ipproto of the rule. + * + * Since: 1.18 + */ +guint8 +nm_ip_routing_rule_get_ipproto(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->ipproto; +} + +/** + * nm_ip_routing_rule_set_ipproto: + * @self: the #NMIPRoutingRule instance + * @ipproto: the ipproto to set + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_ipproto(NMIPRoutingRule *self, guint8 ipproto) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->ipproto = ipproto; +} + +/** + * nm_ip_routing_rule_get_source_port_start: + * @self: the #NMIPRoutingRule instance + * + * Returns: the source port start setting. + * + * Since: 1.18 + */ +guint16 +nm_ip_routing_rule_get_source_port_start(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->sport_start; +} + +/** + * nm_ip_routing_rule_get_source_port_end: + * @self: the #NMIPRoutingRule instance + * + * Returns: the source port end setting. + * + * Since: 1.18 + */ +guint16 +nm_ip_routing_rule_get_source_port_end(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->sport_end; +} + +/** + * nm_ip_routing_rule_set_source_port: + * @self: the #NMIPRoutingRule instance + * @start: the start port to set. + * @end: the end port to set. + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_source_port(NMIPRoutingRule *self, guint16 start, guint16 end) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->sport_start = start; + self->sport_end = end; +} + +/** + * nm_ip_routing_rule_get_destination_port_start: + * @self: the #NMIPRoutingRule instance + * + * Returns: the destination port start setting. + * + * Since: 1.18 + */ +guint16 +nm_ip_routing_rule_get_destination_port_start(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->dport_start; +} + +/** + * nm_ip_routing_rule_get_destination_port_end: + * @self: the #NMIPRoutingRule instance + * + * Returns: the destination port end setting. + * + * Since: 1.18 + */ +guint16 +nm_ip_routing_rule_get_destination_port_end(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->dport_end; +} + +/** + * nm_ip_routing_rule_set_destination_port: + * @self: the #NMIPRoutingRule instance + * @start: the start port to set. + * @end: the end port to set. + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_destination_port(NMIPRoutingRule *self, guint16 start, guint16 end) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->dport_start = start; + self->dport_end = end; +} + +/** + * nm_ip_routing_rule_get_fwmark: + * @self: the #NMIPRoutingRule instance + * + * Returns: the fwmark setting. + * + * Since: 1.18 + */ +guint32 +nm_ip_routing_rule_get_fwmark(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->fwmark; +} + +/** + * nm_ip_routing_rule_get_fwmask: + * @self: the #NMIPRoutingRule instance + * + * Returns: the fwmask setting. + * + * Since: 1.18 + */ +guint32 +nm_ip_routing_rule_get_fwmask(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->fwmask; +} + +/** + * nm_ip_routing_rule_set_fwmark: + * @self: the #NMIPRoutingRule instance + * @fwmark: the fwmark + * @fwmask: the fwmask + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_fwmark(NMIPRoutingRule *self, guint32 fwmark, guint32 fwmask) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->fwmark = fwmark; + self->fwmask = fwmask; +} + +/** + * nm_ip_routing_rule_get_iifname: + * @self: the #NMIPRoutingRule instance. + * + * Returns: (transfer none): the set iifname or %NULL if unset. + * + * Since: 1.18 + */ +const char * +nm_ip_routing_rule_get_iifname(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + return self->iifname; +} + +gboolean +nm_ip_routing_rule_get_xifname_bin(const NMIPRoutingRule *self, + gboolean iif /* or else oif */, + char out_xifname[static 16 /* IFNAMSIZ */]) +{ + gs_free gpointer bin_to_free = NULL; + const char * xifname; + gconstpointer bin; + gsize len; + + nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); + nm_assert(out_xifname); + + xifname = iif ? self->iifname : self->oifname; + + if (!xifname) + return FALSE; + + bin = nm_utils_buf_utf8safe_unescape(xifname, + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, + &len, + &bin_to_free); + + strncpy(out_xifname, bin, 16 /* IFNAMSIZ */); + out_xifname[15] = '\0'; + return TRUE; +} + +/** + * nm_ip_routing_rule_set_iifname: + * @self: the #NMIPRoutingRule instance. + * @iifname: (allow-none): the iifname to set or %NULL to unset. + * + * The name supports C backslash escaping for non-UTF-8 characters. + * Note that nm_ip_routing_rule_from_string() too uses backslash + * escaping when tokenizing the words by whitespace. So, in string + * representation you'd get double backslashes. + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_iifname(NMIPRoutingRule *self, const char *iifname) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + g_free(self->iifname); + self->iifname = g_strdup(iifname); +} + +/** + * nm_ip_routing_rule_get_oifname: + * @self: the #NMIPRoutingRule instance. + * + * Returns: (transfer none): the set oifname or %NULL if unset. + * + * Since: 1.18 + */ +const char * +nm_ip_routing_rule_get_oifname(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + return self->oifname; +} + +/** + * nm_ip_routing_rule_set_oifname: + * @self: the #NMIPRoutingRule instance. + * @oifname: (allow-none): the oifname to set or %NULL to unset. + * + * The name supports C backslash escaping for non-UTF-8 characters. + * Note that nm_ip_routing_rule_from_string() too uses backslash + * escaping when tokenizing the words by whitespace. So, in string + * representation you'd get double backslashes. + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_oifname(NMIPRoutingRule *self, const char *oifname) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + g_free(self->oifname); + self->oifname = g_strdup(oifname); +} + +/** + * nm_ip_routing_rule_get_action: + * @self: the #NMIPRoutingRule instance + * + * Returns: the set action. + * + * Since: 1.18 + */ +guint8 +nm_ip_routing_rule_get_action(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->action; +} + +/** + * nm_ip_routing_rule_set_action: + * @self: the #NMIPRoutingRule instance + * @action: the action to set + * + * Note that currently only certain actions are allowed. nm_ip_routing_rule_validate() + * will reject unsupported actions as invalid. + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_action(NMIPRoutingRule *self, guint8 action) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->action = action; +} + +/** + * nm_ip_routing_rule_get_table: + * @self: the #NMIPRoutingRule instance + * + * Returns: the set table. + * + * Since: 1.18 + */ +guint32 +nm_ip_routing_rule_get_table(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); + + return self->table; +} + +/** + * nm_ip_routing_rule_set_table: + * @self: the #NMIPRoutingRule instance + * @table: the table to set + * + * Since: 1.18 + */ +void +nm_ip_routing_rule_set_table(NMIPRoutingRule *self, guint32 table) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->table = table; +} + +/** + * nm_ip_routing_rule_get_suppress_prefixlength: + * @self: the #NMIPRoutingRule instance + * + * Returns: the suppress_prefixlength of the rule. -1 means that the value is unset. + * + * Since: 1.20 + */ +gint32 +nm_ip_routing_rule_get_suppress_prefixlength(const NMIPRoutingRule *self) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), -1); + + return self->suppress_prefixlength; +} + +/** + * nm_ip_routing_rule_set_suppress_prefixlength: + * @self: the #NMIPRoutingRule instance + * @suppress_prefixlength: the suppress_prefixlength to set. The value -1 means + * unset. + * + * Since: 1.20 + */ +void +nm_ip_routing_rule_set_suppress_prefixlength(NMIPRoutingRule *self, gint32 suppress_prefixlength) +{ + g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); + + self->suppress_prefixlength = suppress_prefixlength; +} + +/** + * nm_ip_routing_rule_cmp: + * @rule: (allow-none): the #NMIPRoutingRule instance to compare + * @other: (allow-none): the other #NMIPRoutingRule instance to compare + * + * Returns: zero, a positive, or a negative integer to indicate + * equality or how the arguments compare. + * + * Since: 1.18 + */ +int +nm_ip_routing_rule_cmp(const NMIPRoutingRule *rule, const NMIPRoutingRule *other) +{ + NM_CMP_SELF(rule, other); + + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), 0); + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(other, TRUE), 0); + + NM_CMP_FIELD_UNSAFE(rule, other, priority_has); + if (rule->priority_has) + NM_CMP_FIELD(rule, other, priority); + + NM_CMP_FIELD_UNSAFE(rule, other, is_v4); + + NM_CMP_FIELD_UNSAFE(rule, other, invert); + + NM_CMP_FIELD(rule, other, tos); + + NM_CMP_FIELD(rule, other, fwmark); + NM_CMP_FIELD(rule, other, fwmask); + + NM_CMP_FIELD(rule, other, action); + + NM_CMP_FIELD(rule, other, table); + + NM_CMP_FIELD(rule, other, suppress_prefixlength); + + NM_CMP_FIELD(rule, other, sport_start); + NM_CMP_FIELD(rule, other, sport_end); + NM_CMP_FIELD(rule, other, dport_start); + NM_CMP_FIELD(rule, other, dport_end); + + NM_CMP_FIELD(rule, other, ipproto); + + /* We compare the plain strings, not the binary values after utf8safe unescaping. + * + * The reason is, that the rules differ already when the direct strings differ, not + * only when the unescaped names differ. */ + NM_CMP_FIELD_STR0(rule, other, iifname); + NM_CMP_FIELD_STR0(rule, other, oifname); + + NM_CMP_FIELD(rule, other, from_len); + + NM_CMP_FIELD_UNSAFE(rule, other, from_has); + if (rule->from_has) { + NM_CMP_FIELD_UNSAFE(rule, other, from_valid); + if (rule->from_valid) { + NM_CMP_RETURN( + memcmp(&rule->from_bin, &other->from_bin, _ip_routing_rule_get_addr_size(rule))); + } else + NM_CMP_FIELD_STR(rule, other, from_str); + } + + NM_CMP_FIELD(rule, other, to_len); + + NM_CMP_FIELD_UNSAFE(rule, other, to_has); + if (rule->to_has) { + NM_CMP_FIELD_UNSAFE(rule, other, to_valid); + if (rule->to_valid) { + NM_CMP_RETURN( + memcmp(&rule->to_bin, &other->to_bin, _ip_routing_rule_get_addr_size(rule))); + } else + NM_CMP_FIELD_STR(rule, other, to_str); + } + + return 0; +} + +static gboolean +_rr_xport_range_valid(guint16 xport_start, guint16 xport_end) +{ + if (xport_start == 0) + return (xport_end == 0); + + return xport_start <= xport_end && xport_end < 0xFFFFu; +} + +static gboolean +_rr_xport_range_parse(char *str, gint64 *out_start, guint16 *out_end) +{ + guint16 start, end; + gint64 i64; + char * s; + + s = strchr(str, '-'); + if (s) + *(s++) = '\0'; + + i64 = _nm_utils_ascii_str_to_int64(str, 10, 0, 0xFFFF, -1); + if (i64 == -1) + return FALSE; + + start = i64; + if (s) { + i64 = _nm_utils_ascii_str_to_int64(s, 10, 0, 0xFFFF, -1); + if (i64 == -1) + return FALSE; + end = i64; + } else + end = start; + + *out_start = start; + *out_end = end; + return TRUE; +} + +/** + * nm_ip_routing_rule_validate: + * @self: the #NMIPRoutingRule instance to validate + * @error: (allow-none) (out): the error result if validation fails. + * + * Returns: %TRUE if the rule validates. + * + * Since: 1.18 + */ +gboolean +nm_ip_routing_rule_validate(const NMIPRoutingRule *self, GError **error) +{ + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + + /* Kernel may be more flexible about validating. We do a strict validation + * here and reject certain settings eagerly. We can always relax it later. */ + + if (!self->priority_has) { + /* iproute2 accepts not specifying the priority, in which case kernel will select + * an unused priority. We don't allow for that, and will always require the user to + * select a priority. + * + * Note that if the user selects priority 0 or a non-unique priority, this is problematic + * due to kernel bugs rh#1685816 and rh#1685816. It may result in NetworkManager wrongly being + * unable to add a rule or deleting the wrong rule. + * This problem is not at all specific to the priority, it affects all rules that + * have default values which confuse kernel. But setting a unique priority avoids + * this problem nicely. */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid priority")); + return FALSE; + } + + if (NM_IN_SET(self->action, FR_ACT_TO_TBL)) { + if (self->table == 0) { + /* with IPv4, kernel allows a table (in RTM_NEWRULE) of zero to automatically select + * an unused table. We don't. The user needs to specify the table. + * + * For IPv6, kernel doesn't allow a table of zero, so we are consistent here. */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("missing table")); + return FALSE; + } + } else { + /* whitelist the actions that we currently. */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid action")); + return FALSE; + } + + if (self->from_len == 0) { + if (self->from_has) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("has from/src but the prefix-length is zero")); + return FALSE; + } + } else if (self->from_len > 0 && self->from_len <= 8 * _ip_routing_rule_get_addr_size(self)) { + if (!self->from_has) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("missing from/src for a non zero prefix-length")); + return FALSE; + } + if (!self->from_valid) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid from/src")); + return FALSE; + } + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid prefix length for from/src")); + return FALSE; + } + + if (self->to_len == 0) { + if (self->to_has) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("has to/dst but the prefix-length is zero")); + return FALSE; + } + } else if (self->to_len > 0 && self->to_len <= 8 * _ip_routing_rule_get_addr_size(self)) { + if (!self->to_has) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("missing to/dst for a non zero prefix-length")); + return FALSE; + } + if (!self->to_valid) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid to/dst")); + return FALSE; + } + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid prefix length for to/dst")); + return FALSE; + } + + if (self->iifname + && (!g_utf8_validate(self->iifname, -1, NULL) + || !nm_utils_is_valid_iface_name_utf8safe(self->iifname))) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid iifname")); + return FALSE; + } + + if (self->oifname + && (!g_utf8_validate(self->oifname, -1, NULL) + || !nm_utils_is_valid_iface_name_utf8safe(self->oifname))) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid oifname")); + return FALSE; + } + + if (!_rr_xport_range_valid(self->sport_start, self->sport_end)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid source port range")); + return FALSE; + } + + if (!_rr_xport_range_valid(self->dport_start, self->dport_end)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid destination port range")); + return FALSE; + } + + if (self->suppress_prefixlength != -1) { + if (self->suppress_prefixlength < -1 + || self->suppress_prefixlength > (self->is_v4 ? 32 : 128)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("suppress_prefixlength out of range")); + return FALSE; + } + if (self->action != FR_ACT_TO_TBL) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("suppress_prefixlength is only allowed with the to-table action")); + return FALSE; + } + } + + return TRUE; +} + +/*****************************************************************************/ + +typedef enum { + RR_DBUS_ATTR_ACTION, + RR_DBUS_ATTR_DPORT_END, + RR_DBUS_ATTR_DPORT_START, + RR_DBUS_ATTR_FAMILY, + RR_DBUS_ATTR_FROM, + RR_DBUS_ATTR_FROM_LEN, + RR_DBUS_ATTR_FWMARK, + RR_DBUS_ATTR_FWMASK, + RR_DBUS_ATTR_IIFNAME, + RR_DBUS_ATTR_INVERT, + RR_DBUS_ATTR_IPPROTO, + RR_DBUS_ATTR_OIFNAME, + RR_DBUS_ATTR_PRIORITY, + RR_DBUS_ATTR_SPORT_END, + RR_DBUS_ATTR_SPORT_START, + RR_DBUS_ATTR_TABLE, + RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, + RR_DBUS_ATTR_TO, + RR_DBUS_ATTR_TOS, + RR_DBUS_ATTR_TO_LEN, + + _RR_DBUS_ATTR_NUM, +} RRDbusAttr; + +typedef struct { + const char * name; + const GVariantType *dbus_type; +} RRDbusData; + +static const RRDbusData rr_dbus_data[_RR_DBUS_ATTR_NUM] = { +#define _D(attr, _name, type) \ + [attr] = { \ + .name = _name, \ + .dbus_type = type, \ + } + _D(RR_DBUS_ATTR_ACTION, NM_IP_ROUTING_RULE_ATTR_ACTION, G_VARIANT_TYPE_BYTE), + _D(RR_DBUS_ATTR_DPORT_END, NM_IP_ROUTING_RULE_ATTR_DPORT_END, G_VARIANT_TYPE_UINT16), + _D(RR_DBUS_ATTR_DPORT_START, NM_IP_ROUTING_RULE_ATTR_DPORT_START, G_VARIANT_TYPE_UINT16), + _D(RR_DBUS_ATTR_FAMILY, NM_IP_ROUTING_RULE_ATTR_FAMILY, G_VARIANT_TYPE_INT32), + _D(RR_DBUS_ATTR_FROM, NM_IP_ROUTING_RULE_ATTR_FROM, G_VARIANT_TYPE_STRING), + _D(RR_DBUS_ATTR_FROM_LEN, NM_IP_ROUTING_RULE_ATTR_FROM_LEN, G_VARIANT_TYPE_BYTE), + _D(RR_DBUS_ATTR_FWMARK, NM_IP_ROUTING_RULE_ATTR_FWMARK, G_VARIANT_TYPE_UINT32), + _D(RR_DBUS_ATTR_FWMASK, NM_IP_ROUTING_RULE_ATTR_FWMASK, G_VARIANT_TYPE_UINT32), + _D(RR_DBUS_ATTR_IIFNAME, NM_IP_ROUTING_RULE_ATTR_IIFNAME, G_VARIANT_TYPE_STRING), + _D(RR_DBUS_ATTR_INVERT, NM_IP_ROUTING_RULE_ATTR_INVERT, G_VARIANT_TYPE_BOOLEAN), + _D(RR_DBUS_ATTR_IPPROTO, NM_IP_ROUTING_RULE_ATTR_IPPROTO, G_VARIANT_TYPE_BYTE), + _D(RR_DBUS_ATTR_OIFNAME, NM_IP_ROUTING_RULE_ATTR_OIFNAME, G_VARIANT_TYPE_STRING), + _D(RR_DBUS_ATTR_PRIORITY, NM_IP_ROUTING_RULE_ATTR_PRIORITY, G_VARIANT_TYPE_UINT32), + _D(RR_DBUS_ATTR_SPORT_END, NM_IP_ROUTING_RULE_ATTR_SPORT_END, G_VARIANT_TYPE_UINT16), + _D(RR_DBUS_ATTR_SPORT_START, NM_IP_ROUTING_RULE_ATTR_SPORT_START, G_VARIANT_TYPE_UINT16), + _D(RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, + NM_IP_ROUTING_RULE_ATTR_SUPPRESS_PREFIXLENGTH, + G_VARIANT_TYPE_INT32), + _D(RR_DBUS_ATTR_TABLE, NM_IP_ROUTING_RULE_ATTR_TABLE, G_VARIANT_TYPE_UINT32), + _D(RR_DBUS_ATTR_TO, NM_IP_ROUTING_RULE_ATTR_TO, G_VARIANT_TYPE_STRING), + _D(RR_DBUS_ATTR_TOS, NM_IP_ROUTING_RULE_ATTR_TOS, G_VARIANT_TYPE_BYTE), + _D(RR_DBUS_ATTR_TO_LEN, NM_IP_ROUTING_RULE_ATTR_TO_LEN, G_VARIANT_TYPE_BYTE), +#undef _D +}; + +static void +_rr_variants_free(GVariant *(*p_variants)[]) +{ + int i; + + for (i = 0; i < _RR_DBUS_ATTR_NUM; i++) { + if ((*p_variants)[i]) + g_variant_unref((*p_variants)[i]); + } +} + +NMIPRoutingRule * +nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error) +{ + nm_auto(_rr_variants_free) GVariant *variants[_RR_DBUS_ATTR_NUM] = {}; + nm_auto_unref_ip_routing_rule NMIPRoutingRule *self = NULL; + RRDbusAttr attr; + GVariantIter iter; + const char * iter_key; + GVariant * iter_val; + int addr_family; + int i; + + g_variant_iter_init(&iter, variant); + +#if NM_MORE_ASSERTS > 10 + for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { + nm_assert(rr_dbus_data[attr].name); + nm_assert(g_variant_type_string_is_valid((const char *) rr_dbus_data[attr].dbus_type)); + } +#endif + + while (g_variant_iter_next(&iter, "{&sv}", &iter_key, &iter_val)) { + gs_unref_variant GVariant *iter_val2 = iter_val; + + for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { + if (nm_streq(iter_key, rr_dbus_data[attr].name)) { + if (variants[attr]) { + if (strict) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("duplicate key %s"), + iter_key); + return NULL; + } + g_variant_unref(variants[attr]); + } + variants[attr] = g_steal_pointer(&iter_val2); + break; + } + } + + if (attr >= _RR_DBUS_ATTR_NUM && strict) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid key \"%s\""), + iter_key); + return NULL; + } + } + + for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { + if (!variants[attr]) + continue; + if (!g_variant_is_of_type(variants[attr], rr_dbus_data[attr].dbus_type)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid variant type '%s' for \"%s\""), + (const char *) rr_dbus_data[attr].dbus_type, + rr_dbus_data[attr].name); + return NULL; + } + } + + if (!variants[RR_DBUS_ATTR_FAMILY]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("missing \"" NM_IP_ROUTING_RULE_ATTR_FAMILY "\"")); + return NULL; + } + addr_family = g_variant_get_int32(variants[RR_DBUS_ATTR_FAMILY]); + if (!NM_IN_SET(addr_family, AF_INET, AF_INET6)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid \"" NM_IP_ROUTING_RULE_ATTR_FAMILY "\"")); + return NULL; + } + + self = nm_ip_routing_rule_new(addr_family); + + if (variants[RR_DBUS_ATTR_PRIORITY]) + nm_ip_routing_rule_set_priority(self, + g_variant_get_uint32(variants[RR_DBUS_ATTR_PRIORITY])); + + if (variants[RR_DBUS_ATTR_INVERT]) + nm_ip_routing_rule_set_invert(self, g_variant_get_boolean(variants[RR_DBUS_ATTR_INVERT])); + + if (variants[RR_DBUS_ATTR_TOS]) + nm_ip_routing_rule_set_tos(self, g_variant_get_byte(variants[RR_DBUS_ATTR_TOS])); + + if (variants[RR_DBUS_ATTR_IPPROTO]) + nm_ip_routing_rule_set_ipproto(self, g_variant_get_byte(variants[RR_DBUS_ATTR_IPPROTO])); + + for (i = 0; i < 2; i++) { + GVariant *v_start = variants[i ? RR_DBUS_ATTR_SPORT_START : RR_DBUS_ATTR_DPORT_START]; + GVariant *v_end = variants[i ? RR_DBUS_ATTR_SPORT_END : RR_DBUS_ATTR_DPORT_END]; + guint16 start, end; + + if (!v_start && !v_end) + continue; + + /* if start or end is missing, it defaults to the other parameter, respectively. */ + if (v_start) + start = g_variant_get_uint16(v_start); + else + start = g_variant_get_uint16(v_end); + if (v_end) + end = g_variant_get_uint16(v_end); + else + end = g_variant_get_uint16(v_start); + + if (i) + nm_ip_routing_rule_set_source_port(self, start, end); + else + nm_ip_routing_rule_set_destination_port(self, start, end); + } + + if (variants[RR_DBUS_ATTR_FWMARK] || variants[RR_DBUS_ATTR_FWMASK]) { + nm_ip_routing_rule_set_fwmark( + self, + variants[RR_DBUS_ATTR_FWMARK] ? g_variant_get_uint32(variants[RR_DBUS_ATTR_FWMARK]) + : 0u, + variants[RR_DBUS_ATTR_FWMASK] ? g_variant_get_uint32(variants[RR_DBUS_ATTR_FWMASK]) + : 0u); + } + + if (variants[RR_DBUS_ATTR_FROM] || variants[RR_DBUS_ATTR_FROM_LEN]) { + nm_ip_routing_rule_set_from( + self, + variants[RR_DBUS_ATTR_FROM] ? g_variant_get_string(variants[RR_DBUS_ATTR_FROM], NULL) + : NULL, + variants[RR_DBUS_ATTR_FROM_LEN] ? g_variant_get_byte(variants[RR_DBUS_ATTR_FROM_LEN]) + : 0u); + } + + if (variants[RR_DBUS_ATTR_TO] || variants[RR_DBUS_ATTR_TO_LEN]) { + nm_ip_routing_rule_set_to( + self, + variants[RR_DBUS_ATTR_TO] ? g_variant_get_string(variants[RR_DBUS_ATTR_TO], NULL) + : NULL, + variants[RR_DBUS_ATTR_TO_LEN] ? g_variant_get_byte(variants[RR_DBUS_ATTR_TO_LEN]) : 0u); + } + + if (variants[RR_DBUS_ATTR_IIFNAME]) + nm_ip_routing_rule_set_iifname(self, + g_variant_get_string(variants[RR_DBUS_ATTR_IIFNAME], NULL)); + + if (variants[RR_DBUS_ATTR_OIFNAME]) + nm_ip_routing_rule_set_oifname(self, + g_variant_get_string(variants[RR_DBUS_ATTR_OIFNAME], NULL)); + + if (variants[RR_DBUS_ATTR_ACTION]) + nm_ip_routing_rule_set_action(self, g_variant_get_byte(variants[RR_DBUS_ATTR_ACTION])); + + if (variants[RR_DBUS_ATTR_TABLE]) + nm_ip_routing_rule_set_table(self, g_variant_get_uint32(variants[RR_DBUS_ATTR_TABLE])); + + if (variants[RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH]) + nm_ip_routing_rule_set_suppress_prefixlength( + self, + g_variant_get_int32(variants[RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH])); + + if (strict && !nm_ip_routing_rule_validate(self, error)) + return NULL; + + return g_steal_pointer(&self); +} + +static void +_rr_to_dbus_add(GVariantBuilder *builder, RRDbusAttr attr, GVariant *value) +{ + nm_assert(builder); + nm_assert(value); + nm_assert(g_variant_is_floating(value)); + nm_assert(g_variant_is_of_type(value, rr_dbus_data[attr].dbus_type)); + + g_variant_builder_add(builder, "{sv}", rr_dbus_data[attr].name, value); +} + +GVariant * +nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self) +{ + GVariantBuilder builder; + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + + _rr_to_dbus_add(&builder, + RR_DBUS_ATTR_FAMILY, + g_variant_new_int32(_ip_routing_rule_get_addr_family(self))); + + if (self->invert) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_INVERT, g_variant_new_boolean(TRUE)); + + if (self->priority_has) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_PRIORITY, g_variant_new_uint32(self->priority)); + + if (self->tos != 0) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TOS, g_variant_new_byte(self->tos)); + + if (self->ipproto != 0) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_IPPROTO, g_variant_new_byte(self->ipproto)); + + if (self->fwmark != 0) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FWMARK, g_variant_new_uint32(self->fwmark)); + + if (self->fwmask != 0) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FWMASK, g_variant_new_uint32(self->fwmask)); + + if (self->sport_start != 0 || self->sport_end != 0) { + _rr_to_dbus_add(&builder, + RR_DBUS_ATTR_SPORT_START, + g_variant_new_uint16(self->sport_start)); + if (self->sport_start != self->sport_end) + _rr_to_dbus_add(&builder, + RR_DBUS_ATTR_SPORT_END, + g_variant_new_uint16(self->sport_end)); + } + + if (self->dport_start != 0 || self->dport_end != 0) { + _rr_to_dbus_add(&builder, + RR_DBUS_ATTR_DPORT_START, + g_variant_new_uint16(self->dport_start)); + if (self->dport_start != self->dport_end) + _rr_to_dbus_add(&builder, + RR_DBUS_ATTR_DPORT_END, + g_variant_new_uint16(self->dport_end)); + } + + if (self->from_has || self->from_len != 0) { + _rr_to_dbus_add( + &builder, + RR_DBUS_ATTR_FROM, + g_variant_new_string(self->from_str + ?: nm_utils_inet_ntop(_ip_routing_rule_get_addr_family(self), + &self->from_bin, + addr_str))); + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FROM_LEN, g_variant_new_byte(self->from_len)); + } + + if (self->to_has || self->to_len != 0) { + _rr_to_dbus_add( + &builder, + RR_DBUS_ATTR_TO, + g_variant_new_string(self->to_str + ?: nm_utils_inet_ntop(_ip_routing_rule_get_addr_family(self), + &self->to_bin, + addr_str))); + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TO_LEN, g_variant_new_byte(self->to_len)); + } + + if (self->iifname) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_IIFNAME, g_variant_new_string(self->iifname)); + + if (self->oifname) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_OIFNAME, g_variant_new_string(self->oifname)); + + if (self->action != FR_ACT_TO_TBL) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_ACTION, g_variant_new_byte(self->action)); + + if (self->table != 0) + _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TABLE, g_variant_new_uint32(self->table)); + + if (self->suppress_prefixlength != -1) + _rr_to_dbus_add(&builder, + RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, + g_variant_new_int32(self->suppress_prefixlength)); + + return g_variant_builder_end(&builder); +} + +/*****************************************************************************/ + +static gboolean +_rr_string_validate(gboolean for_from /* or else to-string */, + NMIPRoutingRuleAsStringFlags to_string_flags, + GHashTable * extra_args, + GError ** error) +{ + if (NM_FLAGS_ANY(to_string_flags, + ~(NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET + | NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 + | NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE))) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("Unsupported to-string-flags argument")); + return FALSE; + } + + if (extra_args && g_hash_table_size(extra_args) > 0) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("Unsupported extra-argument")); + return FALSE; + } + + return TRUE; +} + +static int +_rr_string_addr_family_from_flags(NMIPRoutingRuleAsStringFlags to_string_flags) +{ + if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET)) { + if (!NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6)) + return AF_INET; + } else if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6)) + return AF_INET6; + return AF_UNSPEC; +} + +/** + * nm_ip_routing_rule_from_string: + * @str: the string representation to convert to an #NMIPRoutingRule + * @to_string_flags: #NMIPRoutingRuleAsStringFlags for controlling the + * string conversion. + * @extra_args: (allow-none): extra arguments for controlling the string + * conversion. Currently, not extra arguments are supported. + * @error: (allow-none) (out): the error reason. + * + * Returns: (transfer full): the new #NMIPRoutingRule or %NULL on error. + * + * Since: 1.18 + */ +NMIPRoutingRule * +nm_ip_routing_rule_from_string(const char * str, + NMIPRoutingRuleAsStringFlags to_string_flags, + GHashTable * extra_args, + GError ** error) +{ + nm_auto_unref_ip_routing_rule NMIPRoutingRule *self = NULL; + gs_free const char ** tokens = NULL; + gsize i_token; + gboolean any_words = FALSE; + char * word0 = NULL; + char * word1 = NULL; + char * word_from = NULL; + char * word_to = NULL; + char * word_iifname = NULL; + char * word_oifname = NULL; + gint64 i64_priority = -1; + gint64 i64_table = -1; + gint64 i64_tos = -1; + gint64 i64_fwmark = -1; + gint64 i64_fwmask = -1; + gint64 i64_sport_start = -1; + gint64 i64_ipproto = -1; + gint64 i64_suppress_prefixlength = -1; + guint16 sport_end = 0; + gint64 i64_dport_start = -1; + guint16 dport_end = 0; + gboolean val_invert = FALSE; + int addr_family = AF_UNSPEC; + NMIPAddr val_from = {}; + NMIPAddr val_to = {}; + int val_from_len = -1; + int val_to_len = -1; + char * s; + + g_return_val_if_fail(str, NULL); + + if (!_rr_string_validate(TRUE, to_string_flags, extra_args, error)) + return NULL; + + /* NM_IP_ROUTING_RULE_TO_STRING_TYPE_IPROUTE gives a string representation that is + * partly compatibly with iproute2. That is, the part after `ip -[46] rule add $ARGS`. + * There are differences though: + * + * - trying to convert an invalid rule to string may not be possible. The reason is for + * example that an invalid rule can have nm_ip_routing_rule_get_from() like "bogus", + * but we don't write that as "from bogus". In general, if you try to convert an invalid + * rule to string, the operation may fail or the result may itself not be parsable. + * Of course, valid rules can be converted to string and read back the same (round-trip). + * + * - iproute2 in may regards is flexible about the command lines. For example + * - for tables it accepts table names from /etc/iproute2/rt_tables. We only + * accept the special aliases "main", "local", and "default". + * - key names like "preference" can be abbreviated to "pref", we don't do that. + * - the "preference"/"priority" may be unspecified, in which kernel automatically + * chooses an unused priority (during `ip rule add`). We don't allow for that, the + * priority must be explicitly set. + * + * - iproute2 does not support any escaping. Well, it's the shell that supports quoting + * and escaping and splits the command line. We need to split the command line ourself, + * but we don't support full shell quotation. + * from-string tokenizes words at (ASCII) whitespaces (removing the whitespaces). + * It also supports backslash escaping (e.g. to contain whitespace), but it does + * not support special escape sequences. Values are taken literally, meaning + * "\n\ \111" gives results in "n 111". + * The strings really shouldn't contain any special characters that require escaping, + * but that's the rule. + * This also goes together with the @allow_escaping parameter of nm_utils_strsplit_set(). + * If you concatenate multiple rule expressions with a delimiter, the delimiter inside + * each word can be backslash escaped, and nm_utils_strsplit_set(allow_escaping=TRUE) will + * properly split the words, preserving the backslashes, which then will be removed by + * nm_ip_routing_rule_from_string(). + */ + + addr_family = _rr_string_addr_family_from_flags(to_string_flags); + + tokens = nm_utils_escaped_tokens_split(str, NM_ASCII_SPACES); + for (i_token = 0; tokens && tokens[i_token]; i_token++) { + char *str_word = (char *) tokens[i_token]; + + any_words = TRUE; + if (!word0) + word0 = str_word; + else { + nm_assert(!word1); + word1 = str_word; + } + + /* iproute2 matches keywords with any partial prefix. We don't allow + * for that flexibility. */ + + if (NM_IN_STRSET(word0, "from")) { + if (!word1) + continue; + if (word_from) + goto next_fail_word0_duplicate_key; + word_from = word1; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "to")) { + if (!word1) + continue; + if (word_to) + goto next_fail_word0_duplicate_key; + word_to = word1; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "not")) { + /* we accept multiple "not" specifiers. "not not" still means + * not. */ + val_invert = TRUE; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "priority", "order", "pref", "preference")) { + if (!word1) + continue; + if (i64_priority != -1) + goto next_fail_word0_duplicate_key; + i64_priority = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXUINT32, -1); + if (i64_priority == -1) + goto next_fail_word1_invalid_value; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "table", "lookup")) { + if (!word1) + continue; + if (i64_table != -1) + goto next_fail_word0_duplicate_key; + i64_table = _nm_utils_ascii_str_to_int64(word1, 0, 1, G_MAXUINT32, -1); + if (i64_table == -1) { + if (nm_streq(word1, "main")) + i64_table = RT_TABLE_MAIN; + else if (nm_streq(word1, "local")) + i64_table = RT_TABLE_LOCAL; + else if (nm_streq(word1, "default")) + i64_table = RT_TABLE_DEFAULT; + else + goto next_fail_word1_invalid_value; + } + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "tos", "dsfield")) { + if (!word1) + continue; + if (i64_tos != -1) + goto next_fail_word0_duplicate_key; + i64_tos = _nm_utils_ascii_str_to_int64(word1, 16, 0, G_MAXUINT8, -1); + if (i64_tos == -1) + goto next_fail_word1_invalid_value; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "ipproto")) { + if (!word1) + continue; + if (i64_ipproto != -1) + goto next_fail_word0_duplicate_key; + i64_ipproto = _nm_utils_ascii_str_to_int64(word1, 10, 0, G_MAXUINT8, -1); + if (i64_ipproto == -1) + goto next_fail_word1_invalid_value; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "sport")) { + if (!word1) + continue; + if (i64_sport_start != -1) + goto next_fail_word0_duplicate_key; + if (!_rr_xport_range_parse(word1, &i64_sport_start, &sport_end)) + goto next_fail_word1_invalid_value; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "dport")) { + if (!word1) + continue; + if (i64_dport_start != -1) + goto next_fail_word0_duplicate_key; + if (!_rr_xport_range_parse(word1, &i64_dport_start, &dport_end)) + goto next_fail_word1_invalid_value; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "fwmark")) { + if (!word1) + continue; + if (i64_fwmark != -1) + goto next_fail_word0_duplicate_key; + s = strchr(word1, '/'); + if (s) + *(s++) = '\0'; + i64_fwmark = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXUINT32, -1); + if (i64_fwmark == -1) + goto next_fail_word1_invalid_value; + if (s) { + i64_fwmask = _nm_utils_ascii_str_to_int64(s, 0, 0, G_MAXUINT32, -1); + if (i64_fwmask == -1) + goto next_fail_word1_invalid_value; + } else + i64_fwmask = 0xFFFFFFFFu; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "iif", "dev")) { + if (!word1) + continue; + if (word_iifname) + goto next_fail_word0_duplicate_key; + word_iifname = word1; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "oif")) { + if (!word1) + continue; + if (word_oifname) + goto next_fail_word0_duplicate_key; + word_oifname = word1; + goto next_words_consumed; + } + if (NM_IN_STRSET(word0, "suppress_prefixlength", "sup_pl")) { + if (!word1) + continue; + if (i64_suppress_prefixlength != -1) + goto next_fail_word0_duplicate_key; + i64_suppress_prefixlength = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXINT32, -1); + if (i64_suppress_prefixlength == -1) + goto next_fail_word1_invalid_value; + goto next_words_consumed; + } + + /* also the action is still unsupported. For the moment, we only support + * FR_ACT_TO_TBL, which is the default (by not expressing it on the command + * line). */ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("unsupported key \"%s\""), + word0); + return FALSE; +next_fail_word0_duplicate_key: + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("duplicate key \"%s\""), + word0); + return FALSE; +next_fail_word1_invalid_value: + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid value for \"%s\""), + word0); + return FALSE; +next_words_consumed: + word0 = NULL; + word1 = NULL; + } + + if (!any_words) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("empty text does not describe a rule")); + return FALSE; + } + + if (word0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("missing argument for \"%s\""), + word0); + return FALSE; + } + + if (!NM_IN_STRSET(word_from, NULL, "all")) { + if (!nm_utils_parse_inaddr_prefix_bin(addr_family, + word_from, + &addr_family, + &val_from, + &val_from_len)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid \"from\" part")); + return FALSE; + } + if (val_from_len == -1) + val_from_len = nm_utils_addr_family_to_size(addr_family) * 8; + } + + if (!NM_IN_STRSET(word_to, NULL, "all")) { + if (!nm_utils_parse_inaddr_prefix_bin(addr_family, + word_to, + &addr_family, + &val_to, + &val_to_len)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid \"to\" part")); + return FALSE; + } + if (val_to_len == -1) + val_to_len = nm_utils_addr_family_to_size(addr_family) * 8; + } + + if (!NM_IN_SET(addr_family, AF_INET, AF_INET6)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("cannot detect address family for rule")); + return FALSE; + } + + self = nm_ip_routing_rule_new(addr_family); + + if (val_invert) + self->invert = TRUE; + + if (i64_priority != -1) + nm_ip_routing_rule_set_priority(self, i64_priority); + + if (i64_tos != -1) + nm_ip_routing_rule_set_tos(self, i64_tos); + + if (i64_ipproto != -1) + nm_ip_routing_rule_set_ipproto(self, i64_ipproto); + + if (i64_fwmark != -1) + nm_ip_routing_rule_set_fwmark(self, i64_fwmark, i64_fwmask); + + if (i64_sport_start != -1) + nm_ip_routing_rule_set_source_port(self, i64_sport_start, sport_end); + + if (i64_dport_start != -1) + nm_ip_routing_rule_set_destination_port(self, i64_dport_start, dport_end); + + if (i64_suppress_prefixlength != -1) + nm_ip_routing_rule_set_suppress_prefixlength(self, i64_suppress_prefixlength); + + if (val_from_len > 0 || (val_from_len == 0 && !nm_ip_addr_is_null(addr_family, &val_from))) { + nm_ip_routing_rule_set_from_bin(self, &val_from, val_from_len); + } + + if (val_to_len > 0 || (val_to_len == 0 && !nm_ip_addr_is_null(addr_family, &val_to))) { + nm_ip_routing_rule_set_to_bin(self, &val_to, val_to_len); + } + + if (word_iifname) + nm_ip_routing_rule_set_iifname(self, word_iifname); + + if (word_oifname) + nm_ip_routing_rule_set_oifname(self, word_oifname); + + if (i64_table != -1) + nm_ip_routing_rule_set_table(self, i64_table); + + if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE)) { + gs_free_error GError *local = NULL; + + if (!nm_ip_routing_rule_validate(self, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("rule is invalid: %s"), + local->message); + return NULL; + } + } + + return g_steal_pointer(&self); +} + +static void +_rr_string_append_inet_addr(NMStrBuf * str, + gboolean is_from /* or else is-to */, + gboolean required, + int addr_family, + const NMIPAddr *addr_bin, + guint8 addr_len) +{ + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + + if (addr_len == 0) { + if (required) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(str, ' '), + "%s %s/0", + is_from ? "from" : "to", + (addr_family == AF_INET) ? "0.0.0.0" : "::"); + } + return; + } + + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(str, ' '), + "%s %s", + is_from ? "from" : "to", + nm_utils_inet_ntop(addr_family, addr_bin, addr_str)); + if (addr_len != nm_utils_addr_family_to_size(addr_family) * 8) { + nm_str_buf_append_printf(str, "/%u", addr_len); + } +} + +/** + * nm_ip_routing_rule_to_string: + * @self: the #NMIPRoutingRule instance to convert to string. + * @to_string_flags: #NMIPRoutingRuleAsStringFlags for controlling the + * string conversion. + * @extra_args: (allow-none): extra arguments for controlling the string + * conversion. Currently, not extra arguments are supported. + * @error: (allow-none) (out): the error reason. + * + * Returns: (transfer full): the string representation or %NULL on error. + * + * Since: 1.18 + */ +char * +nm_ip_routing_rule_to_string(const NMIPRoutingRule * self, + NMIPRoutingRuleAsStringFlags to_string_flags, + GHashTable * extra_args, + GError ** error) +{ + int addr_family; + NMStrBuf str; + + g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); + + if (!_rr_string_validate(FALSE, to_string_flags, extra_args, error)) + return NULL; + + addr_family = nm_ip_routing_rule_get_addr_family(self); + + if (!NM_IN_SET(_rr_string_addr_family_from_flags(to_string_flags), AF_UNSPEC, addr_family)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid address family")); + return NULL; + } + + /* It is only guaranteed that valid rules can be expressed as string. + * + * Still, unless requested proceed to convert to string without validating and + * hope for the best. + * + * That is, because self->from_str might contain an invalid IP address (indicated + * by self->from_valid). But we don't support serializing such arbitrary strings + * as "from %s". */ + if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE)) { + gs_free_error GError *local = NULL; + + if (!nm_ip_routing_rule_validate(self, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("rule is invalid: %s"), + local->message); + return NULL; + } + } + + nm_str_buf_init(&str, NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE); + + if (self->priority_has) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), + "priority %u", + (guint) self->priority); + } + + if (self->invert) + nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "not"); + + _rr_string_append_inet_addr(&str, + TRUE, + (!self->to_has || !self->to_valid), + addr_family, + &self->from_bin, + (self->from_has && self->from_valid) ? self->from_len : 0); + + _rr_string_append_inet_addr(&str, + FALSE, + FALSE, + addr_family, + &self->to_bin, + (self->to_has && self->to_valid) ? self->to_len : 0); + + if (self->tos != 0) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), + "tos 0x%02x", + (guint) self->tos); + } + + if (self->ipproto != 0) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), + "ipproto %u", + (guint) self->ipproto); + } + + if (self->fwmark != 0 || self->fwmask != 0) { + if (self->fwmark != 0) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), + "fwmark 0x%x", + self->fwmark); + } else { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), "fwmark 0"); + } + if (self->fwmask != 0xFFFFFFFFu) { + if (self->fwmask != 0) + nm_str_buf_append_printf(&str, "/0x%x", self->fwmask); + else + nm_str_buf_append_printf(&str, "/0"); + } + } + + if (self->sport_start != 0 || self->sport_end != 0) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), + "sport %u", + self->sport_start); + if (self->sport_start != self->sport_end) { + nm_str_buf_append_printf(&str, "-%u", self->sport_end); + } + } + + if (self->dport_start != 0 || self->dport_end != 0) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), + "dport %u", + self->dport_start); + if (self->dport_start != self->dport_end) { + nm_str_buf_append_printf(&str, "-%u", self->dport_end); + } + } + + if (self->iifname) { + nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "iif "); + nm_utils_escaped_tokens_escape_strbuf(self->iifname, NM_ASCII_SPACES, &str); + } + + if (self->oifname) { + nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "oif "); + nm_utils_escaped_tokens_escape_strbuf(self->oifname, NM_ASCII_SPACES, &str); + } + + if (self->table != 0) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), + "table %u", + (guint) self->table); + } + + if (self->suppress_prefixlength != -1) { + nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), + "suppress_prefixlength %d", + (int) self->suppress_prefixlength); + } + + return nm_str_buf_finalize(&str, NULL); +} + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingIPConfig, + PROP_METHOD, + PROP_DNS, + PROP_DNS_SEARCH, + PROP_DNS_OPTIONS, + PROP_DNS_PRIORITY, + PROP_ADDRESSES, + PROP_GATEWAY, + PROP_ROUTES, + PROP_ROUTE_METRIC, + PROP_ROUTE_TABLE, + PROP_IGNORE_AUTO_ROUTES, + PROP_IGNORE_AUTO_DNS, + PROP_DHCP_HOSTNAME, + PROP_DHCP_HOSTNAME_FLAGS, + PROP_DHCP_SEND_HOSTNAME, + PROP_NEVER_DEFAULT, + PROP_MAY_FAIL, + PROP_DAD_TIMEOUT, + PROP_DHCP_TIMEOUT, + PROP_DHCP_IAID, + PROP_DHCP_REJECT_SERVERS, ); + +typedef struct { + GPtrArray *dns; /* array of IP address strings */ + GPtrArray *dns_search; /* array of domain name strings */ + GPtrArray *dns_options; /* array of DNS options */ + GPtrArray *addresses; /* array of NMIPAddress */ + GPtrArray *routes; /* array of NMIPRoute */ + GPtrArray *routing_rules; + GArray * dhcp_reject_servers; + char * method; + char * gateway; + char * dhcp_hostname; + char * dhcp_iaid; + gint64 route_metric; + guint dhcp_hostname_flags; + int dns_priority; + int dad_timeout; + int dhcp_timeout; + guint32 route_table; + bool ignore_auto_routes : 1; + bool ignore_auto_dns : 1; + bool dhcp_send_hostname : 1; + bool never_default : 1; + bool may_fail : 1; +} NMSettingIPConfigPrivate; + +G_DEFINE_ABSTRACT_TYPE(NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING) + +#define NM_SETTING_IP_CONFIG_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfigPrivate)) + +/*****************************************************************************/ + +#define NM_SETTING_IP_CONFIG_GET_FAMILY(setting) \ + (NM_IS_SETTING_IP4_CONFIG(setting) ? AF_INET : AF_INET6) + +/** + * nm_setting_ip_config_get_method: + * @setting: the #NMSettingIPConfig + * + * Returns: the #NMSettingIPConfig:method property of the setting; see + * #NMSettingIP4Config and #NMSettingIP6Config for details of the + * methods available with each type. + **/ +const char * +nm_setting_ip_config_get_method(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->method; +} + +/** + * nm_setting_ip_config_get_num_dns: + * @setting: the #NMSettingIPConfig + * + * Returns: the number of configured DNS servers + **/ +guint +nm_setting_ip_config_get_num_dns(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns->len; +} + +/** + * nm_setting_ip_config_get_dns: + * @setting: the #NMSettingIPConfig + * @idx: index number of the DNS server to return + * + * Returns: the IP address of the DNS server at index @idx + **/ +const char * +nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_val_if_fail(idx >= 0 && idx < priv->dns->len, NULL); + + return priv->dns->pdata[idx]; +} + +/** + * nm_setting_ip_config_add_dns: + * @setting: the #NMSettingIPConfig + * @dns: the IP address of the DNS server to add + * + * Adds a new DNS server to the setting. + * + * Returns: %TRUE if the DNS server was added; %FALSE if the server was already + * known + **/ +gboolean +nm_setting_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns) +{ + NMSettingIPConfigPrivate *priv; + char * dns_canonical; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(dns != NULL, FALSE); + g_return_val_if_fail(nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns), + FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + dns_canonical = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns, FALSE); + for (i = 0; i < priv->dns->len; i++) { + if (!strcmp(dns_canonical, priv->dns->pdata[i])) { + g_free(dns_canonical); + return FALSE; + } + } + + g_ptr_array_add(priv->dns, dns_canonical); + _notify(setting, PROP_DNS); + return TRUE; +} + +/** + * nm_setting_ip_config_remove_dns: + * @setting: the #NMSettingIPConfig + * @idx: index number of the DNS server to remove + * + * Removes the DNS server at index @idx. + **/ +void +nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_if_fail(idx >= 0 && idx < priv->dns->len); + + g_ptr_array_remove_index(priv->dns, idx); + _notify(setting, PROP_DNS); +} + +/** + * nm_setting_ip_config_remove_dns_by_value: + * @setting: the #NMSettingIPConfig + * @dns: the DNS server to remove + * + * Removes the DNS server @dns. + * + * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char *dns) +{ + NMSettingIPConfigPrivate *priv; + char * dns_canonical; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(dns != NULL, FALSE); + g_return_val_if_fail(nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns), + FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + dns_canonical = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns, FALSE); + for (i = 0; i < priv->dns->len; i++) { + if (!strcmp(dns_canonical, priv->dns->pdata[i])) { + g_ptr_array_remove_index(priv->dns, i); + _notify(setting, PROP_DNS); + g_free(dns_canonical); + return TRUE; + } + } + g_free(dns_canonical); + return FALSE; +} + +/** + * nm_setting_ip_config_clear_dns: + * @setting: the #NMSettingIPConfig + * + * Removes all configured DNS servers. + **/ +void +nm_setting_ip_config_clear_dns(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + if (priv->dns->len != 0) { + g_ptr_array_set_size(priv->dns, 0); + _notify(setting, PROP_DNS); + } +} + +/** + * nm_setting_ip_config_get_num_dns_searches: + * @setting: the #NMSettingIPConfig + * + * Returns: the number of configured DNS search domains + **/ +guint +nm_setting_ip_config_get_num_dns_searches(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_search->len; +} + +/** + * nm_setting_ip_config_get_dns_search: + * @setting: the #NMSettingIPConfig + * @idx: index number of the DNS search domain to return + * + * Returns: the DNS search domain at index @idx + **/ +const char * +nm_setting_ip_config_get_dns_search(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_val_if_fail(idx >= 0 && idx < priv->dns_search->len, NULL); + + return priv->dns_search->pdata[idx]; +} + +/** + * nm_setting_ip_config_add_dns_search: + * @setting: the #NMSettingIPConfig + * @dns_search: the search domain to add + * + * Adds a new DNS search domain to the setting. + * + * Returns: %TRUE if the DNS search domain was added; %FALSE if the search + * domain was already known + **/ +gboolean +nm_setting_ip_config_add_dns_search(NMSettingIPConfig *setting, const char *dns_search) +{ + NMSettingIPConfigPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(dns_search != NULL, FALSE); + g_return_val_if_fail(dns_search[0] != '\0', FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + for (i = 0; i < priv->dns_search->len; i++) { + if (!strcmp(dns_search, priv->dns_search->pdata[i])) + return FALSE; + } + + g_ptr_array_add(priv->dns_search, g_strdup(dns_search)); + _notify(setting, PROP_DNS_SEARCH); + return TRUE; +} + +/** + * nm_setting_ip_config_remove_dns_search: + * @setting: the #NMSettingIPConfig + * @idx: index number of the DNS search domain + * + * Removes the DNS search domain at index @idx. + **/ +void +nm_setting_ip_config_remove_dns_search(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_if_fail(idx >= 0 && idx < priv->dns_search->len); + + g_ptr_array_remove_index(priv->dns_search, idx); + _notify(setting, PROP_DNS_SEARCH); +} + +/** + * nm_setting_ip_config_remove_dns_search_by_value: + * @setting: the #NMSettingIPConfig + * @dns_search: the search domain to remove + * + * Removes the DNS search domain @dns_search. + * + * Returns: %TRUE if the DNS search domain was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_ip_config_remove_dns_search_by_value(NMSettingIPConfig *setting, const char *dns_search) +{ + NMSettingIPConfigPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(dns_search != NULL, FALSE); + g_return_val_if_fail(dns_search[0] != '\0', FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + for (i = 0; i < priv->dns_search->len; i++) { + if (!strcmp(dns_search, priv->dns_search->pdata[i])) { + g_ptr_array_remove_index(priv->dns_search, i); + _notify(setting, PROP_DNS_SEARCH); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_ip_config_clear_dns_searches: + * @setting: the #NMSettingIPConfig + * + * Removes all configured DNS search domains. + **/ +void +nm_setting_ip_config_clear_dns_searches(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + if (priv->dns_search->len != 0) { + g_ptr_array_set_size(priv->dns_search, 0); + _notify(setting, PROP_DNS_SEARCH); + } +} + +/** + * nm_setting_ip_config_get_num_dns_options: + * @setting: the #NMSettingIPConfig + * + * Returns: the number of configured DNS options + * + * Since: 1.2 + **/ +guint +nm_setting_ip_config_get_num_dns_options(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + return priv->dns_options ? priv->dns_options->len : 0; +} + +/** + * nm_setting_ip_config_has_dns_options: + * @setting: the #NMSettingIPConfig + * + * NMSettingIPConfig can have a list of dns-options. If the list + * is empty, there are two similar (but differentiated) states. + * Either the options are explicitly set to have no values, + * or the options are left undefined. The latter means to use + * a default configuration, while the former explicitly means "no-options". + * + * Returns: whether DNS options are initialized or left unset (the default). + **/ +gboolean +nm_setting_ip_config_has_dns_options(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return !!NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_options; +} + +/** + * nm_setting_ip_config_get_dns_option: + * @setting: the #NMSettingIPConfig + * @idx: index number of the DNS option + * + * Returns: the DNS option at index @idx + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_config_get_dns_option(NMSettingIPConfig *setting, guint idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_val_if_fail(priv->dns_options, NULL); + g_return_val_if_fail(idx < priv->dns_options->len, NULL); + + return priv->dns_options->pdata[idx]; +} + +/** + * nm_setting_ip_config_next_valid_dns_option: + * @setting: the #NMSettingIPConfig + * @idx: index to start the search from + * + * Returns: the index, greater or equal than @idx, of the first valid + * DNS option, or -1 if no valid option is found + **/ +int +nm_setting_ip_config_next_valid_dns_option(NMSettingIPConfig *setting, guint idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), -1); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + if (!priv->dns_options) + return -1; + + for (; idx < priv->dns_options->len; idx++) { + if (_nm_utils_dns_option_validate(priv->dns_options->pdata[idx], + NULL, + NULL, + NM_IS_SETTING_IP6_CONFIG(setting), + _nm_utils_dns_option_descs)) + return idx; + } + + return -1; +} + +/** + * nm_setting_ip_config_add_dns_option: + * @setting: the #NMSettingIPConfig + * @dns_option: the DNS option to add + * + * Adds a new DNS option to the setting. + * + * Returns: %TRUE if the DNS option was added; %FALSE otherwise + * + * Since: 1.2 + **/ +gboolean +nm_setting_ip_config_add_dns_option(NMSettingIPConfig *setting, const char *dns_option) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(dns_option != NULL, FALSE); + g_return_val_if_fail(dns_option[0] != '\0', FALSE); + + if (!_nm_utils_dns_option_validate(dns_option, NULL, NULL, FALSE, NULL)) + return FALSE; + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + if (!priv->dns_options) + priv->dns_options = g_ptr_array_new_with_free_func(g_free); + else { + if (_nm_utils_dns_option_find_idx(priv->dns_options, dns_option) >= 0) + return FALSE; + } + + g_ptr_array_add(priv->dns_options, g_strdup(dns_option)); + _notify(setting, PROP_DNS_OPTIONS); + return TRUE; +} + +/** + * nm_setting_ip_config_remove_dns_option: + * @setting: the #NMSettingIPConfig + * @idx: index number of the DNS option + * + * Removes the DNS option at index @idx. + * + * Since: 1.2 + **/ +void +nm_setting_ip_config_remove_dns_option(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_if_fail(priv->dns_options); + g_return_if_fail(idx >= 0 && idx < priv->dns_options->len); + + g_ptr_array_remove_index(priv->dns_options, idx); + _notify(setting, PROP_DNS_OPTIONS); +} + +/** + * nm_setting_ip_config_remove_dns_option_by_value: + * @setting: the #NMSettingIPConfig + * @dns_option: the DNS option to remove + * + * Removes the DNS option @dns_option. + * + * Returns: %TRUE if the DNS option was found and removed; %FALSE if it was not. + * + * Since: 1.2 + **/ +gboolean +nm_setting_ip_config_remove_dns_option_by_value(NMSettingIPConfig *setting, const char *dns_option) +{ + NMSettingIPConfigPrivate *priv; + gssize i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(dns_option != NULL, FALSE); + g_return_val_if_fail(dns_option[0] != '\0', FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + if (!priv->dns_options) + return FALSE; + + i = _nm_utils_dns_option_find_idx(priv->dns_options, dns_option); + if (i >= 0) { + g_ptr_array_remove_index(priv->dns_options, i); + _notify(setting, PROP_DNS_OPTIONS); + return TRUE; + } + + return FALSE; +} + +/** + * nm_setting_ip_config_clear_dns_options: + * @setting: the #NMSettingIPConfig + * @is_set: the dns-options can be either empty or unset (default). + * Specify how to clear the options. + * + * Removes all configured DNS options. + * + * Since: 1.2 + **/ +void +nm_setting_ip_config_clear_dns_options(NMSettingIPConfig *setting, gboolean is_set) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + if (!priv->dns_options) { + if (!is_set) + return; + priv->dns_options = g_ptr_array_new_with_free_func(g_free); + } else { + if (!is_set) { + g_ptr_array_unref(priv->dns_options); + priv->dns_options = NULL; + } else { + if (priv->dns_options->len == 0) + return; + g_ptr_array_set_size(priv->dns_options, 0); + } + } + _notify(setting, PROP_DNS_OPTIONS); +} + +/** + * nm_setting_ip_config_get_dns_priority: + * @setting: the #NMSettingIPConfig + * + * Returns: the priority of DNS servers + * + * Since: 1.4 + **/ +int +nm_setting_ip_config_get_dns_priority(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_priority; +} + +/** + * nm_setting_ip_config_get_num_addresses: + * @setting: the #NMSettingIPConfig + * + * Returns: the number of configured addresses + **/ +guint +nm_setting_ip_config_get_num_addresses(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->addresses->len; +} + +/** + * nm_setting_ip_config_get_address: + * @setting: the #NMSettingIPConfig + * @idx: index number of the address to return + * + * Returns: (transfer none): the address at index @idx + **/ +NMIPAddress * +nm_setting_ip_config_get_address(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_val_if_fail(idx >= 0 && idx < priv->addresses->len, NULL); + + return priv->addresses->pdata[idx]; +} + +/** + * nm_setting_ip_config_add_address: + * @setting: the #NMSettingIPConfig + * @address: the new address to add + * + * Adds a new IP address and associated information to the setting. The + * given address is duplicated internally and is not changed by this function. + * + * Returns: %TRUE if the address was added; %FALSE if the address was already + * known. + **/ +gboolean +nm_setting_ip_config_add_address(NMSettingIPConfig *setting, NMIPAddress *address) +{ + NMSettingIPConfigPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(address != NULL, FALSE); + g_return_val_if_fail(address->family == NM_SETTING_IP_CONFIG_GET_FAMILY(setting), FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + for (i = 0; i < priv->addresses->len; i++) { + if (nm_ip_address_equal(priv->addresses->pdata[i], address)) + return FALSE; + } + + g_ptr_array_add(priv->addresses, nm_ip_address_dup(address)); + + _notify(setting, PROP_ADDRESSES); + return TRUE; +} + +/** + * nm_setting_ip_config_remove_address: + * @setting: the #NMSettingIPConfig + * @idx: index number of the address to remove + * + * Removes the address at index @idx. + **/ +void +nm_setting_ip_config_remove_address(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_if_fail(idx >= 0 && idx < priv->addresses->len); + + g_ptr_array_remove_index(priv->addresses, idx); + + _notify(setting, PROP_ADDRESSES); +} + +/** + * nm_setting_ip_config_remove_address_by_value: + * @setting: the #NMSettingIPConfig + * @address: the IP address to remove + * + * Removes the address @address. + * + * Returns: %TRUE if the address was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_ip_config_remove_address_by_value(NMSettingIPConfig *setting, NMIPAddress *address) +{ + NMSettingIPConfigPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(address != NULL, FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + for (i = 0; i < priv->addresses->len; i++) { + if (nm_ip_address_equal(priv->addresses->pdata[i], address)) { + g_ptr_array_remove_index(priv->addresses, i); + _notify(setting, PROP_ADDRESSES); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_ip_config_clear_addresses: + * @setting: the #NMSettingIPConfig + * + * Removes all configured addresses. + **/ +void +nm_setting_ip_config_clear_addresses(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + if (priv->addresses->len != 0) { + g_ptr_array_set_size(priv->addresses, 0); + _notify(setting, PROP_ADDRESSES); + } +} + +/** + * nm_setting_ip_config_get_gateway: + * @setting: the #NMSettingIPConfig + * + * Returns: the IP address of the gateway associated with this configuration, or + * %NULL. + **/ +const char * +nm_setting_ip_config_get_gateway(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->gateway; +} + +/** + * nm_setting_ip_config_get_num_routes: + * @setting: the #NMSettingIPConfig + * + * Returns: the number of configured routes + **/ +guint +nm_setting_ip_config_get_num_routes(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->routes->len; +} + +/** + * nm_setting_ip_config_get_route: + * @setting: the #NMSettingIPConfig + * @idx: index number of the route to return + * + * Returns: (transfer none): the route at index @idx + **/ +NMIPRoute * +nm_setting_ip_config_get_route(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_val_if_fail(idx >= 0 && idx < priv->routes->len, NULL); + + return priv->routes->pdata[idx]; +} + +/** + * nm_setting_ip_config_add_route: + * @setting: the #NMSettingIPConfig + * @route: the route to add + * + * Appends a new route and associated information to the setting. The + * given route is duplicated internally and is not changed by this function. + * If an identical route (considering attributes as well) already exists, the + * route is not added and the function returns %FALSE. + * + * Note that before 1.10, this function would not consider route attributes + * and not add a route that has an existing route with same dest/prefix,next_hop,metric + * parameters. + * + * Returns: %TRUE if the route was added; %FALSE if the route was already known. + **/ +gboolean +nm_setting_ip_config_add_route(NMSettingIPConfig *setting, NMIPRoute *route) +{ + NMSettingIPConfigPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(route != NULL, FALSE); + g_return_val_if_fail(route->family == NM_SETTING_IP_CONFIG_GET_FAMILY(setting), FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + for (i = 0; i < priv->routes->len; i++) { + if (nm_ip_route_equal_full(priv->routes->pdata[i], + route, + NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) + return FALSE; + } + + g_ptr_array_add(priv->routes, nm_ip_route_dup(route)); + _notify(setting, PROP_ROUTES); + return TRUE; +} + +/** + * nm_setting_ip_config_remove_route: + * @setting: the #NMSettingIPConfig + * @idx: index number of the route + * + * Removes the route at index @idx. + **/ +void +nm_setting_ip_config_remove_route(NMSettingIPConfig *setting, int idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_if_fail(idx >= 0 && idx < priv->routes->len); + + g_ptr_array_remove_index(priv->routes, idx); + _notify(setting, PROP_ROUTES); +} + +/** + * nm_setting_ip_config_remove_route_by_value: + * @setting: the #NMSettingIPConfig + * @route: the route to remove + * + * Removes the first matching route that matches @route. + * Note that before 1.10, this function would only compare dest/prefix,next_hop,metric + * and ignore route attributes. Now, @route must match exactly. + * + * Returns: %TRUE if the route was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_ip_config_remove_route_by_value(NMSettingIPConfig *setting, NMIPRoute *route) +{ + NMSettingIPConfigPrivate *priv; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(route != NULL, FALSE); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + for (i = 0; i < priv->routes->len; i++) { + if (nm_ip_route_equal_full(priv->routes->pdata[i], + route, + NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) { + g_ptr_array_remove_index(priv->routes, i); + _notify(setting, PROP_ROUTES); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_ip_config_clear_routes: + * @setting: the #NMSettingIPConfig + * + * Removes all configured routes. + **/ +void +nm_setting_ip_config_clear_routes(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + if (priv->routes->len != 0) { + g_ptr_array_set_size(priv->routes, 0); + _notify(setting, PROP_ROUTES); + } +} + +/** + * nm_setting_ip_config_get_route_metric: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:route-metric + * property. + * + * Returns: the route metric that is used for routes that don't explicitly + * specify a metric. See #NMSettingIPConfig:route-metric for more details. + **/ +gint64 +nm_setting_ip_config_get_route_metric(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), -1); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->route_metric; +} + +/** + * nm_setting_ip_config_get_route_table: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:route-table + * property. + * + * Returns: the configured route-table. + * + * Since: 1.10 + **/ +guint32 +nm_setting_ip_config_get_route_table(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->route_table; +} + +/*****************************************************************************/ + +static void +_routing_rules_notify(NMSettingIPConfig *setting) +{ + _nm_setting_emit_property_changed(NM_SETTING(setting)); +} + +/** + * nm_setting_ip_config_get_num_routing_rules: + * @setting: the #NMSettingIPConfig + * + * Returns: the number of configured routing rules + * + * Since: 1.18 + **/ +guint +nm_setting_ip_config_get_num_routing_rules(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + return priv->routing_rules ? priv->routing_rules->len : 0u; +} + +/** + * nm_setting_ip_config_get_routing_rule: + * @setting: the #NMSettingIPConfig + * @idx: index number of the routing_rule to return + * + * Returns: (transfer none): the routing rule at index @idx + * + * Since: 1.18 + **/ +NMIPRoutingRule * +nm_setting_ip_config_get_routing_rule(NMSettingIPConfig *setting, guint idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + g_return_val_if_fail(priv->routing_rules && idx < priv->routing_rules->len, NULL); + + return priv->routing_rules->pdata[idx]; +} + +/** + * nm_setting_ip_config_add_routing_rule: + * @setting: the #NMSettingIPConfig + * @routing_rule: the #NMIPRoutingRule to add. The address family + * of the added rule must be compatible with the setting. + * + * Appends a new routing-rule and associated information to the setting. The + * given routing rules gets sealed and the reference count is incremented. + * The function does not check whether an identical rule already exists + * and always appends the rule to the end of the list. + * + * Since: 1.18 + **/ +void +nm_setting_ip_config_add_routing_rule(NMSettingIPConfig *setting, NMIPRoutingRule *routing_rule) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + g_return_if_fail(NM_IS_IP_ROUTING_RULE(routing_rule, TRUE)); + g_return_if_fail(_ip_routing_rule_get_addr_family(routing_rule) + == NM_SETTING_IP_CONFIG_GET_FAMILY(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + if (!priv->routing_rules) + priv->routing_rules = + g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); + + nm_ip_routing_rule_seal(routing_rule); + g_ptr_array_add(priv->routing_rules, nm_ip_routing_rule_ref(routing_rule)); + _routing_rules_notify(setting); +} + +/** + * nm_setting_ip_config_remove_routing_rule: + * @setting: the #NMSettingIPConfig + * @idx: index number of the routing_rule + * + * Removes the routing_rule at index @idx. + * + * Since: 1.18 + **/ +void +nm_setting_ip_config_remove_routing_rule(NMSettingIPConfig *setting, guint idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_if_fail(priv->routing_rules && idx < priv->routing_rules->len); + + g_ptr_array_remove_index(priv->routing_rules, idx); + _routing_rules_notify(setting); +} + +/** + * nm_setting_ip_config_clear_routing_rules: + * @setting: the #NMSettingIPConfig + * + * Removes all configured routing rules. + * + * Since: 1.18 + **/ +void +nm_setting_ip_config_clear_routing_rules(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + if (priv->routing_rules && priv->routing_rules->len > 0) { + g_ptr_array_set_size(priv->routing_rules, 0); + _routing_rules_notify(setting); + } +} + +static GVariant * +_routing_rules_dbus_only_synth(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + NMSettingIPConfig * self = NM_SETTING_IP_CONFIG(setting); + NMSettingIPConfigPrivate *priv; + GVariantBuilder builder; + gboolean any = FALSE; + guint i; + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(self); + + if (!priv->routing_rules || priv->routing_rules->len == 0) + return NULL; + + for (i = 0; i < priv->routing_rules->len; i++) { + GVariant *variant; + + variant = nm_ip_routing_rule_to_dbus(priv->routing_rules->pdata[i]); + if (!variant) + continue; + + if (!any) { + any = TRUE; + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + } + g_variant_builder_add(&builder, "@a{sv}", variant); + } + + return any ? g_variant_builder_end(&builder) : NULL; +} + +static gboolean +_routing_rules_dbus_only_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GVariantIter iter_rules; + GVariant * rule_var; + guint i_rule; + gboolean success = FALSE; + gboolean rules_changed = FALSE; + + nm_assert(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}"))); + + g_variant_iter_init(&iter_rules, value); + + i_rule = 0; + while (g_variant_iter_next(&iter_rules, "@a{sv}", &rule_var)) { + _nm_unused gs_unref_variant GVariant *rule_var_unref = rule_var; + nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL; + gs_free_error GError *local = NULL; + + i_rule++; + + rule = + nm_ip_routing_rule_from_dbus(rule_var, + NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT), + &local); + if (!rule) { + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("rule #%u is invalid: %s"), + i_rule, + local->message); + goto out; + } + continue; + } + + nm_setting_ip_config_add_routing_rule(NM_SETTING_IP_CONFIG(setting), rule); + rules_changed = TRUE; + } + + success = TRUE; + +out: + if (rules_changed) + _routing_rules_notify(NM_SETTING_IP_CONFIG(setting)); + return success; +} + +/*****************************************************************************/ + +/** + * nm_setting_ip_config_get_ignore_auto_routes: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:ignore-auto-routes + * property. + * + * Returns: %TRUE if automatically configured (ie via DHCP) routes should be + * ignored. + **/ +gboolean +nm_setting_ip_config_get_ignore_auto_routes(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->ignore_auto_routes; +} + +/** + * nm_setting_ip_config_get_ignore_auto_dns: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:ignore-auto-dns + * property. + * + * Returns: %TRUE if automatically configured (ie via DHCP) DNS information + * should be ignored. + **/ +gboolean +nm_setting_ip_config_get_ignore_auto_dns(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->ignore_auto_dns; +} + +/** + * nm_setting_ip_config_get_dhcp_hostname: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:dhcp-hostname + * property. + * + * Returns: the configured hostname to send to the DHCP server + **/ +const char * +nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_hostname; +} + +/** + * nm_setting_ip_config_get_dhcp_send_hostname: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:dhcp-send-hostname + * property. + * + * Returns: %TRUE if NetworkManager should send the machine hostname to the + * DHCP server when requesting addresses to allow the server to automatically + * update DNS information for this machine. + **/ +gboolean +nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_send_hostname; +} + +/** + * nm_setting_ip_config_get_never_default: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:never-default + * property. + * + * Returns: %TRUE if this connection should never be the default + * connection + **/ +gboolean +nm_setting_ip_config_get_never_default(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->never_default; +} + +/** + * nm_setting_ip_config_get_may_fail: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:may-fail + * property. + * + * Returns: %TRUE if this connection doesn't require this type of IP + * addressing to complete for the connection to succeed. + **/ +gboolean +nm_setting_ip_config_get_may_fail(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->may_fail; +} + +/** + * nm_setting_ip_config_get_dad_timeout: + * @setting: the #NMSettingIPConfig + * + * Returns: the #NMSettingIPConfig:dad-timeout property. + * + * Since: 1.2 + **/ +int +nm_setting_ip_config_get_dad_timeout(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dad_timeout; +} + +/** + * nm_setting_ip_config_get_dhcp_hostname_flags: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:dhcp-hostname-flags + * property. + * + * Returns: flags for the DHCP hostname and FQDN + * + * Since: 1.22 + */ +NMDhcpHostnameFlags +nm_setting_ip_config_get_dhcp_hostname_flags(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NM_DHCP_HOSTNAME_FLAG_NONE); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_hostname_flags; +} + +/** + * nm_setting_ip_config_get_dhcp_timeout: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:dhcp-timeout + * property. + * + * Returns: the configured DHCP timeout in seconds. 0 = default for + * the particular kind of device. + * + * Since: 1.2 + **/ +int +nm_setting_ip_config_get_dhcp_timeout(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_timeout; +} + +/** + * nm_setting_ip_config_get_dhcp_iaid: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:dhcp-iaid + * property. + * + * Returns: the configured DHCP IAID (Identity Association Identifier) + * + * Since: 1.22 + **/ +const char * +nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_iaid; +} + +/** + * nm_setting_ip_config_get_dhcp_reject_servers: + * @setting: the #NMSettingIPConfig + * @out_len: (allow-none) (out): the number of returned elements + * + * Returns: (array length=out_len zero-terminated=1) (transfer none): + * A %NULL terminated array of DHCP reject servers. Even if no reject + * servers are configured, this always returns a non %NULL value. + * + * Since: 1.28 + */ +const char *const * +nm_setting_ip_config_get_dhcp_reject_servers(NMSettingIPConfig *setting, guint *out_len) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); + return nm_strvarray_get_strv(&NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_reject_servers, + out_len); +} + +/** + * nm_setting_ip_config_add_dhcp_reject_server: + * @setting: the #NMSettingIPConfig + * @server: the DHCP reject server to add + * + * Adds a new DHCP reject server to the setting. + * + * Since: 1.28 + **/ +void +nm_setting_ip_config_add_dhcp_reject_server(NMSettingIPConfig *setting, const char *server) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + g_return_if_fail(server != NULL); + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + nm_strvarray_add(nm_strvarray_ensure(&priv->dhcp_reject_servers), server); + _notify(setting, PROP_DHCP_REJECT_SERVERS); +} + +/** + * nm_setting_ip_config_remove_dhcp_reject_server: + * @setting: the #NMSettingIPConfig + * @idx: index number of the DHCP reject server + * + * Removes the DHCP reject server at index @idx. + * + * Since: 1.28 + **/ +void +nm_setting_ip_config_remove_dhcp_reject_server(NMSettingIPConfig *setting, guint idx) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + g_return_if_fail(priv->dhcp_reject_servers && idx < priv->dhcp_reject_servers->len); + + g_array_remove_index(priv->dhcp_reject_servers, idx); + _notify(setting, PROP_DHCP_REJECT_SERVERS); +} + +/** + * nm_setting_ip_config_clear_dhcp_reject_servers: + * @setting: the #NMSettingIPConfig + * + * Removes all configured DHCP reject servers. + * + * Since: 1.28 + **/ +void +nm_setting_ip_config_clear_dhcp_reject_servers(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + if (nm_g_array_len(priv->dhcp_reject_servers) != 0) { + nm_clear_pointer(&priv->dhcp_reject_servers, g_array_unref); + _notify(setting, PROP_DHCP_REJECT_SERVERS); + } +} + +static gboolean +verify_label(const char *label) +{ + const char *p; + char * iface; + + p = strchr(label, ':'); + if (!p) + return FALSE; + iface = g_strndup(label, p - label); + if (!nm_utils_ifname_valid_kernel(iface, NULL)) { + g_free(iface); + return FALSE; + } + g_free(iface); + + for (p++; *p; p++) { + if (!g_ascii_isalnum(*p) && *p != '_') + return FALSE; + } + + return TRUE; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + guint i; + + if (!priv->method) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), NM_SETTING_IP_CONFIG_METHOD); + return FALSE; + } + + if (priv->dhcp_hostname && !*priv->dhcp_hostname) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME); + return FALSE; + } + + /* Validate DNS */ + for (i = 0; i < priv->dns->len; i++) { + const char *dns = priv->dns->pdata[i]; + + if (!nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%d. DNS server address is invalid"), + (int) (i + 1)); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DNS); + return FALSE; + } + } + + /* Validate addresses */ + for (i = 0; i < priv->addresses->len; i++) { + NMIPAddress *addr = (NMIPAddress *) priv->addresses->pdata[i]; + GVariant * label; + + if (nm_ip_address_get_family(addr) != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%d. IP address is invalid"), + (int) (i + 1)); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_ADDRESSES); + return FALSE; + } + + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + if (label) { + if (!g_variant_is_of_type(label, G_VARIANT_TYPE_STRING)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%d. IP address has 'label' property with invalid type"), + (int) (i + 1)); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_ADDRESSES); + return FALSE; + } + if (!verify_label(g_variant_get_string(label, NULL))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%d. IP address has invalid label '%s'"), + (int) (i + 1), + g_variant_get_string(label, NULL)); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_ADDRESSES); + return FALSE; + } + } + } + + /* Validate gateway */ + if (priv->gateway) { + if (!priv->addresses->len) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("gateway cannot be set if there are no addresses configured")); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_GATEWAY); + return FALSE; + } + + if (!nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), priv->gateway)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("gateway is invalid")); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_GATEWAY); + return FALSE; + } + } + + /* Validate routes */ + for (i = 0; i < priv->routes->len; i++) { + gs_free_error GError *local = NULL; + NMIPRoute * route = (NMIPRoute *) priv->routes->pdata[i]; + + if (nm_ip_route_get_family(route) != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%d. route is invalid"), + (int) (i + 1)); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_ROUTES); + return FALSE; + } + + if (!_nm_ip_route_attribute_validate_all(route, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid attribute: %s"), + local->message); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_ROUTES); + return FALSE; + } + } + + if (priv->routing_rules) { + for (i = 0; i < priv->routing_rules->len; i++) { + NMIPRoutingRule *rule = priv->routing_rules->pdata[i]; + gs_free_error GError *local = NULL; + + if (_ip_routing_rule_get_addr_family(rule) + != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%u. rule has wrong address-family"), + i + 1); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_ROUTING_RULES); + return FALSE; + } + if (!nm_ip_routing_rule_validate(rule, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%u. rule is invalid: %s"), + i + 1, + local->message); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_ROUTES); + return FALSE; + } + } + } + + if (priv->dhcp_iaid && !_nm_utils_iaid_verify(priv->dhcp_iaid, NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IAID"), + priv->dhcp_iaid); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DHCP_IAID); + return FALSE; + } + + /* Validate DHCP hostname flags */ + if (priv->dhcp_hostname_flags != NM_DHCP_HOSTNAME_FLAG_NONE && !priv->dhcp_send_hostname) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the property cannot be set when '%s' is disabled"), + NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS); + return FALSE; + } + + if (!_nm_utils_validate_dhcp_hostname_flags(priv->dhcp_hostname_flags, + NM_SETTING_IP_CONFIG_GET_FAMILY(setting), + error)) { + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS); + return FALSE; + } + + /* Validate reject servers */ + if (priv->dhcp_reject_servers && priv->dhcp_reject_servers->len != 0) { + if (NM_SETTING_IP_CONFIG_GET_FAMILY(setting) != AF_INET) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the property is currently supported only for DHCPv4")); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS); + return FALSE; + } + + for (i = 0; i < priv->dhcp_reject_servers->len; i++) { + if (!nm_utils_parse_inaddr_prefix( + NM_SETTING_IP_CONFIG_GET_FAMILY(setting), + g_array_index(priv->dhcp_reject_servers, const char *, i), + NULL, + NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IP or subnet"), + g_array_index(priv->dhcp_reject_servers, const char *, i)); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS); + return FALSE; + } + } + } + + /* Normalizable errors */ + if (priv->gateway && priv->never_default) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("a gateway is incompatible with '%s'"), + NM_SETTING_IP_CONFIG_NEVER_DEFAULT); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_GATEWAY); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingIPConfigPrivate *a_priv; + NMSettingIPConfigPrivate *b_priv; + guint i; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ADDRESSES)) { + if (set_b) { + a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); + b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); + + if (a_priv->addresses->len != b_priv->addresses->len) + return FALSE; + for (i = 0; i < a_priv->addresses->len; i++) { + if (nm_ip_address_cmp_full(a_priv->addresses->pdata[i], + b_priv->addresses->pdata[i], + NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS) + != 0) + return FALSE; + } + } + return TRUE; + } + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ROUTES)) { + if (set_b) { + a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); + b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); + + if (a_priv->routes->len != b_priv->routes->len) + return FALSE; + for (i = 0; i < a_priv->routes->len; i++) { + if (!nm_ip_route_equal_full(a_priv->routes->pdata[i], + b_priv->routes->pdata[i], + NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) + return FALSE; + } + } + return TRUE; + } + + if (nm_streq(sett_info->property_infos[property_idx].name, + NM_SETTING_IP_CONFIG_ROUTING_RULES)) { + if (set_b) { + guint n; + + a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); + b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); + + n = (a_priv->routing_rules) ? a_priv->routing_rules->len : 0u; + if (n != (b_priv->routing_rules ? b_priv->routing_rules->len : 0u)) + return FALSE; + for (i = 0; i < n; i++) { + if (nm_ip_routing_rule_cmp(a_priv->routing_rules->pdata[i], + b_priv->routing_rules->pdata[i]) + != 0) + return FALSE; + } + } + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_ip_config_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +static void +duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) +{ + NMSettingIPConfigPrivate *priv_src = NM_SETTING_IP_CONFIG_GET_PRIVATE(src); + NMSettingIPConfigPrivate *priv_dst = NM_SETTING_IP_CONFIG_GET_PRIVATE(dst); + guint i; + gboolean changed = FALSE; + + NM_SETTING_CLASS(nm_setting_ip_config_parent_class) + ->duplicate_copy_properties(sett_info, src, dst); + + if (priv_dst->routing_rules && priv_dst->routing_rules->len > 0) { + changed = TRUE; + g_ptr_array_set_size(priv_dst->routing_rules, 0); + } + if (priv_src->routing_rules && priv_src->routing_rules->len > 0) { + changed = TRUE; + if (!priv_dst->routing_rules) + priv_dst->routing_rules = + g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); + for (i = 0; i < priv_src->routing_rules->len; i++) { + g_ptr_array_add(priv_dst->routing_rules, + nm_ip_routing_rule_ref(priv_src->routing_rules->pdata[i])); + } + } + if (changed) + _routing_rules_notify(NM_SETTING_IP_CONFIG(dst)); +} + +static void +enumerate_values(const NMSettInfoProperty *property_info, + NMSetting * setting, + NMSettingValueIterFn func, + gpointer user_data) +{ + if (nm_streq(property_info->name, NM_SETTING_IP_CONFIG_ROUTING_RULES)) { + NMSettingIPConfigPrivate * priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + nm_auto_unset_gvalue GValue value = G_VALUE_INIT; + GPtrArray * ptr = NULL; + guint i; + + if (priv->routing_rules && priv->routing_rules->len > 0) { + ptr = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); + for (i = 0; i < priv->routing_rules->len; i++) + g_ptr_array_add(ptr, nm_ip_routing_rule_ref(priv->routing_rules->pdata[i])); + } + g_value_init(&value, G_TYPE_PTR_ARRAY); + g_value_take_boxed(&value, ptr); + func(setting, property_info->name, &value, 0, user_data); + return; + } + + NM_SETTING_CLASS(nm_setting_ip_config_parent_class) + ->enumerate_values(property_info, setting, func, user_data); +} + +/*****************************************************************************/ + +static gboolean +ip_gateway_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + /* FIXME: properly handle errors */ + + /* Don't set from 'gateway' if we're going to use the gateway in 'addresses' */ + if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "gateway")) + return TRUE; + + g_object_set(setting, property, g_variant_get_string(value, NULL), NULL); + return TRUE; +} + +GArray * +_nm_sett_info_property_override_create_array_ip_config(void) +{ + GArray *properties_override = _nm_sett_info_property_override_create_array(); + + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_GATEWAY], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING, + .from_dbus_fcn = ip_gateway_set, )); + + /* ---dbus--- + * property: routing-rules + * format: array of 'a{sv}' + * description: Array of dictionaries for routing rules. + * ---end--- + */ + _nm_properties_override_dbus( + properties_override, + NM_SETTING_IP_CONFIG_ROUTING_RULES, + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = _routing_rules_dbus_only_synth, + .from_dbus_fcn = _routing_rules_dbus_only_set, )); + + return properties_override; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingIPConfig * setting = NM_SETTING_IP_CONFIG(object); + NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_METHOD: + g_value_set_string(value, nm_setting_ip_config_get_method(setting)); + break; + case PROP_DNS: + g_value_take_boxed(value, _nm_utils_ptrarray_to_strv(priv->dns)); + break; + case PROP_DNS_SEARCH: + g_value_take_boxed(value, _nm_utils_ptrarray_to_strv(priv->dns_search)); + break; + case PROP_DNS_OPTIONS: + g_value_take_boxed(value, + priv->dns_options ? _nm_utils_ptrarray_to_strv(priv->dns_options) + : NULL); + break; + case PROP_DNS_PRIORITY: + g_value_set_int(value, priv->dns_priority); + break; + case PROP_ADDRESSES: + g_value_take_boxed(value, + _nm_utils_copy_array(priv->addresses, + (NMUtilsCopyFunc) nm_ip_address_dup, + (GDestroyNotify) nm_ip_address_unref)); + break; + case PROP_GATEWAY: + g_value_set_string(value, nm_setting_ip_config_get_gateway(setting)); + break; + case PROP_ROUTES: + g_value_take_boxed(value, + _nm_utils_copy_array(priv->routes, + (NMUtilsCopyFunc) nm_ip_route_dup, + (GDestroyNotify) nm_ip_route_unref)); + break; + case PROP_ROUTE_METRIC: + g_value_set_int64(value, priv->route_metric); + break; + case PROP_ROUTE_TABLE: + g_value_set_uint(value, priv->route_table); + break; + case PROP_IGNORE_AUTO_ROUTES: + g_value_set_boolean(value, nm_setting_ip_config_get_ignore_auto_routes(setting)); + break; + case PROP_IGNORE_AUTO_DNS: + g_value_set_boolean(value, nm_setting_ip_config_get_ignore_auto_dns(setting)); + break; + case PROP_DHCP_HOSTNAME: + g_value_set_string(value, nm_setting_ip_config_get_dhcp_hostname(setting)); + break; + case PROP_DHCP_SEND_HOSTNAME: + g_value_set_boolean(value, nm_setting_ip_config_get_dhcp_send_hostname(setting)); + break; + case PROP_NEVER_DEFAULT: + g_value_set_boolean(value, priv->never_default); + break; + case PROP_MAY_FAIL: + g_value_set_boolean(value, priv->may_fail); + break; + case PROP_DAD_TIMEOUT: + g_value_set_int(value, nm_setting_ip_config_get_dad_timeout(setting)); + break; + case PROP_DHCP_TIMEOUT: + g_value_set_int(value, nm_setting_ip_config_get_dhcp_timeout(setting)); + break; + case PROP_DHCP_IAID: + g_value_set_string(value, nm_setting_ip_config_get_dhcp_iaid(setting)); + break; + case PROP_DHCP_HOSTNAME_FLAGS: + g_value_set_uint(value, nm_setting_ip_config_get_dhcp_hostname_flags(setting)); + break; + case PROP_DHCP_REJECT_SERVERS: + g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(priv->dhcp_reject_servers, NULL)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingIPConfig * setting = NM_SETTING_IP_CONFIG(object); + NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + const char * gateway; + char ** strv; + guint i; + + switch (prop_id) { + case PROP_METHOD: + g_free(priv->method); + priv->method = g_value_dup_string(value); + break; + case PROP_DNS: + g_ptr_array_unref(priv->dns); + priv->dns = _nm_utils_strv_to_ptrarray(g_value_get_boxed(value)); + break; + case PROP_DNS_SEARCH: + g_ptr_array_unref(priv->dns_search); + priv->dns_search = _nm_utils_strv_to_ptrarray(g_value_get_boxed(value)); + break; + case PROP_DNS_OPTIONS: + strv = g_value_get_boxed(value); + if (!strv) { + if (priv->dns_options) { + g_ptr_array_unref(priv->dns_options); + priv->dns_options = NULL; + } + } else { + if (priv->dns_options) + g_ptr_array_set_size(priv->dns_options, 0); + else + priv->dns_options = g_ptr_array_new_with_free_func(g_free); + for (i = 0; strv[i]; i++) { + if (_nm_utils_dns_option_validate(strv[i], NULL, NULL, FALSE, NULL) + && _nm_utils_dns_option_find_idx(priv->dns_options, strv[i]) < 0) + g_ptr_array_add(priv->dns_options, g_strdup(strv[i])); + } + } + break; + case PROP_DNS_PRIORITY: + priv->dns_priority = g_value_get_int(value); + break; + case PROP_ADDRESSES: + g_ptr_array_unref(priv->addresses); + priv->addresses = _nm_utils_copy_array(g_value_get_boxed(value), + (NMUtilsCopyFunc) nm_ip_address_dup, + (GDestroyNotify) nm_ip_address_unref); + break; + case PROP_GATEWAY: + gateway = g_value_get_string(value); + g_return_if_fail( + !gateway + || nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), gateway)); + g_free(priv->gateway); + priv->gateway = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), gateway, TRUE); + break; + case PROP_ROUTES: + g_ptr_array_unref(priv->routes); + priv->routes = _nm_utils_copy_array(g_value_get_boxed(value), + (NMUtilsCopyFunc) nm_ip_route_dup, + (GDestroyNotify) nm_ip_route_unref); + break; + case PROP_ROUTE_METRIC: + priv->route_metric = g_value_get_int64(value); + break; + case PROP_ROUTE_TABLE: + priv->route_table = g_value_get_uint(value); + break; + case PROP_IGNORE_AUTO_ROUTES: + priv->ignore_auto_routes = g_value_get_boolean(value); + break; + case PROP_IGNORE_AUTO_DNS: + priv->ignore_auto_dns = g_value_get_boolean(value); + break; + case PROP_DHCP_HOSTNAME: + g_free(priv->dhcp_hostname); + priv->dhcp_hostname = g_value_dup_string(value); + break; + case PROP_DHCP_SEND_HOSTNAME: + priv->dhcp_send_hostname = g_value_get_boolean(value); + break; + case PROP_NEVER_DEFAULT: + priv->never_default = g_value_get_boolean(value); + break; + case PROP_MAY_FAIL: + priv->may_fail = g_value_get_boolean(value); + break; + case PROP_DAD_TIMEOUT: + priv->dad_timeout = g_value_get_int(value); + break; + case PROP_DHCP_TIMEOUT: + priv->dhcp_timeout = g_value_get_int(value); + break; + case PROP_DHCP_IAID: + priv->dhcp_iaid = g_value_dup_string(value); + break; + case PROP_DHCP_HOSTNAME_FLAGS: + priv->dhcp_hostname_flags = g_value_get_uint(value); + break; + case PROP_DHCP_REJECT_SERVERS: + nm_strvarray_set_strv(&priv->dhcp_reject_servers, g_value_get_boxed(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ip_config_init(NMSettingIPConfig *setting) +{ + NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + priv->dns = g_ptr_array_new_with_free_func(g_free); + priv->dns_search = g_ptr_array_new_with_free_func(g_free); + priv->addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + priv->routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); + priv->route_metric = -1; + priv->dhcp_send_hostname = TRUE; + priv->may_fail = TRUE; + priv->dad_timeout = -1; +} + +static void +finalize(GObject *object) +{ + NMSettingIPConfig * self = NM_SETTING_IP_CONFIG(object); + NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(self); + + g_free(priv->method); + g_free(priv->gateway); + g_free(priv->dhcp_hostname); + g_free(priv->dhcp_iaid); + + g_ptr_array_unref(priv->dns); + g_ptr_array_unref(priv->dns_search); + if (priv->dns_options) + g_ptr_array_unref(priv->dns_options); + g_ptr_array_unref(priv->addresses); + g_ptr_array_unref(priv->routes); + if (priv->routing_rules) + g_ptr_array_unref(priv->routing_rules); + nm_clear_pointer(&priv->dhcp_reject_servers, g_array_unref); + + G_OBJECT_CLASS(nm_setting_ip_config_parent_class)->finalize(object); +} + +static void +nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingIPConfigPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->compare_property = compare_property; + setting_class->duplicate_copy_properties = duplicate_copy_properties; + setting_class->enumerate_values = enumerate_values; + + /** + * NMSettingIPConfig:method: + * + * IP configuration method. + * + * #NMSettingIP4Config and #NMSettingIP6Config both support "disabled", + * "auto", "manual", and "link-local". See the subclass-specific + * documentation for other values. + * + * In general, for the "auto" method, properties such as + * #NMSettingIPConfig:dns and #NMSettingIPConfig:routes specify information + * that is added on to the information returned from automatic + * configuration. The #NMSettingIPConfig:ignore-auto-routes and + * #NMSettingIPConfig:ignore-auto-dns properties modify this behavior. + * + * For methods that imply no upstream network, such as "shared" or + * "link-local", these properties must be empty. + * + * For IPv4 method "shared", the IP subnet can be configured by adding one + * manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the + * shared method must be configured on the interface which shares the internet + * to a subnet, not on the uplink which is shared. + **/ + obj_properties[PROP_METHOD] = g_param_spec_string( + NM_SETTING_IP_CONFIG_METHOD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dns: + * + * Array of IP addresses of DNS servers. + **/ + obj_properties[PROP_DNS] = g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dns-search: + * + * Array of DNS search domains. Domains starting with a tilde ('~') + * are considered 'routing' domains and are used only to decide the + * interface over which a query must be forwarded; they are not used + * to complete unqualified host names. + * + * When using a DNS plugin that supports Conditional Forwarding or + * Split DNS, then the search domains specify which name servers to + * query. This makes the behavior different from running with plain + * /etc/resolv.conf. For more information see also the dns-priority setting. + **/ + obj_properties[PROP_DNS_SEARCH] = + g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS_SEARCH, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dns-options: + * + * Array of DNS options as described in man 5 resolv.conf. + * + * %NULL means that the options are unset and left at the default. + * In this case NetworkManager will use default options. This is + * distinct from an empty list of properties. + * + * The currently supported options are "attempts", "debug", "edns0", + * "inet6", "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", + * "no-ip6-dotint", "no-reload", "no-tld-query", "rotate", "single-request", + * "single-request-reopen", "timeout", "trust-ad", "use-vc". + * + * The "trust-ad" setting is only honored if the profile contributes + * name servers to resolv.conf, and if all contributing profiles have + * "trust-ad" enabled. + * + * When using a caching DNS plugin (dnsmasq or systemd-resolved in + * NetworkManager.conf) then "edns0" and "trust-ad" are automatically + * added. + * + * Since: 1.2 + **/ + obj_properties[PROP_DNS_OPTIONS] = + g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS_OPTIONS, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dns-priority: + * + * DNS servers priority. + * + * The relative priority for DNS servers specified by this setting. A lower + * numerical value is better (higher priority). + * + * Negative values have the special effect of excluding other configurations + * with a greater numerical priority value; so in presence of at least one negative + * priority, only DNS servers from connections with the lowest priority value will be used. + * To avoid all DNS leaks, set the priority of the profile that should be used + * to the most negative value of all active connections profiles. + * + * Zero selects a globally configured default value. If the latter is missing + * or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for + * other connections. + * + * Note that the priority is to order DNS settings for multiple active + * connections. It does not disambiguate multiple DNS servers within the + * same connection profile. + * + * When multiple devices have configurations with the same priority, VPNs will be + * considered first, then devices with the best (lowest metric) default + * route and then all other devices. + * + * When using dns=default, servers with higher priority will be on top of + * resolv.conf. To prioritize a given server over another one within the + * same connection, just specify them in the desired order. + * Note that commonly the resolver tries name servers in /etc/resolv.conf + * in the order listed, proceeding with the next server in the list + * on failure. See for example the "rotate" option of the dns-options setting. + * If there are any negative DNS priorities, then only name servers from + * the devices with that lowest priority will be considered. + * + * When using a DNS resolver that supports Conditional Forwarding or + * Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection + * is used to query domains in its search list. The search domains determine which + * name servers to ask, and the DNS priority is used to prioritize + * name servers based on the domain. Queries for domains not present in any + * search list are routed through connections having the '~.' special wildcard + * domain, which is added automatically to connections with the default route + * (or can be added manually). When multiple connections specify the same domain, the + * one with the best priority (lowest numerical value) wins. If a sub domain + * is configured on another interface it will be accepted regardless the priority, + * unless parent domain on the other interface has a negative priority, which causes + * the sub domain to be shadowed. + * With Split DNS one can avoid undesired DNS leaks by properly configuring + * DNS priorities and the search domains, so that only name servers of the desired + * interface are configured. + * + * Since: 1.4 + **/ + obj_properties[PROP_DNS_PRIORITY] = + g_param_spec_int(NM_SETTING_IP_CONFIG_DNS_PRIORITY, + "", + "", + G_MININT32, + G_MAXINT32, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:addresses: (type GPtrArray(NMIPAddress)) + * + * Array of IP addresses. + **/ + obj_properties[PROP_ADDRESSES] = + g_param_spec_boxed(NM_SETTING_IP_CONFIG_ADDRESSES, + "", + "", + G_TYPE_PTR_ARRAY, + /* "addresses" is a legacy D-Bus property, because the + * "addresses" GObject property normally gets set from + * the "address-data" D-Bus property... + */ + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | NM_SETTING_PARAM_LEGACY + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:gateway: + * + * The gateway associated with this configuration. This is only meaningful + * if #NMSettingIPConfig:addresses is also set. + * + * The gateway's main purpose is to control the next hop of the standard default route on the device. + * Hence, the gateway property conflicts with #NMSettingIPConfig:never-default and will be + * automatically dropped if the IP configuration is set to never-default. + * + * As an alternative to set the gateway, configure a static default route with /0 as prefix + * length. + **/ + obj_properties[PROP_GATEWAY] = g_param_spec_string( + NM_SETTING_IP_CONFIG_GATEWAY, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:routes: (type GPtrArray(NMIPRoute)) + * + * Array of IP routes. + **/ + obj_properties[PROP_ROUTES] = + g_param_spec_boxed(NM_SETTING_IP_CONFIG_ROUTES, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | + /* See :addresses above Re: LEGACY */ + NM_SETTING_PARAM_LEGACY | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:route-metric: + * + * The default metric for routes that don't explicitly specify a metric. + * The default value -1 means that the metric is chosen automatically + * based on the device type. + * The metric applies to dynamic routes, manual (static) routes that + * don't have an explicit metric setting, address prefix routes, and + * the default route. + * Note that for IPv6, the kernel accepts zero (0) but coerces it to + * 1024 (user default). Hence, setting this property to zero effectively + * mean setting it to 1024. + * For IPv4, zero is a regular value for the metric. + **/ + obj_properties[PROP_ROUTE_METRIC] = + g_param_spec_int64(NM_SETTING_IP_CONFIG_ROUTE_METRIC, + "", + "", + -1, + G_MAXUINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:route-table: + * + * Enable policy routing (source routing) and set the routing table used when adding routes. + * + * This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes + * and static routes. But note that static routes can individually overwrite the setting + * by explicitly specifying a non-zero routing table. + * + * If the table setting is left at zero, it is eligible to be overwritten via global + * configuration. If the property is zero even after applying the global configuration + * value, policy routing is disabled for the address family of this connection. + * + * Policy routing disabled means that NetworkManager will add all routes to the main + * table (except static routes that explicitly configure a different table). Additionally, + * NetworkManager will not delete any extraneous routes from tables except the main table. + * This is to preserve backward compatibility for users who manage routing tables outside + * of NetworkManager. + * + * Since: 1.10 + **/ + obj_properties[PROP_ROUTE_TABLE] = g_param_spec_uint( + NM_SETTING_IP_CONFIG_ROUTE_TABLE, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingIPConfig:ignore-auto-routes: + * + * When #NMSettingIPConfig:method is set to "auto" and this property to + * %TRUE, automatically configured routes are ignored and only routes + * specified in the #NMSettingIPConfig:routes property, if any, are used. + **/ + obj_properties[PROP_IGNORE_AUTO_ROUTES] = + g_param_spec_boolean(NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:ignore-auto-dns: + * + * When #NMSettingIPConfig:method is set to "auto" and this property to + * %TRUE, automatically configured name servers and search domains are + * ignored and only name servers and search domains specified in the + * #NMSettingIPConfig:dns and #NMSettingIPConfig:dns-search properties, if + * any, are used. + **/ + obj_properties[PROP_IGNORE_AUTO_DNS] = + g_param_spec_boolean(NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dhcp-hostname: + * + * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the + * specified name will be sent to the DHCP server when acquiring a lease. + * This property and #NMSettingIP4Config:dhcp-fqdn are mutually exclusive and + * cannot be set at the same time. + **/ + obj_properties[PROP_DHCP_HOSTNAME] = + g_param_spec_string(NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dhcp-send-hostname: + * + * If %TRUE, a hostname is sent to the DHCP server when acquiring a lease. + * Some DHCP servers use this hostname to update DNS databases, essentially + * providing a static hostname for the computer. If the + * #NMSettingIPConfig:dhcp-hostname property is %NULL and this property is + * %TRUE, the current persistent hostname of the computer is sent. + **/ + obj_properties[PROP_DHCP_SEND_HOSTNAME] = + g_param_spec_boolean(NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:never-default: + * + * If %TRUE, this connection will never be the default connection for this + * IP type, meaning it will never be assigned the default route by + * NetworkManager. + **/ + obj_properties[PROP_NEVER_DEFAULT] = + g_param_spec_boolean(NM_SETTING_IP_CONFIG_NEVER_DEFAULT, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:may-fail: + * + * If %TRUE, allow overall network configuration to proceed even if the + * configuration specified by this property times out. Note that at least + * one IP configuration must succeed or overall network configuration will + * still fail. For example, in IPv6-only networks, setting this property to + * %TRUE on the #NMSettingIP4Config allows the overall network configuration + * to succeed if IPv4 configuration fails but IPv6 configuration completes + * successfully. + **/ + obj_properties[PROP_MAY_FAIL] = + g_param_spec_boolean(NM_SETTING_IP_CONFIG_MAY_FAIL, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dad-timeout: + * + * Timeout in milliseconds used to check for the presence of duplicate IP + * addresses on the network. If an address conflict is detected, the + * activation will fail. A zero value means that no duplicate address + * detection is performed, -1 means the default value (either configuration + * ipvx.dad-timeout override or zero). A value greater than zero is a + * timeout in milliseconds. + * + * The property is currently implemented only for IPv4. + * + * Since: 1.2 + **/ + obj_properties[PROP_DAD_TIMEOUT] = g_param_spec_int( + NM_SETTING_IP_CONFIG_DAD_TIMEOUT, + "", + "", + -1, + NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX, + -1, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dhcp-timeout: + * + * A timeout for a DHCP transaction in seconds. If zero (the default), a + * globally configured default is used. If still unspecified, a device specific + * timeout is used (usually 45 seconds). + * + * Set to 2147483647 (MAXINT32) for infinity. + **/ + obj_properties[PROP_DHCP_TIMEOUT] = g_param_spec_int( + NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, + "", + "", + 0, + G_MAXINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dhcp-iaid: + * + * A string containing the "Identity Association Identifier" (IAID) used + * by the DHCP client. The property is a 32-bit decimal value or a + * special value among "mac", "perm-mac", "ifname" and "stable". When + * set to "mac" (or "perm-mac"), the last 4 bytes of the current (or + * permanent) MAC address are used as IAID. When set to "ifname", the + * IAID is computed by hashing the interface name. The special value + * "stable" can be used to generate an IAID based on the stable-id (see + * connection.stable-id), a per-host key and the interface name. When + * the property is unset, the value from global configuration is used; + * if no global default is set then the IAID is assumed to be + * "ifname". Note that at the moment this property is ignored for IPv6 + * by dhclient, which always derives the IAID from the MAC address. + * + * Since: 1.22 + **/ + obj_properties[PROP_DHCP_IAID] = + g_param_spec_string(NM_SETTING_IP_CONFIG_DHCP_IAID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dhcp-hostname-flags: + * + * Flags for the DHCP hostname and FQDN. + * + * Currently, this property only includes flags to control the FQDN flags + * set in the DHCP FQDN option. Supported FQDN flags are + * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, + * %NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED and + * %NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE. When no FQDN flag is set and + * %NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS is set, the DHCP FQDN option will + * contain no flag. Otherwise, if no FQDN flag is set and + * %NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS is not set, the standard FQDN flags + * are set in the request: + * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, + * %NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED for IPv4 and + * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE for IPv6. + * + * When this property is set to the default value %NM_DHCP_HOSTNAME_FLAG_NONE, + * a global default is looked up in NetworkManager configuration. If that value + * is unset or also %NM_DHCP_HOSTNAME_FLAG_NONE, then the standard FQDN flags + * described above are sent in the DHCP requests. + * + * Since: 1.22 + */ + obj_properties[PROP_DHCP_HOSTNAME_FLAGS] = + g_param_spec_uint(NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, + "", + "", + 0, + G_MAXUINT32, + NM_DHCP_HOSTNAME_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPConfig:dhcp-reject-servers: + * + * Array of servers from which DHCP offers must be rejected. This property + * is useful to avoid getting a lease from misconfigured or rogue servers. + * + * For DHCPv4, each element must be an IPv4 address, optionally + * followed by a slash and a prefix length (e.g. "192.168.122.0/24"). + * + * This property is currently not implemented for DHCPv6. + * + * Since: 1.28 + **/ + obj_properties[PROP_DHCP_REJECT_SERVERS] = + g_param_spec_boxed(NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} diff --git a/src/libnm-core-impl/nm-setting-ip-tunnel.c b/src/libnm-core-impl/nm-setting-ip-tunnel.c new file mode 100644 index 0000000000..5cdcdc81b1 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ip-tunnel.c @@ -0,0 +1,867 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ip-tunnel.h" + +#include "nm-setting-private.h" +#include "nm-utils.h" + +/** + * SECTION:nm-setting-ip-tunnel + * @short_description: Describes connection properties for IP tunnel devices + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, + PROP_MODE, + PROP_LOCAL, + PROP_REMOTE, + PROP_TTL, + PROP_TOS, + PROP_PATH_MTU_DISCOVERY, + PROP_INPUT_KEY, + PROP_OUTPUT_KEY, + PROP_ENCAPSULATION_LIMIT, + PROP_FLOW_LABEL, + PROP_MTU, + PROP_FLAGS, ); + +typedef struct { + char * parent; + char * local; + char * remote; + char * input_key; + char * output_key; + guint ttl; + guint tos; + guint encapsulation_limit; + guint flow_label; + NMIPTunnelMode mode; + guint32 mtu; + guint32 flags; + bool path_mtu_discovery : 1; +} NMSettingIPTunnelPrivate; + +G_DEFINE_TYPE(NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING) + +#define NM_SETTING_IP_TUNNEL_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_ip_tunnel_get_parent: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:parent property of the setting + * + * Returns: the parent device + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_parent(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->parent; +} + +/** + * nm_setting_ip_tunnel_get_mode: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:mode property of the setting. + * + * Returns: the tunnel mode + * + * Since: 1.2 + **/ +NMIPTunnelMode +nm_setting_ip_tunnel_get_mode(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->mode; +} + +/** + * nm_setting_ip_tunnel_get_local: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:local property of the setting. + * + * Returns: the local endpoint + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_local(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->local; +} + +/** + * nm_setting_ip_tunnel_get_remote: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:remote property of the setting. + * + * Returns: the remote endpoint + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_remote(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->remote; +} + +/** + * nm_setting_ip_tunnel_get_ttl: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:ttl property of the setting. + * + * Returns: the Time-to-live value + * + * Since: 1.2 + **/ + +guint +nm_setting_ip_tunnel_get_ttl(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->ttl; +} + +/** + * nm_setting_ip_tunnel_get_tos: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:tos property of the setting. + * + * Returns: the TOS value + * + * Since: 1.2 + **/ +guint +nm_setting_ip_tunnel_get_tos(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->tos; +} + +/** + * nm_setting_ip_tunnel_get_path_mtu_discovery: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:path-mtu-discovery property of the setting. + * + * Returns: whether path MTU discovery is enabled + * + * Since: 1.2 + **/ +gboolean +nm_setting_ip_tunnel_get_path_mtu_discovery(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), TRUE); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->path_mtu_discovery; +} + +/** + * nm_setting_ip_tunnel_get_input_key: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:input-key property of the setting. + * + * Returns: the input key + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_input_key(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->input_key; +} + +/** + * nm_setting_ip_tunnel_get_output_key: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:output-key property of the setting. + * + * Returns: the output key + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_output_key(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NULL); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->output_key; +} + +/** + * nm_setting_ip_tunnel_get_encapsulation_limit: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:encapsulation-limit property of the setting. + * + * Returns: the encapsulation limit value + * + * Since: 1.2 + **/ +guint +nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->encapsulation_limit; +} + +/** + * nm_setting_ip_tunnel_get_flow_label: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:flow-label property of the setting. + * + * Returns: the flow label value + * + * Since: 1.2 + **/ +guint +nm_setting_ip_tunnel_get_flow_label(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->flow_label; +} + +/** + * nm_setting_ip_tunnel_get_mtu: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:mtu property of the setting. + * + * Returns: the MTU + * + * Since: 1.2 + **/ +guint +nm_setting_ip_tunnel_get_mtu(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->mtu; +} + +/* + * nm_setting_ip_tunnel_get_flags: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:flags property of the setting. + * + * Returns: the tunnel flags + * + * Since: 1.12 + **/ +NMIPTunnelFlags +nm_setting_ip_tunnel_get_flags(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), NM_IP_TUNNEL_FLAG_NONE); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->flags; +} + +/*****************************************************************************/ + +gboolean +_nm_ip_tunnel_mode_is_layer2(NMIPTunnelMode mode) +{ + return NM_IN_SET(mode, NM_IP_TUNNEL_MODE_GRETAP, NM_IP_TUNNEL_MODE_IP6GRETAP); +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting); + int family = AF_UNSPEC; + guint32 flags; + + switch (priv->mode) { + case NM_IP_TUNNEL_MODE_IPIP: + case NM_IP_TUNNEL_MODE_SIT: + case NM_IP_TUNNEL_MODE_ISATAP: + case NM_IP_TUNNEL_MODE_GRE: + case NM_IP_TUNNEL_MODE_VTI: + case NM_IP_TUNNEL_MODE_GRETAP: + family = AF_INET; + break; + case NM_IP_TUNNEL_MODE_IP6IP6: + case NM_IP_TUNNEL_MODE_IPIP6: + case NM_IP_TUNNEL_MODE_IP6GRE: + case NM_IP_TUNNEL_MODE_VTI6: + case NM_IP_TUNNEL_MODE_IP6GRETAP: + family = AF_INET6; + break; + case NM_IP_TUNNEL_MODE_UNKNOWN: + break; + } + + if (family == AF_UNSPEC) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%d' is not a valid tunnel mode"), + (int) priv->mode); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_MODE); + return FALSE; + } + + if (priv->parent && !nm_utils_ifname_valid_kernel(priv->parent, NULL) + && !nm_utils_is_uuid(priv->parent)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_PARENT); + return FALSE; + } + + if (priv->local && !nm_utils_ipaddr_is_valid(family, priv->local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IPv%c address"), + priv->local, + family == AF_INET ? '4' : '6'); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_LOCAL); + return FALSE; + } + + if (!priv->remote) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_REMOTE); + return FALSE; + } + + if (!nm_utils_ipaddr_is_valid(family, priv->remote)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IPv%c address"), + priv->remote, + family == AF_INET ? '4' : '6'); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_REMOTE); + return FALSE; + } + + if ((priv->input_key && priv->input_key[0]) || (priv->output_key && priv->output_key[0])) { + if (!NM_IN_SET(priv->mode, + NM_IP_TUNNEL_MODE_GRE, + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRE, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("tunnel keys can only be specified for GRE tunnels")); + return FALSE; + } + } + + if (priv->input_key && priv->input_key[0]) { + gint64 val; + + val = _nm_utils_ascii_str_to_int64(priv->input_key, 10, 0, G_MAXUINT32, -1); + if (val == -1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid tunnel key"), + priv->input_key); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_INPUT_KEY); + return FALSE; + } + } + + if (priv->output_key && priv->output_key[0]) { + gint64 val; + + val = _nm_utils_ascii_str_to_int64(priv->output_key, 10, 0, G_MAXUINT32, -1); + if (val == -1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid tunnel key"), + priv->output_key); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_OUTPUT_KEY); + return FALSE; + } + } + + if (!priv->path_mtu_discovery && priv->ttl != 0) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("a fixed TTL is allowed only when path MTU discovery is enabled")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_TTL); + return FALSE; + } + + flags = priv->flags; + if (NM_IN_SET(priv->mode, NM_IP_TUNNEL_MODE_IPIP6, NM_IP_TUNNEL_MODE_IP6IP6)) + flags &= (guint32)(~_NM_IP_TUNNEL_FLAG_ALL_IP6TNL); + if (flags) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("some flags are invalid for the select mode: %s"), + nm_utils_enum_to_str(nm_ip_tunnel_flags_get_type(), flags)); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_FLAGS); + return FALSE; + } + + if (nm_connection_get_setting_wired(connection) && !_nm_ip_tunnel_mode_is_layer2(priv->mode)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("wired setting not allowed for mode %s"), + nm_utils_enum_to_str(nm_ip_tunnel_mode_get_type(), priv->mode)); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_MODE); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingIPTunnel * setting = NM_SETTING_IP_TUNNEL(object); + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string(value, priv->parent); + break; + case PROP_MODE: + g_value_set_uint(value, priv->mode); + break; + case PROP_LOCAL: + g_value_set_string(value, priv->local); + break; + case PROP_REMOTE: + g_value_set_string(value, priv->remote); + break; + case PROP_TTL: + g_value_set_uint(value, priv->ttl); + break; + case PROP_TOS: + g_value_set_uint(value, priv->tos); + break; + case PROP_PATH_MTU_DISCOVERY: + g_value_set_boolean(value, priv->path_mtu_discovery); + break; + case PROP_INPUT_KEY: + g_value_set_string(value, priv->input_key); + break; + case PROP_OUTPUT_KEY: + g_value_set_string(value, priv->output_key); + break; + case PROP_ENCAPSULATION_LIMIT: + g_value_set_uint(value, priv->encapsulation_limit); + break; + case PROP_FLOW_LABEL: + g_value_set_uint(value, priv->flow_label); + break; + case PROP_MTU: + g_value_set_uint(value, priv->mtu); + break; + case PROP_FLAGS: + g_value_set_uint(value, priv->flags); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingIPTunnel * setting = NM_SETTING_IP_TUNNEL(object); + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_free(priv->parent); + priv->parent = g_value_dup_string(value); + break; + case PROP_MODE: + priv->mode = g_value_get_uint(value); + break; + case PROP_LOCAL: + g_free(priv->local); + priv->local = g_value_dup_string(value); + break; + case PROP_REMOTE: + g_free(priv->remote); + priv->remote = g_value_dup_string(value); + break; + case PROP_TTL: + priv->ttl = g_value_get_uint(value); + break; + case PROP_TOS: + priv->tos = g_value_get_uint(value); + break; + case PROP_PATH_MTU_DISCOVERY: + priv->path_mtu_discovery = g_value_get_boolean(value); + break; + case PROP_INPUT_KEY: + g_free(priv->input_key); + priv->input_key = g_value_dup_string(value); + break; + case PROP_OUTPUT_KEY: + g_free(priv->output_key); + priv->output_key = g_value_dup_string(value); + break; + case PROP_ENCAPSULATION_LIMIT: + priv->encapsulation_limit = g_value_get_uint(value); + break; + case PROP_FLOW_LABEL: + priv->flow_label = g_value_get_uint(value); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint(value); + break; + case PROP_FLAGS: + priv->flags = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ip_tunnel_init(NMSettingIPTunnel *self) +{ + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(self); + + priv->path_mtu_discovery = TRUE; +} + +/** + * nm_setting_ip_tunnel_new: + * + * Creates a new #NMSettingIPTunnel object with default values. + * + * Returns: (transfer full): the new empty #NMSettingIPTunnel object + * + * Since: 1.2 + **/ +NMSetting * +nm_setting_ip_tunnel_new(void) +{ + return g_object_new(NM_TYPE_SETTING_IP_TUNNEL, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingIPTunnel * setting = NM_SETTING_IP_TUNNEL(object); + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting); + + g_free(priv->parent); + g_free(priv->local); + g_free(priv->remote); + g_free(priv->input_key); + g_free(priv->output_key); + + G_OBJECT_CLASS(nm_setting_ip_tunnel_parent_class)->finalize(object); +} + +static void +nm_setting_ip_tunnel_class_init(NMSettingIPTunnelClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingIPTunnelPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingIPTunnel:parent: + * + * If given, specifies the parent interface name or parent connection UUID + * the new device will be bound to so that tunneled packets will only be + * routed via that interface. + * + * Since: 1.2 + **/ + obj_properties[PROP_PARENT] = g_param_spec_string( + NM_SETTING_IP_TUNNEL_PARENT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:mode: + * + * The tunneling mode, for example %NM_IP_TUNNEL_MODE_IPIP or + * %NM_IP_TUNNEL_MODE_GRE. + * + * Since: 1.2 + **/ + obj_properties[PROP_MODE] = + g_param_spec_uint(NM_SETTING_IP_TUNNEL_MODE, + "", + "", + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:local: + * + * The local endpoint of the tunnel; the value can be empty, otherwise it + * must contain an IPv4 or IPv6 address. + * + * Since: 1.2 + **/ + obj_properties[PROP_LOCAL] = g_param_spec_string(NM_SETTING_IP_TUNNEL_LOCAL, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:remote: + * + * The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 + * address. + * + * Since: 1.2 + **/ + obj_properties[PROP_REMOTE] = g_param_spec_string( + NM_SETTING_IP_TUNNEL_REMOTE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:ttl + * + * The TTL to assign to tunneled packets. 0 is a special value meaning that + * packets inherit the TTL value. + * + * Since: 1.2 + **/ + obj_properties[PROP_TTL] = + g_param_spec_uint(NM_SETTING_IP_TUNNEL_TTL, + "", + "", + 0, + 255, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:tos + * + * The type of service (IPv4) or traffic class (IPv6) field to be set on + * tunneled packets. + * + * Since: 1.2 + **/ + obj_properties[PROP_TOS] = + g_param_spec_uint(NM_SETTING_IP_TUNNEL_TOS, + "", + "", + 0, + 255, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:path-mtu-discovery + * + * Whether to enable Path MTU Discovery on this tunnel. + * + * Since: 1.2 + **/ + obj_properties[PROP_PATH_MTU_DISCOVERY] = g_param_spec_boolean( + NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, + "", + "", + TRUE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:input-key: + * + * The key used for tunnel input packets; the property is valid only for + * certain tunnel modes (GRE, IP6GRE). If empty, no key is used. + * + * Since: 1.2 + **/ + obj_properties[PROP_INPUT_KEY] = g_param_spec_string( + NM_SETTING_IP_TUNNEL_INPUT_KEY, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:output-key: + * + * The key used for tunnel output packets; the property is valid only for + * certain tunnel modes (GRE, IP6GRE). If empty, no key is used. + * + * Since: 1.2 + **/ + obj_properties[PROP_OUTPUT_KEY] = g_param_spec_string( + NM_SETTING_IP_TUNNEL_OUTPUT_KEY, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:encapsulation-limit: + * + * How many additional levels of encapsulation are permitted to be prepended + * to packets. This property applies only to IPv6 tunnels. + * + * Since: 1.2 + **/ + obj_properties[PROP_ENCAPSULATION_LIMIT] = + g_param_spec_uint(NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, + "", + "", + 0, + 255, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:flow-label: + * + * The flow label to assign to tunnel packets. This property applies only to + * IPv6 tunnels. + * + * Since: 1.2 + **/ + obj_properties[PROP_FLOW_LABEL] = + g_param_spec_uint(NM_SETTING_IP_TUNNEL_FLOW_LABEL, + "", + "", + 0, + (1 << 20) - 1, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple fragments. + * + * Since: 1.2 + **/ + obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_IP_TUNNEL_MTU, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIPTunnel:flags: + * + * Tunnel flags. Currently, the following values are supported: + * %NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT, %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS, + * %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL, %NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV, + * %NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY, %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK. + * They are valid only for IPv6 tunnels. + * + * Since: 1.12 + **/ + obj_properties[PROP_FLAGS] = g_param_spec_uint(NM_SETTING_IP_TUNNEL_FLAGS, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_IP_TUNNEL); +} diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c new file mode 100644 index 0000000000..e08bc52e19 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -0,0 +1,1033 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2014 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ip4-config.h" + +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ip4-config + * @short_description: Describes IPv4 addressing, routing, and name service properties + * + * The #NMSettingIP4Config object is a #NMSetting subclass that describes + * properties related to IPv4 addressing, routing, and Domain Name Service. + * + * #NMSettingIP4Config has few properties or methods of its own; it inherits + * almost everything from #NMSettingIPConfig. + * + * NetworkManager supports 5 values for the #NMSettingIPConfig:method property + * for IPv4. If "auto" is specified then the appropriate automatic method + * (DHCP, PPP, etc) is used for the interface and most other properties can be + * left unset. If "link-local" is specified, then a link-local address in the + * 169.254/16 range will be assigned to the interface. If "manual" is + * specified, static IP addressing is used and at least one IP address must be + * given in the "addresses" property. If "shared" is specified (indicating that + * this connection will provide network access to other computers) then the + * interface is assigned an address in the 10.42.x.1/24 range and a DHCP and + * forwarding DNS server are started, and the interface is NAT-ed to the current + * default network connection. "disabled" means IPv4 will not be used on this + * connection. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_DHCP_CLIENT_ID, + PROP_DHCP_FQDN, + PROP_DHCP_VENDOR_CLASS_IDENTIFIER, ); + +typedef struct { + char *dhcp_client_id; + char *dhcp_fqdn; + char *dhcp_vendor_class_identifier; +} NMSettingIP4ConfigPrivate; + +G_DEFINE_TYPE(NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG) + +#define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_ip4_config_get_dhcp_client_id: + * @setting: the #NMSettingIP4Config + * + * Returns the value contained in the #NMSettingIP4Config:dhcp-client-id + * property. + * + * Returns: the configured Client ID to send to the DHCP server when requesting + * addresses via DHCP. + **/ +const char * +nm_setting_ip4_config_get_dhcp_client_id(NMSettingIP4Config *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_client_id; +} + +/** + * nm_setting_ip4_config_get_dhcp_fqdn: + * @setting: the #NMSettingIP4Config + * + * Returns the value contained in the #NMSettingIP4Config:dhcp-fqdn + * property. + * + * Returns: the configured FQDN to send to the DHCP server + * + * Since: 1.2 + **/ +const char * +nm_setting_ip4_config_get_dhcp_fqdn(NMSettingIP4Config *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_fqdn; +} + +/** + * nm_setting_ip4_config_get_dhcp_vendor_class_identifier: + * @setting: the #NMSettingIP4Config + * + * Returns the value contained in the #NMSettingIP4Config:dhcp_vendor_class_identifier + * property. + * + * Returns: the vendor class identifier option to send to the DHCP server + * + * Since: 1.28 + **/ +const char * +nm_setting_ip4_config_get_dhcp_vendor_class_identifier(NMSettingIP4Config *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_vendor_class_identifier; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting); + NMSettingIPConfig * s_ip = NM_SETTING_IP_CONFIG(setting); + NMSettingVerifyResult ret; + const char * method; + + ret = NM_SETTING_CLASS(nm_setting_ip4_config_parent_class)->verify(setting, connection, error); + if (ret != NM_SETTING_VERIFY_SUCCESS) + return ret; + + method = nm_setting_ip_config_get_method(s_ip); + /* Base class already checked that it exists */ + g_assert(method); + + if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { + if (nm_setting_ip_config_get_num_addresses(s_ip) == 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("this property cannot be empty for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_ADDRESSES); + return FALSE; + } + } else if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) + || !strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) + || !strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { + if (nm_setting_ip_config_get_num_dns(s_ip) > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("this property is not allowed for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_DNS); + return FALSE; + } + + if (nm_setting_ip_config_get_num_dns_searches(s_ip) > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("this property is not allowed for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_DNS_SEARCH); + return FALSE; + } + + /* Shared allows IP addresses; link-local and disabled do not */ + if (strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) { + if (nm_setting_ip_config_get_num_addresses(s_ip) > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("this property is not allowed for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_ADDRESSES); + return FALSE; + } + } + } else if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + /* nothing to do */ + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_METHOD); + return FALSE; + } + + if (priv->dhcp_client_id && !priv->dhcp_client_id[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID); + return FALSE; + } + + if (priv->dhcp_fqdn && !*priv->dhcp_fqdn) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_DHCP_FQDN); + return FALSE; + } + + if (priv->dhcp_fqdn && !strchr(priv->dhcp_fqdn, '.')) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid FQDN"), + priv->dhcp_fqdn); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_DHCP_FQDN); + return FALSE; + } + + if (priv->dhcp_fqdn && nm_setting_ip_config_get_dhcp_hostname(s_ip)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property cannot be set when dhcp-hostname is also set")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_DHCP_FQDN); + return FALSE; + } + + if (NM_FLAGS_ANY(nm_setting_ip_config_get_dhcp_hostname_flags(s_ip), + NM_DHCP_HOSTNAME_FLAGS_FQDN_MASK) + && !priv->dhcp_fqdn) { + /* Currently, we send a FQDN option only when ipv4.dhcp-fqdn is set */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("FQDN flags requires a FQDN set")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS); + return FALSE; + } + + if (priv->dhcp_vendor_class_identifier + && !nm_utils_validate_dhcp4_vendor_class_id(priv->dhcp_vendor_class_identifier, error)) + return FALSE; + + /* Failures from here on are NORMALIZABLE_ERROR... */ + + if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) + && nm_setting_ip_config_get_num_addresses(s_ip) > 1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("multiple addresses are not allowed for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_SHARED); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_ADDRESSES); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + /* Failures from here on are NORMALIZABLE... */ + + if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) + && !nm_setting_ip_config_get_may_fail(s_ip)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property should be TRUE when method is set to disabled")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_MAY_FAIL); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + return TRUE; +} + +static GVariant * +ip4_dns_to_dbus(const GValue *prop_value) +{ + return nm_utils_ip4_dns_to_variant(g_value_get_boxed(prop_value)); +} + +static void +ip4_dns_from_dbus(GVariant *dbus_value, GValue *prop_value) +{ + g_value_take_boxed(prop_value, nm_utils_ip4_dns_from_variant(dbus_value)); +} + +static GVariant * +ip4_addresses_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *addrs = NULL; + const char * gateway; + + g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); + gateway = nm_setting_ip_config_get_gateway(NM_SETTING_IP_CONFIG(setting)); + return nm_utils_ip4_addresses_to_variant(addrs, gateway); +} + +static gboolean +ip4_addresses_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *addrs; + GVariant * s_ip4; + char ** labels, *gateway = NULL; + int i; + + /* FIXME: properly handle errors */ + + if (!_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) + return TRUE; + + addrs = nm_utils_ip4_addresses_from_variant(value, &gateway); + + s_ip4 = g_variant_lookup_value(connection_dict, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + if (g_variant_lookup(s_ip4, "address-labels", "^as", &labels)) { + for (i = 0; i < addrs->len && labels[i]; i++) + if (*labels[i]) + nm_ip_address_set_attribute(addrs->pdata[i], + NM_IP_ADDRESS_ATTRIBUTE_LABEL, + g_variant_new_string(labels[i])); + g_strfreev(labels); + } + g_variant_unref(s_ip4); + + g_object_set(setting, + NM_SETTING_IP_CONFIG_ADDRESSES, + addrs, + NM_SETTING_IP_CONFIG_GATEWAY, + gateway, + NULL); + g_ptr_array_unref(addrs); + g_free(gateway); + return TRUE; +} + +static GVariant * +ip4_address_labels_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG(setting); + gboolean have_labels = FALSE; + GPtrArray * labels; + GVariant * ret; + int num_addrs, i; + + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + return NULL; + + num_addrs = nm_setting_ip_config_get_num_addresses(s_ip); + for (i = 0; i < num_addrs; i++) { + NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i); + GVariant * label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + + if (label) { + have_labels = TRUE; + break; + } + } + if (!have_labels) + return NULL; + + labels = g_ptr_array_sized_new(num_addrs); + for (i = 0; i < num_addrs; i++) { + NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i); + GVariant * label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + + g_ptr_array_add(labels, (char *) (label ? g_variant_get_string(label, NULL) : "")); + } + + ret = g_variant_new_strv((const char *const *) labels->pdata, labels->len); + g_ptr_array_unref(labels); + + return ret; +} + +static GVariant * +ip4_address_data_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *addrs = NULL; + + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + return NULL; + + g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); + return nm_utils_ip_addresses_to_variant(addrs); +} + +static gboolean +ip4_address_data_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *addrs; + + /* FIXME: properly handle errors */ + + /* Ignore 'address-data' if we're going to process 'addresses' */ + if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) + return TRUE; + + addrs = nm_utils_ip_addresses_from_variant(value, AF_INET); + g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); + g_ptr_array_unref(addrs); + return TRUE; +} + +static GVariant * +ip4_routes_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *routes = NULL; + + g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL); + return nm_utils_ip4_routes_to_variant(routes); +} + +static gboolean +ip4_routes_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *routes; + + /* FIXME: properly handle errors */ + + if (!_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) + return TRUE; + + routes = nm_utils_ip4_routes_from_variant(value); + g_object_set(setting, property, routes, NULL); + g_ptr_array_unref(routes); + return TRUE; +} + +static GVariant * +ip4_route_data_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *routes = NULL; + + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + return NULL; + + g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL); + return nm_utils_ip_routes_to_variant(routes); +} + +static gboolean +ip4_route_data_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *routes; + + /* FIXME: properly handle errors */ + + /* Ignore 'route-data' if we're going to process 'routes' */ + if (_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) + return TRUE; + + routes = nm_utils_ip_routes_from_variant(value, AF_INET); + g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); + g_ptr_array_unref(routes); + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingIP4Config *s_ip4 = NM_SETTING_IP4_CONFIG(object); + + switch (prop_id) { + case PROP_DHCP_CLIENT_ID: + g_value_set_string(value, nm_setting_ip4_config_get_dhcp_client_id(s_ip4)); + break; + case PROP_DHCP_FQDN: + g_value_set_string(value, nm_setting_ip4_config_get_dhcp_fqdn(s_ip4)); + break; + case PROP_DHCP_VENDOR_CLASS_IDENTIFIER: + g_value_set_string(value, nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_DHCP_CLIENT_ID: + g_free(priv->dhcp_client_id); + priv->dhcp_client_id = g_value_dup_string(value); + break; + case PROP_DHCP_FQDN: + g_free(priv->dhcp_fqdn); + priv->dhcp_fqdn = g_value_dup_string(value); + break; + case PROP_DHCP_VENDOR_CLASS_IDENTIFIER: + g_free(priv->dhcp_vendor_class_identifier); + priv->dhcp_vendor_class_identifier = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ip4_config_init(NMSettingIP4Config *setting) +{} + +/** + * nm_setting_ip4_config_new: + * + * Creates a new #NMSettingIP4Config object with default values. + * + * Returns: (transfer full): the new empty #NMSettingIP4Config object + **/ +NMSetting * +nm_setting_ip4_config_new(void) +{ + return g_object_new(NM_TYPE_SETTING_IP4_CONFIG, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(object); + + g_free(priv->dhcp_client_id); + g_free(priv->dhcp_fqdn); + g_free(priv->dhcp_vendor_class_identifier); + + G_OBJECT_CLASS(nm_setting_ip4_config_parent_class)->finalize(object); +} + +static void +nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array_ip_config(); + + g_type_class_add_private(setting_class, sizeof(NMSettingIP4ConfigPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /* ---ifcfg-rh--- + * property: method + * variable: BOOTPROTO + * format: string + * values: none, dhcp (bootp), static, ibft, autoip, shared + * default: none + * description: Method used for IPv4 protocol configuration. + * ---end--- + */ + + /* ---keyfile--- + * property: dns + * format: list of DNS IP addresses + * description: List of DNS servers. + * example: dns=1.2.3.4;8.8.8.8;8.8.4.4; + * ---end--- + * ---ifcfg-rh--- + * property: dns + * variable: DNS1, DNS2, ... + * format: string + * description: List of DNS servers. Even if NetworkManager supports many DNS + * servers, initscripts and resolver only care about the first three, usually. + * example: DNS1=1.2.3.4 DNS2=10.0.0.254 DNS3=8.8.8.8 + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dns-search + * variable: DOMAIN + * format: string (space-separated domains) + * description: List of DNS search domains. + * ---end--- + */ + + /* ---keyfile--- + * property: addresses + * variable: address1, address2, ... + * format: address/plen + * description: List of static IP addresses. + * example: address1=192.168.100.100/24 address2=10.1.1.5/24 + * ---end--- + * ---ifcfg-rh--- + * property: addresses + * variable: IPADDR, PREFIX (NETMASK), IPADDR1, PREFIX1 (NETMASK1), ... + * description: List of static IP addresses. + * example: IPADDR=10.5.5.23 PREFIX=24 IPADDR1=1.1.1.2 PREFIX1=16 + * ---end--- + */ + + /* ---keyfile--- + * property: gateway + * variable: gateway + * format: string + * description: Gateway IP addresses as a string. + * example: gateway=192.168.100.1 + * ---end--- + * ---ifcfg-rh--- + * property: gateway + * variable: GATEWAY + * description: Gateway IP address. + * example: GATEWAY=10.5.5.1 + * ---end--- + */ + + /* ---keyfile--- + * property: routes + * variable: route1, route2, ... + * format: route/plen[,gateway,metric] + * description: List of IP routes. + * example: route1=8.8.8.0/24,10.1.1.1,77 + * route2=7.7.0.0/16 + * ---end--- + * ---ifcfg-rh--- + * property: routes + * variable: ADDRESS1, NETMASK1, GATEWAY1, METRIC1, OPTIONS1, ... + * description: List of static routes. They are not stored in ifcfg-* file, + * but in route-* file instead. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: ignore-auto-routes + * variable: PEERROUTES(+) + * default: yes + * description: PEERROUTES has the opposite meaning as 'ignore-auto-routes' property. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: ignore-auto-dns + * variable: PEERDNS + * default: yes + * description: PEERDNS has the opposite meaning as 'ignore-auto-dns' property. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dhcp-send-hostname + * variable: DHCP_SEND_HOSTNAME(+) + * default: yes + * description: Whether DHCP_HOSTNAME should be sent to the DHCP server. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dhcp-hostname + * variable: DHCP_HOSTNAME + * description: Hostname to send to the DHCP server. When both DHCP_HOSTNAME and + * DHCP_FQDN are specified only the latter is used. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: never-default + * variable: DEFROUTE (GATEWAYDEV in /etc/sysconfig/network) + * default: yes + * description: DEFROUTE=no tells NetworkManager that this connection + * should not be assigned the default route. DEFROUTE has the opposite + * meaning as 'never-default' property. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: may-fail + * variable: IPV4_FAILURE_FATAL(+) + * default: no + * description: IPV4_FAILURE_FATAL has the opposite meaning as 'may-fail' property. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: route-metric + * variable: IPV4_ROUTE_METRIC(+) + * default: -1 + * description: IPV4_ROUTE_METRIC is the default IPv4 metric for routes on this connection. + * If set to -1, a default metric based on the device type is used. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: route-table + * variable: IPV4_ROUTE_TABLE(+) + * default: 0 + * description: IPV4_ROUTE_TABLE enables policy-routing and sets the default routing table. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dns-options + * variable: RES_OPTIONS(+) + * description: List of DNS options to be added to /etc/resolv.conf + * example: RES_OPTIONS=ndots:2 timeout:3 + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dns-priority + * variable: IPV4_DNS_PRIORITY(+) + * description: The priority for DNS servers of this connection. Lower values have higher priority. + * If zero, the default value will be used (50 for VPNs, 100 for other connections). + * A negative value prevents DNS from other connections with greater values to be used. + * default: 0 + * example: IPV4_DNS_PRIORITY=20 + * ---end--- + */ + + /** + * NMSettingIP4Config:dhcp-client-id: + * + * A string sent to the DHCP server to identify the local machine which the + * DHCP server may use to customize the DHCP lease and options. + * When the property is a hex string ('aa:bb:cc') it is interpreted as a + * binary client ID, in which case the first byte is assumed to be the + * 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be + * an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet + * ARP type and the rest is a MAC address). + * If the property is not a hex string it is considered as a + * non-hardware-address client ID and the 'type' field is set to 0. + * + * The special values "mac" and "perm-mac" are supported, which use the + * current or permanent MAC address of the device to generate a client identifier + * with type ethernet (01). Currently, these options only work for ethernet + * type of links. + * + * The special value "ipv6-duid" uses the DUID from "ipv6.dhcp-duid" property as + * an RFC4361-compliant client identifier. As IAID it uses "ipv4.dhcp-iaid" + * and falls back to "ipv6.dhcp-iaid" if unset. + * + * The special value "duid" generates a RFC4361-compliant client identifier based + * on "ipv4.dhcp-iaid" and uses a DUID generated by hashing /etc/machine-id. + * + * The special value "stable" is supported to generate a type 0 client identifier based + * on the stable-id (see connection.stable-id) and a per-host key. If you set the + * stable-id, you may want to include the "${DEVICE}" or "${MAC}" specifier to get a + * per-device key. + * + * If unset, a globally configured default is used. If still unset, the default + * depends on the DHCP plugin. + **/ + /* ---ifcfg-rh--- + * property: dhcp-client-id + * variable: DHCP_CLIENT_ID(+) + * description: A string sent to the DHCP server to identify the local machine. + * A binary value can be specified using hex notation ('aa:bb:cc'). + * example: DHCP_CLIENT_ID=ax-srv-1; DHCP_CLIENT_ID=01:44:44:44:44:44:44 + * ---end--- + */ + obj_properties[PROP_DHCP_CLIENT_ID] = + g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /* ---ifcfg-rh--- + * property: dad-timeout + * variable: ACD_TIMEOUT(+), ARPING_WAIT + * default: missing variable means global default (config override or zero) + * description: Timeout (in milliseconds for ACD_TIMEOUT or in seconds + * for ARPING_WAIT) for address conflict detection before configuring + * IPv4 addresses. 0 turns off the ACD completely, -1 means default value. + * example: ACD_TIMEOUT=2000 or ARPING_WAIT=2 + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dhcp-timeout + * variable: IPV4_DHCP_TIMEOUT(+) + * description: A timeout after which the DHCP transaction fails in case of no response. + * example: IPV4_DHCP_TIMEOUT=10 + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dhcp-hostname-flags + * variable: DHCP_HOSTNAME_FLAGS + * description: flags for the DHCP hostname and FQDN properties + * example: DHCP_HOSTNAME_FLAGS=5 + */ + + /** + * NMSettingIP4Config:dhcp-fqdn: + * + * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the + * specified FQDN will be sent to the DHCP server when acquiring a lease. This + * property and #NMSettingIPConfig:dhcp-hostname are mutually exclusive and + * cannot be set at the same time. + * + * Since: 1.2 + */ + /* ---ifcfg-rh--- + * property: dhcp-fqdn + * variable: DHCP_FQDN + * description: FQDN to send to the DHCP server. When both DHCP_HOSTNAME and + * DHCP_FQDN are specified only the latter is used. + * example: DHCP_FQDN=foo.bar.com + * ---end--- + */ + obj_properties[PROP_DHCP_FQDN] = + g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_FQDN, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIP4Config:dhcp-vendor-class-identifier: + * + * The Vendor Class Identifier DHCP option (60). + * Special characters in the data string may be escaped using C-style escapes, + * nevertheless this property cannot contain nul bytes. + * If the per-profile value is unspecified (the default), + * a global connection default gets consulted. + * If still unspecified, the DHCP option is not sent to the server. + * + * Since 1.28 + */ + /* ---ifcfg-rh--- + * property: dhcp-vendor-class-identifier + * variable: DHCP_VENDOR_CLASS_IDENTIFIER(+) + * description: The Vendor Class Identifier DHCP option (60). + * example: DHCP_VENDOR_CLASS_IDENTIFIER=foo + * ---end--- + */ + obj_properties[PROP_DHCP_VENDOR_CLASS_IDENTIFIER] = + g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /* IP4-specific property overrides */ + + /* ---dbus--- + * property: dns + * format: array of uint32 + * description: Array of IP addresses of DNS servers (as network-byte-order + * integers) + * ---end--- + */ + _nm_properties_override_gobj( + properties_override, + g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS), + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("au"), + .gprop_to_dbus_fcn = ip4_dns_to_dbus, + .gprop_from_dbus_fcn = ip4_dns_from_dbus, )); + + /* ---dbus--- + * property: addresses + * format: array of array of uint32 + * description: Deprecated in favor of the 'address-data' and 'gateway' + * properties, but this can be used for backward-compatibility with older + * daemons. Note that if you send this property the daemon will ignore + * 'address-data' and 'gateway'. + * + * Array of IPv4 address structures. Each IPv4 address structure is + * composed of 3 32-bit values; the first being the IPv4 address (network + * byte order), the second the prefix (1 - 32), and last the IPv4 gateway + * (network byte order). The gateway may be left as 0 if no gateway exists + * for that subnet. + * ---end--- + */ + /* ---nmcli--- + * property: addresses + * format: a comma separated list of addresses + * description: A list of IPv4 addresses and their prefix length. Multiple addresses + * can be separated by comma. For example "192.168.1.5/24, 10.1.0.5/24". + * ---end--- + */ + _nm_properties_override_gobj( + properties_override, + g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES), + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aau"), + .to_dbus_fcn = ip4_addresses_get, + .from_dbus_fcn = ip4_addresses_set, )); + _nm_properties_override_dbus( + properties_override, + "address-labels", + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING_ARRAY, + .to_dbus_fcn = ip4_address_labels_get, )); + + /* ---dbus--- + * property: address-data + * format: array of vardict + * description: Array of IPv4 addresses. Each address dictionary contains at + * least 'address' and 'prefix' entries, containing the IP address as a + * string, and the prefix length as a uint32. Additional attributes may + * also exist on some addresses. + * ---end--- + */ + _nm_properties_override_dbus( + properties_override, + "address-data", + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = ip4_address_data_get, + .from_dbus_fcn = ip4_address_data_set, )); + + /* ---dbus--- + * property: routes + * format: array of array of uint32 + * description: Deprecated in favor of the 'route-data' property, but this + * can be used for backward-compatibility with older daemons. Note that if + * you send this property the daemon will ignore 'route-data'. + * + * Array of IPv4 route structures. Each IPv4 route structure is composed + * of 4 32-bit values; the first being the destination IPv4 network or + * address (network byte order), the second the destination network or + * address prefix (1 - 32), the third being the next-hop (network byte + * order) if any, and the fourth being the route metric. If the metric is + * 0, NM will choose an appropriate default metric for the device. (There + * is no way to explicitly specify an actual metric of 0 with this + * property.) + * ---end--- + */ + _nm_properties_override_gobj( + properties_override, + g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES), + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aau"), + .to_dbus_fcn = ip4_routes_get, + .from_dbus_fcn = ip4_routes_set, )); + + /* ---dbus--- + * property: route-data + * format: array of vardict + * description: Array of IPv4 routes. Each route dictionary contains at + * least 'dest' and 'prefix' entries, containing the destination IP + * address as a string, and the prefix length as a uint32. Most routes + * will also have a 'next-hop' entry, containing the next hop IP address as + * a string. If the route has a 'metric' entry (containing a uint32), that + * will be used as the metric for the route (otherwise NM will pick a + * default value appropriate to the device). Additional attributes may + * also exist on some routes. + * ---end--- + */ + _nm_properties_override_dbus(properties_override, + "route-data", + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = ip4_route_data_get, + .from_dbus_fcn = ip4_route_data_set, )); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_IP4_CONFIG, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c new file mode 100644 index 0000000000..4477436edb --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -0,0 +1,1085 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ip6-config.h" + +#include + +#include "nm-setting-private.h" +#include "nm-core-enum-types.h" +#include "libnm-core-intern/nm-core-internal.h" + +/** + * SECTION:nm-setting-ip6-config + * @short_description: Describes IPv6 addressing, routing, and name service properties + * + * The #NMSettingIP6Config object is a #NMSetting subclass that describes + * properties related to IPv6 addressing, routing, and Domain Name Service + * + * #NMSettingIP6Config has few properties or methods of its own; it inherits + * almost everything from #NMSettingIPConfig. + * + * NetworkManager supports 7 values for the #NMSettingIPConfig:method property + * for IPv6. If "auto" is specified then the appropriate automatic method (PPP, + * router advertisement, etc) is used for the device and most other properties + * can be left unset. To force the use of DHCP only, specify "dhcp"; this + * method is only valid for Ethernet- based hardware. If "link-local" is + * specified, then an IPv6 link-local address will be assigned to the interface. + * If "manual" is specified, static IP addressing is used and at least one IP + * address must be given in the "addresses" property. If "ignore" is specified, + * IPv6 configuration is not done. Note: the "shared" method is not yet + * supported. If "disabled" is specified, IPv6 is disabled completely for the + * interface. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_IP6_PRIVACY, + PROP_ADDR_GEN_MODE, + PROP_TOKEN, + PROP_DHCP_DUID, + PROP_RA_TIMEOUT, ); + +typedef struct { + char * token; + char * dhcp_duid; + NMSettingIP6ConfigPrivacy ip6_privacy; + NMSettingIP6ConfigAddrGenMode addr_gen_mode; + gint32 ra_timeout; +} NMSettingIP6ConfigPrivate; + +G_DEFINE_TYPE(NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG) + +#define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_ip6_config_get_ip6_privacy: + * @setting: the #NMSettingIP6Config + * + * Returns the value contained in the #NMSettingIP6Config:ip6-privacy + * property. + * + * Returns: IPv6 Privacy Extensions configuration value (#NMSettingIP6ConfigPrivacy). + **/ +NMSettingIP6ConfigPrivacy +nm_setting_ip6_config_get_ip6_privacy(NMSettingIP6Config *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->ip6_privacy; +} + +/** + * nm_setting_ip6_config_get_addr_gen_mode: + * @setting: the #NMSettingIP6Config + * + * Returns the value contained in the #NMSettingIP6Config:addr-gen-mode + * property. + * + * Returns: IPv6 Address Generation Mode. + * + * Since: 1.2 + **/ +NMSettingIP6ConfigAddrGenMode +nm_setting_ip6_config_get_addr_gen_mode(NMSettingIP6Config *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->addr_gen_mode; +} + +/** + * nm_setting_ip6_config_get_token: + * @setting: the #NMSettingIP6Config + * + * Returns the value contained in the #NMSettingIP6Config:token + * property. + * + * Returns: A string. + * + * Since: 1.4 + **/ +const char * +nm_setting_ip6_config_get_token(NMSettingIP6Config *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), NULL); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->token; +} + +/** + * nm_setting_ip6_config_get_dhcp_duid: + * @setting: the #NMSettingIP6Config + * + * Returns the value contained in the #NMSettingIP6Config:dhcp-duid + * property. + * + * Returns: The configured DUID value to be included in the DHCPv6 requests + * sent to the DHCPv6 servers. + * + * Since: 1.12 + **/ +const char * +nm_setting_ip6_config_get_dhcp_duid(NMSettingIP6Config *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), NULL); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->dhcp_duid; +} + +/** + * nm_setting_ip6_config_get_ra_timeout: + * @setting: the #NMSettingIP6Config + * + * Returns: The configured %NM_SETTING_IP6_CONFIG_RA_TIMEOUT value with the + * timeout for router advertisements in seconds. + * + * Since: 1.24 + **/ +gint32 +nm_setting_ip6_config_get_ra_timeout(NMSettingIP6Config *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP6_CONFIG(setting), 0); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting)->ra_timeout; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting); + NMSettingIPConfig * s_ip = NM_SETTING_IP_CONFIG(setting); + NMSettingVerifyResult ret; + const char * method; + gboolean token_needs_normalization = FALSE; + + ret = NM_SETTING_CLASS(nm_setting_ip6_config_parent_class)->verify(setting, connection, error); + if (ret != NM_SETTING_VERIFY_SUCCESS) + return ret; + + method = nm_setting_ip_config_get_method(s_ip); + /* Base class already checked that it exists */ + g_assert(method); + + if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { + if (nm_setting_ip_config_get_num_addresses(s_ip) == 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("this property cannot be empty for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_ADDRESSES); + return FALSE; + } + } else if (NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, + NM_SETTING_IP6_CONFIG_METHOD_SHARED, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { + /* Shared allows IP addresses and DNS; other methods do not */ + if (!nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { + if (nm_setting_ip_config_get_num_dns(s_ip) > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("this property is not allowed for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_DNS); + return FALSE; + } + + if (nm_setting_ip_config_get_num_dns_searches(s_ip) > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("this property is not allowed for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_DNS_SEARCH); + return FALSE; + } + + if (nm_setting_ip_config_get_num_addresses(s_ip) > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("this property is not allowed for '%s=%s'"), + NM_SETTING_IP_CONFIG_METHOD, + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_ADDRESSES); + return FALSE; + } + } + } else if (NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { + /* nothing to do */ + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_METHOD); + return FALSE; + } + + if (!NM_IN_SET(priv->addr_gen_mode, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE); + return FALSE; + } + + if (priv->token) { + if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { + struct in6_addr i6_token; + char s_token[NM_UTILS_INET_ADDRSTRLEN]; + + if (inet_pton(AF_INET6, priv->token, &i6_token) != 1 + || !_nm_utils_inet6_is_token(&i6_token)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value is not a valid token")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_TOKEN); + return FALSE; + } + + if (g_strcmp0(priv->token, _nm_utils_inet6_ntop(&i6_token, s_token))) + token_needs_normalization = TRUE; + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("only makes sense with EUI64 address generation mode")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_TOKEN); + return FALSE; + } + } + + if (priv->dhcp_duid) { + if (!_nm_utils_dhcp_duid_valid(priv->dhcp_duid, NULL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid DUID")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DHCP_DUID); + return FALSE; + } + } + + /* Failures from here on, are NORMALIZABLE_ERROR... */ + + if (token_needs_normalization) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("token is not in canonical form")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_TOKEN); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + /* Failures from here on are NORMALIZABLE... */ + + if (NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED) + && !nm_setting_ip_config_get_may_fail(s_ip)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property should be TRUE when method is set to ignore or disabled")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_MAY_FAIL); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + return TRUE; +} + +static GVariant * +ip6_dns_to_dbus(const GValue *prop_value) +{ + return nm_utils_ip6_dns_to_variant(g_value_get_boxed(prop_value)); +} + +static void +ip6_dns_from_dbus(GVariant *dbus_value, GValue *prop_value) +{ + g_value_take_boxed(prop_value, nm_utils_ip6_dns_from_variant(dbus_value)); +} + +static GVariant * +ip6_addresses_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *addrs = NULL; + const char * gateway; + + g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); + gateway = nm_setting_ip_config_get_gateway(NM_SETTING_IP_CONFIG(setting)); + return nm_utils_ip6_addresses_to_variant(addrs, gateway); +} + +static gboolean +ip6_addresses_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *addrs; + char * gateway = NULL; + + /* FIXME: properly handle errors */ + + if (!_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) + return TRUE; + + addrs = nm_utils_ip6_addresses_from_variant(value, &gateway); + + g_object_set(setting, + NM_SETTING_IP_CONFIG_ADDRESSES, + addrs, + NM_SETTING_IP_CONFIG_GATEWAY, + gateway, + NULL); + g_ptr_array_unref(addrs); + g_free(gateway); + return TRUE; +} + +static GVariant * +ip6_address_data_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *addrs = NULL; + + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + return NULL; + + g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); + return nm_utils_ip_addresses_to_variant(addrs); +} + +static gboolean +ip6_address_data_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *addrs; + + /* FIXME: properly handle errors */ + + /* Ignore 'address-data' if we're going to process 'addresses' */ + if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) + return TRUE; + + addrs = nm_utils_ip_addresses_from_variant(value, AF_INET6); + g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); + g_ptr_array_unref(addrs); + return TRUE; +} + +static GVariant * +ip6_routes_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *routes = NULL; + + g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL); + return nm_utils_ip6_routes_to_variant(routes); +} + +static gboolean +ip6_routes_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *routes; + + /* FIXME: properly handle errors */ + + if (!_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) + return TRUE; + + routes = nm_utils_ip6_routes_from_variant(value); + g_object_set(setting, property, routes, NULL); + g_ptr_array_unref(routes); + return TRUE; +} + +static GVariant * +ip6_route_data_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *routes = NULL; + + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + return NULL; + + g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL); + return nm_utils_ip_routes_to_variant(routes); +} + +static gboolean +ip6_route_data_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *routes; + + /* FIXME: properly handle errors */ + + /* Ignore 'route-data' if we're going to process 'routes' */ + if (_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) + return TRUE; + + routes = nm_utils_ip_routes_from_variant(value, AF_INET6); + g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); + g_ptr_array_unref(routes); + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_IP6_PRIVACY: + g_value_set_enum(value, priv->ip6_privacy); + break; + case PROP_ADDR_GEN_MODE: + g_value_set_int(value, priv->addr_gen_mode); + break; + case PROP_TOKEN: + g_value_set_string(value, priv->token); + break; + case PROP_DHCP_DUID: + g_value_set_string(value, priv->dhcp_duid); + break; + case PROP_RA_TIMEOUT: + g_value_set_int(value, priv->ra_timeout); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_IP6_PRIVACY: + priv->ip6_privacy = g_value_get_enum(value); + break; + case PROP_ADDR_GEN_MODE: + priv->addr_gen_mode = g_value_get_int(value); + break; + case PROP_TOKEN: + g_free(priv->token); + priv->token = g_value_dup_string(value); + break; + case PROP_DHCP_DUID: + g_free(priv->dhcp_duid); + priv->dhcp_duid = g_value_dup_string(value); + break; + case PROP_RA_TIMEOUT: + priv->ra_timeout = g_value_get_int(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ip6_config_init(NMSettingIP6Config *setting) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(setting); + + priv->ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + priv->addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY; +} + +/** + * nm_setting_ip6_config_new: + * + * Creates a new #NMSettingIP6Config object with default values. + * + * Returns: (transfer full): the new empty #NMSettingIP6Config object + **/ +NMSetting * +nm_setting_ip6_config_new(void) +{ + return g_object_new(NM_TYPE_SETTING_IP6_CONFIG, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingIP6Config * self = NM_SETTING_IP6_CONFIG(object); + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE(self); + + g_free(priv->token); + g_free(priv->dhcp_duid); + + G_OBJECT_CLASS(nm_setting_ip6_config_parent_class)->finalize(object); +} + +static void +nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array_ip_config(); + + g_type_class_add_private(klass, sizeof(NMSettingIP6ConfigPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /* ---ifcfg-rh--- + * property: method + * variable: IPV6INIT, IPV6FORWARDING, IPV6_AUTOCONF, DHCPV6C, IPV6_DISABLED + * default: IPV6INIT=yes; IPV6FORWARDING=no; IPV6_AUTOCONF=!IPV6FORWARDING, DHCPV6=no + * description: Method used for IPv6 protocol configuration. + * ignore ~ IPV6INIT=no; auto ~ IPV6_AUTOCONF=yes; dhcp ~ IPV6_AUTOCONF=no and DHCPV6C=yes; + * disabled ~ IPV6_DISABLED=yes + * ---end--- + */ + + /* ---keyfile--- + * property: dns + * format: list of DNS IP addresses + * description: List of DNS servers. + * example: dns=2001:4860:4860::8888;2001:4860:4860::8844; + * ---end--- + * ---ifcfg-rh--- + * property: dns + * variable: DNS1, DNS2, ... + * format: string + * description: List of DNS servers. NetworkManager uses the variables both + * for IPv4 and IPv6. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dns-search + * variable: IPV6_DOMAIN(+) + * format: string (space-separated domains) + * description: List of DNS search domains. + * ---end--- + */ + + /* ---keyfile--- + * property: addresses + * variable: address1, address2, ... + * format: address/plen + * description: List of static IP addresses. + * example: address1=abbe::cafe/96 address2=2001::1234 + * ---end--- + * ---ifcfg-rh--- + * property: addresses + * variable: IPV6ADDR, IPV6ADDR_SECONDARIES + * description: List of static IP addresses. + * example: IPV6ADDR=ab12:9876::1 + * IPV6ADDR_SECONDARIES="ab12:9876::2 ab12:9876::3" + * ---end--- + */ + + /* ---keyfile--- + * property: gateway + * variable: gateway + * format: string + * description: Gateway IP addresses as a string. + * example: gateway=abbe::1 + * ---end--- + * ---ifcfg-rh--- + * property: gateway + * variable: IPV6_DEFAULTGW + * description: Gateway IP address. + * example: IPV6_DEFAULTGW=abbe::1 + * ---end--- + */ + + /* ---keyfile--- + * property: routes + * variable: route1, route2, ... + * format: route/plen[,gateway,metric] + * description: List of IP routes. + * example: route1=2001:4860:4860::/64,2620:52:0:2219:222:68ff:fe11:5403 + * ---end--- + * ---ifcfg-rh--- + * property: routes + * variable: (none) + * description: List of static routes. They are not stored in ifcfg-* file, + * but in route6-* file instead in the form of command line for 'ip route add'. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: ignore-auto-routes + * variable: IPV6_PEERROUTES(+) + * default: yes + * description: IPV6_PEERROUTES has the opposite meaning as 'ignore-auto-routes' property. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: ignore-auto-dns + * variable: IPV6_PEERDNS(+) + * default: yes + * description: IPV6_PEERDNS has the opposite meaning as 'ignore-auto-dns' property. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dhcp-hostname + * variable: DHCPV6_HOSTNAME + * description: Hostname to send the DHCP server. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dhcp-timeout + * variable: IPV6_DHCP_TIMEOUT(+) + * description: A timeout after which the DHCP transaction fails in case of no response. + * example: IPV6_DHCP_TIMEOUT=10 + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dhcp-hostname-flags + * variable: DHCPV6_HOSTNAME_FLAGS + * description: flags for the DHCP hostname property + * example: DHCPV6_HOSTNAME_FLAGS=5 + */ + + /* ---ifcfg-rh--- + * property: never-default + * variable: IPV6_DEFROUTE(+), (and IPV6_DEFAULTGW, IPV6_DEFAULTDEV in /etc/sysconfig/network) + * default: IPV6_DEFROUTE=yes (when no variable specified) + * description: IPV6_DEFROUTE=no tells NetworkManager that this connection + * should not be assigned the default IPv6 route. IPV6_DEFROUTE has the opposite + * meaning as 'never-default' property. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: may-fail + * variable: IPV6_FAILURE_FATAL(+) + * default: no + * description: IPV6_FAILURE_FATAL has the opposite meaning as 'may-fail' property. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: route-metric + * variable: IPV6_ROUTE_METRIC(+) + * default: -1 + * description: IPV6_ROUTE_METRIC is the default IPv6 metric for routes on this connection. + * If set to -1, a default metric based on the device type is used. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: route-table + * variable: IPV6_ROUTE_TABLE(+) + * default: 0 + * description: IPV6_ROUTE_TABLE enables policy-routing and sets the default routing table. + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dns-priority + * variable: IPV6_DNS_PRIORITY(+) + * description: The priority for DNS servers of this connection. Lower values have higher priority. + * If zero, the default value will be used (50 for VPNs, 100 for other connections). + * A negative value prevents DNS from other connections with greater values to be used. + * default: 0 + * example: IPV6_DNS_PRIORITY=20 + * ---end--- + */ + + /* ---ifcfg-rh--- + * property: dns-options + * variable: IPV6_RES_OPTIONS(+) + * description: List of DNS options to be added to /etc/resolv.conf + * example: IPV6_RES_OPTIONS=ndots:2 timeout:3 + * ---end--- + */ + + /** + * NMSettingIP6Config:ip6-privacy: + * + * Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If + * enabled, it makes the kernel generate a temporary IPv6 address in + * addition to the public one generated from MAC address via modified + * EUI-64. This enhances privacy, but could cause problems in some + * applications, on the other hand. The permitted values are: -1: unknown, + * 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary + * addresses). + * + * Having a per-connection setting set to "-1" (unknown) means fallback to + * global configuration "ipv6.ip6-privacy". + * + * If also global configuration is unspecified or set to "-1", fallback to read + * "/proc/sys/net/ipv6/conf/default/use_tempaddr". + * + * Note that this setting is distinct from the Stable Privacy addresses + * that can be enabled with the "addr-gen-mode" property's "stable-privacy" + * setting as another way of avoiding host tracking with IPv6 addresses. + **/ + /* ---ifcfg-rh--- + * property: ip6-privacy + * variable: IPV6_PRIVACY, IPV6_PRIVACY_PREFER_PUBLIC_IP(+) + * values: IPV6_PRIVACY: no, yes (rfc3041 or rfc4941); + * IPV6_PRIVACY_PREFER_PUBLIC_IP: yes, no + * default: no + * description: Configure IPv6 Privacy Extensions for SLAAC (RFC4941). + * example: IPV6_PRIVACY=rfc3041 IPV6_PRIVACY_PREFER_PUBLIC_IP=yes + * ---end--- + */ + obj_properties[PROP_IP6_PRIVACY] = + g_param_spec_enum(NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + "", + "", + NM_TYPE_SETTING_IP6_CONFIG_PRIVACY, + NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIP6Config:addr-gen-mode: + * + * Configure method for creating the address for use with RFC4862 IPv6 + * Stateless Address Autoconfiguration. The permitted values are: + * %NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 or + * %NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY. + * + * If the property is set to EUI64, the addresses will be generated + * using the interface tokens derived from hardware address. This makes + * the host part of the address to stay constant, making it possible + * to track host's presence when it changes networks. The address changes + * when the interface hardware is replaced. + * + * The value of stable-privacy enables use of cryptographically + * secure hash of a secret host-specific key along with the connection's + * stable-id and the network address as specified by RFC7217. + * This makes it impossible to use the address track host's presence, + * and makes the address stable when the network interface hardware is + * replaced. + * + * On D-Bus, the absence of an addr-gen-mode setting equals enabling + * stable-privacy. For keyfile plugin, the absence of the setting + * on disk means EUI64 so that the property doesn't change on upgrade + * from older versions. + * + * Note that this setting is distinct from the Privacy Extensions as + * configured by "ip6-privacy" property and it does not affect the + * temporary addresses configured with this option. + * + * Since: 1.2 + **/ + /* ---ifcfg-rh--- + * property: addr-gen-mode + * variable: IPV6_ADDR_GEN_MODE + * values: IPV6_ADDR_GEN_MODE: eui64, stable-privacy + * default: eui64 + * description: Configure IPv6 Stable Privacy addressing for SLAAC (RFC7217). + * example: IPV6_ADDR_GEN_MODE=stable-privacy + * ---end--- + */ + obj_properties[PROP_ADDR_GEN_MODE] = + g_param_spec_int(NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + "", + "", + G_MININT, + G_MAXINT, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIP6Config:token: + * + * Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 + * IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode. + * + * Since: 1.4 + **/ + /* ---ifcfg-rh--- + * property: token + * variable: IPV6_TOKEN + * description: The IPv6 tokenized interface identifier token + * example: IPV6_TOKEN=::53 + * ---end--- + */ + obj_properties[PROP_TOKEN] = g_param_spec_string(NM_SETTING_IP6_CONFIG_TOKEN, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIP6Config:ra-timeout: + * + * A timeout for waiting Router Advertisements in seconds. If zero (the default), a + * globally configured default is used. If still unspecified, the timeout depends on the + * sysctl settings of the device. + * + * Set to 2147483647 (MAXINT32) for infinity. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: dhcp-timeout + * variable: IPV6_RA_TIMEOUT(+) + * description: A timeout for waiting Router Advertisements in seconds. + * example: IPV6_RA_TIMEOUT=10 + * ---end--- + */ + + obj_properties[PROP_RA_TIMEOUT] = g_param_spec_int( + NM_SETTING_IP6_CONFIG_RA_TIMEOUT, + "", + "", + 0, + G_MAXINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingIP6Config:dhcp-duid: + * + * A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp + * client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried + * in the Client Identifier option. + * If the property is a hex string ('aa:bb:cc') it is interpreted as a binary + * DUID and filled as an opaque value in the Client Identifier option. + * + * The special value "lease" will retrieve the DUID previously used from the + * lease file belonging to the connection. If no DUID is found and "dhclient" + * is the configured dhcp client, the DUID is searched in the system-wide + * dhclient lease file. If still no DUID is found, or another dhcp client is + * used, a global and permanent DUID-UUID (RFC 6355) will be generated based + * on the machine-id. + * + * The special values "llt" and "ll" will generate a DUID of type LLT or LL + * (see RFC 3315) based on the current MAC address of the device. In order to + * try providing a stable DUID-LLT, the time field will contain a constant + * timestamp that is used globally (for all profiles) and persisted to disk. + * + * The special values "stable-llt", "stable-ll" and "stable-uuid" will generate + * a DUID of the corresponding type, derived from the connection's stable-id and + * a per-host unique key. You may want to include the "${DEVICE}" or "${MAC}" specifier + * in the stable-id, in case this profile gets activated on multiple devices. + * So, the link-layer address of "stable-ll" and "stable-llt" will be a generated + * address derived from the stable id. The DUID-LLT time value in the "stable-llt" + * option will be picked among a static timespan of three years (the upper bound + * of the interval is the same constant timestamp used in "llt"). + * + * When the property is unset, the global value provided for "ipv6.dhcp-duid" is + * used. If no global value is provided, the default "lease" value is assumed. + * + * Since: 1.12 + **/ + /* ---ifcfg-rh--- + * property: dhcp-duid + * variable: DHCPV6_DUID(+) + * description: A string sent to the DHCPv6 server to identify the local machine. + * Apart from the special values "lease", "stable-llt", "stable-ll", "stable-uuid", + * "llt" and "ll" a binary value in hex format is expected. An hex string where + * each octet is separated by a colon is also accepted. + * example: DHCPV6_DUID=LL; DHCPV6_DUID=0301deadbeef0001; DHCPV6_DUID=03:01:de:ad:be:ef:00:01 + * ---end--- + */ + obj_properties[PROP_DHCP_DUID] = + g_param_spec_string(NM_SETTING_IP6_CONFIG_DHCP_DUID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /* IP6-specific property overrides */ + + /* ---dbus--- + * property: dns + * format: array of byte array + * description: Array of IP addresses of DNS servers (in network byte order) + * ---end--- + */ + _nm_properties_override_gobj( + properties_override, + g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS), + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aay"), + .gprop_to_dbus_fcn = ip6_dns_to_dbus, + .gprop_from_dbus_fcn = ip6_dns_from_dbus, )); + + /* ---dbus--- + * property: addresses + * format: array of legacy IPv6 address struct (a(ayuay)) + * description: Deprecated in favor of the 'address-data' and 'gateway' + * properties, but this can be used for backward-compatibility with older + * daemons. Note that if you send this property the daemon will ignore + * 'address-data' and 'gateway'. + * + * Array of IPv6 address structures. Each IPv6 address structure is + * composed of an IPv6 address, a prefix length (1 - 128), and an IPv6 + * gateway address. The gateway may be zeroed out if no gateway exists for + * that subnet. + * ---end--- + */ + _nm_properties_override_gobj( + properties_override, + g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES), + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("a(ayuay)"), + .to_dbus_fcn = ip6_addresses_get, + .from_dbus_fcn = ip6_addresses_set, )); + + /* ---dbus--- + * property: address-data + * format: array of vardict + * description: Array of IPv6 addresses. Each address dictionary contains at + * least 'address' and 'prefix' entries, containing the IP address as a + * string, and the prefix length as a uint32. Additional attributes may + * also exist on some addresses. + * ---end--- + */ + _nm_properties_override_dbus( + properties_override, + "address-data", + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = ip6_address_data_get, + .from_dbus_fcn = ip6_address_data_set, )); + + /* ---dbus--- + * property: routes + * format: array of legacy IPv6 route struct (a(ayuayu)) + * description: Deprecated in favor of the 'route-data' property, but this + * can be used for backward-compatibility with older daemons. Note that if + * you send this property the daemon will ignore 'route-data'. + * + * Array of IPv6 route structures. Each IPv6 route structure is + * composed of an IPv6 address, a prefix length (1 - 128), an IPv6 + * next hop address (which may be zeroed out if there is no next hop), + * and a metric. If the metric is 0, NM will choose an appropriate + * default metric for the device. + * ---end--- + */ + _nm_properties_override_gobj( + properties_override, + g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES), + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("a(ayuayu)"), + .to_dbus_fcn = ip6_routes_get, + .from_dbus_fcn = ip6_routes_set, )); + + /* ---dbus--- + * property: route-data + * format: array of vardict + * description: Array of IPv6 routes. Each route dictionary contains at + * least 'dest' and 'prefix' entries, containing the destination IP + * address as a string, and the prefix length as a uint32. Most routes + * will also have a 'next-hop' entry, containing the next hop IP address as + * a string. If the route has a 'metric' entry (containing a uint32), that + * will be used as the metric for the route (otherwise NM will pick a + * default value appropriate to the device). Additional attributes may + * also exist on some routes. + * ---end--- + */ + _nm_properties_override_dbus(properties_override, + "route-data", + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = ip6_route_data_get, + .from_dbus_fcn = ip6_route_data_set, )); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_IP6_CONFIG, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-macsec.c b/src/libnm-core-impl/nm-setting-macsec.c new file mode 100644 index 0000000000..e2a87ffc18 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-macsec.c @@ -0,0 +1,671 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-macsec.h" + +#include + +#include "nm-glib-aux/nm-secret-utils.h" + +#include "nm-utils.h" +#include "libnm-core-intern/nm-core-types-internal.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" +#include "nm-setting-wired.h" +#include "nm-connection-private.h" + +/** + * SECTION:nm-setting-macsec + * @short_description: Describes connection properties for MACSEC interfaces + * + * The #NMSettingMacsec object is a #NMSetting subclass that describes properties + * necessary for connection to MACsec (IEEE 802.1AE) interfaces. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, + PROP_MODE, + PROP_ENCRYPT, + PROP_MKA_CAK, + PROP_MKA_CAK_FLAGS, + PROP_MKA_CKN, + PROP_PORT, + PROP_VALIDATION, + PROP_SEND_SCI, ); + +typedef struct { + char * parent; + char * mka_cak; + char * mka_ckn; + int port; + NMSettingMacsecMode mode; + NMSettingSecretFlags mka_cak_flags; + NMSettingMacsecValidation validation; + bool encrypt : 1; + bool send_sci : 1; +} NMSettingMacsecPrivate; + +G_DEFINE_TYPE(NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING) + +#define NM_SETTING_MACSEC_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_MACSEC, NMSettingMacsecPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_macsec_get_parent: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:parent property of the setting + * + * Since: 1.6 + **/ +const char * +nm_setting_macsec_get_parent(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NULL); + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->parent; +} + +/** + * nm_setting_macsec_get_mode: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:mode property of the setting + * + * Since: 1.6 + **/ +NMSettingMacsecMode +nm_setting_macsec_get_mode(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NM_SETTING_MACSEC_MODE_PSK); + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->mode; +} + +/** + * nm_setting_macsec_get_encrypt: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:encrypt property of the setting + * + * Since: 1.6 + **/ +gboolean +nm_setting_macsec_get_encrypt(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), TRUE); + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->encrypt; +} + +/** + * nm_setting_macsec_get_mka_cak + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:mka-cak property of the setting + * + * Since: 1.6 + **/ +const char * +nm_setting_macsec_get_mka_cak(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NULL); + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->mka_cak; +} + +/** + * nm_setting_macsec_get_mka_cak_flags: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingMacsec:mka-cak + * + * Since: 1.6 + **/ +NMSettingSecretFlags +nm_setting_macsec_get_mka_cak_flags(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->mka_cak_flags; +} + +/** + * nm_setting_macsec_get_mka_ckn: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:mka-ckn property of the setting + * + * Since: 1.6 + **/ +const char * +nm_setting_macsec_get_mka_ckn(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NULL); + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->mka_ckn; +} + +/** + * nm_setting_macsec_get_port: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:port property of the setting + * + * Since: 1.6 + **/ +int +nm_setting_macsec_get_port(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), 1); + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->port; +} + +/** + * nm_setting_macsec_get_validation: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:validation property of the setting + * + * Since: 1.6 + **/ +NMSettingMacsecValidation +nm_setting_macsec_get_validation(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NM_SETTING_MACSEC_VALIDATION_DISABLE); + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->validation; +} + +/** + * nm_setting_macsec_get_send_sci: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:send-sci property of the setting + * + * Since: 1.12 + **/ +gboolean +nm_setting_macsec_get_send_sci(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), TRUE); + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->send_sci; +} + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); + GPtrArray * secrets = NULL; + + if (priv->mode == NM_SETTING_MACSEC_MODE_PSK) { + if (!priv->mka_cak + && !NM_FLAGS_HAS(priv->mka_cak_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { + secrets = g_ptr_array_sized_new(1); + g_ptr_array_add(secrets, NM_SETTING_MACSEC_MKA_CAK); + } + } + + return secrets; +} + +/*********************************************************************/ + +static gboolean +verify_macsec_key(const char *key, gboolean cak, GError **error) +{ + int req_len; + + /* CAK is a connection secret and can be NULL for various + * reasons (agent-owned, no permissions to get secrets, etc.) + */ + if (cak && !key) + return TRUE; + + if (!key || !key[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the key is empty")); + return FALSE; + } + + req_len = cak ? NM_SETTING_MACSEC_MKA_CAK_LENGTH : NM_SETTING_MACSEC_MKA_CKN_LENGTH; + if (strlen(key) != (gsize) req_len) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the key must be %d characters"), + req_len); + return FALSE; + } + + if (!NM_STRCHAR_ALL(key, ch, g_ascii_isxdigit(ch))) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the key contains non-hexadecimal characters")); + return FALSE; + } + + return TRUE; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); + NMSettingConnection * s_con = NULL; + NMSettingWired * s_wired = NULL; + NMSetting8021x * s_8021x = NULL; + + if (connection) { + s_con = nm_connection_get_setting_connection(connection); + s_wired = nm_connection_get_setting_wired(connection); + s_8021x = nm_connection_get_setting_802_1x(connection); + } + + if (priv->parent) { + if (nm_utils_is_uuid(priv->parent)) { + /* If we have an NMSettingConnection:master with slave-type="macsec", + * then it must be the same UUID. + */ + if (s_con) { + const char *master = NULL, *slave_type = NULL; + + slave_type = nm_setting_connection_get_slave_type(s_con); + if (!g_strcmp0(slave_type, NM_SETTING_MACSEC_SETTING_NAME)) + master = nm_setting_connection_get_master(s_con); + + if (master && g_strcmp0(priv->parent, master) != 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' value doesn't match '%s=%s'"), + priv->parent, + NM_SETTING_CONNECTION_MASTER, + master); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACSEC_SETTING_NAME, + NM_SETTING_MACSEC_PARENT); + return FALSE; + } + } + } else if (!nm_utils_iface_valid_name(priv->parent)) { + /* parent must be either a UUID or an interface name */ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACSEC_SETTING_NAME, + NM_SETTING_MACSEC_PARENT); + return FALSE; + } + } else { + /* If parent is NULL, the parent must be specified via + * NMSettingWired:mac-address. + */ + if (connection && (!s_wired || !nm_setting_wired_get_mac_address(s_wired))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is not specified and neither is '%s:%s'"), + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_MAC_ADDRESS); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACSEC_SETTING_NAME, + NM_SETTING_MACSEC_PARENT); + return FALSE; + } + } + + if (priv->mode == NM_SETTING_MACSEC_MODE_PSK) { + if (!verify_macsec_key(priv->mka_ckn, FALSE, error)) { + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACSEC_SETTING_NAME, + NM_SETTING_MACSEC_MKA_CKN); + return FALSE; + } + if (!verify_macsec_key(priv->mka_cak, TRUE, error)) { + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACSEC_SETTING_NAME, + NM_SETTING_MACSEC_MKA_CAK); + return FALSE; + } + } else if (priv->mode == NM_SETTING_MACSEC_MODE_EAP) { + if (!s_8021x) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("EAP key management requires '%s' setting presence"), + NM_SETTING_802_1X_SETTING_NAME); + g_prefix_error(error, "%s: ", NM_SETTING_MACSEC_SETTING_NAME); + return FALSE; + } + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("must be either psk (0) or eap (1)")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_MACSEC_SETTING_NAME, NM_SETTING_MACSEC_MODE); + return FALSE; + } + + if (priv->port <= 0 || priv->port > 65534) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("invalid port %d"), + priv->port); + g_prefix_error(error, "%s.%s: ", NM_SETTING_MACSEC_SETTING_NAME, NM_SETTING_MACSEC_PORT); + return FALSE; + } + + if (priv->mode != NM_SETTING_MACSEC_MODE_PSK && (priv->mka_cak || priv->mka_ckn)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("only valid for psk mode")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACSEC_SETTING_NAME, + priv->mka_cak ? NM_SETTING_MACSEC_MKA_CAK : NM_SETTING_MACSEC_MKA_CKN); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingMacsec * setting = NM_SETTING_MACSEC(object); + NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string(value, priv->parent); + break; + case PROP_MODE: + g_value_set_int(value, priv->mode); + break; + case PROP_ENCRYPT: + g_value_set_boolean(value, priv->encrypt); + break; + case PROP_MKA_CAK: + g_value_set_string(value, priv->mka_cak); + break; + case PROP_MKA_CAK_FLAGS: + g_value_set_flags(value, priv->mka_cak_flags); + break; + case PROP_MKA_CKN: + g_value_set_string(value, priv->mka_ckn); + break; + case PROP_PORT: + g_value_set_int(value, priv->port); + break; + case PROP_VALIDATION: + g_value_set_int(value, priv->validation); + break; + case PROP_SEND_SCI: + g_value_set_boolean(value, priv->send_sci); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingMacsec * setting = NM_SETTING_MACSEC(object); + NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_free(priv->parent); + priv->parent = g_value_dup_string(value); + break; + case PROP_MODE: + priv->mode = g_value_get_int(value); + break; + case PROP_ENCRYPT: + priv->encrypt = g_value_get_boolean(value); + break; + case PROP_MKA_CAK: + nm_free_secret(priv->mka_cak); + priv->mka_cak = g_value_dup_string(value); + break; + case PROP_MKA_CAK_FLAGS: + priv->mka_cak_flags = g_value_get_flags(value); + break; + case PROP_MKA_CKN: + g_free(priv->mka_ckn); + priv->mka_ckn = g_value_dup_string(value); + break; + case PROP_PORT: + priv->port = g_value_get_int(value); + break; + case PROP_VALIDATION: + priv->validation = g_value_get_int(value); + break; + case PROP_SEND_SCI: + priv->send_sci = g_value_get_boolean(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_macsec_init(NMSettingMacsec *self) +{ + NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(self); + + nm_assert(priv->mode == NM_SETTING_MACSEC_MODE_PSK); + priv->encrypt = TRUE; + priv->port = 1; + priv->send_sci = TRUE; + priv->validation = NM_SETTING_MACSEC_VALIDATION_STRICT; +} + +/** + * nm_setting_macsec_new: + * + * Creates a new #NMSettingMacsec object with default values. + * + * Returns: (transfer full): the new empty #NMSettingMacsec object + * + * Since: 1.6 + **/ +NMSetting * +nm_setting_macsec_new(void) +{ + return g_object_new(NM_TYPE_SETTING_MACSEC, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingMacsec * setting = NM_SETTING_MACSEC(object); + NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); + + g_free(priv->parent); + nm_free_secret(priv->mka_cak); + g_free(priv->mka_ckn); + + G_OBJECT_CLASS(nm_setting_macsec_parent_class)->finalize(object); +} + +static void +nm_setting_macsec_class_init(NMSettingMacsecClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingMacsecPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; + + /** + * NMSettingMacsec:parent: + * + * If given, specifies the parent interface name or parent connection UUID + * from which this MACSEC interface should be created. If this property is + * not specified, the connection must contain an #NMSettingWired setting + * with a #NMSettingWired:mac-address property. + * + * Since: 1.6 + **/ + obj_properties[PROP_PARENT] = g_param_spec_string( + NM_SETTING_MACSEC_PARENT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacsec:mode: + * + * Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key + * Agreement) is obtained. + * + * Since: 1.6 + **/ + obj_properties[PROP_MODE] = + g_param_spec_int(NM_SETTING_MACSEC_MODE, + "", + "", + G_MININT, + G_MAXINT, + NM_SETTING_MACSEC_MODE_PSK, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacsec:encrypt: + * + * Whether the transmitted traffic must be encrypted. + * + * Since: 1.6 + **/ + obj_properties[PROP_ENCRYPT] = g_param_spec_boolean(NM_SETTING_MACSEC_ENCRYPT, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacsec:mka-cak: + * + * The pre-shared CAK (Connectivity Association Key) for MACsec + * Key Agreement. + * + * Since: 1.6 + **/ + obj_properties[PROP_MKA_CAK] = + g_param_spec_string(NM_SETTING_MACSEC_MKA_CAK, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacsec:mka-cak-flags: + * + * Flags indicating how to handle the #NMSettingMacsec:mka-cak + * property. + * + * Since: 1.6 + **/ + obj_properties[PROP_MKA_CAK_FLAGS] = + g_param_spec_flags(NM_SETTING_MACSEC_MKA_CAK_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacsec:mka-ckn: + * + * The pre-shared CKN (Connectivity-association Key Name) for + * MACsec Key Agreement. + * + * Since: 1.6 + **/ + obj_properties[PROP_MKA_CKN] = g_param_spec_string(NM_SETTING_MACSEC_MKA_CKN, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacsec:port: + * + * The port component of the SCI (Secure Channel Identifier), between 1 and 65534. + * + * Since: 1.6 + **/ + obj_properties[PROP_PORT] = + g_param_spec_int(NM_SETTING_MACSEC_PORT, + "", + "", + 1, + 65534, + 1, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacsec:validation: + * + * Specifies the validation mode for incoming frames. + * + * Since: 1.6 + **/ + obj_properties[PROP_VALIDATION] = + g_param_spec_int(NM_SETTING_MACSEC_VALIDATION, + "", + "", + G_MININT, + G_MAXINT, + NM_SETTING_MACSEC_VALIDATION_STRICT, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacsec:send-sci: + * + * Specifies whether the SCI (Secure Channel Identifier) is included + * in every packet. + * + * Since: 1.12 + **/ + obj_properties[PROP_SEND_SCI] = + g_param_spec_boolean(NM_SETTING_MACSEC_SEND_SCI, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_MACSEC); +} diff --git a/src/libnm-core-impl/nm-setting-macvlan.c b/src/libnm-core-impl/nm-setting-macvlan.c new file mode 100644 index 0000000000..0e6414bce2 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-macvlan.c @@ -0,0 +1,332 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-macvlan.h" + +#include + +#include "nm-utils.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" +#include "nm-setting-wired.h" +#include "nm-connection-private.h" + +/** + * SECTION:nm-setting-macvlan + * @short_description: Describes connection properties for macvlan interfaces + * + * The #NMSettingMacvlan object is a #NMSetting subclass that describes properties + * necessary for connection to macvlan interfaces. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, PROP_MODE, PROP_PROMISCUOUS, PROP_TAP, ); + +typedef struct { + char * parent; + NMSettingMacvlanMode mode; + bool promiscuous : 1; + bool tap : 1; +} NMSettingMacvlanPrivate; + +G_DEFINE_TYPE(NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING) + +#define NM_SETTING_MACVLAN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_macvlan_get_parent: + * @setting: the #NMSettingMacvlan + * + * Returns: the #NMSettingMacvlan:parent property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_macvlan_get_parent(NMSettingMacvlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACVLAN(setting), NULL); + return NM_SETTING_MACVLAN_GET_PRIVATE(setting)->parent; +} + +/** + * nm_setting_macvlan_get_mode: + * @setting: the #NMSettingMacvlan + * + * Returns: the #NMSettingMacvlan:mode property of the setting + * + * Since: 1.2 + **/ +NMSettingMacvlanMode +nm_setting_macvlan_get_mode(NMSettingMacvlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACVLAN(setting), NM_SETTING_MACVLAN_MODE_UNKNOWN); + return NM_SETTING_MACVLAN_GET_PRIVATE(setting)->mode; +} + +/** + * nm_setting_macvlan_get_promiscuous: + * @setting: the #NMSettingMacvlan + * + * Returns: the #NMSettingMacvlan:promiscuous property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_macvlan_get_promiscuous(NMSettingMacvlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACVLAN(setting), FALSE); + return NM_SETTING_MACVLAN_GET_PRIVATE(setting)->promiscuous; +} + +/** + * nm_setting_macvlan_get_tap: + * @setting: the #NMSettingMacvlan + * + * Returns: the #NMSettingMacvlan:tap property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_macvlan_get_tap(NMSettingMacvlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACVLAN(setting), FALSE); + return NM_SETTING_MACVLAN_GET_PRIVATE(setting)->tap; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(setting); + NMSettingWired * s_wired; + + if (connection) + s_wired = nm_connection_get_setting_wired(connection); + else + s_wired = NULL; + + if (priv->parent) { + if (!nm_utils_is_uuid(priv->parent) && !nm_utils_ifname_valid_kernel(priv->parent, NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACVLAN_SETTING_NAME, + NM_SETTING_MACVLAN_PARENT); + return FALSE; + } + } else { + /* If parent is NULL, the parent must be specified via + * NMSettingWired:mac-address. + */ + if (connection && (!s_wired || !nm_setting_wired_get_mac_address(s_wired))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is not specified and neither is '%s:%s'"), + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_MAC_ADDRESS); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACVLAN_SETTING_NAME, + NM_SETTING_MACVLAN_PARENT); + return FALSE; + } + } + + if (!priv->promiscuous && priv->mode != NM_SETTING_MACVLAN_MODE_PASSTHRU) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("non promiscuous operation is allowed only in passthru mode")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MACVLAN_SETTING_NAME, + NM_SETTING_MACVLAN_PROMISCUOUS); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingMacvlan * setting = NM_SETTING_MACVLAN(object); + NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string(value, priv->parent); + break; + case PROP_MODE: + g_value_set_uint(value, priv->mode); + break; + case PROP_PROMISCUOUS: + g_value_set_boolean(value, priv->promiscuous); + break; + case PROP_TAP: + g_value_set_boolean(value, priv->tap); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingMacvlan * setting = NM_SETTING_MACVLAN(object); + NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_free(priv->parent); + priv->parent = g_value_dup_string(value); + break; + case PROP_MODE: + priv->mode = g_value_get_uint(value); + break; + case PROP_PROMISCUOUS: + priv->promiscuous = g_value_get_boolean(value); + break; + case PROP_TAP: + priv->tap = g_value_get_boolean(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_macvlan_init(NMSettingMacvlan *self) +{ + NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(self); + + priv->promiscuous = TRUE; +} + +/** + * nm_setting_macvlan_new: + * + * Creates a new #NMSettingMacvlan object with default values. + * + * Returns: (transfer full): the new empty #NMSettingMacvlan object + * + * Since: 1.2 + **/ +NMSetting * +nm_setting_macvlan_new(void) +{ + return g_object_new(NM_TYPE_SETTING_MACVLAN, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingMacvlan * setting = NM_SETTING_MACVLAN(object); + NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE(setting); + + g_free(priv->parent); + + G_OBJECT_CLASS(nm_setting_macvlan_parent_class)->finalize(object); +} + +static void +nm_setting_macvlan_class_init(NMSettingMacvlanClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingMacvlanPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingMacvlan:parent: + * + * If given, specifies the parent interface name or parent connection UUID + * from which this MAC-VLAN interface should be created. If this property is + * not specified, the connection must contain an #NMSettingWired setting + * with a #NMSettingWired:mac-address property. + * + * Since: 1.2 + **/ + obj_properties[PROP_PARENT] = g_param_spec_string( + NM_SETTING_MACVLAN_PARENT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacvlan:mode: + * + * The macvlan mode, which specifies the communication mechanism between multiple + * macvlans on the same lower device. + * + * Since: 1.2 + **/ + obj_properties[PROP_MODE] = + g_param_spec_uint(NM_SETTING_MACVLAN_MODE, + "", + "", + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacvlan:promiscuous: + * + * Whether the interface should be put in promiscuous mode. + * + * Since: 1.2 + **/ + obj_properties[PROP_PROMISCUOUS] = g_param_spec_boolean( + NM_SETTING_MACVLAN_PROMISCUOUS, + "", + "", + TRUE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMacvlan:tap: + * + * Whether the interface should be a MACVTAP. + * + * Since: 1.2 + **/ + obj_properties[PROP_TAP] = g_param_spec_boolean(NM_SETTING_MACVLAN_TAP, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_MACVLAN); +} diff --git a/src/libnm-core-impl/nm-setting-match.c b/src/libnm-core-impl/nm-setting-match.c new file mode 100644 index 0000000000..fbc02c574e --- /dev/null +++ b/src/libnm-core-impl/nm-setting-match.c @@ -0,0 +1,899 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-match.h" + +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-match + * @short_description: Properties to match a connection with a device. + * @include: nm-setting-match.h + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingMatch, + PROP_INTERFACE_NAME, + PROP_KERNEL_COMMAND_LINE, + PROP_DRIVER, + PROP_PATH, ); + +/** + * NMSettingMatch: + * + * Match settings + * + * Since: 1.14 + */ +struct _NMSettingMatch { + NMSetting parent; + GArray * interface_name; + GArray * kernel_command_line; + GArray * driver; + GArray * path; +}; + +struct _NMSettingMatchClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingMatch, nm_setting_match, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_match_get_num_interface_names: + * @setting: the #NMSettingMatch + * + * Returns: the number of configured interface names + * + * Since: 1.14 + **/ +guint +nm_setting_match_get_num_interface_names(NMSettingMatch *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), 0); + + return nm_g_array_len(setting->interface_name); +} + +/** + * nm_setting_match_get_interface_name: + * @setting: the #NMSettingMatch + * @idx: index number of the DNS search domain to return + * + * Returns: the interface name at index @idx + * + * Since: 1.14 + **/ +const char * +nm_setting_match_get_interface_name(NMSettingMatch *setting, int idx) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); + + g_return_val_if_fail(setting->interface_name && idx >= 0 && idx < setting->interface_name->len, + NULL); + + return g_array_index(setting->interface_name, const char *, idx); +} + +/** + * nm_setting_match_add_interface_name: + * @setting: the #NMSettingMatch + * @interface_name: the interface name to add + * + * Adds a new interface name to the setting. + * + * Since: 1.14 + **/ +void +nm_setting_match_add_interface_name(NMSettingMatch *setting, const char *interface_name) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + g_return_if_fail(interface_name != NULL); + g_return_if_fail(interface_name[0] != '\0'); + + nm_strvarray_add(nm_strvarray_ensure(&setting->interface_name), interface_name); + _notify(setting, PROP_INTERFACE_NAME); +} + +/** + * nm_setting_match_remove_interface_name: + * @setting: the #NMSettingMatch + * @idx: index number of the interface name + * + * Removes the interface name at index @idx. + * + * Since: 1.14 + **/ +void +nm_setting_match_remove_interface_name(NMSettingMatch *setting, int idx) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + + g_return_if_fail(setting->interface_name && idx >= 0 && idx < setting->interface_name->len); + + g_array_remove_index(setting->interface_name, idx); + _notify(setting, PROP_INTERFACE_NAME); +} + +/** + * nm_setting_match_remove_interface_name_by_value: + * @setting: the #NMSettingMatch + * @interface_name: the interface name to remove + * + * Removes @interface_name. + * + * Returns: %TRUE if the interface name was found and removed; %FALSE if it was not. + * + * Since: 1.14 + **/ +gboolean +nm_setting_match_remove_interface_name_by_value(NMSettingMatch *setting, const char *interface_name) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), FALSE); + g_return_val_if_fail(interface_name != NULL, FALSE); + g_return_val_if_fail(interface_name[0] != '\0', FALSE); + + if (nm_strvarray_remove_first(setting->interface_name, interface_name)) { + _notify(setting, PROP_INTERFACE_NAME); + return TRUE; + } + + return FALSE; +} + +/** + * nm_setting_match_clear_interface_names: + * @setting: the #NMSettingMatch + * + * Removes all configured interface names. + * + * Since: 1.14 + **/ +void +nm_setting_match_clear_interface_names(NMSettingMatch *setting) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + + if (nm_g_array_len(setting->interface_name) != 0) { + nm_clear_pointer(&setting->interface_name, g_array_unref); + _notify(setting, PROP_INTERFACE_NAME); + } +} + +/** + * nm_setting_match_get_interface_names: + * @setting: the #NMSettingMatch + * @length: (out) (allow-none): the length of the returned interface names array. + * + * Returns all the interface names. + * + * Returns: (transfer none) (array length=length): the NULL terminated list of + * configured interface names. + * + * Before 1.26, the returned array was not %NULL terminated and you MUST provide a length. + * + * Since: 1.14 + **/ +const char *const * +nm_setting_match_get_interface_names(NMSettingMatch *setting, guint *length) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); + + return nm_strvarray_get_strv(&setting->interface_name, length); +} + +/*****************************************************************************/ + +/** + * nm_setting_match_get_num_kernel_command_lines: + * @setting: the #NMSettingMatch + * + * Returns: the number of configured kernel command line arguments + * + * Since: 1.26 + **/ +guint +nm_setting_match_get_num_kernel_command_lines(NMSettingMatch *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), 0); + + return nm_g_array_len(setting->kernel_command_line); +} + +/** + * nm_setting_match_get_kernel_command_line: + * @setting: the #NMSettingMatch + * @idx: index number of the kernel command line argument to return + * + * Returns: the kernel command line argument at index @idx + * + * Since: 1.26 + **/ +const char * +nm_setting_match_get_kernel_command_line(NMSettingMatch *setting, guint idx) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); + + g_return_val_if_fail(setting->kernel_command_line && idx < setting->kernel_command_line->len, + NULL); + + return g_array_index(setting->kernel_command_line, const char *, idx); +} + +/** + * nm_setting_match_add_kernel_command_line: + * @setting: the #NMSettingMatch + * @kernel_command_line: the kernel command line argument to add + * + * Adds a new kernel command line argument to the setting. + * + * Since: 1.26 + **/ +void +nm_setting_match_add_kernel_command_line(NMSettingMatch *setting, const char *kernel_command_line) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + g_return_if_fail(kernel_command_line != NULL); + g_return_if_fail(kernel_command_line[0] != '\0'); + + nm_strvarray_add(nm_strvarray_ensure(&setting->kernel_command_line), kernel_command_line); + _notify(setting, PROP_KERNEL_COMMAND_LINE); +} + +/** + * nm_setting_match_remove_kernel_command_line: + * @setting: the #NMSettingMatch + * @idx: index number of the kernel command line argument + * + * Removes the kernel command line argument at index @idx. + * + * Since: 1.26 + **/ +void +nm_setting_match_remove_kernel_command_line(NMSettingMatch *setting, guint idx) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + + g_return_if_fail(setting->kernel_command_line && idx < setting->kernel_command_line->len); + + g_array_remove_index(setting->kernel_command_line, idx); + _notify(setting, PROP_KERNEL_COMMAND_LINE); +} + +/** + * nm_setting_match_remove_kernel_command_line_by_value: + * @setting: the #NMSettingMatch + * @kernel_command_line: the kernel command line argument name to remove + * + * Removes @kernel_command_line. + * + * Returns: %TRUE if the kernel command line argument was found and removed; %FALSE if it was not. + * + * Since: 1.26 + **/ +gboolean +nm_setting_match_remove_kernel_command_line_by_value(NMSettingMatch *setting, + const char * kernel_command_line) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), FALSE); + g_return_val_if_fail(kernel_command_line != NULL, FALSE); + g_return_val_if_fail(kernel_command_line[0] != '\0', FALSE); + + if (nm_strvarray_remove_first(setting->kernel_command_line, kernel_command_line)) { + _notify(setting, PROP_KERNEL_COMMAND_LINE); + return TRUE; + } + + return FALSE; +} + +/** + * nm_setting_match_clear_kernel_command_lines: + * @setting: the #NMSettingMatch + * + * Removes all configured kernel command line arguments. + * + * Since: 1.26 + **/ +void +nm_setting_match_clear_kernel_command_lines(NMSettingMatch *setting) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + + if (nm_g_array_len(setting->kernel_command_line) != 0) { + nm_clear_pointer(&setting->kernel_command_line, g_array_unref); + _notify(setting, PROP_KERNEL_COMMAND_LINE); + } +} + +/** + * nm_setting_match_get_kernel_command_lines: + * @setting: the #NMSettingMatch + * @length: (out) (allow-none): the length of the returned interface names array. + * + * Returns all the interface names. + * + * Returns: (transfer none) (array length=length): the configured interface names. + * + * Since: 1.26 + **/ +const char *const * +nm_setting_match_get_kernel_command_lines(NMSettingMatch *setting, guint *length) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); + + return nm_strvarray_get_strv(&setting->kernel_command_line, length); +} + +/*****************************************************************************/ + +/** + * nm_setting_match_get_num_drivers: + * @setting: the #NMSettingMatch + * + * Returns: the number of configured drivers + * + * Since: 1.26 + **/ +guint +nm_setting_match_get_num_drivers(NMSettingMatch *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), 0); + + return nm_g_array_len(setting->driver); +} + +/** + * nm_setting_match_get_driver: + * @setting: the #NMSettingMatch + * @idx: index number of the DNS search domain to return + * + * Returns: the driver at index @idx + * + * Since: 1.26 + **/ +const char * +nm_setting_match_get_driver(NMSettingMatch *setting, guint idx) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); + + g_return_val_if_fail(setting->driver && idx < setting->driver->len, NULL); + + return g_array_index(setting->driver, const char *, idx); +} + +/** + * nm_setting_match_add_driver: + * @setting: the #NMSettingMatch + * @driver: the driver to add + * + * Adds a new driver to the setting. + * + * Since: 1.26 + **/ +void +nm_setting_match_add_driver(NMSettingMatch *setting, const char *driver) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + g_return_if_fail(driver != NULL); + g_return_if_fail(driver[0] != '\0'); + + nm_strvarray_add(nm_strvarray_ensure(&setting->driver), driver); + _notify(setting, PROP_DRIVER); +} + +/** + * nm_setting_match_remove_driver: + * @setting: the #NMSettingMatch + * @idx: index number of the driver + * + * Removes the driver at index @idx. + * + * Since: 1.26 + **/ +void +nm_setting_match_remove_driver(NMSettingMatch *setting, guint idx) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + + g_return_if_fail(setting->driver && idx < setting->driver->len); + + g_array_remove_index(setting->driver, idx); + _notify(setting, PROP_DRIVER); +} + +/** + * nm_setting_match_remove_driver_by_value: + * @setting: the #NMSettingMatch + * @driver: the driver to remove + * + * Removes @driver. + * + * Returns: %TRUE if the driver was found and removed; %FALSE if it was not. + * + * Since: 1.26 + **/ +gboolean +nm_setting_match_remove_driver_by_value(NMSettingMatch *setting, const char *driver) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), FALSE); + g_return_val_if_fail(driver != NULL, FALSE); + g_return_val_if_fail(driver[0] != '\0', FALSE); + + if (nm_strvarray_remove_first(setting->driver, driver)) { + _notify(setting, PROP_DRIVER); + return TRUE; + } + + return FALSE; +} + +/** + * nm_setting_match_clear_drivers: + * @setting: the #NMSettingMatch + * + * Removes all configured drivers. + * + * Since: 1.26 + **/ +void +nm_setting_match_clear_drivers(NMSettingMatch *setting) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + + if (nm_g_array_len(setting->driver) != 0) { + nm_clear_pointer(&setting->driver, g_array_unref); + _notify(setting, PROP_DRIVER); + } +} + +/** + * nm_setting_match_get_drivers: + * @setting: the #NMSettingMatch + * @length: (out) (allow-none): the length of the returned interface names array. + * + * Returns all the drivers. + * + * Returns: (transfer none) (array length=length): the configured drivers. + * + * Since: 1.26 + **/ +const char *const * +nm_setting_match_get_drivers(NMSettingMatch *setting, guint *length) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); + + return nm_strvarray_get_strv(&setting->driver, length); +} + +/*****************************************************************************/ + +/** + * nm_setting_match_get_num_paths: + * @setting: the #NMSettingMatch + * + * Returns: the number of configured paths + * + * Since: 1.26 + **/ +guint +nm_setting_match_get_num_paths(NMSettingMatch *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), 0); + + return nm_g_array_len(setting->path); +} + +/** + * nm_setting_match_get_path: + * @setting: the #NMSettingMatch + * @idx: index number of the path to return + * + * Returns: the path at index @idx + * + * Since: 1.26 + **/ +const char * +nm_setting_match_get_path(NMSettingMatch *setting, guint idx) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); + + g_return_val_if_fail(setting->path && idx < setting->path->len, NULL); + + return g_array_index(setting->path, const char *, idx); +} + +/** + * nm_setting_match_add_path: + * @setting: the #NMSettingMatch + * @path: the path to add + * + * Adds a new path to the setting. + * + * Since: 1.26 + **/ +void +nm_setting_match_add_path(NMSettingMatch *setting, const char *path) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + g_return_if_fail(path != NULL); + g_return_if_fail(path[0] != '\0'); + + nm_strvarray_add(nm_strvarray_ensure(&setting->path), path); + _notify(setting, PROP_PATH); +} + +/** + * nm_setting_match_remove_path: + * @setting: the #NMSettingMatch + * @idx: index number of the path + * + * Removes the path at index @idx. + * + * Since: 1.26 + **/ +void +nm_setting_match_remove_path(NMSettingMatch *setting, guint idx) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + + g_return_if_fail(setting->path && idx < setting->path->len); + + g_array_remove_index(setting->path, idx); + _notify(setting, PROP_PATH); +} + +/** + * nm_setting_match_remove_path_by_value: + * @setting: the #NMSettingMatch + * @path: the path to remove + * + * Removes @path. + * + * Returns: %TRUE if the path was found and removed; %FALSE if it was not. + * + * Since: 1.26 + **/ +gboolean +nm_setting_match_remove_path_by_value(NMSettingMatch *setting, const char *path) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), FALSE); + g_return_val_if_fail(path != NULL, FALSE); + g_return_val_if_fail(path[0] != '\0', FALSE); + + if (nm_strvarray_remove_first(setting->path, path)) { + _notify(setting, PROP_PATH); + return TRUE; + } + + return FALSE; +} + +/** + * nm_setting_match_clear_paths: + * @setting: the #NMSettingMatch + * + * Removes all configured paths. + * + * Since: 1.26 + **/ +void +nm_setting_match_clear_paths(NMSettingMatch *setting) +{ + g_return_if_fail(NM_IS_SETTING_MATCH(setting)); + + if (nm_g_array_len(setting->path) != 0) { + nm_clear_pointer(&setting->path, g_array_unref); + _notify(setting, PROP_PATH); + } +} + +/** + * nm_setting_match_get_paths: + * @setting: the #NMSettingMatch + * @length: (out) (allow-none): the length of the returned paths array. + * + * Returns all the paths. + * + * Returns: (transfer none) (array length=length): the configured paths. + * + * Since: 1.26 + **/ +const char *const * +nm_setting_match_get_paths(NMSettingMatch *setting, guint *length) +{ + g_return_val_if_fail(NM_IS_SETTING_MATCH(setting), NULL); + + return nm_strvarray_get_strv(&setting->path, length); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingMatch *self = NM_SETTING_MATCH(object); + + switch (prop_id) { + case PROP_INTERFACE_NAME: + g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(self->interface_name, NULL)); + break; + case PROP_KERNEL_COMMAND_LINE: + g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(self->kernel_command_line, NULL)); + break; + case PROP_DRIVER: + g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(self->driver, NULL)); + break; + case PROP_PATH: + g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(self->path, NULL)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingMatch *self = NM_SETTING_MATCH(object); + + switch (prop_id) { + case PROP_INTERFACE_NAME: + nm_strvarray_set_strv(&self->interface_name, g_value_get_boxed(value)); + break; + case PROP_KERNEL_COMMAND_LINE: + nm_strvarray_set_strv(&self->kernel_command_line, g_value_get_boxed(value)); + break; + case PROP_DRIVER: + nm_strvarray_set_strv(&self->driver, g_value_get_boxed(value)); + break; + case PROP_PATH: + nm_strvarray_set_strv(&self->path, g_value_get_boxed(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_match_init(NMSettingMatch *setting) +{} + +/** + * nm_setting_match_new: + * + * Creates a new #NMSettingMatch object with default values. + * + * Returns: (transfer full): the new empty #NMSettingMatch object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_match_new(void) +{ + return g_object_new(NM_TYPE_SETTING_MATCH, NULL); +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingMatch *self = NM_SETTING_MATCH(setting); + guint i; + + if (self->interface_name) { + for (i = 0; i < self->interface_name->len; i++) { + if (nm_str_is_empty(g_array_index(self->interface_name, const char *, i))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MATCH_SETTING_NAME, + NM_SETTING_MATCH_INTERFACE_NAME); + return FALSE; + } + } + } + + if (self->kernel_command_line) { + for (i = 0; i < self->kernel_command_line->len; i++) { + if (nm_str_is_empty(g_array_index(self->kernel_command_line, const char *, i))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MATCH_SETTING_NAME, + NM_SETTING_MATCH_KERNEL_COMMAND_LINE); + return FALSE; + } + } + } + + if (self->driver) { + for (i = 0; i < self->driver->len; i++) { + if (nm_str_is_empty(g_array_index(self->driver, const char *, i))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MATCH_SETTING_NAME, + NM_SETTING_MATCH_DRIVER); + return FALSE; + } + } + } + + if (self->path) { + for (i = 0; i < self->path->len; i++) { + if (nm_str_is_empty(g_array_index(self->path, const char *, i))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_MATCH_SETTING_NAME, + NM_SETTING_MATCH_PATH); + return FALSE; + } + } + } + + return TRUE; +} + +static void +finalize(GObject *object) +{ + NMSettingMatch *self = NM_SETTING_MATCH(object); + + nm_clear_pointer(&self->interface_name, g_array_unref); + nm_clear_pointer(&self->kernel_command_line, g_array_unref); + nm_clear_pointer(&self->driver, g_array_unref); + nm_clear_pointer(&self->path, g_array_unref); + + G_OBJECT_CLASS(nm_setting_match_parent_class)->finalize(object); +} + +static void +nm_setting_match_class_init(NMSettingMatchClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingMatch:interface-name + * + * A list of interface names to match. Each element is a shell wildcard + * pattern. + * + * An element can be prefixed with a pipe symbol (|) or an ampersand (&). + * The former means that the element is optional and the latter means that + * it is mandatory. If there are any optional elements, than the match + * evaluates to true if at least one of the optional element matches + * (logical OR). If there are any mandatory elements, then they all + * must match (logical AND). By default, an element is optional. This means + * that an element "foo" behaves the same as "|foo". An element can also be inverted + * with exclamation mark (!) between the pipe symbol (or the ampersand) and before + * the pattern. Note that "!foo" is a shortcut for the mandatory match "&!foo". Finally, + * a backslash can be used at the beginning of the element (after the optional special characters) + * to escape the start of the pattern. For example, "&\\!a" is an mandatory match for literally "!a". + * + * Since: 1.14 + **/ + obj_properties[PROP_INTERFACE_NAME] = g_param_spec_boxed( + NM_SETTING_MATCH_INTERFACE_NAME, + "", + "", + G_TYPE_STRV, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMatch:kernel-command-line + * + * A list of kernel command line arguments to match. This may be used to check + * whether a specific kernel command line option is set (or if prefixed with + * the exclamation mark unset). The argument must either be a single word, or + * an assignment (i.e. two words, separated "="). In the former case the kernel + * command line is searched for the word appearing as is, or as left hand side + * of an assignment. In the latter case, the exact assignment is looked for + * with right and left hand side matching. + * + * See NMSettingMatch:interface-name for how special characters '|', '&', + * '!' and '\\' are used for optional and mandatory matches and inverting the + * pattern. + * + * Since: 1.26 + **/ + obj_properties[PROP_KERNEL_COMMAND_LINE] = g_param_spec_boxed( + NM_SETTING_MATCH_KERNEL_COMMAND_LINE, + "", + "", + G_TYPE_STRV, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMatch:driver + * + * A list of driver names to match. Each element is a shell wildcard pattern. + * + * See NMSettingMatch:interface-name for how special characters '|', '&', + * '!' and '\\' are used for optional and mandatory matches and inverting the + * pattern. + * + * Since: 1.26 + **/ + obj_properties[PROP_DRIVER] = g_param_spec_boxed( + NM_SETTING_MATCH_DRIVER, + "", + "", + G_TYPE_STRV, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingMatch:path + * + * A list of paths to match against the ID_PATH udev property of + * devices. ID_PATH represents the topological persistent path of a + * device. It typically contains a subsystem string (pci, usb, platform, + * etc.) and a subsystem-specific identifier. + * + * For PCI devices the path has the form + * "pci-$domain:$bus:$device.$function", where each variable is an + * hexadecimal value; for example "pci-0000:0a:00.0". + * + * The path of a device can be obtained with "udevadm info + * /sys/class/net/$dev | grep ID_PATH=" or by looking at the "path" + * property exported by NetworkManager ("nmcli -f general.path device + * show $dev"). + * + * Each element of the list is a shell wildcard pattern. + * + * See NMSettingMatch:interface-name for how special characters '|', '&', + * '!' and '\\' are used for optional and mandatory matches and inverting the + * pattern. + * + * Since: 1.26 + **/ + /* ---ifcfg-rh--- + * property: path + * variable: MATCH_PATH + * description: space-separated list of paths to match against the udev + * property ID_PATHS of devices + * example: MATCH_PATH="pci-0000:01:00.0 pci-0000:0c:00.0" + * ---end--- + */ + obj_properties[PROP_PATH] = g_param_spec_boxed(NM_SETTING_MATCH_PATH, + "", + "", + G_TYPE_STRV, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_MATCH); +} diff --git a/src/libnm-core-impl/nm-setting-olpc-mesh.c b/src/libnm-core-impl/nm-setting-olpc-mesh.c new file mode 100644 index 0000000000..04e24ffc36 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-olpc-mesh.c @@ -0,0 +1,274 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2009 One Laptop per Child + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-olpc-mesh.h" + +#include + +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-olpc-mesh + * @short_description: Describes connection properties for OLPC-Mesh devices + * + * The #NMSettingOlpcMesh object is a #NMSetting subclass that describes properties + * necessary for connection to OLPC-Mesh devices. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_SSID, PROP_CHANNEL, PROP_DHCP_ANYCAST_ADDRESS, ); + +typedef struct { + GBytes *ssid; + char * dhcp_anycast_addr; + guint32 channel; +} NMSettingOlpcMeshPrivate; + +G_DEFINE_TYPE(NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING) + +#define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_olpc_mesh_get_ssid: + * @setting: the #NMSettingOlpcMesh + * + * Returns: (transfer none): + */ +GBytes * +nm_setting_olpc_mesh_get_ssid(NMSettingOlpcMesh *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_OLPC_MESH(setting), NULL); + + return NM_SETTING_OLPC_MESH_GET_PRIVATE(setting)->ssid; +} + +guint32 +nm_setting_olpc_mesh_get_channel(NMSettingOlpcMesh *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_OLPC_MESH(setting), 0); + + return NM_SETTING_OLPC_MESH_GET_PRIVATE(setting)->channel; +} + +const char * +nm_setting_olpc_mesh_get_dhcp_anycast_address(NMSettingOlpcMesh *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_OLPC_MESH(setting), NULL); + + return NM_SETTING_OLPC_MESH_GET_PRIVATE(setting)->dhcp_anycast_addr; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE(setting); + gsize length; + + if (!priv->ssid) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OLPC_MESH_SETTING_NAME, + NM_SETTING_OLPC_MESH_SSID); + return FALSE; + } + + length = g_bytes_get_size(priv->ssid); + if (length == 0 || length > 32) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("SSID length is out of range <1-32> bytes")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OLPC_MESH_SETTING_NAME, + NM_SETTING_OLPC_MESH_SSID); + return FALSE; + } + + if (priv->channel == 0 || priv->channel > 13) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%d' is not a valid channel"), + priv->channel); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OLPC_MESH_SETTING_NAME, + NM_SETTING_OLPC_MESH_CHANNEL); + return FALSE; + } + + if (priv->dhcp_anycast_addr && !nm_utils_hwaddr_valid(priv->dhcp_anycast_addr, ETH_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OLPC_MESH_SETTING_NAME, + NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOlpcMesh *setting = NM_SETTING_OLPC_MESH(object); + + switch (prop_id) { + case PROP_SSID: + g_value_set_boxed(value, nm_setting_olpc_mesh_get_ssid(setting)); + break; + case PROP_CHANNEL: + g_value_set_uint(value, nm_setting_olpc_mesh_get_channel(setting)); + break; + case PROP_DHCP_ANYCAST_ADDRESS: + g_value_set_string(value, nm_setting_olpc_mesh_get_dhcp_anycast_address(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_SSID: + if (priv->ssid) + g_bytes_unref(priv->ssid); + priv->ssid = g_value_dup_boxed(value); + break; + case PROP_CHANNEL: + priv->channel = g_value_get_uint(value); + break; + case PROP_DHCP_ANYCAST_ADDRESS: + g_free(priv->dhcp_anycast_addr); + priv->dhcp_anycast_addr = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_olpc_mesh_init(NMSettingOlpcMesh *setting) +{} + +/** + * nm_setting_olpc_mesh_new: + * + * Creates a new #NMSettingOlpcMesh object with default values. + * + * Returns: the new empty #NMSettingOlpcMesh object + **/ +NMSetting * +nm_setting_olpc_mesh_new(void) +{ + return g_object_new(NM_TYPE_SETTING_OLPC_MESH, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE(object); + + if (priv->ssid) + g_bytes_unref(priv->ssid); + g_free(priv->dhcp_anycast_addr); + + G_OBJECT_CLASS(nm_setting_olpc_mesh_parent_class)->finalize(object); +} + +static void +nm_setting_olpc_mesh_class_init(NMSettingOlpcMeshClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingOlpcMeshPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingOlpcMesh:ssid: + * + * SSID of the mesh network to join. + **/ + obj_properties[PROP_SSID] = g_param_spec_boxed(NM_SETTING_OLPC_MESH_SSID, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOlpcMesh:channel: + * + * Channel on which the mesh network to join is located. + **/ + obj_properties[PROP_CHANNEL] = + g_param_spec_uint(NM_SETTING_OLPC_MESH_CHANNEL, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOlpcMesh:dhcp-anycast-address: + * + * Anycast DHCP MAC address used when requesting an IP address via DHCP. + * The specific anycast address used determines which DHCP server class + * answers the request. + **/ + obj_properties[PROP_DHCP_ANYCAST_ADDRESS] = + g_param_spec_string(NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_DHCP_ANYCAST_ADDRESS], + &nm_sett_info_propert_type_mac_address); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_OLPC_MESH, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-ovs-bridge.c b/src/libnm-core-impl/nm-setting-ovs-bridge.c new file mode 100644 index 0000000000..9d67231b93 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ovs-bridge.c @@ -0,0 +1,374 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ovs-bridge.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-bridge + * @short_description: Describes connection properties for Open vSwitch bridges. + * + * The #NMSettingOvsBridge object is a #NMSetting subclass that describes properties + * necessary for Open vSwitch bridges. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_FAIL_MODE, + PROP_MCAST_SNOOPING_ENABLE, + PROP_RSTP_ENABLE, + PROP_STP_ENABLE, + PROP_DATAPATH_TYPE, ); + +/** + * NMSettingOvsBridge: + * + * OvsBridge Link Settings + */ +struct _NMSettingOvsBridge { + NMSetting parent; + + char *fail_mode; + char *datapath_type; + bool mcast_snooping_enable : 1; + bool rstp_enable : 1; + bool stp_enable : 1; +}; + +struct _NMSettingOvsBridgeClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_bridge_get_fail_mode: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:fail_mode property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_bridge_get_fail_mode(NMSettingOvsBridge *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), NULL); + + return self->fail_mode; +} + +/** + * nm_setting_ovs_bridge_get_mcast_snooping_enable: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:mcast_snooping_enable property of the setting + * + * Since: 1.10 + **/ +gboolean +nm_setting_ovs_bridge_get_mcast_snooping_enable(NMSettingOvsBridge *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), FALSE); + + return self->mcast_snooping_enable; +} + +/** + * nm_setting_ovs_bridge_get_rstp_enable: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:rstp_enable property of the setting + * + * Since: 1.10 + **/ +gboolean +nm_setting_ovs_bridge_get_rstp_enable(NMSettingOvsBridge *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), FALSE); + + return self->rstp_enable; +} + +/** + * nm_setting_ovs_bridge_get_stp_enable: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:stp_enable property of the setting + * + * Since: 1.10 + **/ +gboolean +nm_setting_ovs_bridge_get_stp_enable(NMSettingOvsBridge *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), FALSE); + + return self->stp_enable; +} + +/** + * nm_setting_ovs_bridge_get_datapath_type: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:datapath_type property of the setting + * + * Since: 1.20 + **/ +const char * +nm_setting_ovs_bridge_get_datapath_type(NMSettingOvsBridge *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_BRIDGE(self), NULL); + + return self->datapath_type; +} + +/*****************************************************************************/ + +static int +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE(setting); + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + if (connection) { + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + if (nm_setting_connection_get_master(s_con)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must not have a master."), + NM_SETTING_OVS_BRIDGE_SETTING_NAME); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_MASTER); + return FALSE; + } + } + + if (!NM_IN_STRSET(self->fail_mode, "secure", "standalone", NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not allowed in fail_mode"), + self->fail_mode); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_FAIL_MODE); + return FALSE; + } + + if (!NM_IN_STRSET(self->datapath_type, "system", "netdev", NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not valid"), + self->datapath_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_DATAPATH_TYPE); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE(object); + + switch (prop_id) { + case PROP_FAIL_MODE: + g_value_set_string(value, self->fail_mode); + break; + case PROP_MCAST_SNOOPING_ENABLE: + g_value_set_boolean(value, self->mcast_snooping_enable); + break; + case PROP_RSTP_ENABLE: + g_value_set_boolean(value, self->rstp_enable); + break; + case PROP_STP_ENABLE: + g_value_set_boolean(value, self->stp_enable); + break; + case PROP_DATAPATH_TYPE: + g_value_set_string(value, self->datapath_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE(object); + + switch (prop_id) { + case PROP_FAIL_MODE: + g_free(self->fail_mode); + self->fail_mode = g_value_dup_string(value); + break; + case PROP_MCAST_SNOOPING_ENABLE: + self->mcast_snooping_enable = g_value_get_boolean(value); + break; + case PROP_RSTP_ENABLE: + self->rstp_enable = g_value_get_boolean(value); + break; + case PROP_STP_ENABLE: + self->stp_enable = g_value_get_boolean(value); + break; + case PROP_DATAPATH_TYPE: + g_free(self->datapath_type); + self->datapath_type = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_bridge_init(NMSettingOvsBridge *self) +{} + +/** + * nm_setting_ovs_bridge_new: + * + * Creates a new #NMSettingOvsBridge object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsBridge object + * + * Since: 1.10 + **/ +NMSetting * +nm_setting_ovs_bridge_new(void) +{ + return g_object_new(NM_TYPE_SETTING_OVS_BRIDGE, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE(object); + + g_free(self->fail_mode); + g_free(self->datapath_type); + + G_OBJECT_CLASS(nm_setting_ovs_bridge_parent_class)->finalize(object); +} + +static void +nm_setting_ovs_bridge_class_init(NMSettingOvsBridgeClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingOvsBridge:fail-mode: + * + * The bridge failure mode. One of "secure", "standalone" or empty. + * + * Since: 1.10 + **/ + obj_properties[PROP_FAIL_MODE] = g_param_spec_string( + NM_SETTING_OVS_BRIDGE_FAIL_MODE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsBridge:mcast-snooping-enable: + * + * Enable or disable multicast snooping. + * + * Since: 1.10 + **/ + obj_properties[PROP_MCAST_SNOOPING_ENABLE] = + g_param_spec_boolean(NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsBridge:rstp-enable: + * + * Enable or disable RSTP. + * + * Since: 1.10 + **/ + obj_properties[PROP_RSTP_ENABLE] = + g_param_spec_boolean(NM_SETTING_OVS_BRIDGE_RSTP_ENABLE, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsBridge:stp-enable: + * + * Enable or disable STP. + * + * Since: 1.10 + **/ + obj_properties[PROP_STP_ENABLE] = + g_param_spec_boolean(NM_SETTING_OVS_BRIDGE_STP_ENABLE, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsBridge:datapath-type: + * + * The data path type. One of "system", "netdev" or empty. + * + * Since: 1.20 + **/ + obj_properties[PROP_DATAPATH_TYPE] = g_param_spec_string( + NM_SETTING_OVS_BRIDGE_DATAPATH_TYPE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_BRIDGE); +} diff --git a/src/libnm-core-impl/nm-setting-ovs-dpdk.c b/src/libnm-core-impl/nm-setting-ovs-dpdk.c new file mode 100644 index 0000000000..957b0f5716 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ovs-dpdk.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ovs-dpdk.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-dpdk + * @short_description: Describes connection properties for Open vSwitch DPDK interfaces. + * + * The #NMSettingOvsDpdk object is a #NMSetting subclass that describes properties + * necessary for Open vSwitch interfaces of type "dpdk". + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_DEVARGS, ); + +/** + * NMSettingOvsDpdk: + * + * OvsDpdk Link Settings + */ +struct _NMSettingOvsDpdk { + NMSetting parent; + + char *devargs; +}; + +struct _NMSettingOvsDpdkClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingOvsDpdk, nm_setting_ovs_dpdk, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_dpdk_get_devargs: + * @self: the #NMSettingOvsDpdk + * + * Returns: the #NMSettingOvsDpdk:devargs property of the setting + * + * Since: 1.20 + **/ +const char * +nm_setting_ovs_dpdk_get_devargs(NMSettingOvsDpdk *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_DPDK(self), NULL); + + return self->devargs; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOvsDpdk *self = NM_SETTING_OVS_DPDK(object); + + switch (prop_id) { + case PROP_DEVARGS: + g_value_set_string(value, self->devargs); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsDpdk *self = NM_SETTING_OVS_DPDK(object); + + switch (prop_id) { + case PROP_DEVARGS: + g_free(self->devargs); + self->devargs = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_dpdk_init(NMSettingOvsDpdk *self) +{} + +/** + * nm_setting_ovs_dpdk_new: + * + * Creates a new #NMSettingOvsDpdk object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsDpdk object + * + * Since: 1.20 + **/ +NMSetting * +nm_setting_ovs_dpdk_new(void) +{ + return g_object_new(NM_TYPE_SETTING_OVS_DPDK, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingOvsDpdk *self = NM_SETTING_OVS_DPDK(object); + + g_free(self->devargs); + + G_OBJECT_CLASS(nm_setting_ovs_dpdk_parent_class)->finalize(object); +} + +static void +nm_setting_ovs_dpdk_class_init(NMSettingOvsDpdkClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /** + * NMSettingOvsDpdk:devargs: + * + * Open vSwitch DPDK device arguments. + * + * Since: 1.20 + **/ + obj_properties[PROP_DEVARGS] = g_param_spec_string( + NM_SETTING_OVS_DPDK_DEVARGS, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_DPDK); +} diff --git a/src/libnm-core-impl/nm-setting-ovs-external-ids.c b/src/libnm-core-impl/nm-setting-ovs-external-ids.c new file mode 100644 index 0000000000..b73c1af497 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ovs-external-ids.c @@ -0,0 +1,551 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 - 2020 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ovs-external-ids.h" + +#include "nm-setting-private.h" +#include "nm-utils-private.h" +#include "nm-connection-private.h" + +#define MAX_NUM_KEYS 256 + +/*****************************************************************************/ + +/** + * SECTION:nm-setting-ovs-external-ids + * @short_description: External-IDs for OVS database + * + * The #NMSettingOvsExternalIDs object is a #NMSetting subclass that allow to + * configure external ids for OVS. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingOvsExternalIDs, PROP_DATA, ); + +typedef struct { + GHashTable * data; + const char **data_keys; +} NMSettingOvsExternalIDsPrivate; + +/** + * NMSettingOvsExternalIDs: + * + * OVS External IDs Settings + */ +struct _NMSettingOvsExternalIDs { + NMSetting parent; + NMSettingOvsExternalIDsPrivate _priv; +}; + +struct _NMSettingOvsExternalIDsClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingOvsExternalIDs, nm_setting_ovs_external_ids, NM_TYPE_SETTING) + +#define NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingOvsExternalIDs, NM_IS_SETTING_OVS_EXTERNAL_IDS) + +/*****************************************************************************/ + +static gboolean +_exid_key_char_is_regular(char ch) +{ + /* allow words of printable characters, plus some + * special characters, for example to support base64 encoding. */ + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') + || NM_IN_SET(ch, '-', '_', '+', '/', '=', '.'); +} + +/** + * nm_setting_ovs_external_ids_check_key: + * @key: (allow-none): the key to check + * @error: a #GError, %NULL to ignore. + * + * Checks whether @key is a valid key for OVS' external-ids. + * This means, the key cannot be %NULL, not too large and valid ASCII. + * Also, only digits and numbers are allowed with a few special + * characters. They key must also not start with "NM.". + * + * Since: 1.30 + * + * Returns: %TRUE if @key is a valid user data key. + */ +gboolean +nm_setting_ovs_external_ids_check_key(const char *key, GError **error) +{ + gsize len; + + g_return_val_if_fail(!error || !*error, FALSE); + + if (!key || !key[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("missing key")); + return FALSE; + } + len = strlen(key); + if (len > 255u) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key is too long")); + return FALSE; + } + if (!g_utf8_validate(key, len, NULL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key must be UTF8")); + return FALSE; + } + if (!NM_STRCHAR_ALL(key, ch, _exid_key_char_is_regular(ch))) { + /* Probably OVS is more forgiving about what makes a valid key for + * an external-id. However, we are strict (at least, for now). */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key contains invalid characters")); + return FALSE; + } + + if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX)) { + /* these keys are reserved. */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key cannot start with \"NM.\"")); + return FALSE; + } + + return TRUE; +} + +/** + * nm_setting_ovs_external_ids_check_val: + * @val: (allow-none): the value to check + * @error: a #GError, %NULL to ignore. + * + * Checks whether @val is a valid user data value. This means, + * value is not %NULL, not too large and valid UTF-8. + * + * Since: 1.30 + * + * Returns: %TRUE if @val is a valid user data value. + */ +gboolean +nm_setting_ovs_external_ids_check_val(const char *val, GError **error) +{ + gsize len; + + g_return_val_if_fail(!error || !*error, FALSE); + + if (!val) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value is missing")); + return FALSE; + } + + len = strlen(val); + if (len > (8u * 1024u)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value is too large")); + return FALSE; + } + + if (!g_utf8_validate(val, len, NULL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value is not valid UTF8")); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static GHashTable * +_create_data_hash(void) +{ + return g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); +} + +GHashTable * +_nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *self) +{ + return NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self)->data; +} + +/** + * nm_setting_ovs_external_ids_get_data_keys: + * @setting: the #NMSettingOvsExternalIDs + * @out_len: (out): the length of the returned array + * + * Returns: (array length=out_len) (transfer none): a + * %NULL-terminated array containing each key from the table. + **/ +const char *const * +nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting, guint *out_len) +{ + NMSettingOvsExternalIDs * self = setting; + NMSettingOvsExternalIDsPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self), NULL); + + priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); + + if (priv->data_keys) { + NM_SET_OUT(out_len, g_hash_table_size(priv->data)); + return priv->data_keys; + } + + priv->data_keys = nm_utils_strdict_get_keys(priv->data, TRUE, out_len); + + /* don't return %NULL, but hijack the @data_keys fields as a pseudo + * empty strv array. */ + return priv->data_keys ?: ((const char **) &priv->data_keys); +} + +/*****************************************************************************/ + +/** + * nm_setting_ovs_external_ids_get_data: + * @setting: the #NMSettingOvsExternalIDs instance + * @key: the external-id to lookup + * + * Since: 1.30 + * + * Returns: (transfer none): the value associated with @key or %NULL if no such + * value exists. + */ +const char * +nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *setting, const char *key) +{ + NMSettingOvsExternalIDs * self = setting; + NMSettingOvsExternalIDsPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self), NULL); + g_return_val_if_fail(key, NULL); + + priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); + + if (!priv->data) + return NULL; + + return g_hash_table_lookup(priv->data, key); +} + +/** + * nm_setting_ovs_external_ids_set_data: + * @setting: the #NMSettingOvsExternalIDs instance + * @key: the key to set + * @val: (allow-none): the value to set or %NULL to clear a key. + * + * Since: 1.30 + */ +void +nm_setting_ovs_external_ids_set_data(NMSettingOvsExternalIDs *setting, + const char * key, + const char * val) +{ + NMSettingOvsExternalIDs * self = setting; + NMSettingOvsExternalIDsPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self)); + + priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); + + if (!val) { + if (priv->data && g_hash_table_remove(priv->data, key)) + goto out_changed; + return; + } + + if (priv->data) { + const char *val2; + + if (g_hash_table_lookup_extended(priv->data, key, NULL, (gpointer *) &val2)) { + if (nm_streq(val, val2)) + return; + } + } else + priv->data = _create_data_hash(); + + g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); + +out_changed: + nm_clear_g_free(&priv->data_keys); + _notify(self, PROP_DATA); +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(setting); + NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); + + if (priv->data) { + gs_free_error GError *local = NULL; + GHashTableIter iter; + const char * key; + const char * val; + + g_hash_table_iter_init(&iter, priv->data); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + if (!nm_setting_ovs_external_ids_check_key(key, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid key \"%s\": %s"), + key, + local->message); + } else if (!nm_setting_ovs_external_ids_check_val(val, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid value for \"%s\": %s"), + key, + local->message); + } else + continue; + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + NM_SETTING_OVS_EXTERNAL_IDS_DATA); + return FALSE; + } + } + + if (priv->data && g_hash_table_size(priv->data) > MAX_NUM_KEYS) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("maximum number of user data entries reached (%u instead of %u)"), + g_hash_table_size(priv->data), + (unsigned) MAX_NUM_KEYS); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + NM_SETTING_OVS_EXTERNAL_IDS_DATA); + return FALSE; + } + + if (connection) { + NMSettingConnection *s_con; + const char * type; + const char * slave_type; + + type = nm_connection_get_connection_type(connection); + if (!type) { + NMSetting *s_base; + + s_base = _nm_connection_find_base_type_setting(connection); + if (s_base) + type = nm_setting_get_name(s_base); + } + if (NM_IN_STRSET(type, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME)) + goto connection_type_is_good; + + if ((s_con = nm_connection_get_setting_connection(connection)) + && _nm_connection_detect_slave_type_full(s_con, + connection, + &slave_type, + NULL, + NULL, + NULL, + NULL) + && nm_streq0(slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) + goto connection_type_is_good; + + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("OVS external IDs can only be added to a profile of type OVS " + "bridge/port/interface or to OVS system interface")); + return FALSE; + } +connection_type_is_good: + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingOvsExternalIDsPrivate *priv; + NMSettingOvsExternalIDsPrivate *pri2; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) + return NM_TERNARY_DEFAULT; + + if (!set_b) + return TRUE; + + priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(NM_SETTING_OVS_EXTERNAL_IDS(set_a)); + pri2 = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(NM_SETTING_OVS_EXTERNAL_IDS(set_b)); + return nm_utils_hashtable_equal(priv->data, pri2->data, TRUE, g_str_equal); + } + + return NM_SETTING_CLASS(nm_setting_ovs_external_ids_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object); + NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); + GHashTableIter iter; + GHashTable * data; + const char * key; + const char * val; + + switch (prop_id) { + case PROP_DATA: + data = _create_data_hash(); + if (priv->data) { + g_hash_table_iter_init(&iter, priv->data); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert(data, g_strdup(key), g_strdup(val)); + } + g_value_take_boxed(value, data); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object); + NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); + + switch (prop_id) { + case PROP_DATA: + { + gs_unref_hashtable GHashTable *old = NULL; + GHashTableIter iter; + GHashTable * data; + const char * key; + const char * val; + + nm_clear_g_free(&priv->data_keys); + + old = g_steal_pointer(&priv->data); + + data = g_value_get_boxed(value); + if (nm_g_hash_table_size(data) <= 0) + return; + + priv->data = _create_data_hash(); + g_hash_table_iter_init(&iter, data); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_external_ids_init(NMSettingOvsExternalIDs *self) +{} + +/** + * nm_setting_ovs_external_ids_new: + * + * Creates a new #NMSettingOvsExternalIDs object with default values. + * + * Returns: (transfer full) (type NMSettingOvsExternalIDs): the new empty + * #NMSettingOvsExternalIDs object + * + * Since: 1.30 + */ +NMSetting * +nm_setting_ovs_external_ids_new(void) +{ + return g_object_new(NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object); + NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); + + g_free(priv->data_keys); + if (priv->data) + g_hash_table_unref(priv->data); + + G_OBJECT_CLASS(nm_setting_ovs_external_ids_parent_class)->finalize(object); +} + +static void +nm_setting_ovs_external_ids_class_init(NMSettingOvsExternalIDsClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + + /** + * NMSettingOvsExternalIDs:data: (type GHashTable(utf8,utf8)) + * + * A dictionary of key/value pairs with exernal-ids for OVS. + * + * Since: 1.30 + **/ + obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_OVS_EXTERNAL_IDS_DATA, + "", + "", + G_TYPE_HASH_TABLE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_DATA], + &nm_sett_info_propert_type_strdict); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-ovs-interface.c b/src/libnm-core-impl/nm-setting-ovs-interface.c new file mode 100644 index 0000000000..1fde96050a --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ovs-interface.c @@ -0,0 +1,427 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ovs-interface.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-interface + * @short_description: Describes connection properties for Open vSwitch interfaces. + * + * The #NMSettingOvsInterface object is a #NMSetting subclass that describes properties + * necessary for Open vSwitch interfaces. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_TYPE, ); + +/** + * NMSettingOvsInterface: + * + * Open vSwitch Interface Settings + */ +struct _NMSettingOvsInterface { + NMSetting parent; + + char *type; +}; + +struct _NMSettingOvsInterfaceClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_interface_get_interface_type: + * @self: the #NMSettingOvsInterface + * + * Returns: the #NMSettingOvsInterface:type property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_interface_get_interface_type(NMSettingOvsInterface *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_INTERFACE(self), NULL); + + return self->type; +} + +/*****************************************************************************/ + +int +_nm_setting_ovs_interface_verify_interface_type(NMSettingOvsInterface *self, + const char * type, + NMConnection * connection, + gboolean normalize, + gboolean * out_modified, + const char ** out_normalized_type, + GError ** error) +{ + const char *type_from_setting = NULL; + const char *type_setting = NULL; + const char *connection_type; + gboolean is_ovs_connection_type; + + if (normalize) { + g_return_val_if_fail(NM_IS_SETTING_OVS_INTERFACE(self), FALSE); + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + nm_assert(self == nm_connection_get_setting_ovs_interface(connection)); + } else { + g_return_val_if_fail(!self || NM_IS_SETTING_OVS_INTERFACE(self), FALSE); + g_return_val_if_fail(!connection || NM_IS_CONNECTION(connection), FALSE); + } + + NM_SET_OUT(out_modified, FALSE); + NM_SET_OUT(out_normalized_type, NULL); + + if (type && !NM_IN_STRSET(type, "internal", "system", "patch", "dpdk")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid interface type"), + type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + + if (!connection) { + NM_SET_OUT(out_normalized_type, type); + return TRUE; + } + + connection_type = nm_connection_get_connection_type(connection); + if (!connection_type) { + /* if we have an ovs-interface, then the connection type must be either + * "ovs-interface" (for non "system" type) or anything else (for "system" type). + * + * The connection type usually can be normalized based on the presence of a + * base setting. However, in this case, if the connection type is missing, + * that is too complicate to guess what the user wanted. + * + * Require the use to be explicit and fail. */ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting needs connection.type explicitly set"), + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TYPE); + return FALSE; + } + + if (nm_streq(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) { + if (type && nm_streq(type, "system")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection of type '%s' cannot have ovs-interface.type \"system\""), + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + is_ovs_connection_type = TRUE; + } else { + if (type && !nm_streq(type, "system")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection of type '%s' cannot have an ovs-interface.type \"%s\""), + connection_type, + type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + is_ovs_connection_type = FALSE; + } + + if (nm_connection_get_setting_by_name(connection, NM_SETTING_OVS_PATCH_SETTING_NAME)) { + type_from_setting = "patch"; + type_setting = NM_SETTING_OVS_PATCH_SETTING_NAME; + } + + if (nm_connection_get_setting_by_name(connection, NM_SETTING_OVS_DPDK_SETTING_NAME)) { + if (type_from_setting) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection can not have both '%s' and '%s' settings at the same time"), + NM_SETTING_OVS_DPDK_SETTING_NAME, + type_setting); + return FALSE; + } + type_from_setting = "dpdk"; + type_setting = NM_SETTING_OVS_DPDK_SETTING_NAME; + } + + if (type_from_setting) { + if (!is_ovs_connection_type) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with '%s' setting must be of connection.type " + "\"ovs-interface\" but is \"%s\""), + NM_SETTING_OVS_PATCH_SETTING_NAME, + connection_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + + if (type) { + if (!nm_streq(type, type_from_setting)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with '%s' setting needs to be of '%s' interface type, " + "not '%s'"), + type_setting, + type_from_setting, + type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + NM_SET_OUT(out_normalized_type, type); + return TRUE; + } + type = type_from_setting; + goto normalize; + } else { + if (nm_streq0(type, "patch")) { + g_set_error( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("A connection with ovs-interface.type '%s' setting a 'ovs-patch' setting"), + type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + } + + if (type) { + NM_SET_OUT(out_normalized_type, type); + return TRUE; + } + + if (is_ovs_connection_type) + type = "internal"; + else + type = "system"; + + NM_SET_OUT(out_normalized_type, type); + +normalize: + if (!normalize) { + if (!self) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("Missing ovs interface setting")); + g_prefix_error(error, "%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME); + } else { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("Missing ovs interface type")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_TYPE); + } + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + if (!self) { + self = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); + nm_connection_add_setting(connection, NM_SETTING(self)); + } + g_object_set(self, NM_SETTING_OVS_INTERFACE_TYPE, type, NULL); + NM_SET_OUT(out_modified, TRUE); + + return TRUE; +} + +static int +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE(setting); + NMSettingConnection * s_con = NULL; + + if (connection) { + const char *slave_type; + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + if (!nm_setting_connection_get_master(s_con)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have a master."), + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_MASTER); + return FALSE; + } + + slave_type = nm_setting_connection_get_slave_type(s_con); + if (slave_type && !nm_streq(slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have the slave-type set to '%s'. " + "Instead it is '%s'"), + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME, + slave_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + } + + return _nm_setting_ovs_interface_verify_interface_type(self, + self->type, + connection, + FALSE, + NULL, + NULL, + error); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE(object); + + switch (prop_id) { + case PROP_TYPE: + g_value_set_string(value, self->type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE(object); + + switch (prop_id) { + case PROP_TYPE: + g_free(self->type); + self->type = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_interface_init(NMSettingOvsInterface *self) +{} + +/** + * nm_setting_ovs_interface_new: + * + * Creates a new #NMSettingOvsInterface object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsInterface object + * + * Since: 1.10 + **/ +NMSetting * +nm_setting_ovs_interface_new(void) +{ + return g_object_new(NM_TYPE_SETTING_OVS_INTERFACE, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE(object); + + g_free(self->type); + + G_OBJECT_CLASS(nm_setting_ovs_interface_parent_class)->finalize(object); +} + +static void +nm_setting_ovs_interface_class_init(NMSettingOvsInterfaceClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingOvsInterface:type: + * + * The interface type. Either "internal", "system", "patch", "dpdk", or empty. + * + * Since: 1.10 + **/ + obj_properties[PROP_TYPE] = g_param_spec_string(NM_SETTING_OVS_INTERFACE_TYPE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_INTERFACE); +} diff --git a/src/libnm-core-impl/nm-setting-ovs-patch.c b/src/libnm-core-impl/nm-setting-ovs-patch.c new file mode 100644 index 0000000000..a226a26d47 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ovs-patch.c @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ovs-patch.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-patch + * @short_description: Describes connection properties for Open vSwitch patch interfaces. + * + * The #NMSettingOvsPatch object is a #NMSetting subclass that describes properties + * necessary for Open vSwitch interfaces of type "patch". + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PEER, ); + +/** + * NMSettingOvsPatch: + * + * OvsPatch Link Settings + */ +struct _NMSettingOvsPatch { + NMSetting parent; + + char *peer; +}; + +struct _NMSettingOvsPatchClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_patch_get_peer: + * @self: the #NMSettingOvsPatch + * + * Returns: the #NMSettingOvsPatch:peer property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_patch_get_peer(NMSettingOvsPatch *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PATCH(self), NULL); + + return self->peer; +} + +/*****************************************************************************/ + +static int +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH(setting); + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + if (!self->peer) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_PATCH_SETTING_NAME, + NM_SETTING_OVS_PATCH_PEER); + return FALSE; + } + + if (!nm_utils_ifname_valid(self->peer, NMU_IFACE_OVS, error)) { + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_PATCH_SETTING_NAME, + NM_SETTING_OVS_PATCH_PEER); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH(object); + + switch (prop_id) { + case PROP_PEER: + g_value_set_string(value, self->peer); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH(object); + + switch (prop_id) { + case PROP_PEER: + g_free(self->peer); + self->peer = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_patch_init(NMSettingOvsPatch *self) +{} + +/** + * nm_setting_ovs_patch_new: + * + * Creates a new #NMSettingOvsPatch object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsPatch object + * + * Since: 1.10 + **/ +NMSetting * +nm_setting_ovs_patch_new(void) +{ + return g_object_new(NM_TYPE_SETTING_OVS_PATCH, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH(object); + + g_free(self->peer); + + G_OBJECT_CLASS(nm_setting_ovs_patch_parent_class)->finalize(object); +} + +static void +nm_setting_ovs_patch_class_init(NMSettingOvsPatchClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingOvsPatch:peer: + * + * Specifies the name of the interface for the other side of the patch. + * The patch on the other side must also set this interface as peer. + * + * Since: 1.10 + **/ + obj_properties[PROP_PEER] = g_param_spec_string(NM_SETTING_OVS_PATCH_PEER, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_PATCH); +} diff --git a/src/libnm-core-impl/nm-setting-ovs-port.c b/src/libnm-core-impl/nm-setting-ovs-port.c new file mode 100644 index 0000000000..821f29ab14 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ovs-port.c @@ -0,0 +1,467 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ovs-port.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-port + * @short_description: Describes connection properties for Open vSwitch ports. + * + * The #NMSettingOvsPort object is a #NMSetting subclass that describes properties + * necessary for Open vSwitch ports. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_VLAN_MODE, + PROP_TAG, + PROP_LACP, + PROP_BOND_MODE, + PROP_BOND_UPDELAY, + PROP_BOND_DOWNDELAY, ); + +/** + * NMSettingOvsPort: + * + * OvsPort Link Settings + */ +struct _NMSettingOvsPort { + NMSetting parent; + + char *vlan_mode; + char *lacp; + char *bond_mode; + guint tag; + guint bond_updelay; + guint bond_downdelay; +}; + +struct _NMSettingOvsPortClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_port_get_vlan_mode: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:vlan-mode property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_port_get_vlan_mode(NMSettingOvsPort *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), NULL); + + return self->vlan_mode; +} + +/** + * nm_setting_ovs_port_get_tag: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:tag property of the setting + * + * Since: 1.10 + **/ +guint +nm_setting_ovs_port_get_tag(NMSettingOvsPort *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), 0); + + return self->tag; +} + +/** + * nm_setting_ovs_port_get_lacp: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:lacp property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_port_get_lacp(NMSettingOvsPort *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), NULL); + + return self->lacp; +} + +/** + * nm_setting_ovs_port_get_bond_mode: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:bond-mode property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_port_get_bond_mode(NMSettingOvsPort *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), NULL); + + return self->bond_mode; +} + +/** + * nm_setting_ovs_port_get_bond_updelay: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:bond-updelay property of the setting + * + * Since: 1.10 + **/ +guint +nm_setting_ovs_port_get_bond_updelay(NMSettingOvsPort *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), 0); + + return self->bond_updelay; +} + +/** + * nm_setting_ovs_port_get_bond_downdelay: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:bond-downdelay property of the setting + * + * Since: 1.10 + **/ +guint +nm_setting_ovs_port_get_bond_downdelay(NMSettingOvsPort *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), 0); + + return self->bond_downdelay; +} + +/*****************************************************************************/ + +static int +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT(setting); + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + if (connection) { + NMSettingConnection *s_con; + const char * slave_type; + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + if (!nm_setting_connection_get_master(s_con)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have a master."), + NM_SETTING_OVS_PORT_SETTING_NAME); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_MASTER); + return FALSE; + } + + slave_type = nm_setting_connection_get_slave_type(s_con); + if (slave_type && strcmp(slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have the slave-type set to '%s'. " + "Instead it is '%s'"), + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + slave_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + } + + if (!NM_IN_STRSET(self->vlan_mode, + "access", + "native-tagged", + "native-untagged", + "trunk", + NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not allowed in vlan_mode"), + self->vlan_mode); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_PORT_VLAN_MODE); + return FALSE; + } + + if (self->tag >= 4095) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the tag id must be in range 0-4094 but is %u"), + self->tag); + g_prefix_error(error, "%s.%s: ", NM_SETTING_OVS_PORT_SETTING_NAME, NM_SETTING_OVS_PORT_TAG); + return FALSE; + } + + if (!NM_IN_STRSET(self->lacp, "active", "off", "passive", NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not allowed in lacp"), + self->lacp); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_PORT_LACP); + return FALSE; + } + + if (!NM_IN_STRSET(self->bond_mode, "active-backup", "balance-slb", "balance-tcp", NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not allowed in bond_mode"), + self->bond_mode); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_PORT_BOND_MODE); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); + + switch (prop_id) { + case PROP_VLAN_MODE: + g_value_set_string(value, self->vlan_mode); + break; + case PROP_TAG: + g_value_set_uint(value, self->tag); + break; + case PROP_LACP: + g_value_set_string(value, self->lacp); + break; + case PROP_BOND_MODE: + g_value_set_string(value, self->bond_mode); + break; + case PROP_BOND_UPDELAY: + g_value_set_uint(value, self->bond_updelay); + break; + case PROP_BOND_DOWNDELAY: + g_value_set_uint(value, self->bond_downdelay); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); + + switch (prop_id) { + case PROP_VLAN_MODE: + g_free(self->vlan_mode); + self->vlan_mode = g_value_dup_string(value); + break; + case PROP_TAG: + self->tag = g_value_get_uint(value); + break; + case PROP_LACP: + g_free(self->lacp); + self->lacp = g_value_dup_string(value); + break; + case PROP_BOND_MODE: + g_free(self->bond_mode); + self->bond_mode = g_value_dup_string(value); + break; + case PROP_BOND_UPDELAY: + self->bond_updelay = g_value_get_uint(value); + break; + case PROP_BOND_DOWNDELAY: + self->bond_downdelay = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_port_init(NMSettingOvsPort *self) +{} + +/** + * nm_setting_ovs_port_new: + * + * Creates a new #NMSettingOvsPort object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsPort object + * + * Since: 1.10 + **/ +NMSetting * +nm_setting_ovs_port_new(void) +{ + return g_object_new(NM_TYPE_SETTING_OVS_PORT, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); + + g_free(self->vlan_mode); + g_free(self->lacp); + g_free(self->bond_mode); + + G_OBJECT_CLASS(nm_setting_ovs_port_parent_class)->finalize(object); +} + +static void +nm_setting_ovs_port_class_init(NMSettingOvsPortClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingOvsPort:vlan-mode: + * + * The VLAN mode. One of "access", "native-tagged", "native-untagged", + * "trunk" or unset. + * + * Since: 1.10 + **/ + obj_properties[PROP_VLAN_MODE] = g_param_spec_string( + NM_SETTING_OVS_PORT_VLAN_MODE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsPort:tag: + * + * The VLAN tag in the range 0-4095. + * + * Since: 1.10 + **/ + obj_properties[PROP_TAG] = + g_param_spec_uint(NM_SETTING_OVS_PORT_TAG, + "", + "", + 0, + 4095, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsPort:lacp: + * + * LACP mode. One of "active", "off", or "passive". + * + * Since: 1.10 + **/ + obj_properties[PROP_LACP] = g_param_spec_string(NM_SETTING_OVS_PORT_LACP, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsPort:bond-mode: + * + * Bonding mode. One of "active-backup", "balance-slb", or "balance-tcp". + * + * Since: 1.10 + **/ + obj_properties[PROP_BOND_MODE] = g_param_spec_string( + NM_SETTING_OVS_PORT_BOND_MODE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsPort:bond-updelay: + * + * The time port must be active before it starts forwarding traffic. + * + * Since: 1.10 + **/ + obj_properties[PROP_BOND_UPDELAY] = + g_param_spec_uint(NM_SETTING_OVS_PORT_BOND_UPDELAY, + "", + "", + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingOvsPort:bond-downdelay: + * + * The time port must be inactive in order to be considered down. + * + * Since: 1.10 + **/ + obj_properties[PROP_BOND_DOWNDELAY] = + g_param_spec_uint(NM_SETTING_OVS_PORT_BOND_DOWNDELAY, + "", + "", + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_OVS_PORT); +} diff --git a/src/libnm-core-impl/nm-setting-ppp.c b/src/libnm-core-impl/nm-setting-ppp.c new file mode 100644 index 0000000000..cddd83420f --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ppp.c @@ -0,0 +1,778 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ppp.h" + +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ppp + * @short_description: Describes connection properties for devices/networks + * that require PPP to deliver IP capability + * + * The #NMSettingPpp object is a #NMSetting subclass that describes properties + * necessary for connection to networks that require PPP transport, like PPPoE + * cable and DSL modems and some mobile broadband devices. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_NOAUTH, + PROP_REFUSE_EAP, + PROP_REFUSE_PAP, + PROP_REFUSE_CHAP, + PROP_REFUSE_MSCHAP, + PROP_REFUSE_MSCHAPV2, + PROP_NOBSDCOMP, + PROP_NODEFLATE, + PROP_NO_VJ_COMP, + PROP_REQUIRE_MPPE, + PROP_REQUIRE_MPPE_128, + PROP_MPPE_STATEFUL, + PROP_CRTSCTS, + PROP_BAUD, + PROP_MRU, + PROP_MTU, + PROP_LCP_ECHO_FAILURE, + PROP_LCP_ECHO_INTERVAL, ); + +typedef struct { + guint32 baud; + guint32 mru; + guint32 mtu; + guint32 lcp_echo_failure; + guint32 lcp_echo_interval; + bool noauth : 1; + bool refuse_eap : 1; + bool refuse_pap : 1; + bool refuse_chap : 1; + bool refuse_mschap : 1; + bool refuse_mschapv2 : 1; + bool nobsdcomp : 1; + bool nodeflate : 1; + bool no_vj_comp : 1; + bool require_mppe : 1; + bool require_mppe_128 : 1; + bool mppe_stateful : 1; + bool crtscts : 1; +} NMSettingPppPrivate; + +G_DEFINE_TYPE(NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING) + +#define NM_SETTING_PPP_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_PPP, NMSettingPppPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_ppp_get_noauth: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:noauth property of the setting + **/ +gboolean +nm_setting_ppp_get_noauth(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->noauth; +} + +/** + * nm_setting_ppp_get_refuse_eap: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:refuse-eap property of the setting + **/ +gboolean +nm_setting_ppp_get_refuse_eap(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_eap; +} + +/** + * nm_setting_ppp_get_refuse_pap: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:refuse-pap property of the setting + **/ +gboolean +nm_setting_ppp_get_refuse_pap(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_pap; +} + +/** + * nm_setting_ppp_get_refuse_chap: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:refuse-chap property of the setting + **/ +gboolean +nm_setting_ppp_get_refuse_chap(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_chap; +} + +/** + * nm_setting_ppp_get_refuse_mschap: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:refuse-mschap property of the setting + **/ +gboolean +nm_setting_ppp_get_refuse_mschap(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_mschap; +} + +/** + * nm_setting_ppp_get_refuse_mschapv2: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:refuse-mschapv2 property of the setting + **/ +gboolean +nm_setting_ppp_get_refuse_mschapv2(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->refuse_mschapv2; +} + +/** + * nm_setting_ppp_get_nobsdcomp: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:nobsdcomp property of the setting + **/ +gboolean +nm_setting_ppp_get_nobsdcomp(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->nobsdcomp; +} + +/** + * nm_setting_ppp_get_nodeflate: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:nodeflate property of the setting + **/ +gboolean +nm_setting_ppp_get_nodeflate(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->nodeflate; +} + +/** + * nm_setting_ppp_get_no_vj_comp: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:no-vj-comp property of the setting + **/ +gboolean +nm_setting_ppp_get_no_vj_comp(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->no_vj_comp; +} + +/** + * nm_setting_ppp_get_require_mppe: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:require-mppe property of the setting + **/ +gboolean +nm_setting_ppp_get_require_mppe(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->require_mppe; +} + +/** + * nm_setting_ppp_get_require_mppe_128: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:require-mppe-128 property of the setting + **/ +gboolean +nm_setting_ppp_get_require_mppe_128(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->require_mppe_128; +} + +/** + * nm_setting_ppp_get_mppe_stateful: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:mppe-stateful property of the setting + **/ +gboolean +nm_setting_ppp_get_mppe_stateful(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->mppe_stateful; +} + +/** + * nm_setting_ppp_get_crtscts: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:crtscts property of the setting + **/ +gboolean +nm_setting_ppp_get_crtscts(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->crtscts; +} + +/** + * nm_setting_ppp_get_baud: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:baud property of the setting + **/ +guint32 +nm_setting_ppp_get_baud(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->baud; +} + +/** + * nm_setting_ppp_get_mru: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:mru property of the setting + **/ +guint32 +nm_setting_ppp_get_mru(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->mru; +} + +/** + * nm_setting_ppp_get_mtu: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:mtu property of the setting + **/ +guint32 +nm_setting_ppp_get_mtu(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->mtu; +} + +/** + * nm_setting_ppp_get_lcp_echo_failure: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:lcp-echo-failure property of the setting + **/ +guint32 +nm_setting_ppp_get_lcp_echo_failure(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->lcp_echo_failure; +} + +/** + * nm_setting_ppp_get_lcp_echo_interval: + * @setting: the #NMSettingPpp + * + * Returns: the #NMSettingPpp:lcp-echo-interval property of the setting + **/ +guint32 +nm_setting_ppp_get_lcp_echo_interval(NMSettingPpp *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPP(setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE(setting)->lcp_echo_interval; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE(setting); + + /* FIXME: Do we even want this or can we just let pppd evaluate the options? */ + if (priv->mru > 0) { + if (priv->mru < 128 || priv->mru > 16384) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%d' is out of valid range <128-16384>"), + priv->mru); + g_prefix_error(error, "%s.%s: ", NM_SETTING_PPP_SETTING_NAME, NM_SETTING_PPP_MRU); + return FALSE; + } + } + + if (priv->lcp_echo_failure > 0) { + /* lcp_echo_interval must also be non-zero */ + if (priv->lcp_echo_interval == 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("setting this property requires non-zero '%s' property"), + NM_SETTING_PPP_LCP_ECHO_INTERVAL); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_PPP_SETTING_NAME, + NM_SETTING_PPP_LCP_ECHO_FAILURE); + return FALSE; + } + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingPpp *setting = NM_SETTING_PPP(object); + + switch (prop_id) { + case PROP_NOAUTH: + g_value_set_boolean(value, nm_setting_ppp_get_noauth(setting)); + break; + case PROP_REFUSE_EAP: + g_value_set_boolean(value, nm_setting_ppp_get_refuse_eap(setting)); + break; + case PROP_REFUSE_PAP: + g_value_set_boolean(value, nm_setting_ppp_get_refuse_pap(setting)); + break; + case PROP_REFUSE_CHAP: + g_value_set_boolean(value, nm_setting_ppp_get_refuse_chap(setting)); + break; + case PROP_REFUSE_MSCHAP: + g_value_set_boolean(value, nm_setting_ppp_get_refuse_mschap(setting)); + break; + case PROP_REFUSE_MSCHAPV2: + g_value_set_boolean(value, nm_setting_ppp_get_refuse_mschapv2(setting)); + break; + case PROP_NOBSDCOMP: + g_value_set_boolean(value, nm_setting_ppp_get_nobsdcomp(setting)); + break; + case PROP_NODEFLATE: + g_value_set_boolean(value, nm_setting_ppp_get_nodeflate(setting)); + break; + case PROP_NO_VJ_COMP: + g_value_set_boolean(value, nm_setting_ppp_get_no_vj_comp(setting)); + break; + case PROP_REQUIRE_MPPE: + g_value_set_boolean(value, nm_setting_ppp_get_require_mppe(setting)); + break; + case PROP_REQUIRE_MPPE_128: + g_value_set_boolean(value, nm_setting_ppp_get_require_mppe_128(setting)); + break; + case PROP_MPPE_STATEFUL: + g_value_set_boolean(value, nm_setting_ppp_get_mppe_stateful(setting)); + break; + case PROP_CRTSCTS: + g_value_set_boolean(value, nm_setting_ppp_get_crtscts(setting)); + break; + case PROP_BAUD: + g_value_set_uint(value, nm_setting_ppp_get_baud(setting)); + break; + case PROP_MRU: + g_value_set_uint(value, nm_setting_ppp_get_mru(setting)); + break; + case PROP_MTU: + g_value_set_uint(value, nm_setting_ppp_get_mtu(setting)); + break; + case PROP_LCP_ECHO_FAILURE: + g_value_set_uint(value, nm_setting_ppp_get_lcp_echo_failure(setting)); + break; + case PROP_LCP_ECHO_INTERVAL: + g_value_set_uint(value, nm_setting_ppp_get_lcp_echo_interval(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_NOAUTH: + priv->noauth = g_value_get_boolean(value); + break; + case PROP_REFUSE_EAP: + priv->refuse_eap = g_value_get_boolean(value); + break; + case PROP_REFUSE_PAP: + priv->refuse_pap = g_value_get_boolean(value); + break; + case PROP_REFUSE_CHAP: + priv->refuse_chap = g_value_get_boolean(value); + break; + case PROP_REFUSE_MSCHAP: + priv->refuse_mschap = g_value_get_boolean(value); + break; + case PROP_REFUSE_MSCHAPV2: + priv->refuse_mschapv2 = g_value_get_boolean(value); + break; + case PROP_NOBSDCOMP: + priv->nobsdcomp = g_value_get_boolean(value); + break; + case PROP_NODEFLATE: + priv->nodeflate = g_value_get_boolean(value); + break; + case PROP_NO_VJ_COMP: + priv->no_vj_comp = g_value_get_boolean(value); + break; + case PROP_REQUIRE_MPPE: + priv->require_mppe = g_value_get_boolean(value); + break; + case PROP_REQUIRE_MPPE_128: + priv->require_mppe_128 = g_value_get_boolean(value); + break; + case PROP_MPPE_STATEFUL: + priv->mppe_stateful = g_value_get_boolean(value); + break; + case PROP_CRTSCTS: + priv->crtscts = g_value_get_boolean(value); + break; + case PROP_BAUD: + priv->baud = g_value_get_uint(value); + break; + case PROP_MRU: + priv->mru = g_value_get_uint(value); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint(value); + break; + case PROP_LCP_ECHO_FAILURE: + priv->lcp_echo_failure = g_value_get_uint(value); + break; + case PROP_LCP_ECHO_INTERVAL: + priv->lcp_echo_interval = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ppp_init(NMSettingPpp *self) +{ + NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE(self); + + priv->noauth = TRUE; +} + +/** + * nm_setting_ppp_new: + * + * Creates a new #NMSettingPpp object with default values. + * + * Returns: (transfer full): the new empty #NMSettingPpp object + **/ +NMSetting * +nm_setting_ppp_new(void) +{ + return g_object_new(NM_TYPE_SETTING_PPP, NULL); +} + +static void +nm_setting_ppp_class_init(NMSettingPppClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingPppPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + + setting_class->verify = verify; + + /** + * NMSettingPpp:noauth: + * + * If %TRUE, do not require the other side (usually the PPP server) to + * authenticate itself to the client. If %FALSE, require authentication + * from the remote side. In almost all cases, this should be %TRUE. + **/ + obj_properties[PROP_NOAUTH] = g_param_spec_boolean(NM_SETTING_PPP_NOAUTH, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:refuse-eap: + * + * If %TRUE, the EAP authentication method will not be used. + **/ + obj_properties[PROP_REFUSE_EAP] = + g_param_spec_boolean(NM_SETTING_PPP_REFUSE_EAP, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:refuse-pap: + * + * If %TRUE, the PAP authentication method will not be used. + **/ + obj_properties[PROP_REFUSE_PAP] = + g_param_spec_boolean(NM_SETTING_PPP_REFUSE_PAP, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:refuse-chap: + * + * If %TRUE, the CHAP authentication method will not be used. + **/ + obj_properties[PROP_REFUSE_CHAP] = + g_param_spec_boolean(NM_SETTING_PPP_REFUSE_CHAP, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:refuse-mschap: + * + * If %TRUE, the MSCHAP authentication method will not be used. + **/ + obj_properties[PROP_REFUSE_MSCHAP] = + g_param_spec_boolean(NM_SETTING_PPP_REFUSE_MSCHAP, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:refuse-mschapv2: + * + * If %TRUE, the MSCHAPv2 authentication method will not be used. + **/ + obj_properties[PROP_REFUSE_MSCHAPV2] = + g_param_spec_boolean(NM_SETTING_PPP_REFUSE_MSCHAPV2, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:nobsdcomp: + * + * If %TRUE, BSD compression will not be requested. + **/ + obj_properties[PROP_NOBSDCOMP] = g_param_spec_boolean( + NM_SETTING_PPP_NOBSDCOMP, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:nodeflate: + * + * If %TRUE, "deflate" compression will not be requested. + **/ + obj_properties[PROP_NODEFLATE] = g_param_spec_boolean( + NM_SETTING_PPP_NODEFLATE, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:no-vj-comp: + * + * If %TRUE, Van Jacobsen TCP header compression will not be requested. + **/ + obj_properties[PROP_NO_VJ_COMP] = g_param_spec_boolean( + NM_SETTING_PPP_NO_VJ_COMP, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:require-mppe: + * + * If %TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for + * the PPP session. If either 64-bit or 128-bit MPPE is not available the + * session will fail. Note that MPPE is not used on mobile broadband + * connections. + **/ + obj_properties[PROP_REQUIRE_MPPE] = + g_param_spec_boolean(NM_SETTING_PPP_REQUIRE_MPPE, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:require-mppe-128: + * + * If %TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be + * required for the PPP session, and the "require-mppe" property must also + * be set to %TRUE. If 128-bit MPPE is not available the session will fail. + **/ + obj_properties[PROP_REQUIRE_MPPE_128] = + g_param_spec_boolean(NM_SETTING_PPP_REQUIRE_MPPE_128, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:mppe-stateful: + * + * If %TRUE, stateful MPPE is used. See pppd documentation for more + * information on stateful MPPE. + **/ + obj_properties[PROP_MPPE_STATEFUL] = + g_param_spec_boolean(NM_SETTING_PPP_MPPE_STATEFUL, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:crtscts: + * + * If %TRUE, specify that pppd should set the serial port to use hardware + * flow control with RTS and CTS signals. This value should normally be set + * to %FALSE. + **/ + obj_properties[PROP_CRTSCTS] = g_param_spec_boolean(NM_SETTING_PPP_CRTSCTS, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:baud: + * + * If non-zero, instruct pppd to set the serial port to the specified + * baudrate. This value should normally be left as 0 to automatically + * choose the speed. + **/ + obj_properties[PROP_BAUD] = g_param_spec_uint(NM_SETTING_PPP_BAUD, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:mru: + * + * If non-zero, instruct pppd to request that the peer send packets no + * larger than the specified size. If non-zero, the MRU should be between + * 128 and 16384. + */ + obj_properties[PROP_MRU] = g_param_spec_uint(NM_SETTING_PPP_MRU, + "", + "", + 0, + 16384, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:mtu: + * + * If non-zero, instruct pppd to send packets no larger than the specified + * size. + **/ + obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_PPP_MTU, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:lcp-echo-failure: + * + * If non-zero, instruct pppd to presume the connection to the peer has + * failed if the specified number of LCP echo-requests go unanswered by the + * peer. The "lcp-echo-interval" property must also be set to a non-zero + * value if this property is used. + **/ + obj_properties[PROP_LCP_ECHO_FAILURE] = g_param_spec_uint( + NM_SETTING_PPP_LCP_ECHO_FAILURE, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPpp:lcp-echo-interval: + * + * If non-zero, instruct pppd to send an LCP echo-request frame to the peer + * every n seconds (where n is the specified value). Note that some PPP + * peers will respond to echo requests and some will not, and it is not + * possible to autodetect this. + **/ + obj_properties[PROP_LCP_ECHO_INTERVAL] = g_param_spec_uint( + NM_SETTING_PPP_LCP_ECHO_INTERVAL, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_PPP); +} diff --git a/src/libnm-core-impl/nm-setting-pppoe.c b/src/libnm-core-impl/nm-setting-pppoe.c new file mode 100644 index 0000000000..218bf94e7e --- /dev/null +++ b/src/libnm-core-impl/nm-setting-pppoe.c @@ -0,0 +1,358 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-pppoe.h" + +#include "nm-setting-ppp.h" +#include "nm-setting-private.h" +#include "nm-core-enum-types.h" + +/** + * SECTION:nm-setting-pppoe + * @short_description: Describes PPPoE connection properties + * + * The #NMSettingPppoe object is a #NMSetting subclass that describes + * properties necessary for connection to networks that require PPPoE connections + * to provide IP transport, for example cable or DSL modems. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, + PROP_SERVICE, + PROP_USERNAME, + PROP_PASSWORD, + PROP_PASSWORD_FLAGS, ); + +typedef struct { + char * parent; + char * service; + char * username; + char * password; + NMSettingSecretFlags password_flags; +} NMSettingPppoePrivate; + +G_DEFINE_TYPE(NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING) + +#define NM_SETTING_PPPOE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_PPPOE, NMSettingPppoePrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_pppoe_get_parent: + * @setting: the #NMSettingPppoe + * + * Returns: the #NMSettingPppoe:parent property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_pppoe_get_parent(NMSettingPppoe *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NULL); + + return NM_SETTING_PPPOE_GET_PRIVATE(setting)->parent; +} + +/** + * nm_setting_pppoe_get_service: + * @setting: the #NMSettingPppoe + * + * Returns: the #NMSettingPppoe:service property of the setting + **/ +const char * +nm_setting_pppoe_get_service(NMSettingPppoe *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NULL); + + return NM_SETTING_PPPOE_GET_PRIVATE(setting)->service; +} + +/** + * nm_setting_pppoe_get_username: + * @setting: the #NMSettingPppoe + * + * Returns: the #NMSettingPppoe:username property of the setting + **/ +const char * +nm_setting_pppoe_get_username(NMSettingPppoe *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NULL); + + return NM_SETTING_PPPOE_GET_PRIVATE(setting)->username; +} + +/** + * nm_setting_pppoe_get_password: + * @setting: the #NMSettingPppoe + * + * Returns: the #NMSettingPppoe:password property of the setting + **/ +const char * +nm_setting_pppoe_get_password(NMSettingPppoe *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NULL); + + return NM_SETTING_PPPOE_GET_PRIVATE(setting)->password; +} + +/** + * nm_setting_pppoe_get_password_flags: + * @setting: the #NMSettingPppoe + * + * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingPppoe:password + **/ +NMSettingSecretFlags +nm_setting_pppoe_get_password_flags(NMSettingPppoe *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PPPOE(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_PPPOE_GET_PRIVATE(setting)->password_flags; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(setting); + gs_free_error GError *local_error = NULL; + + if (!priv->username) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_USERNAME); + return FALSE; + } else if (!strlen(priv->username)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_USERNAME); + return FALSE; + } + + if (priv->service && !strlen(priv->service)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_SERVICE); + return FALSE; + } + + if (priv->parent && !nm_utils_ifname_valid_kernel(priv->parent, &local_error)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "'%s': %s", + priv->parent, + local_error->message); + g_prefix_error(error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_PARENT); + return FALSE; + } + + return TRUE; +} + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(setting); + GPtrArray * secrets = NULL; + + if (priv->password) + return NULL; + + if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { + secrets = g_ptr_array_sized_new(1); + g_ptr_array_add(secrets, NM_SETTING_PPPOE_PASSWORD); + } + + return secrets; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingPppoe *setting = NM_SETTING_PPPOE(object); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string(value, nm_setting_pppoe_get_parent(setting)); + break; + case PROP_SERVICE: + g_value_set_string(value, nm_setting_pppoe_get_service(setting)); + break; + case PROP_USERNAME: + g_value_set_string(value, nm_setting_pppoe_get_username(setting)); + break; + case PROP_PASSWORD: + g_value_set_string(value, nm_setting_pppoe_get_password(setting)); + break; + case PROP_PASSWORD_FLAGS: + g_value_set_flags(value, nm_setting_pppoe_get_password_flags(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_PARENT: + g_free(priv->parent); + priv->parent = g_value_dup_string(value); + break; + case PROP_SERVICE: + g_free(priv->service); + priv->service = g_value_dup_string(value); + break; + case PROP_USERNAME: + g_free(priv->username); + priv->username = g_value_dup_string(value); + break; + case PROP_PASSWORD: + g_free(priv->password); + priv->password = g_value_dup_string(value); + break; + case PROP_PASSWORD_FLAGS: + priv->password_flags = g_value_get_flags(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_pppoe_init(NMSettingPppoe *setting) +{} + +/** + * nm_setting_pppoe_new: + * + * Creates a new #NMSettingPppoe object with default values. + * + * Returns: (transfer full): the new empty #NMSettingPppoe object + **/ +NMSetting * +nm_setting_pppoe_new(void) +{ + return g_object_new(NM_TYPE_SETTING_PPPOE, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(object); + + g_free(priv->parent); + g_free(priv->username); + g_free(priv->password); + g_free(priv->service); + + G_OBJECT_CLASS(nm_setting_pppoe_parent_class)->finalize(object); +} + +static void +nm_setting_pppoe_class_init(NMSettingPppoeClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingPppoePrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; + + /** + * NMSettingPppoe:parent: + * + * If given, specifies the parent interface name on which this PPPoE + * connection should be created. If this property is not specified, + * the connection is activated on the interface specified in + * #NMSettingConnection:interface-name of #NMSettingConnection. + * + * Since: 1.10 + **/ + obj_properties[PROP_PARENT] = g_param_spec_string( + NM_SETTING_PPPOE_PARENT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPppoe:service: + * + * If specified, instruct PPPoE to only initiate sessions with access + * concentrators that provide the specified service. For most providers, + * this should be left blank. It is only required if there are multiple + * access concentrators or a specific service is known to be required. + **/ + obj_properties[PROP_SERVICE] = g_param_spec_string(NM_SETTING_PPPOE_SERVICE, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPppoe:username: + * + * Username used to authenticate with the PPPoE service. + **/ + obj_properties[PROP_USERNAME] = g_param_spec_string(NM_SETTING_PPPOE_USERNAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPppoe:password: + * + * Password used to authenticate with the PPPoE service. + **/ + obj_properties[PROP_PASSWORD] = + g_param_spec_string(NM_SETTING_PPPOE_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingPppoe:password-flags: + * + * Flags indicating how to handle the #NMSettingPppoe:password property. + **/ + obj_properties[PROP_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_PPPOE_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_PPPOE); +} diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h new file mode 100644 index 0000000000..bf59a3c802 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-private.h @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_PRIVATE_H__ +#define __NM_SETTING_PRIVATE_H__ + +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) + #error Cannot use this header. +#endif + +#include "nm-setting.h" +#include "nm-setting-bridge.h" +#include "nm-connection.h" +#include "nm-core-enum-types.h" + +#include "libnm-core-intern/nm-core-internal.h" + +/*****************************************************************************/ + +NMSettingPriority _nm_setting_get_base_type_priority(NMSetting *setting); +int _nm_setting_compare_priority(gconstpointer a, gconstpointer b); + +/*****************************************************************************/ + +void _nm_setting_emit_property_changed(NMSetting *setting); + +typedef enum NMSettingUpdateSecretResult { + NM_SETTING_UPDATE_SECRET_ERROR = FALSE, + NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE, + NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED = 2, +} NMSettingUpdateSecretResult; + +NMSettingUpdateSecretResult + _nm_setting_update_secrets(NMSetting *setting, GVariant *secrets, GError **error); +gboolean _nm_setting_clear_secrets(NMSetting * setting, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data); + +/* The property of the #NMSetting should be considered during comparisons that + * use the %NM_SETTING_COMPARE_FLAG_INFERRABLE flag. Properties that don't have + * this flag, are ignored when doing an infrerrable comparison. This flag should + * be set on all properties that are read from the kernel or the system when a + * connection is generated. eg, IP addresses/routes can be read from the + * kernel, but the 'autoconnect' property cannot, so + * %NM_SETTING_IP4_CONFIG_ADDRESSES gets the INFERRABLE flag, but + * %NM_SETTING_CONNECTION_AUTOCONNECT would not. + * + * This flag should not be used with properties where the default cannot be + * read separately from the current value, like MTU or wired duplex mode. + */ +#define NM_SETTING_PARAM_INFERRABLE (1 << (4 + G_PARAM_USER_SHIFT)) + +/* This is a legacy property, which clients should not send to the daemon. */ +#define NM_SETTING_PARAM_LEGACY (1 << (5 + G_PARAM_USER_SHIFT)) + +/* When a connection is active and gets modified, usually the change + * to the settings-connection does not propagate automatically to the + * applied-connection of the device. For certain properties like the + * firewall zone and the metered property, this is different. + * + * Such fields can be ignored during nm_connection_compare() with the + * NMSettingCompareFlag NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY. + */ +#define NM_SETTING_PARAM_REAPPLY_IMMEDIATELY (1 << (6 + G_PARAM_USER_SHIFT)) + +/* property_to_dbus() should ignore the property flags, and instead always calls to_dbus_fcn() + */ +#define NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS (1 << (7 + G_PARAM_USER_SHIFT)) + +extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_interface_name; +extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_i; +extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_u; + +extern const NMSettInfoPropertType nm_sett_info_propert_type_plain_i; +extern const NMSettInfoPropertType nm_sett_info_propert_type_plain_u; + +NMSettingVerifyResult +_nm_setting_verify(NMSetting *setting, NMConnection *connection, GError **error); + +gboolean _nm_setting_verify_secret_string(const char *str, + const char *setting_name, + const char *property, + GError ** error); + +gboolean _nm_setting_aggregate(NMSetting *setting, NMConnectionAggregateType type, gpointer arg); + +gboolean _nm_setting_slave_type_is_valid(const char *slave_type, const char **out_port_type); + +GVariant *_nm_setting_to_dbus(NMSetting * setting, + NMConnection * connection, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options); + +NMSetting *_nm_setting_new_from_dbus(GType setting_type, + GVariant * setting_dict, + GVariant * connection_dict, + NMSettingParseFlags parse_flags, + GError ** error); + +gboolean _nm_setting_property_is_regular_secret(NMSetting *setting, const char *secret_name); +gboolean _nm_setting_property_is_regular_secret_flags(NMSetting * setting, + const char *secret_flags_name); + +/*****************************************************************************/ + +static inline GArray * +_nm_sett_info_property_override_create_array(void) +{ + return g_array_new(FALSE, FALSE, sizeof(NMSettInfoProperty)); +} + +GArray *_nm_sett_info_property_override_create_array_ip_config(void); + +void _nm_setting_class_commit_full(NMSettingClass * setting_class, + NMMetaSettingType meta_type, + const NMSettInfoSettDetail *detail, + GArray * properties_override); + +static inline void +_nm_setting_class_commit(NMSettingClass *setting_class, NMMetaSettingType meta_type) +{ + _nm_setting_class_commit_full(setting_class, meta_type, NULL, NULL); +} + +#define NM_SETT_INFO_SETT_GENDATA(...) \ + ({ \ + static const NMSettInfoSettGendata _g = {__VA_ARGS__}; \ + \ + &_g; \ + }) + +#define NM_SETT_INFO_SETT_DETAIL(...) (&((const NMSettInfoSettDetail){__VA_ARGS__})) + +#define NM_SETT_INFO_PROPERT_TYPE(...) \ + ({ \ + static const NMSettInfoPropertType _g = {__VA_ARGS__}; \ + \ + &_g; \ + }) + +#define NM_SETT_INFO_PROPERTY(...) (&((const NMSettInfoProperty){__VA_ARGS__})) + +gboolean _nm_properties_override_assert(const NMSettInfoProperty *prop_info); + +static inline void +_nm_properties_override(GArray *properties_override, const NMSettInfoProperty *prop_info) +{ + nm_assert(properties_override); + nm_assert(_nm_properties_override_assert(prop_info)); + g_array_append_vals(properties_override, prop_info, 1); +} + +#define _nm_properties_override_gobj(properties_override, p_param_spec, p_property_type) \ + _nm_properties_override( \ + (properties_override), \ + NM_SETT_INFO_PROPERTY(.param_spec = (p_param_spec), .property_type = (p_property_type), )) + +#define _nm_properties_override_dbus(properties_override, p_name, p_property_type) \ + _nm_properties_override( \ + (properties_override), \ + NM_SETT_INFO_PROPERTY(.name = ("" p_name ""), .property_type = (p_property_type), )) + +/*****************************************************************************/ + +gboolean _nm_setting_use_legacy_property(NMSetting * setting, + GVariant * connection_dict, + const char *legacy_property, + const char *new_property); + +GPtrArray *_nm_setting_need_secrets(NMSetting *setting); + +gboolean _nm_setting_should_compare_secret_property(NMSetting * setting, + NMSetting * other, + const char * secret_name, + NMSettingCompareFlags flags); + +NMBridgeVlan *_nm_bridge_vlan_dup(const NMBridgeVlan *vlan); +NMBridgeVlan *_nm_bridge_vlan_dup_and_seal(const NMBridgeVlan *vlan); + +/*****************************************************************************/ + +#endif /* NM_SETTING_PRIVATE_H */ diff --git a/src/libnm-core-impl/nm-setting-proxy.c b/src/libnm-core-impl/nm-setting-proxy.c new file mode 100644 index 0000000000..1e7eca8238 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-proxy.c @@ -0,0 +1,383 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2016 Atul Anand . + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-proxy.h" + +#include "nm-utils.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-proxy + * @short_description: Describes proxy URL, script and other related properties + * + * The #NMSettingProxy object is a #NMSetting subclass that describes properties + * related to Proxy settings like PAC URL, PAC script etc. + * + * NetworkManager support 2 values for the #NMSettingProxy:method property for + * proxy. If "auto" is specified then WPAD takes place and the appropriate details + * are pushed into PacRunner or user can override this URL with a new PAC URL or a + * PAC script. If "none" is selected then no proxy configuration is given to PacRunner + * to fulfill client queries. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_METHOD, PROP_BROWSER_ONLY, PROP_PAC_URL, PROP_PAC_SCRIPT, ); + +typedef struct { + char *pac_url; + char *pac_script; + int method; + bool browser_only : 1; +} NMSettingProxyPrivate; + +G_DEFINE_TYPE(NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING) + +#define NM_SETTING_PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_PROXY, NMSettingProxyPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_proxy_get_method: + * @setting: the #NMSettingProxy + * + * Returns the proxy configuration method. By default the value is %NM_SETTING_PROXY_METHOD_NONE. + * %NM_SETTING_PROXY_METHOD_NONE should be selected for a connection intended for direct network + * access. + * + * Returns: the proxy configuration method + * + * Since: 1.6 + **/ +NMSettingProxyMethod +nm_setting_proxy_get_method(NMSettingProxy *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PROXY(setting), NM_SETTING_PROXY_METHOD_NONE); + + return NM_SETTING_PROXY_GET_PRIVATE(setting)->method; +} + +/** + * nm_setting_proxy_get_browser_only: + * @setting: the #NMSettingProxy + * + * Returns: %TRUE if this proxy configuration is only for browser + * clients/schemes, %FALSE otherwise. + * + * Since: 1.6 + **/ +gboolean +nm_setting_proxy_get_browser_only(NMSettingProxy *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PROXY(setting), FALSE); + + return NM_SETTING_PROXY_GET_PRIVATE(setting)->browser_only; +} + +/** + * nm_setting_proxy_get_pac_url: + * @setting: the #NMSettingProxy + * + * Returns: the PAC URL for obtaining PAC file + * + * Since: 1.6 + **/ +const char * +nm_setting_proxy_get_pac_url(NMSettingProxy *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PROXY(setting), NULL); + + return NM_SETTING_PROXY_GET_PRIVATE(setting)->pac_url; +} + +/** + * nm_setting_proxy_get_pac_script: + * @setting: the #NMSettingProxy + * + * Returns: the PAC script + * + * Since: 1.6 + **/ +const char * +nm_setting_proxy_get_pac_script(NMSettingProxy *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_PROXY(setting), NULL); + + return NM_SETTING_PROXY_GET_PRIVATE(setting)->pac_script; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE(setting); + + if (!NM_IN_SET(priv->method, NM_SETTING_PROXY_METHOD_NONE, NM_SETTING_PROXY_METHOD_AUTO)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid proxy method")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_PROXY_PAC_URL); + return FALSE; + } + + if (priv->method != NM_SETTING_PROXY_METHOD_AUTO) { + if (priv->pac_url) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("this property is not allowed for method none")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_PROXY_PAC_URL); + return FALSE; + } + + if (priv->pac_script) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("this property is not allowed for method none")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_PROXY_PAC_SCRIPT); + return FALSE; + } + } + + if (priv->pac_script) { + if (strlen(priv->pac_script) > 1 * 1024 * 1024) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the script is too large")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_PROXY_PAC_SCRIPT); + return FALSE; + } + if (!g_utf8_validate(priv->pac_script, -1, NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the script is not valid utf8")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_PROXY_PAC_SCRIPT); + return FALSE; + } + if (!strstr(priv->pac_script, "FindProxyForURL")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the script lacks FindProxyForURL function")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_PROXY_PAC_SCRIPT); + return FALSE; + } + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingProxy *setting = NM_SETTING_PROXY(object); + + switch (prop_id) { + case PROP_METHOD: + g_value_set_int(value, nm_setting_proxy_get_method(setting)); + break; + case PROP_BROWSER_ONLY: + g_value_set_boolean(value, nm_setting_proxy_get_browser_only(setting)); + break; + case PROP_PAC_URL: + g_value_set_string(value, nm_setting_proxy_get_pac_url(setting)); + break; + case PROP_PAC_SCRIPT: + g_value_set_string(value, nm_setting_proxy_get_pac_script(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_METHOD: + priv->method = g_value_get_int(value); + break; + case PROP_BROWSER_ONLY: + priv->browser_only = g_value_get_boolean(value); + break; + case PROP_PAC_URL: + g_free(priv->pac_url); + priv->pac_url = g_value_dup_string(value); + break; + case PROP_PAC_SCRIPT: + g_free(priv->pac_script); + priv->pac_script = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_proxy_init(NMSettingProxy *self) +{ + nm_assert(NM_SETTING_PROXY_GET_PRIVATE(self)->method == NM_SETTING_PROXY_METHOD_NONE); +} + +/** + * nm_setting_proxy_new: + * + * Creates a new #NMSettingProxy object. + * + * Returns: the new empty #NMSettingProxy object + * + * Since: 1.6 + **/ +NMSetting * +nm_setting_proxy_new(void) +{ + return g_object_new(NM_TYPE_SETTING_PROXY, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingProxy * self = NM_SETTING_PROXY(object); + NMSettingProxyPrivate *priv = NM_SETTING_PROXY_GET_PRIVATE(self); + + g_free(priv->pac_url); + g_free(priv->pac_script); + + G_OBJECT_CLASS(nm_setting_proxy_parent_class)->finalize(object); +} + +static void +nm_setting_proxy_class_init(NMSettingProxyClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingProxyPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingProxy:method: + * + * Method for proxy configuration, Default is %NM_SETTING_PROXY_METHOD_NONE + * + * Since: 1.6 + **/ + /* ---ifcfg-rh--- + * property: method + * variable: PROXY_METHOD(+) + * default: none + * description: Method for proxy configuration. For "auto", WPAD is used for + * proxy configuration, or set the PAC file via PAC_URL or PAC_SCRIPT. + * values: none, auto + * ---end--- + */ + obj_properties[PROP_METHOD] = g_param_spec_int(NM_SETTING_PROXY_METHOD, + "", + "", + G_MININT32, + G_MAXINT32, + NM_SETTING_PROXY_METHOD_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingProxy:browser-only: + * + * Whether the proxy configuration is for browser only. + * + * Since: 1.6 + **/ + /* ---ifcfg-rh--- + * property: browser-only + * variable: BROWSER_ONLY(+) + * default: no + * description: Whether the proxy configuration is for browser only. + * ---end--- + */ + obj_properties[PROP_BROWSER_ONLY] = + g_param_spec_boolean(NM_SETTING_PROXY_BROWSER_ONLY, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingProxy:pac-url: + * + * PAC URL for obtaining PAC file. + * + * Since: 1.6 + **/ + /* ---ifcfg-rh--- + * property: pac-url + * variable: PAC_URL(+) + * description: URL for PAC file. + * example: PAC_URL=http://wpad.mycompany.com/wpad.dat + * ---end--- + */ + obj_properties[PROP_PAC_URL] = g_param_spec_string(NM_SETTING_PROXY_PAC_URL, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingProxy:pac-script: + * + * PAC script for the connection. + * + * Since: 1.6 + **/ + /* ---ifcfg-rh--- + * property: pac-script + * variable: PAC_SCRIPT(+) + * description: Path of the PAC script. + * example: PAC_SCRIPT=/home/joe/proxy.pac + * ---end--- + */ + obj_properties[PROP_PAC_SCRIPT] = + g_param_spec_string(NM_SETTING_PROXY_PAC_SCRIPT, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_PROXY); +} diff --git a/src/libnm-core-impl/nm-setting-serial.c b/src/libnm-core-impl/nm-setting-serial.c new file mode 100644 index 0000000000..1df87b638d --- /dev/null +++ b/src/libnm-core-impl/nm-setting-serial.c @@ -0,0 +1,336 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2018 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-serial.h" + +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-serial + * @short_description: Describes connection properties for devices that use + * serial communications + * + * The #NMSettingSerial object is a #NMSetting subclass that describes + * properties necessary for connections that may use serial communications, + * such as mobile broadband or analog telephone connections. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_BAUD, + PROP_BITS, + PROP_PARITY, + PROP_STOPBITS, + PROP_SEND_DELAY, ); + +typedef struct { + guint64 send_delay; + guint baud; + guint bits; + guint stopbits; + char parity; +} NMSettingSerialPrivate; + +G_DEFINE_TYPE(NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING) + +#define NM_SETTING_SERIAL_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_SERIAL, NMSettingSerialPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_serial_get_baud: + * @setting: the #NMSettingSerial + * + * Returns: the #NMSettingSerial:baud property of the setting + **/ +guint +nm_setting_serial_get_baud(NMSettingSerial *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE(setting)->baud; +} + +/** + * nm_setting_serial_get_bits: + * @setting: the #NMSettingSerial + * + * Returns: the #NMSettingSerial:bits property of the setting + **/ +guint +nm_setting_serial_get_bits(NMSettingSerial *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE(setting)->bits; +} + +/** + * nm_setting_serial_get_parity: + * @setting: the #NMSettingSerial + * + * Returns: the #NMSettingSerial:parity property of the setting + **/ +NMSettingSerialParity +nm_setting_serial_get_parity(NMSettingSerial *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE(setting)->parity; +} + +/** + * nm_setting_serial_get_stopbits: + * @setting: the #NMSettingSerial + * + * Returns: the #NMSettingSerial:stopbits property of the setting + **/ +guint +nm_setting_serial_get_stopbits(NMSettingSerial *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE(setting)->stopbits; +} + +/** + * nm_setting_serial_get_send_delay: + * @setting: the #NMSettingSerial + * + * Returns: the #NMSettingSerial:send-delay property of the setting + **/ +guint64 +nm_setting_serial_get_send_delay(NMSettingSerial *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SERIAL(setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE(setting)->send_delay; +} + +static GVariant * +parity_to_dbus(const GValue *from) +{ + switch (g_value_get_enum(from)) { + case NM_SETTING_SERIAL_PARITY_EVEN: + return g_variant_new_byte('E'); + case NM_SETTING_SERIAL_PARITY_ODD: + return g_variant_new_byte('o'); + case NM_SETTING_SERIAL_PARITY_NONE: + default: + return g_variant_new_byte('n'); + } +} + +static void +parity_from_dbus(GVariant *from, GValue *to) +{ + switch (g_variant_get_byte(from)) { + case 'E': + g_value_set_enum(to, NM_SETTING_SERIAL_PARITY_EVEN); + break; + case 'o': + g_value_set_enum(to, NM_SETTING_SERIAL_PARITY_ODD); + break; + case 'n': + default: + g_value_set_enum(to, NM_SETTING_SERIAL_PARITY_NONE); + break; + } +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingSerial *setting = NM_SETTING_SERIAL(object); + + switch (prop_id) { + case PROP_BAUD: + g_value_set_uint(value, nm_setting_serial_get_baud(setting)); + break; + case PROP_BITS: + g_value_set_uint(value, nm_setting_serial_get_bits(setting)); + break; + case PROP_PARITY: + g_value_set_enum(value, nm_setting_serial_get_parity(setting)); + break; + case PROP_STOPBITS: + g_value_set_uint(value, nm_setting_serial_get_stopbits(setting)); + break; + case PROP_SEND_DELAY: + g_value_set_uint64(value, nm_setting_serial_get_send_delay(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingSerialPrivate *priv = NM_SETTING_SERIAL_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_BAUD: + priv->baud = g_value_get_uint(value); + break; + case PROP_BITS: + priv->bits = g_value_get_uint(value); + break; + case PROP_PARITY: + priv->parity = g_value_get_enum(value); + break; + case PROP_STOPBITS: + priv->stopbits = g_value_get_uint(value); + break; + case PROP_SEND_DELAY: + priv->send_delay = g_value_get_uint64(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_serial_init(NMSettingSerial *self) +{ + NMSettingSerialPrivate *priv = NM_SETTING_SERIAL_GET_PRIVATE(self); + + nm_assert(priv->parity == NM_SETTING_SERIAL_PARITY_NONE); + priv->stopbits = 1; + priv->baud = 57600; + priv->bits = 8; +} + +/** + * nm_setting_serial_new: + * + * Creates a new #NMSettingSerial object with default values. + * + * Returns: (transfer full): the new empty #NMSettingSerial object + **/ +NMSetting * +nm_setting_serial_new(void) +{ + return g_object_new(NM_TYPE_SETTING_SERIAL, NULL); +} + +static void +nm_setting_serial_class_init(NMSettingSerialClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingSerialPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + + /** + * NMSettingSerial:baud: + * + * Speed to use for communication over the serial port. Note that this + * value usually has no effect for mobile broadband modems as they generally + * ignore speed settings and use the highest available speed. + **/ + obj_properties[PROP_BAUD] = g_param_spec_uint(NM_SETTING_SERIAL_BAUD, + "", + "", + 0, + G_MAXUINT, + 57600, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingSerial:bits: + * + * Byte-width of the serial communication. The 8 in "8n1" for example. + **/ + obj_properties[PROP_BITS] = g_param_spec_uint(NM_SETTING_SERIAL_BITS, + "", + "", + 5, + 8, + 8, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingSerial:parity: + * + * Parity setting of the serial port. + **/ + /* ---keyfile--- + * property: parity + * format: 'e', 'o', or 'n' + * description: The connection parity; even, odd, or none. Note that older + * versions of NetworkManager stored this as an integer: 69 ('E') for even, + * 111 ('o') for odd, or 110 ('n') for none. + * example: parity=n + * ---end--- + * ---dbus--- + * property: parity + * format: byte + * description: The connection parity: 69 (ASCII 'E') for even parity, + * 111 (ASCII 'o') for odd, 110 (ASCII 'n') for none. + * ---end--- + */ + obj_properties[PROP_PARITY] = g_param_spec_enum(NM_SETTING_SERIAL_PARITY, + "", + "", + NM_TYPE_SETTING_SERIAL_PARITY, + NM_SETTING_SERIAL_PARITY_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_PARITY], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BYTE, + .gprop_to_dbus_fcn = parity_to_dbus, + .gprop_from_dbus_fcn = parity_from_dbus, )); + + /** + * NMSettingSerial:stopbits: + * + * Number of stop bits for communication on the serial port. Either 1 or 2. + * The 1 in "8n1" for example. + **/ + obj_properties[PROP_STOPBITS] = g_param_spec_uint(NM_SETTING_SERIAL_STOPBITS, + "", + "", + 1, + 2, + 1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingSerial:send-delay: + * + * Time to delay between each byte sent to the modem, in microseconds. + **/ + obj_properties[PROP_SEND_DELAY] = + g_param_spec_uint64(NM_SETTING_SERIAL_SEND_DELAY, + "", + "", + 0, + G_MAXUINT64, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_SERIAL, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-sriov.c b/src/libnm-core-impl/nm-setting-sriov.c new file mode 100644 index 0000000000..70e542d1cd --- /dev/null +++ b/src/libnm-core-impl/nm-setting-sriov.c @@ -0,0 +1,1372 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-sriov.h" + +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-sriov + * @short_description: Describes SR-IOV connection properties + * @include: nm-setting-sriov.h + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingSriov, PROP_TOTAL_VFS, PROP_VFS, PROP_AUTOPROBE_DRIVERS, ); + +/** + * NMSettingSriov: + * + * SR-IOV settings + * + * Since: 1.14 + */ +struct _NMSettingSriov { + NMSetting parent; + GPtrArray *vfs; + guint total_vfs; + NMTernary autoprobe_drivers; +}; + +struct _NMSettingSriovClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingSriov, nm_setting_sriov, NM_TYPE_SETTING) + +/*****************************************************************************/ + +G_DEFINE_BOXED_TYPE(NMSriovVF, nm_sriov_vf, nm_sriov_vf_dup, nm_sriov_vf_unref) + +struct _NMSriovVF { + guint refcount; + guint index; + GHashTable *attributes; + GHashTable *vlans; + guint * vlan_ids; +}; + +typedef struct { + guint id; + guint qos; + NMSriovVFVlanProtocol protocol; +} VFVlan; + +static guint +_vf_vlan_hash(gconstpointer ptr) +{ + return nm_hash_val(1348254767u, *((guint *) ptr)); +} + +static gboolean +_vf_vlan_equal(gconstpointer a, gconstpointer b) +{ + return *((guint *) a) == *((guint *) b); +} + +static GHashTable * +_vf_vlan_create_hash(void) +{ + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(VFVlan, id) == 0); + return g_hash_table_new_full(_vf_vlan_hash, _vf_vlan_equal, NULL, nm_g_slice_free_fcn(VFVlan)); +} + +/** + * nm_sriov_vf_new: + * @index: the VF index + * + * Creates a new #NMSriovVF object. + * + * Returns: (transfer full): the new #NMSriovVF object. + * + * Since: 1.14 + **/ +NMSriovVF * +nm_sriov_vf_new(guint index) +{ + NMSriovVF *vf; + + vf = g_slice_new(NMSriovVF); + *vf = (NMSriovVF){ + .refcount = 1, + .index = index, + .attributes = g_hash_table_new_full(nm_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_variant_unref), + }; + return vf; +} + +/** + * nm_sriov_vf_ref: + * @vf: the #NMSriovVF + * + * Increases the reference count of the object. + * + * Since: 1.14 + **/ +void +nm_sriov_vf_ref(NMSriovVF *vf) +{ + g_return_if_fail(vf); + g_return_if_fail(vf->refcount > 0); + + vf->refcount++; +} + +/** + * nm_sriov_vf_unref: + * @vf: the #NMSriovVF + * + * Decreases the reference count of the object. If the reference count + * reaches zero, the object will be destroyed. + * + * Since: 1.14 + **/ +void +nm_sriov_vf_unref(NMSriovVF *vf) +{ + g_return_if_fail(vf); + g_return_if_fail(vf->refcount > 0); + + vf->refcount--; + if (vf->refcount == 0) { + g_hash_table_unref(vf->attributes); + if (vf->vlans) + g_hash_table_unref(vf->vlans); + g_free(vf->vlan_ids); + nm_g_slice_free(vf); + } +} + +/** + * nm_sriov_vf_equal: + * @vf: the #NMSriovVF + * @other: the #NMSriovVF to compare @vf to. + * + * Determines if two #NMSriovVF objects have the same index, + * attributes and VLANs. + * + * Returns: %TRUE if the objects contain the same values, %FALSE + * if they do not. + * + * Since: 1.14 + **/ +gboolean +nm_sriov_vf_equal(const NMSriovVF *vf, const NMSriovVF *other) +{ + GHashTableIter iter; + const char * key; + GVariant * value, *value2; + VFVlan * vlan, *vlan2; + guint n_vlans; + + g_return_val_if_fail(vf, FALSE); + g_return_val_if_fail(vf->refcount > 0, FALSE); + g_return_val_if_fail(other, FALSE); + g_return_val_if_fail(other->refcount > 0, FALSE); + + if (vf == other) + return TRUE; + + if (vf->index != other->index) + return FALSE; + + if (g_hash_table_size(vf->attributes) != g_hash_table_size(other->attributes)) + return FALSE; + g_hash_table_iter_init(&iter, vf->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { + value2 = g_hash_table_lookup(other->attributes, key); + if (!value2) + return FALSE; + if (!g_variant_equal(value, value2)) + return FALSE; + } + + n_vlans = vf->vlans ? g_hash_table_size(vf->vlans) : 0u; + if (n_vlans != (other->vlans ? g_hash_table_size(other->vlans) : 0u)) + return FALSE; + if (n_vlans > 0) { + g_hash_table_iter_init(&iter, vf->vlans); + while (g_hash_table_iter_next(&iter, (gpointer *) &vlan, NULL)) { + vlan2 = g_hash_table_lookup(other->vlans, vlan); + if (!vlan2) + return FALSE; + if (vlan->qos != vlan2->qos || vlan->protocol != vlan2->protocol) + return FALSE; + } + } + + return TRUE; +} + +static void +vf_add_vlan(NMSriovVF *vf, guint vlan_id, guint qos, NMSriovVFVlanProtocol protocol) +{ + VFVlan *vlan; + + vlan = g_slice_new(VFVlan); + *vlan = (VFVlan){ + .id = vlan_id, + .qos = qos, + .protocol = protocol, + }; + + if (!vf->vlans) + vf->vlans = _vf_vlan_create_hash(); + + g_hash_table_add(vf->vlans, vlan); + nm_clear_g_free(&vf->vlan_ids); +} + +/** + * nm_sriov_vf_dup: + * @vf: the #NMSriovVF + * + * Creates a copy of @vf. + * + * Returns: (transfer full): a copy of @vf + * + * Since: 1.14 + **/ +NMSriovVF * +nm_sriov_vf_dup(const NMSriovVF *vf) +{ + NMSriovVF * copy; + GHashTableIter iter; + const char * name; + GVariant * variant; + VFVlan * vlan; + + g_return_val_if_fail(vf, NULL); + g_return_val_if_fail(vf->refcount > 0, NULL); + + copy = nm_sriov_vf_new(vf->index); + + g_hash_table_iter_init(&iter, vf->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) + nm_sriov_vf_set_attribute(copy, name, variant); + + if (vf->vlans) { + g_hash_table_iter_init(&iter, vf->vlans); + while (g_hash_table_iter_next(&iter, (gpointer *) &vlan, NULL)) + vf_add_vlan(copy, vlan->id, vlan->qos, vlan->protocol); + } + + return copy; +} + +/** + * nm_sriov_vf_get_index: + * @vf: the #NMSriovVF + * + * Gets the index property of this VF object. + * + * Returns: the VF index + * + * Since: 1.14 + **/ +guint +nm_sriov_vf_get_index(const NMSriovVF *vf) +{ + g_return_val_if_fail(vf, 0); + g_return_val_if_fail(vf->refcount > 0, 0); + + return vf->index; +} + +/** + * nm_sriov_vf_set_attribute: + * @vf: the #NMSriovVF + * @name: the name of a route attribute + * @value: (transfer none) (allow-none): the value + * + * Sets the named attribute on @vf to the given value. + * + * Since: 1.14 + **/ +void +nm_sriov_vf_set_attribute(NMSriovVF *vf, const char *name, GVariant *value) +{ + g_return_if_fail(vf); + g_return_if_fail(vf->refcount > 0); + g_return_if_fail(name && *name != '\0'); + g_return_if_fail(!nm_streq(name, "index")); + + if (value) { + g_hash_table_insert(vf->attributes, g_strdup(name), g_variant_ref_sink(value)); + } else + g_hash_table_remove(vf->attributes, name); +} + +/** + * nm_sriov_vf_get_attribute_names: + * @vf: the #NMSriovVF + * + * Gets an array of attribute names defined on @vf. + * + * Returns: (transfer container): a %NULL-terminated array of attribute names + * + * Since: 1.14 + **/ +const char ** +nm_sriov_vf_get_attribute_names(const NMSriovVF *vf) +{ + g_return_val_if_fail(vf, NULL); + g_return_val_if_fail(vf->refcount > 0, NULL); + + return nm_utils_strdict_get_keys(vf->attributes, TRUE, NULL); +} + +/** + * nm_sriov_vf_get_attribute: + * @vf: the #NMSriovVF + * @name: the name of a VF attribute + * + * Gets the value of the attribute with name @name on @vf + * + * Returns: (transfer none): the value of the attribute with name @name on + * @vf, or %NULL if @vf has no such attribute. + * + * Since: 1.14 + **/ +GVariant * +nm_sriov_vf_get_attribute(const NMSriovVF *vf, const char *name) +{ + g_return_val_if_fail(vf, NULL); + g_return_val_if_fail(vf->refcount > 0, NULL); + g_return_val_if_fail(name && *name != '\0', NULL); + + return g_hash_table_lookup(vf->attributes, name); +} + +const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MAC, + G_VARIANT_TYPE_STRING, + .str_type = 'm', ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, ), + /* D-Bus only, synthetic attributes */ + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("vlans", G_VARIANT_TYPE_STRING, .str_type = 'd', ), + NULL, +}; + +/** + * nm_sriov_vf_attribute_validate: + * @name: the attribute name + * @value: the attribute value + * @known: (out): on return, whether the attribute name is a known one + * @error: (allow-none): return location for a #GError, or %NULL + * + * Validates a VF attribute, i.e. checks that the attribute is a known one, + * the value is of the correct type and well-formed. + * + * Returns: %TRUE if the attribute is valid, %FALSE otherwise + * + * Since: 1.14 + */ +gboolean +nm_sriov_vf_attribute_validate(const char *name, GVariant *value, gboolean *known, GError **error) +{ + const NMVariantAttributeSpec *const *iter; + const NMVariantAttributeSpec * spec = NULL; + + g_return_val_if_fail(name, FALSE); + g_return_val_if_fail(value, FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + + for (iter = _nm_sriov_vf_attribute_spec; *iter; iter++) { + if (nm_streq(name, (*iter)->name)) { + spec = *iter; + break; + } + } + + if (!spec || spec->str_type == 'd') { + NM_SET_OUT(known, FALSE); + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("unknown attribute")); + return FALSE; + } + + NM_SET_OUT(known, TRUE); + + if (!g_variant_is_of_type(value, spec->type)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid attribute type '%s'"), + g_variant_get_type_string(value)); + return FALSE; + } + + if (g_variant_type_equal(spec->type, G_VARIANT_TYPE_STRING)) { + const char *string; + + switch (spec->str_type) { + case 'm': /* MAC address */ + string = g_variant_get_string(value, NULL); + if (!nm_utils_hwaddr_valid(string, -1)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("'%s' is not a valid MAC address"), + string); + return FALSE; + } + break; + default: + break; + } + } + + return TRUE; +} + +gboolean +_nm_sriov_vf_attribute_validate_all(const NMSriovVF *vf, GError **error) +{ + GHashTableIter iter; + const char * name; + GVariant * variant; + GVariant * min, *max; + + g_return_val_if_fail(vf, FALSE); + g_return_val_if_fail(vf->refcount > 0, FALSE); + + g_hash_table_iter_init(&iter, vf->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) { + if (!nm_sriov_vf_attribute_validate(name, variant, NULL, error)) { + g_prefix_error(error, "attribute '%s':", name); + return FALSE; + } + } + + min = g_hash_table_lookup(vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE); + max = g_hash_table_lookup(vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE); + if (min && max && g_variant_get_uint32(min) > g_variant_get_uint32(max)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "min_tx_rate is greater than max_tx_rate"); + return FALSE; + } + + return TRUE; +} + +/** + * nm_sriov_vf_add_vlan: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * + * Adds a VLAN to the VF. + * + * Returns: %TRUE if the VLAN was added; %FALSE if it already existed + * + * Since: 1.14 + **/ +gboolean +nm_sriov_vf_add_vlan(NMSriovVF *vf, guint vlan_id) +{ + g_return_val_if_fail(vf, FALSE); + g_return_val_if_fail(vf->refcount > 0, FALSE); + + if (vf->vlans && g_hash_table_contains(vf->vlans, &vlan_id)) + return FALSE; + + vf_add_vlan(vf, vlan_id, 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + + return TRUE; +} + +/** + * nm_sriov_vf_remove_vlan: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * + * Removes a VLAN from a VF. + * + * Returns: %TRUE if the VLAN was removed, %FALSE if the VLAN @vlan_id + * did not belong to the VF. + * + * Since: 1.14 + */ +gboolean +nm_sriov_vf_remove_vlan(NMSriovVF *vf, guint vlan_id) +{ + g_return_val_if_fail(vf, FALSE); + g_return_val_if_fail(vf->refcount > 0, FALSE); + + if (!vf->vlans || !g_hash_table_remove(vf->vlans, &vlan_id)) + return FALSE; + + nm_clear_g_free(&vf->vlan_ids); + return TRUE; +} + +static int +vlan_id_compare(gconstpointer a, gconstpointer b, gpointer user_data) +{ + guint id_a = *(guint *) a; + guint id_b = *(guint *) b; + + if (id_a < id_b) + return -1; + else if (id_a > id_b) + return 1; + else + return 0; +} + +/** + * nm_sriov_vf_get_vlan_ids: + * @vf: the #NMSriovVF + * @length: (out) (allow-none): on return, the number of VLANs configured + * + * Returns the VLANs currently configured on the VF. + * + * Returns: (transfer none) (array length=length): a list of VLAN ids configured on the VF. + * + * Since: 1.14 + */ +const guint * +nm_sriov_vf_get_vlan_ids(const NMSriovVF *vf, guint *length) +{ + GHashTableIter iter; + VFVlan * vlan; + guint num, i; + + g_return_val_if_fail(vf, NULL); + g_return_val_if_fail(vf->refcount > 0, NULL); + + num = vf->vlans ? g_hash_table_size(vf->vlans) : 0u; + NM_SET_OUT(length, num); + + if (vf->vlan_ids) + return vf->vlan_ids; + if (num == 0) + return NULL; + + /* vf is const, however, vlan_ids is a mutable field caching the + * result ("mutable" in C++ terminology) */ + ((NMSriovVF *) vf)->vlan_ids = g_new0(guint, num); + + i = 0; + g_hash_table_iter_init(&iter, vf->vlans); + while (g_hash_table_iter_next(&iter, (gpointer *) &vlan, NULL)) + vf->vlan_ids[i++] = vlan->id; + + nm_assert(num == i); + + g_qsort_with_data(vf->vlan_ids, num, sizeof(guint), vlan_id_compare, NULL); + + return vf->vlan_ids; +} + +/** + * nm_sriov_vf_set_vlan_qos: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * @qos: a QoS (priority) value + * + * Sets a QoS value for the given VLAN. + * + * Since: 1.14 + */ +void +nm_sriov_vf_set_vlan_qos(NMSriovVF *vf, guint vlan_id, guint32 qos) +{ + VFVlan *vlan; + + g_return_if_fail(vf); + g_return_if_fail(vf->refcount > 0); + + if (!vf->vlans || !(vlan = g_hash_table_lookup(vf->vlans, &vlan_id))) + g_return_if_reached(); + + vlan->qos = qos; +} + +/** + * nm_sriov_vf_set_vlan_protocol: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * @protocol: the VLAN protocol + * + * Sets the protocol for the given VLAN. + * + * Since: 1.14 + */ +void +nm_sriov_vf_set_vlan_protocol(NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol) +{ + VFVlan *vlan; + + g_return_if_fail(vf); + g_return_if_fail(vf->refcount > 0); + + if (!vf->vlans || !(vlan = g_hash_table_lookup(vf->vlans, &vlan_id))) + g_return_if_reached(); + + vlan->protocol = protocol; +} + +/** + * nm_sriov_vf_get_vlan_qos: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * + * Returns the QoS value for the given VLAN. + * + * Returns: the QoS value + * + * Since: 1.14 + */ +guint32 +nm_sriov_vf_get_vlan_qos(const NMSriovVF *vf, guint vlan_id) +{ + VFVlan *vlan; + + g_return_val_if_fail(vf, 0); + g_return_val_if_fail(vf->refcount > 0, 0); + + if (!vf->vlans || !(vlan = g_hash_table_lookup(vf->vlans, &vlan_id))) + g_return_val_if_reached(0); + + return vlan->qos; +} + +/* + * nm_sriov_vf_get_vlan_protocol: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * + * Returns the configured protocol for the given VLAN. + * + * Returns: the configured protocol + * + * Since: 1.14 + */ +NMSriovVFVlanProtocol +nm_sriov_vf_get_vlan_protocol(const NMSriovVF *vf, guint vlan_id) +{ + VFVlan *vlan; + + g_return_val_if_fail(vf, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_return_val_if_fail(vf->refcount > 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + + if (!vf->vlans || !(vlan = g_hash_table_lookup(vf->vlans, &vlan_id))) + g_return_val_if_reached(NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + + return vlan->protocol; +} + +/*****************************************************************************/ + +/** + * nm_setting_sriov_get_total_vfs: + * @setting: the #NMSettingSriov + * + * Returns the value contained in the #NMSettingSriov:total-vfs + * property. + * + * Returns: the total number of SR-IOV virtual functions to create + * + * Since: 1.14 + **/ +guint +nm_setting_sriov_get_total_vfs(NMSettingSriov *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), 0); + + return setting->total_vfs; +} + +/** + * nm_setting_sriov_get_num_vfs: + * @setting: the #NMSettingSriov + * + * Returns: the number of configured VFs + * + * Since: 1.14 + **/ +guint +nm_setting_sriov_get_num_vfs(NMSettingSriov *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), 0); + + return setting->vfs->len; +} + +/** + * nm_setting_sriov_get_vf: + * @setting: the #NMSettingSriov + * @idx: index number of the VF to return + * + * Returns: (transfer none): the VF at index @idx + * + * Since: 1.14 + **/ +NMSriovVF * +nm_setting_sriov_get_vf(NMSettingSriov *setting, guint idx) +{ + g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NULL); + g_return_val_if_fail(idx < setting->vfs->len, NULL); + + return setting->vfs->pdata[idx]; +} + +/** + * nm_setting_sriov_add_vf: + * @setting: the #NMSettingSriov + * @vf: the VF to add + * + * Appends a new VF and associated information to the setting. The + * given VF is duplicated internally and is not changed by this function. + * + * Since: 1.14 + **/ +void +nm_setting_sriov_add_vf(NMSettingSriov *setting, NMSriovVF *vf) +{ + g_return_if_fail(NM_IS_SETTING_SRIOV(setting)); + g_return_if_fail(vf); + g_return_if_fail(vf->refcount > 0); + + g_ptr_array_add(setting->vfs, nm_sriov_vf_dup(vf)); + _notify(setting, PROP_VFS); +} + +/** + * nm_setting_sriov_remove_vf: + * @setting: the #NMSettingSriov + * @idx: index number of the VF + * + * Removes the VF at index @idx. + * + * Since: 1.14 + **/ +void +nm_setting_sriov_remove_vf(NMSettingSriov *setting, guint idx) +{ + g_return_if_fail(NM_IS_SETTING_SRIOV(setting)); + g_return_if_fail(idx < setting->vfs->len); + + g_ptr_array_remove_index(setting->vfs, idx); + _notify(setting, PROP_VFS); +} + +/** + * nm_setting_sriov_remove_vf_by_index: + * @setting: the #NMSettingSriov + * @index: the VF index of the VF to remove + * + * Removes the VF with VF index @index. + * + * Returns: %TRUE if the VF was found and removed; %FALSE if it was not + * + * Since: 1.14 + **/ +gboolean +nm_setting_sriov_remove_vf_by_index(NMSettingSriov *setting, guint index) +{ + guint i; + + g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), FALSE); + + for (i = 0; i < setting->vfs->len; i++) { + if (nm_sriov_vf_get_index(setting->vfs->pdata[i]) == index) { + g_ptr_array_remove_index(setting->vfs, i); + _notify(setting, PROP_VFS); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_sriov_clear_vfs: + * @setting: the #NMSettingSriov + * + * Removes all configured VFs. + * + * Since: 1.14 + **/ +void +nm_setting_sriov_clear_vfs(NMSettingSriov *setting) +{ + g_return_if_fail(NM_IS_SETTING_SRIOV(setting)); + + if (setting->vfs->len != 0) { + g_ptr_array_set_size(setting->vfs, 0); + _notify(setting, PROP_VFS); + } +} + +/** + * nm_setting_sriov_get_autoprobe_drivers: + * @setting: the #NMSettingSriov + * + * Returns the value contained in the #NMSettingSriov:autoprobe-drivers + * property. + * + * Returns: the autoprobe-drivers property value + * + * Since: 1.14 + **/ +NMTernary +nm_setting_sriov_get_autoprobe_drivers(NMSettingSriov *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NM_TERNARY_DEFAULT); + + return setting->autoprobe_drivers; +} + +static int +vf_index_compare(gconstpointer a, gconstpointer b) +{ + NMSriovVF *vf_a = *(NMSriovVF **) a; + NMSriovVF *vf_b = *(NMSriovVF **) b; + + if (vf_a->index < vf_b->index) + return -1; + else if (vf_a->index > vf_b->index) + return 1; + else + return 0; +} + +gboolean +_nm_setting_sriov_sort_vfs(NMSettingSriov *setting) +{ + gboolean need_sort = FALSE; + guint i; + + for (i = 1; i < setting->vfs->len; i++) { + NMSriovVF *vf_prev = setting->vfs->pdata[i - 1]; + NMSriovVF *vf = setting->vfs->pdata[i]; + + if (vf->index <= vf_prev->index) { + need_sort = TRUE; + break; + } + } + + if (need_sort) { + g_ptr_array_sort(setting->vfs, vf_index_compare); + _notify(setting, PROP_VFS); + } + + return need_sort; +} + +/*****************************************************************************/ + +static GVariant * +vfs_to_dbus(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *vfs = NULL; + GVariantBuilder builder; + guint i; + + g_object_get(setting, NM_SETTING_SRIOV_VFS, &vfs, NULL); + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + if (vfs) { + for (i = 0; i < vfs->len; i++) { + gs_free const char **attr_names = NULL; + NMSriovVF * vf = vfs->pdata[i]; + GVariantBuilder vf_builder; + const guint * vlan_ids; + const char ** name; + guint num_vlans = 0; + + g_variant_builder_init(&vf_builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&vf_builder, + "{sv}", + "index", + g_variant_new_uint32(nm_sriov_vf_get_index(vf))); + + attr_names = nm_utils_strdict_get_keys(vf->attributes, TRUE, NULL); + if (attr_names) { + for (name = attr_names; *name; name++) { + g_variant_builder_add(&vf_builder, + "{sv}", + *name, + nm_sriov_vf_get_attribute(vf, *name)); + } + } + + /* VLANs are translated into an array of maps, where each map has + * keys 'id', 'qos' and 'proto'. This guarantees enough flexibility + * to accommodate any future new option. */ + vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num_vlans); + if (num_vlans) { + GVariantBuilder vlans_builder; + guint j; + + g_variant_builder_init(&vlans_builder, G_VARIANT_TYPE("aa{sv}")); + for (j = 0; j < num_vlans; j++) { + GVariantBuilder vlan_builder; + + g_variant_builder_init(&vlan_builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&vlan_builder, + "{sv}", + "id", + g_variant_new_uint32(vlan_ids[j])); + g_variant_builder_add( + &vlan_builder, + "{sv}", + "qos", + g_variant_new_uint32(nm_sriov_vf_get_vlan_qos(vf, vlan_ids[j]))); + g_variant_builder_add( + &vlan_builder, + "{sv}", + "protocol", + g_variant_new_uint32(nm_sriov_vf_get_vlan_protocol(vf, vlan_ids[j]))); + g_variant_builder_add(&vlans_builder, "a{sv}", &vlan_builder); + } + g_variant_builder_add(&vf_builder, + "{sv}", + "vlans", + g_variant_builder_end(&vlans_builder)); + } + g_variant_builder_add(&builder, "a{sv}", &vf_builder); + } + } + + return g_variant_builder_end(&builder); +} + +static gboolean +vfs_from_dbus(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray * vfs; + GVariantIter vf_iter; + GVariant * vf_var; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), FALSE); + + vfs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_sriov_vf_unref); + g_variant_iter_init(&vf_iter, value); + while (g_variant_iter_next(&vf_iter, "@a{sv}", &vf_var)) { + NMSriovVF * vf; + guint32 index; + GVariantIter attr_iter; + const char * attr_name; + GVariant * attr_var, *vlans_var; + + if (!g_variant_lookup(vf_var, "index", "u", &index)) + goto next; + + vf = nm_sriov_vf_new(index); + + g_variant_iter_init(&attr_iter, vf_var); + while (g_variant_iter_next(&attr_iter, "{&sv}", &attr_name, &attr_var)) { + if (!NM_IN_STRSET(attr_name, "index", "vlans")) + nm_sriov_vf_set_attribute(vf, attr_name, attr_var); + g_variant_unref(attr_var); + } + + if (g_variant_lookup(vf_var, "vlans", "@aa{sv}", &vlans_var)) { + GVariantIter vlan_iter; + GVariant * vlan_var; + + g_variant_iter_init(&vlan_iter, vlans_var); + while (g_variant_iter_next(&vlan_iter, "@a{sv}", &vlan_var)) { + NMSriovVFVlanProtocol proto = NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q; + gint64 vlan_id = -1; + guint qos = 0; + + g_variant_iter_init(&attr_iter, vlan_var); + while (g_variant_iter_next(&attr_iter, "{&sv}", &attr_name, &attr_var)) { + if (nm_streq(attr_name, "id") + && g_variant_is_of_type(attr_var, G_VARIANT_TYPE_UINT32)) + vlan_id = g_variant_get_uint32(attr_var); + else if (nm_streq(attr_name, "qos") + && g_variant_is_of_type(attr_var, G_VARIANT_TYPE_UINT32)) + qos = g_variant_get_uint32(attr_var); + else if (nm_streq(attr_name, "protocol") + && g_variant_is_of_type(attr_var, G_VARIANT_TYPE_UINT32)) + proto = g_variant_get_uint32(attr_var); + g_variant_unref(attr_var); + } + if (vlan_id != -1) + vf_add_vlan(vf, vlan_id, qos, proto); + g_variant_unref(vlan_var); + } + g_variant_unref(vlans_var); + } + + g_ptr_array_add(vfs, vf); +next: + g_variant_unref(vf_var); + } + + g_object_set(setting, NM_SETTING_SRIOV_VFS, vfs, NULL); + g_ptr_array_unref(vfs); + + return TRUE; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingSriov *self = NM_SETTING_SRIOV(setting); + guint i; + + if (self->vfs->len) { + gs_unref_hashtable GHashTable *h = NULL; + + h = g_hash_table_new(nm_direct_hash, NULL); + for (i = 0; i < self->vfs->len; i++) { + NMSriovVF * vf = self->vfs->pdata[i]; + gs_free_error GError *local = NULL; + + if (vf->index >= self->total_vfs) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("VF with index %u, but the total number of VFs is %u"), + vf->index, + self->total_vfs); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_SRIOV_SETTING_NAME, + NM_SETTING_SRIOV_VFS); + return FALSE; + } + + if (!_nm_sriov_vf_attribute_validate_all(vf, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid VF %u: %s"), + vf->index, + local->message); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_SRIOV_SETTING_NAME, + NM_SETTING_SRIOV_VFS); + return FALSE; + } + + if (g_hash_table_contains(h, GUINT_TO_POINTER(vf->index))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("duplicate VF index %u"), + vf->index); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_SRIOV_SETTING_NAME, + NM_SETTING_SRIOV_VFS); + return FALSE; + } + + g_hash_table_add(h, GUINT_TO_POINTER(vf->index)); + } + } + + /* Failures from here on are NORMALIZABLE... */ + + if (self->vfs->len) { + for (i = 1; i < self->vfs->len; i++) { + NMSriovVF *vf_prev = self->vfs->pdata[i - 1]; + NMSriovVF *vf = self->vfs->pdata[i]; + + if (vf->index <= vf_prev->index) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("VFs %d and %d are not sorted by ascending index"), + vf_prev->index, + vf->index); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_SRIOV_SETTING_NAME, + NM_SETTING_SRIOV_VFS); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + } + } + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingSriov *a; + NMSettingSriov *b; + guint i; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_SRIOV_VFS)) { + if (set_b) { + a = NM_SETTING_SRIOV(set_a); + b = NM_SETTING_SRIOV(set_b); + + if (a->vfs->len != b->vfs->len) + return FALSE; + for (i = 0; i < a->vfs->len; i++) { + if (!nm_sriov_vf_equal(a->vfs->pdata[i], b->vfs->pdata[i])) + return FALSE; + } + } + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_sriov_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingSriov *self = NM_SETTING_SRIOV(object); + + switch (prop_id) { + case PROP_TOTAL_VFS: + g_value_set_uint(value, self->total_vfs); + break; + case PROP_VFS: + g_value_take_boxed(value, + _nm_utils_copy_array(self->vfs, + (NMUtilsCopyFunc) nm_sriov_vf_dup, + (GDestroyNotify) nm_sriov_vf_unref)); + break; + case PROP_AUTOPROBE_DRIVERS: + g_value_set_enum(value, self->autoprobe_drivers); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingSriov *self = NM_SETTING_SRIOV(object); + + switch (prop_id) { + case PROP_TOTAL_VFS: + self->total_vfs = g_value_get_uint(value); + break; + case PROP_VFS: + g_ptr_array_unref(self->vfs); + self->vfs = _nm_utils_copy_array(g_value_get_boxed(value), + (NMUtilsCopyFunc) nm_sriov_vf_dup, + (GDestroyNotify) nm_sriov_vf_unref); + break; + case PROP_AUTOPROBE_DRIVERS: + self->autoprobe_drivers = g_value_get_enum(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_sriov_init(NMSettingSriov *setting) +{ + setting->vfs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_sriov_vf_unref); + + setting->autoprobe_drivers = NM_TERNARY_DEFAULT; +} + +/** + * nm_setting_sriov_new: + * + * Creates a new #NMSettingSriov object with default values. + * + * Returns: (transfer full): the new empty #NMSettingSriov object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_sriov_new(void) +{ + return g_object_new(NM_TYPE_SETTING_SRIOV, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingSriov *self = NM_SETTING_SRIOV(object); + + g_ptr_array_unref(self->vfs); + + G_OBJECT_CLASS(nm_setting_sriov_parent_class)->finalize(object); +} + +static void +nm_setting_sriov_class_init(NMSettingSriovClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + + /** + * NMSettingSriov:total-vfs + * + * The total number of virtual functions to create. + * + * Note that when the sriov setting is present NetworkManager + * enforces the number of virtual functions on the interface + * (also when it is zero) during activation and resets it + * upon deactivation. To prevent any changes to SR-IOV + * parameters don't add a sriov setting to the connection. + * + * Since: 1.14 + **/ + /* ---ifcfg-rh--- + * property: total-vfs + * variable: SRIOV_TOTAL_VFS(+) + * description: The total number of virtual functions to create + * example: SRIOV_TOTAL_VFS=16 + * ---end--- + */ + obj_properties[PROP_TOTAL_VFS] = g_param_spec_uint( + NM_SETTING_SRIOV_TOTAL_VFS, + "", + "", + 0, + G_MAXUINT32, + 0, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingSriov:vfs: (type GPtrArray(NMSriovVF)) + * + * Array of virtual function descriptors. + * + * Each VF descriptor is a dictionary mapping attribute names + * to GVariant values. The 'index' entry is mandatory for + * each VF. + * + * When represented as string a VF is in the form: + * + * "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". + * + * for example: + * + * "2 mac=00:11:22:33:44:55 spoof-check=true". + * + * Multiple VFs can be specified using a comma as separator. + * Currently, the following attributes are supported: mac, + * spoof-check, trust, min-tx-rate, max-tx-rate, vlans. + * + * The "vlans" attribute is represented as a semicolon-separated + * list of VLAN descriptors, where each descriptor has the form + * + * "ID[.PRIORITY[.PROTO]]". + * + * PROTO can be either 'q' for 802.1Q (the default) or 'ad' for + * 802.1ad. + * + + * Since: 1.14 + **/ + /* ---ifcfg-rh--- + * property: vfs + * variable: SRIOV_VF1(+), SRIOV_VF2(+), ... + * description: SR-IOV virtual function descriptors + * example: SRIOV_VF10="mac=00:11:22:33:44:55", ... + * ---end--- + */ + obj_properties[PROP_VFS] = g_param_spec_boxed(NM_SETTING_SRIOV_VFS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_VFS], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = vfs_to_dbus, + .from_dbus_fcn = vfs_from_dbus, )); + + /** + * NMSettingSriov:autoprobe-drivers + * + * Whether to autoprobe virtual functions by a compatible driver. + * + * If set to %NM_TERNARY_TRUE, the kernel will try to bind VFs to + * a compatible driver and if this succeeds a new network + * interface will be instantiated for each VF. + * + * If set to %NM_TERNARY_FALSE, VFs will not be claimed and no + * network interfaces will be created for them. + * + * When set to %NM_TERNARY_DEFAULT, the global default is used; in + * case the global default is unspecified it is assumed to be + * %NM_TERNARY_TRUE. + * + * Since: 1.14 + **/ + /* ---ifcfg-rh--- + * property: autoprobe-drivers + * variable: SRIOV_AUTOPROBE_DRIVERS(+) + * default: missing variable means global default + * description: Whether to autoprobe virtual functions by a compatible driver + * example: SRIOV_AUTOPROBE_DRIVERS=0,1 + * ---end--- + */ + obj_properties[PROP_AUTOPROBE_DRIVERS] = g_param_spec_enum( + NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, + "", + "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_SRIOV, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-tc-config.c b/src/libnm-core-impl/nm-setting-tc-config.c new file mode 100644 index 0000000000..c5b28b502d --- /dev/null +++ b/src/libnm-core-impl/nm-setting-tc-config.c @@ -0,0 +1,1863 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-tc-config.h" + +#include + +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-tc-config + * @short_description: Describes connection properties for the Linux Traffic Control + * @include: nm-setting-tc-config.h + **/ + +/*****************************************************************************/ + +G_DEFINE_BOXED_TYPE(NMTCQdisc, nm_tc_qdisc, nm_tc_qdisc_dup, nm_tc_qdisc_unref) + +struct NMTCQdisc { + guint refcount; + + char * kind; + guint32 handle; + guint32 parent; + GHashTable *attributes; +}; + +/** + * nm_tc_qdisc_new: + * @kind: name of the queueing discipline + * @parent: the parent queueing discipline + * @error: location to store error, or %NULL + * + * Creates a new #NMTCQdisc object. + * + * Returns: (transfer full): the new #NMTCQdisc object, or %NULL on error + * + * Since: 1.12 + **/ +NMTCQdisc * +nm_tc_qdisc_new(const char *kind, guint32 parent, GError **error) +{ + NMTCQdisc *qdisc; + + if (!kind || !*kind) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("kind is missing")); + return NULL; + } + + if (strchr(kind, ' ') || strchr(kind, '\t')) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid kind"), + kind); + return NULL; + } + + if (!parent) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("parent handle missing")); + return NULL; + } + + qdisc = g_slice_new0(NMTCQdisc); + qdisc->refcount = 1; + + qdisc->kind = g_strdup(kind); + qdisc->parent = parent; + + return qdisc; +} + +/** + * nm_tc_qdisc_ref: + * @qdisc: the #NMTCQdisc + * + * Increases the reference count of the object. + * + * Since: 1.12 + **/ +void +nm_tc_qdisc_ref(NMTCQdisc *qdisc) +{ + g_return_if_fail(qdisc != NULL); + g_return_if_fail(qdisc->refcount > 0); + + qdisc->refcount++; +} + +/** + * nm_tc_qdisc_unref: + * @qdisc: the #NMTCQdisc + * + * Decreases the reference count of the object. If the reference count + * reaches zero, the object will be destroyed. + * + * Since: 1.12 + **/ +void +nm_tc_qdisc_unref(NMTCQdisc *qdisc) +{ + g_return_if_fail(qdisc != NULL); + g_return_if_fail(qdisc->refcount > 0); + + qdisc->refcount--; + if (qdisc->refcount == 0) { + g_free(qdisc->kind); + if (qdisc->attributes) + g_hash_table_unref(qdisc->attributes); + g_slice_free(NMTCQdisc, qdisc); + } +} + +/** + * nm_tc_qdisc_equal: + * @qdisc: the #NMTCQdisc + * @other: the #NMTCQdisc to compare @qdisc to. + * + * Determines if two #NMTCQdisc objects contain the same kind, * handle + * and parent. + * + * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. + * + * Since: 1.12 + **/ +gboolean +nm_tc_qdisc_equal(NMTCQdisc *qdisc, NMTCQdisc *other) +{ + GHashTableIter iter; + const char * key; + GVariant * value, *value2; + guint n; + + g_return_val_if_fail(qdisc != NULL, FALSE); + g_return_val_if_fail(qdisc->refcount > 0, FALSE); + + g_return_val_if_fail(other != NULL, FALSE); + g_return_val_if_fail(other->refcount > 0, FALSE); + + if (qdisc->handle != other->handle || qdisc->parent != other->parent + || g_strcmp0(qdisc->kind, other->kind) != 0) + return FALSE; + + n = qdisc->attributes ? g_hash_table_size(qdisc->attributes) : 0; + if (n != (other->attributes ? g_hash_table_size(other->attributes) : 0)) + return FALSE; + if (n) { + g_hash_table_iter_init(&iter, qdisc->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { + value2 = g_hash_table_lookup(other->attributes, key); + if (!value2) + return FALSE; + if (!g_variant_equal(value, value2)) + return FALSE; + } + } + + return TRUE; +} + +static guint +_nm_tc_qdisc_hash(NMTCQdisc *qdisc) +{ + NMUtilsNamedValue attrs_static[30]; + gs_free NMUtilsNamedValue *attrs_free = NULL; + const NMUtilsNamedValue * attrs; + NMHashState h; + guint length; + guint i; + + attrs = + nm_utils_named_values_from_strdict(qdisc->attributes, &length, attrs_static, &attrs_free); + + nm_hash_init(&h, 43869703); + nm_hash_update_vals(&h, qdisc->handle, qdisc->parent, length); + nm_hash_update_str0(&h, qdisc->kind); + for (i = 0; i < length; i++) { + const char * key = attrs[i].name; + GVariant * variant = attrs[i].value_ptr; + const GVariantType *vtype; + + vtype = g_variant_get_type(variant); + + nm_hash_update_str(&h, key); + nm_hash_update_str(&h, (const char *) vtype); + if (g_variant_type_is_basic(vtype)) + nm_hash_update_val(&h, g_variant_hash(variant)); + } + + return nm_hash_complete(&h); +} + +/** + * nm_tc_qdisc_dup: + * @qdisc: the #NMTCQdisc + * + * Creates a copy of @qdisc + * + * Returns: (transfer full): a copy of @qdisc + * + * Since: 1.12 + **/ +NMTCQdisc * +nm_tc_qdisc_dup(NMTCQdisc *qdisc) +{ + NMTCQdisc *copy; + + g_return_val_if_fail(qdisc != NULL, NULL); + g_return_val_if_fail(qdisc->refcount > 0, NULL); + + copy = nm_tc_qdisc_new(qdisc->kind, qdisc->parent, NULL); + nm_tc_qdisc_set_handle(copy, qdisc->handle); + + if (qdisc->attributes) { + GHashTableIter iter; + const char * key; + GVariant * value; + + g_hash_table_iter_init(&iter, qdisc->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) + nm_tc_qdisc_set_attribute(copy, key, value); + } + + return copy; +} + +/** + * nm_tc_qdisc_get_kind: + * @qdisc: the #NMTCQdisc + * + * Returns: + * + * Since: 1.12 + **/ +const char * +nm_tc_qdisc_get_kind(NMTCQdisc *qdisc) +{ + g_return_val_if_fail(qdisc != NULL, NULL); + g_return_val_if_fail(qdisc->refcount > 0, NULL); + + return qdisc->kind; +} + +/** + * nm_tc_qdisc_get_handle: + * @qdisc: the #NMTCQdisc + * + * Returns: the queueing discipline handle + * + * Since: 1.12 + **/ +guint32 +nm_tc_qdisc_get_handle(NMTCQdisc *qdisc) +{ + g_return_val_if_fail(qdisc != NULL, TC_H_UNSPEC); + g_return_val_if_fail(qdisc->refcount > 0, TC_H_UNSPEC); + + return qdisc->handle; +} + +/** + * nm_tc_qdisc_set_handle: + * @qdisc: the #NMTCQdisc + * @handle: the queueing discipline handle + * + * Sets the queueing discipline handle. + * + * Since: 1.12 + **/ +void +nm_tc_qdisc_set_handle(NMTCQdisc *qdisc, guint32 handle) +{ + g_return_if_fail(qdisc != NULL); + g_return_if_fail(qdisc->refcount > 0); + + qdisc->handle = handle; +} + +/** + * nm_tc_qdisc_get_parent: + * @qdisc: the #NMTCQdisc + * + * Returns: the parent class + * + * Since: 1.12 + **/ +guint32 +nm_tc_qdisc_get_parent(NMTCQdisc *qdisc) +{ + g_return_val_if_fail(qdisc != NULL, TC_H_UNSPEC); + g_return_val_if_fail(qdisc->refcount > 0, TC_H_UNSPEC); + + return qdisc->parent; +} + +/** + * nm_tc_qdisc_get_attribute_names: + * @qdisc: the #NMTCQdisc + * + * Gets an array of attribute names defined on @qdisc. + * + * Returns: (transfer container): a %NULL-terminated array of attribute names + * or %NULL if no attributes are set. + * + * Since: 1.18 + **/ +const char ** +nm_tc_qdisc_get_attribute_names(NMTCQdisc *qdisc) +{ + g_return_val_if_fail(qdisc, NULL); + + return nm_utils_strdict_get_keys(qdisc->attributes, TRUE, NULL); +} + +GHashTable * +_nm_tc_qdisc_get_attributes(NMTCQdisc *qdisc) +{ + nm_assert(qdisc); + + return qdisc->attributes; +} + +/** + * nm_tc_qdisc_get_attribute: + * @qdisc: the #NMTCQdisc + * @name: the name of an qdisc attribute + * + * Gets the value of the attribute with name @name on @qdisc + * + * Returns: (transfer none): the value of the attribute with name @name on + * @qdisc, or %NULL if @qdisc has no such attribute. + * + * Since: 1.18 + **/ +GVariant * +nm_tc_qdisc_get_attribute(NMTCQdisc *qdisc, const char *name) +{ + g_return_val_if_fail(qdisc != NULL, NULL); + g_return_val_if_fail(name != NULL && *name != '\0', NULL); + + if (qdisc->attributes) + return g_hash_table_lookup(qdisc->attributes, name); + else + return NULL; +} + +/** + * nm_tc_qdisc_set_attribute: + * @qdisc: the #NMTCQdisc + * @name: the name of an qdisc attribute + * @value: (transfer none) (allow-none): the value + * + * Sets or clears the named attribute on @qdisc to the given value. + * + * Since: 1.18 + **/ +void +nm_tc_qdisc_set_attribute(NMTCQdisc *qdisc, const char *name, GVariant *value) +{ + g_return_if_fail(qdisc != NULL); + g_return_if_fail(name != NULL && *name != '\0'); + g_return_if_fail(strcmp(name, "kind") != 0); + + if (!qdisc->attributes) { + qdisc->attributes = g_hash_table_new_full(nm_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_variant_unref); + } + + if (value) + g_hash_table_insert(qdisc->attributes, g_strdup(name), g_variant_ref_sink(value)); + else + g_hash_table_remove(qdisc->attributes, name); +} + +/*****************************************************************************/ + +G_DEFINE_BOXED_TYPE(NMTCAction, nm_tc_action, nm_tc_action_dup, nm_tc_action_unref) + +struct NMTCAction { + guint refcount; + + char *kind; + + GHashTable *attributes; +}; + +/** + * nm_tc_action_new: + * @kind: name of the queueing discipline + * @error: location to store error, or %NULL + * + * Creates a new #NMTCAction object. + * + * Returns: (transfer full): the new #NMTCAction object, or %NULL on error + * + * Since: 1.12 + **/ +NMTCAction * +nm_tc_action_new(const char *kind, GError **error) +{ + NMTCAction *action; + + if (!kind || !*kind) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("kind is missing")); + return NULL; + } + + if (strchr(kind, ' ') || strchr(kind, '\t')) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid kind"), + kind); + return NULL; + } + + action = g_slice_new0(NMTCAction); + action->refcount = 1; + + action->kind = g_strdup(kind); + + return action; +} + +/** + * nm_tc_action_ref: + * @action: the #NMTCAction + * + * Increases the reference count of the object. + * + * Since: 1.12 + **/ +void +nm_tc_action_ref(NMTCAction *action) +{ + g_return_if_fail(action != NULL); + g_return_if_fail(action->refcount > 0); + + action->refcount++; +} + +/** + * nm_tc_action_unref: + * @action: the #NMTCAction + * + * Decreases the reference count of the object. If the reference count + * reaches zero, the object will be destroyed. + * + * Since: 1.12 + **/ +void +nm_tc_action_unref(NMTCAction *action) +{ + g_return_if_fail(action != NULL); + g_return_if_fail(action->refcount > 0); + + action->refcount--; + if (action->refcount == 0) { + g_free(action->kind); + if (action->attributes) + g_hash_table_unref(action->attributes); + g_slice_free(NMTCAction, action); + } +} + +/** + * nm_tc_action_equal: + * @action: the #NMTCAction + * @other: the #NMTCAction to compare @action to. + * + * Determines if two #NMTCAction objects contain the same kind, family, + * handle, parent and info. + * + * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. + * + * Since: 1.12 + **/ +gboolean +nm_tc_action_equal(NMTCAction *action, NMTCAction *other) +{ + GHashTableIter iter; + const char * key; + GVariant * value, *value2; + guint n; + + g_return_val_if_fail(!action || action->refcount > 0, FALSE); + g_return_val_if_fail(!other || other->refcount > 0, FALSE); + + if (action == other) + return TRUE; + if (!action || !other) + return FALSE; + + if (g_strcmp0(action->kind, other->kind) != 0) + return FALSE; + + n = action->attributes ? g_hash_table_size(action->attributes) : 0; + if (n != (other->attributes ? g_hash_table_size(other->attributes) : 0)) + return FALSE; + if (n) { + g_hash_table_iter_init(&iter, action->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { + value2 = g_hash_table_lookup(other->attributes, key); + if (!value2) + return FALSE; + if (!g_variant_equal(value, value2)) + return FALSE; + } + } + + return TRUE; +} + +/** + * nm_tc_action_dup: + * @action: the #NMTCAction + * + * Creates a copy of @action + * + * Returns: (transfer full): a copy of @action + * + * Since: 1.12 + **/ +NMTCAction * +nm_tc_action_dup(NMTCAction *action) +{ + NMTCAction *copy; + + g_return_val_if_fail(action != NULL, NULL); + g_return_val_if_fail(action->refcount > 0, NULL); + + copy = nm_tc_action_new(action->kind, NULL); + + if (action->attributes) { + GHashTableIter iter; + const char * key; + GVariant * value; + + g_hash_table_iter_init(&iter, action->attributes); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) + nm_tc_action_set_attribute(copy, key, value); + } + + return copy; +} + +/** + * nm_tc_action_get_kind: + * @action: the #NMTCAction + * + * Returns: + * + * Since: 1.12 + **/ +const char * +nm_tc_action_get_kind(NMTCAction *action) +{ + g_return_val_if_fail(action != NULL, NULL); + g_return_val_if_fail(action->refcount > 0, NULL); + + return action->kind; +} + +/** + * nm_tc_action_get_attribute_names: + * @action: the #NMTCAction + * + * Gets an array of attribute names defined on @action. + * + * Returns: (transfer full): a %NULL-terminated array of attribute names, + * + * Since: 1.12 + **/ +char ** +nm_tc_action_get_attribute_names(NMTCAction *action) +{ + const char **names; + + g_return_val_if_fail(action, NULL); + + names = nm_utils_strdict_get_keys(action->attributes, TRUE, NULL); + return nm_utils_strv_make_deep_copied_nonnull(names); +} + +GHashTable * +_nm_tc_action_get_attributes(NMTCAction *action) +{ + nm_assert(action); + + return action->attributes; +} + +/** + * nm_tc_action_get_attribute: + * @action: the #NMTCAction + * @name: the name of an action attribute + * + * Gets the value of the attribute with name @name on @action + * + * Returns: (transfer none): the value of the attribute with name @name on + * @action, or %NULL if @action has no such attribute. + * + * Since: 1.12 + **/ +GVariant * +nm_tc_action_get_attribute(NMTCAction *action, const char *name) +{ + g_return_val_if_fail(action != NULL, NULL); + g_return_val_if_fail(name != NULL && *name != '\0', NULL); + + if (action->attributes) + return g_hash_table_lookup(action->attributes, name); + else + return NULL; +} + +/** + * nm_tc_action_set_attribute: + * @action: the #NMTCAction + * @name: the name of an action attribute + * @value: (transfer none) (allow-none): the value + * + * Sets or clears the named attribute on @action to the given value. + * + * Since: 1.12 + **/ +void +nm_tc_action_set_attribute(NMTCAction *action, const char *name, GVariant *value) +{ + g_return_if_fail(action != NULL); + g_return_if_fail(name != NULL && *name != '\0'); + g_return_if_fail(strcmp(name, "kind") != 0); + + if (!action->attributes) { + action->attributes = g_hash_table_new_full(nm_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_variant_unref); + } + + if (value) + g_hash_table_insert(action->attributes, g_strdup(name), g_variant_ref_sink(value)); + else + g_hash_table_remove(action->attributes, name); +} + +/*****************************************************************************/ + +G_DEFINE_BOXED_TYPE(NMTCTfilter, nm_tc_tfilter, nm_tc_tfilter_dup, nm_tc_tfilter_unref) + +struct NMTCTfilter { + guint refcount; + + char * kind; + guint32 handle; + guint32 parent; + NMTCAction *action; +}; + +/** + * nm_tc_tfilter_new: + * @kind: name of the queueing discipline + * @parent: the parent queueing discipline + * @error: location to store error, or %NULL + * + * Creates a new #NMTCTfilter object. + * + * Returns: (transfer full): the new #NMTCTfilter object, or %NULL on error + * + * Since: 1.12 + **/ +NMTCTfilter * +nm_tc_tfilter_new(const char *kind, guint32 parent, GError **error) +{ + NMTCTfilter *tfilter; + + if (!kind || !*kind) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("kind is missing")); + return NULL; + } + + if (strchr(kind, ' ') || strchr(kind, '\t')) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid kind"), + kind); + return NULL; + } + + if (!parent) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("parent handle missing")); + return NULL; + } + + tfilter = g_slice_new0(NMTCTfilter); + tfilter->refcount = 1; + + tfilter->kind = g_strdup(kind); + tfilter->parent = parent; + + return tfilter; +} + +/** + * nm_tc_tfilter_ref: + * @tfilter: the #NMTCTfilter + * + * Increases the reference count of the object. + * + * Since: 1.12 + **/ +void +nm_tc_tfilter_ref(NMTCTfilter *tfilter) +{ + g_return_if_fail(tfilter != NULL); + g_return_if_fail(tfilter->refcount > 0); + + tfilter->refcount++; +} + +/** + * nm_tc_tfilter_unref: + * @tfilter: the #NMTCTfilter + * + * Decreases the reference count of the object. If the reference count + * reaches zero, the object will be destroyed. + * + * Since: 1.12 + **/ +void +nm_tc_tfilter_unref(NMTCTfilter *tfilter) +{ + g_return_if_fail(tfilter != NULL); + g_return_if_fail(tfilter->refcount > 0); + + tfilter->refcount--; + if (tfilter->refcount == 0) { + g_free(tfilter->kind); + if (tfilter->action) + nm_tc_action_unref(tfilter->action); + g_slice_free(NMTCTfilter, tfilter); + } +} + +/** + * nm_tc_tfilter_equal: + * @tfilter: the #NMTCTfilter + * @other: the #NMTCTfilter to compare @tfilter to. + * + * Determines if two #NMTCTfilter objects contain the same kind, family, + * handle, parent and info. + * + * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. + * + * Since: 1.12 + **/ +gboolean +nm_tc_tfilter_equal(NMTCTfilter *tfilter, NMTCTfilter *other) +{ + g_return_val_if_fail(tfilter != NULL, FALSE); + g_return_val_if_fail(tfilter->refcount > 0, FALSE); + + g_return_val_if_fail(other != NULL, FALSE); + g_return_val_if_fail(other->refcount > 0, FALSE); + + if (tfilter->handle != other->handle || tfilter->parent != other->parent + || g_strcmp0(tfilter->kind, other->kind) != 0 + || !nm_tc_action_equal(tfilter->action, other->action)) + return FALSE; + + return TRUE; +} + +static guint +_nm_tc_tfilter_hash(NMTCTfilter *tfilter) +{ + NMHashState h; + + nm_hash_init(&h, 63624437); + nm_hash_update_vals(&h, tfilter->handle, tfilter->parent); + nm_hash_update_str0(&h, tfilter->kind); + + if (tfilter->action) { + gs_free NMUtilsNamedValue *attrs_free = NULL; + NMUtilsNamedValue attrs_static[30]; + const NMUtilsNamedValue * attrs; + guint length; + guint i; + + nm_hash_update_str0(&h, tfilter->action->kind); + + attrs = nm_utils_named_values_from_strdict(tfilter->action->attributes, + &length, + attrs_static, + &attrs_free); + for (i = 0; i < length; i++) { + GVariant *variant = attrs[i].value_ptr; + + nm_hash_update_str(&h, attrs[i].name); + if (g_variant_type_is_basic(g_variant_get_type(variant))) { + guint attr_hash; + + /* g_variant_hash() works only for basic types, thus + * we ignore any non-basic attribute. Actions differing + * only for non-basic attributes will collide. */ + attr_hash = g_variant_hash(variant); + nm_hash_update_val(&h, attr_hash); + } + } + } + + return nm_hash_complete(&h); +} + +/** + * nm_tc_tfilter_dup: + * @tfilter: the #NMTCTfilter + * + * Creates a copy of @tfilter + * + * Returns: (transfer full): a copy of @tfilter + * + * Since: 1.12 + **/ +NMTCTfilter * +nm_tc_tfilter_dup(NMTCTfilter *tfilter) +{ + NMTCTfilter *copy; + + g_return_val_if_fail(tfilter != NULL, NULL); + g_return_val_if_fail(tfilter->refcount > 0, NULL); + + copy = nm_tc_tfilter_new(tfilter->kind, tfilter->parent, NULL); + nm_tc_tfilter_set_handle(copy, tfilter->handle); + nm_tc_tfilter_set_action(copy, tfilter->action); + + return copy; +} + +/** + * nm_tc_tfilter_get_kind: + * @tfilter: the #NMTCTfilter + * + * Returns: + * + * Since: 1.12 + **/ +const char * +nm_tc_tfilter_get_kind(NMTCTfilter *tfilter) +{ + g_return_val_if_fail(tfilter != NULL, NULL); + g_return_val_if_fail(tfilter->refcount > 0, NULL); + + return tfilter->kind; +} + +/** + * nm_tc_tfilter_get_handle: + * @tfilter: the #NMTCTfilter + * + * Returns: the queueing discipline handle + * + * Since: 1.12 + **/ +guint32 +nm_tc_tfilter_get_handle(NMTCTfilter *tfilter) +{ + g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC); + g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC); + + return tfilter->handle; +} + +/** + * nm_tc_tfilter_set_handle: + * @tfilter: the #NMTCTfilter + * @handle: the queueing discipline handle + * + * Sets the queueing discipline handle. + * + * Since: 1.12 + **/ +void +nm_tc_tfilter_set_handle(NMTCTfilter *tfilter, guint32 handle) +{ + g_return_if_fail(tfilter != NULL); + g_return_if_fail(tfilter->refcount > 0); + + tfilter->handle = handle; +} + +/** + * nm_tc_tfilter_get_parent: + * @tfilter: the #NMTCTfilter + * + * Returns: the parent class + * + * Since: 1.12 + **/ +guint32 +nm_tc_tfilter_get_parent(NMTCTfilter *tfilter) +{ + g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC); + g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC); + + return tfilter->parent; +} + +/** + * nm_tc_tfilter_get_action: + * @tfilter: the #NMTCTfilter + * + * Returns: the action associated with a traffic filter. + * + * Since: 1.12 + **/ +NMTCAction * +nm_tc_tfilter_get_action(NMTCTfilter *tfilter) +{ + g_return_val_if_fail(tfilter != NULL, TC_H_UNSPEC); + g_return_val_if_fail(tfilter->refcount > 0, TC_H_UNSPEC); + + if (tfilter->action == NULL) + return NULL; + + return tfilter->action; +} + +/** + * nm_tc_tfilter_set_action: + * @tfilter: the #NMTCTfilter + * @action: the action object + * + * Sets the action associated with a traffic filter. + * + * Since: 1.12 + **/ +void +nm_tc_tfilter_set_action(NMTCTfilter *tfilter, NMTCAction *action) +{ + g_return_if_fail(tfilter != NULL); + g_return_if_fail(tfilter->refcount > 0); + + if (action) + nm_tc_action_ref(action); + if (tfilter->action) + nm_tc_action_unref(tfilter->action); + tfilter->action = action; +} + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingTCConfig, PROP_QDISCS, PROP_TFILTERS, ); + +/** + * NMSettingTCConfig: + * + * Linux Traffic Control Settings + * + * Since: 1.12 + */ +struct _NMSettingTCConfig { + NMSetting parent; + GPtrArray *qdiscs; + GPtrArray *tfilters; +}; + +struct _NMSettingTCConfigClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_tc_config_get_num_qdiscs: + * @setting: the #NMSettingTCConfig + * + * Returns: the number of configured queueing disciplines + * + * Since: 1.12 + **/ +guint +nm_setting_tc_config_get_num_qdiscs(NMSettingTCConfig *self) +{ + g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), 0); + + return self->qdiscs->len; +} + +/** + * nm_setting_tc_config_get_qdisc: + * @setting: the #NMSettingTCConfig + * @idx: index number of the qdisc to return + * + * Returns: (transfer none): the qdisc at index @idx + * + * Since: 1.12 + **/ +NMTCQdisc * +nm_setting_tc_config_get_qdisc(NMSettingTCConfig *self, guint idx) +{ + g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), NULL); + g_return_val_if_fail(idx < self->qdiscs->len, NULL); + + return self->qdiscs->pdata[idx]; +} + +/** + * nm_setting_tc_config_add_qdisc: + * @setting: the #NMSettingTCConfig + * @qdisc: the qdisc to add + * + * Appends a new qdisc and associated information to the setting. The + * given qdisc is duplicated internally and is not changed by this function. + * If an identical qdisc (considering attributes as well) already exists, the + * qdisc is not added and the function returns %FALSE. + * + * Returns: %TRUE if the qdisc was added; %FALSE if the qdisc was already known. + * + * Since: 1.12 + **/ +gboolean +nm_setting_tc_config_add_qdisc(NMSettingTCConfig *self, NMTCQdisc *qdisc) +{ + guint i; + + g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE); + g_return_val_if_fail(qdisc != NULL, FALSE); + + for (i = 0; i < self->qdiscs->len; i++) { + if (nm_tc_qdisc_equal(self->qdiscs->pdata[i], qdisc)) + return FALSE; + } + + g_ptr_array_add(self->qdiscs, nm_tc_qdisc_dup(qdisc)); + _notify(self, PROP_QDISCS); + return TRUE; +} + +/** + * nm_setting_tc_config_remove_qdisc: + * @setting: the #NMSettingTCConfig + * @idx: index number of the qdisc + * + * Removes the qdisc at index @idx. + * + * Since: 1.12 + **/ +void +nm_setting_tc_config_remove_qdisc(NMSettingTCConfig *self, guint idx) +{ + g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self)); + + g_return_if_fail(idx < self->qdiscs->len); + + g_ptr_array_remove_index(self->qdiscs, idx); + _notify(self, PROP_QDISCS); +} + +/** + * nm_setting_tc_config_remove_qdisc_by_value: + * @setting: the #NMSettingTCConfig + * @qdisc: the qdisc to remove + * + * Removes the first matching qdisc that matches @qdisc. + * + * Returns: %TRUE if the qdisc was found and removed; %FALSE if it was not. + * + * Since: 1.12 + **/ +gboolean +nm_setting_tc_config_remove_qdisc_by_value(NMSettingTCConfig *self, NMTCQdisc *qdisc) +{ + guint i; + + g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE); + g_return_val_if_fail(qdisc != NULL, FALSE); + + for (i = 0; i < self->qdiscs->len; i++) { + if (nm_tc_qdisc_equal(self->qdiscs->pdata[i], qdisc)) { + g_ptr_array_remove_index(self->qdiscs, i); + _notify(self, PROP_QDISCS); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_tc_config_clear_qdiscs: + * @setting: the #NMSettingTCConfig + * + * Removes all configured queueing disciplines. + * + * Since: 1.12 + **/ +void +nm_setting_tc_config_clear_qdiscs(NMSettingTCConfig *self) +{ + g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self)); + + if (self->qdiscs->len != 0) { + g_ptr_array_set_size(self->qdiscs, 0); + _notify(self, PROP_QDISCS); + } +} + +/*****************************************************************************/ +/** + * nm_setting_tc_config_get_num_tfilters: + * @setting: the #NMSettingTCConfig + * + * Returns: the number of configured queueing disciplines + * + * Since: 1.12 + **/ +guint +nm_setting_tc_config_get_num_tfilters(NMSettingTCConfig *self) +{ + g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), 0); + + return self->tfilters->len; +} + +/** + * nm_setting_tc_config_get_tfilter: + * @setting: the #NMSettingTCConfig + * @idx: index number of the tfilter to return + * + * Returns: (transfer none): the tfilter at index @idx + * + * Since: 1.12 + **/ +NMTCTfilter * +nm_setting_tc_config_get_tfilter(NMSettingTCConfig *self, guint idx) +{ + g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), NULL); + g_return_val_if_fail(idx < self->tfilters->len, NULL); + + return self->tfilters->pdata[idx]; +} + +/** + * nm_setting_tc_config_add_tfilter: + * @setting: the #NMSettingTCConfig + * @tfilter: the tfilter to add + * + * Appends a new tfilter and associated information to the setting. The + * given tfilter is duplicated internally and is not changed by this function. + * If an identical tfilter (considering attributes as well) already exists, the + * tfilter is not added and the function returns %FALSE. + * + * Returns: %TRUE if the tfilter was added; %FALSE if the tfilter was already known. + * + * Since: 1.12 + **/ +gboolean +nm_setting_tc_config_add_tfilter(NMSettingTCConfig *self, NMTCTfilter *tfilter) +{ + guint i; + + g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE); + g_return_val_if_fail(tfilter != NULL, FALSE); + + for (i = 0; i < self->tfilters->len; i++) { + if (nm_tc_tfilter_equal(self->tfilters->pdata[i], tfilter)) + return FALSE; + } + + g_ptr_array_add(self->tfilters, nm_tc_tfilter_dup(tfilter)); + _notify(self, PROP_TFILTERS); + return TRUE; +} + +/** + * nm_setting_tc_config_remove_tfilter: + * @setting: the #NMSettingTCConfig + * @idx: index number of the tfilter + * + * Removes the tfilter at index @idx. + * + * Since: 1.12 + **/ +void +nm_setting_tc_config_remove_tfilter(NMSettingTCConfig *self, guint idx) +{ + g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self)); + g_return_if_fail(idx < self->tfilters->len); + + g_ptr_array_remove_index(self->tfilters, idx); + _notify(self, PROP_TFILTERS); +} + +/** + * nm_setting_tc_config_remove_tfilter_by_value: + * @setting: the #NMSettingTCConfig + * @tfilter: the tfilter to remove + * + * Removes the first matching tfilter that matches @tfilter. + * + * Returns: %TRUE if the tfilter was found and removed; %FALSE if it was not. + * + * Since: 1.12 + **/ +gboolean +nm_setting_tc_config_remove_tfilter_by_value(NMSettingTCConfig *self, NMTCTfilter *tfilter) +{ + guint i; + + g_return_val_if_fail(NM_IS_SETTING_TC_CONFIG(self), FALSE); + g_return_val_if_fail(tfilter != NULL, FALSE); + + for (i = 0; i < self->tfilters->len; i++) { + if (nm_tc_tfilter_equal(self->tfilters->pdata[i], tfilter)) { + g_ptr_array_remove_index(self->tfilters, i); + _notify(self, PROP_TFILTERS); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_tc_config_clear_tfilters: + * @setting: the #NMSettingTCConfig + * + * Removes all configured queueing disciplines. + * + * Since: 1.12 + **/ +void +nm_setting_tc_config_clear_tfilters(NMSettingTCConfig *self) +{ + g_return_if_fail(NM_IS_SETTING_TC_CONFIG(self)); + + if (self->tfilters->len != 0) { + g_ptr_array_set_size(self->tfilters, 0); + _notify(self, PROP_TFILTERS); + } +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(setting); + guint i; + + if (self->qdiscs->len != 0) { + gs_unref_hashtable GHashTable *ht = NULL; + + ht = g_hash_table_new((GHashFunc) _nm_tc_qdisc_hash, (GEqualFunc) nm_tc_qdisc_equal); + for (i = 0; i < self->qdiscs->len; i++) { + if (!g_hash_table_add(ht, self->qdiscs->pdata[i])) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("there are duplicate TC qdiscs")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_TC_CONFIG_SETTING_NAME, + NM_SETTING_TC_CONFIG_QDISCS); + return FALSE; + } + } + } + + if (self->tfilters->len != 0) { + gs_unref_hashtable GHashTable *ht = NULL; + + ht = g_hash_table_new((GHashFunc) _nm_tc_tfilter_hash, (GEqualFunc) nm_tc_tfilter_equal); + for (i = 0; i < self->tfilters->len; i++) { + if (!g_hash_table_add(ht, self->tfilters->pdata[i])) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("there are duplicate TC filters")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_TC_CONFIG_SETTING_NAME, + NM_SETTING_TC_CONFIG_TFILTERS); + return FALSE; + } + } + } + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingTCConfig *a_tc_config = NM_SETTING_TC_CONFIG(set_a); + NMSettingTCConfig *b_tc_config = NM_SETTING_TC_CONFIG(set_b); + guint i; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TC_CONFIG_QDISCS)) { + if (set_b) { + if (a_tc_config->qdiscs->len != b_tc_config->qdiscs->len) + return FALSE; + for (i = 0; i < a_tc_config->qdiscs->len; i++) { + if (!nm_tc_qdisc_equal(a_tc_config->qdiscs->pdata[i], + b_tc_config->qdiscs->pdata[i])) + return FALSE; + } + } + return TRUE; + } + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TC_CONFIG_TFILTERS)) { + if (set_b) { + if (a_tc_config->tfilters->len != b_tc_config->tfilters->len) + return FALSE; + for (i = 0; i < a_tc_config->tfilters->len; i++) { + if (!nm_tc_tfilter_equal(a_tc_config->tfilters->pdata[i], + b_tc_config->tfilters->pdata[i])) + return FALSE; + } + } + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_tc_config_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/** + * _qdiscs_to_variant: + * @qdiscs: (element-type NMTCQdisc): an array of #NMTCQdisc objects + * + * Utility function to convert a #GPtrArray of #NMTCQdisc objects representing + * TC qdiscs into a #GVariant of type 'aa{sv}' representing an array + * of NetworkManager TC qdiscs. + * + * Returns: (transfer none): a new floating #GVariant representing @qdiscs. + **/ +static GVariant * +_qdiscs_to_variant(GPtrArray *qdiscs) +{ + GVariantBuilder builder; + int i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + if (qdiscs) { + for (i = 0; i < qdiscs->len; i++) { + NMUtilsNamedValue attrs_static[30]; + gs_free NMUtilsNamedValue *attrs_free = NULL; + const NMUtilsNamedValue * attrs; + NMTCQdisc * qdisc = qdiscs->pdata[i]; + guint length; + GVariantBuilder qdisc_builder; + guint y; + + g_variant_builder_init(&qdisc_builder, G_VARIANT_TYPE_VARDICT); + + g_variant_builder_add(&qdisc_builder, + "{sv}", + "kind", + g_variant_new_string(nm_tc_qdisc_get_kind(qdisc))); + + g_variant_builder_add(&qdisc_builder, + "{sv}", + "handle", + g_variant_new_uint32(nm_tc_qdisc_get_handle(qdisc))); + + g_variant_builder_add(&qdisc_builder, + "{sv}", + "parent", + g_variant_new_uint32(nm_tc_qdisc_get_parent(qdisc))); + + attrs = nm_utils_named_values_from_strdict(qdisc->attributes, + &length, + attrs_static, + &attrs_free); + for (y = 0; y < length; y++) { + g_variant_builder_add(&qdisc_builder, "{sv}", attrs[y].name, attrs[y].value_ptr); + } + + g_variant_builder_add(&builder, "a{sv}", &qdisc_builder); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * _qdiscs_from_variant: + * @value: a #GVariant of type 'aa{sv}' + * + * Utility function to convert a #GVariant representing a list of TC qdiscs + * into a #GPtrArray of * #NMTCQdisc objects. + * + * Returns: (transfer full) (element-type NMTCQdisc): a newly allocated + * #GPtrArray of #NMTCQdisc objects + **/ +static GPtrArray * +_qdiscs_from_variant(GVariant *value) +{ + GPtrArray * qdiscs; + GVariant * qdisc_var; + GVariantIter iter; + GError * error = NULL; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); + + g_variant_iter_init(&iter, value); + qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref); + + while (g_variant_iter_next(&iter, "@a{sv}", &qdisc_var)) { + const char * kind; + guint32 parent; + NMTCQdisc * qdisc; + GVariantIter qdisc_iter; + const char * key; + GVariant * attr_value; + + if (!g_variant_lookup(qdisc_var, "kind", "&s", &kind) + || !g_variant_lookup(qdisc_var, "parent", "u", &parent)) { + //g_warning ("Ignoring invalid qdisc"); + goto next; + } + + qdisc = nm_tc_qdisc_new(kind, parent, &error); + if (!qdisc) { + //g_warning ("Ignoring invalid qdisc: %s", error->message); + g_clear_error(&error); + goto next; + } + + g_variant_iter_init(&qdisc_iter, qdisc_var); + while (g_variant_iter_next(&qdisc_iter, "{&sv}", &key, &attr_value)) { + if (strcmp(key, "kind") == 0 || strcmp(key, "parent") == 0) { + /* Already processed above */ + } else if (strcmp(key, "handle") == 0) { + nm_tc_qdisc_set_handle(qdisc, g_variant_get_uint32(attr_value)); + } else { + nm_tc_qdisc_set_attribute(qdisc, key, attr_value); + } + g_variant_unref(attr_value); + } + + g_ptr_array_add(qdiscs, qdisc); +next: + g_variant_unref(qdisc_var); + } + + return qdiscs; +} + +static GVariant * +tc_qdiscs_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *qdiscs = NULL; + + g_object_get(setting, NM_SETTING_TC_CONFIG_QDISCS, &qdiscs, NULL); + return _qdiscs_to_variant(qdiscs); +} + +static gboolean +tc_qdiscs_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GPtrArray *qdiscs; + + qdiscs = _qdiscs_from_variant(value); + g_object_set(setting, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL); + g_ptr_array_unref(qdiscs); + + return TRUE; +} + +static GVariant * +_action_to_variant(NMTCAction *action) +{ + GVariantBuilder builder; + gs_strfreev char **attrs = nm_tc_action_get_attribute_names(action); + int i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + + g_variant_builder_add(&builder, + "{sv}", + "kind", + g_variant_new_string(nm_tc_action_get_kind(action))); + + for (i = 0; attrs[i]; i++) { + g_variant_builder_add(&builder, + "{sv}", + attrs[i], + nm_tc_action_get_attribute(action, attrs[i])); + } + + return g_variant_builder_end(&builder); +} + +/** + * _tfilters_to_variant: + * @tfilters: (element-type NMTCTfilter): an array of #NMTCTfilter objects + * + * Utility function to convert a #GPtrArray of #NMTCTfilter objects representing + * TC tfilters into a #GVariant of type 'aa{sv}' representing an array + * of NetworkManager TC tfilters. + * + * Returns: (transfer none): a new floating #GVariant representing @tfilters. + **/ +static GVariant * +_tfilters_to_variant(GPtrArray *tfilters) +{ + GVariantBuilder builder; + int i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + if (tfilters) { + for (i = 0; i < tfilters->len; i++) { + NMTCTfilter * tfilter = tfilters->pdata[i]; + NMTCAction * action = nm_tc_tfilter_get_action(tfilter); + GVariantBuilder tfilter_builder; + + g_variant_builder_init(&tfilter_builder, G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add(&tfilter_builder, + "{sv}", + "kind", + g_variant_new_string(nm_tc_tfilter_get_kind(tfilter))); + g_variant_builder_add(&tfilter_builder, + "{sv}", + "handle", + g_variant_new_uint32(nm_tc_tfilter_get_handle(tfilter))); + g_variant_builder_add(&tfilter_builder, + "{sv}", + "parent", + g_variant_new_uint32(nm_tc_tfilter_get_parent(tfilter))); + + if (action) { + g_variant_builder_add(&tfilter_builder, + "{sv}", + "action", + _action_to_variant(action)); + } + + g_variant_builder_add(&builder, "a{sv}", &tfilter_builder); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * _tfilters_from_variant: + * @value: a #GVariant of type 'aa{sv}' + * + * Utility function to convert a #GVariant representing a list of TC tfilters + * into a #GPtrArray of * #NMTCTfilter objects. + * + * Returns: (transfer full) (element-type NMTCTfilter): a newly allocated + * #GPtrArray of #NMTCTfilter objects + **/ +static GPtrArray * +_tfilters_from_variant(GVariant *value) +{ + GPtrArray * tfilters; + GVariant * tfilter_var; + GVariantIter iter; + GError * error = NULL; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); + + g_variant_iter_init(&iter, value); + tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref); + + while (g_variant_iter_next(&iter, "@a{sv}", &tfilter_var)) { + NMTCTfilter *tfilter = NULL; + const char * kind; + guint32 handle; + guint32 parent; + NMTCAction * action; + const char * action_kind = NULL; + char * action_key; + GVariantIter action_iter; + GVariant * action_var = NULL; + GVariant * action_val; + + if (!g_variant_lookup(tfilter_var, "kind", "&s", &kind) + || !g_variant_lookup(tfilter_var, "parent", "u", &parent)) { + //g_warning ("Ignoring invalid tfilter"); + goto next; + } + + tfilter = nm_tc_tfilter_new(kind, parent, &error); + if (!tfilter) { + //g_warning ("Ignoring invalid tfilter: %s", error->message); + g_clear_error(&error); + goto next; + } + + if (g_variant_lookup(tfilter_var, "handle", "u", &handle)) + nm_tc_tfilter_set_handle(tfilter, handle); + + action_var = g_variant_lookup_value(tfilter_var, "action", G_VARIANT_TYPE_VARDICT); + + if (action_var) { + if (!g_variant_lookup(action_var, "kind", "&s", &action_kind)) { + //g_warning ("Ignoring tfilter with invalid action"); + goto next; + } + + action = nm_tc_action_new(action_kind, &error); + if (!action) { + //g_warning ("Ignoring tfilter with invalid action: %s", error->message); + g_clear_error(&error); + goto next; + } + + g_variant_iter_init(&action_iter, action_var); + while (g_variant_iter_next(&action_iter, "{&sv}", &action_key, &action_val)) { + if (strcmp(action_key, "kind") != 0) + nm_tc_action_set_attribute(action, action_key, action_val); + g_variant_unref(action_val); + } + + nm_tc_tfilter_set_action(tfilter, action); + nm_tc_action_unref(action); + } + + nm_tc_tfilter_ref(tfilter); + g_ptr_array_add(tfilters, tfilter); +next: + if (tfilter) + nm_tc_tfilter_unref(tfilter); + if (action_var) + g_variant_unref(action_var); + g_variant_unref(tfilter_var); + } + + return tfilters; +} + +static GVariant * +tc_tfilters_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *tfilters = NULL; + + g_object_get(setting, NM_SETTING_TC_CONFIG_TFILTERS, &tfilters, NULL); + return _tfilters_to_variant(tfilters); +} + +static gboolean +tc_tfilters_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + gs_unref_ptrarray GPtrArray *tfilters = NULL; + + tfilters = _tfilters_from_variant(value); + g_object_set(setting, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL); + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object); + + switch (prop_id) { + case PROP_QDISCS: + g_value_take_boxed(value, + _nm_utils_copy_array(self->qdiscs, + (NMUtilsCopyFunc) nm_tc_qdisc_dup, + (GDestroyNotify) nm_tc_qdisc_unref)); + break; + case PROP_TFILTERS: + g_value_take_boxed(value, + _nm_utils_copy_array(self->tfilters, + (NMUtilsCopyFunc) nm_tc_tfilter_dup, + (GDestroyNotify) nm_tc_tfilter_unref)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object); + + switch (prop_id) { + case PROP_QDISCS: + g_ptr_array_unref(self->qdiscs); + self->qdiscs = _nm_utils_copy_array(g_value_get_boxed(value), + (NMUtilsCopyFunc) nm_tc_qdisc_dup, + (GDestroyNotify) nm_tc_qdisc_unref); + break; + case PROP_TFILTERS: + g_ptr_array_unref(self->tfilters); + self->tfilters = _nm_utils_copy_array(g_value_get_boxed(value), + (NMUtilsCopyFunc) nm_tc_tfilter_dup, + (GDestroyNotify) nm_tc_tfilter_unref); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_tc_config_init(NMSettingTCConfig *self) +{ + self->qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref); + self->tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref); +} + +/** + * nm_setting_tc_config_new: + * + * Creates a new #NMSettingTCConfig object with default values. + * + * Returns: (transfer full): the new empty #NMSettingTCConfig object + * + * Since: 1.12 + **/ +NMSetting * +nm_setting_tc_config_new(void) +{ + return g_object_new(NM_TYPE_SETTING_TC_CONFIG, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingTCConfig *self = NM_SETTING_TC_CONFIG(object); + + g_ptr_array_unref(self->qdiscs); + g_ptr_array_unref(self->tfilters); + + G_OBJECT_CLASS(nm_setting_tc_config_parent_class)->finalize(object); +} + +static void +nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + + /** + * NMSettingTCConfig:qdiscs: (type GPtrArray(NMTCQdisc)) + * + * Array of TC queueing disciplines. + **/ + /* ---ifcfg-rh--- + * property: qdiscs + * variable: QDISC1(+), QDISC2(+), ... + * description: Queueing disciplines + * example: QDISC1=ingress, QDISC2="root handle 1234: fq_codel" + * ---end--- + */ + obj_properties[PROP_QDISCS] = g_param_spec_boxed(NM_SETTING_TC_CONFIG_QDISCS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_QDISCS], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = tc_qdiscs_get, + .from_dbus_fcn = tc_qdiscs_set, )); + + /** + * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter)) + * + * Array of TC traffic filters. + **/ + /* ---ifcfg-rh--- + * property: qdiscs + * variable: FILTER1(+), FILTER2(+), ... + * description: Traffic filters + * example: FILTER1="parent ffff: matchall action simple sdata Input", ... + * ---end--- + */ + obj_properties[PROP_TFILTERS] = g_param_spec_boxed( + NM_SETTING_TC_CONFIG_TFILTERS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_TFILTERS], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = tc_tfilters_get, + .from_dbus_fcn = tc_tfilters_set, )); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_TC_CONFIG, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-team-port.c b/src/libnm-core-impl/nm-setting-team-port.c new file mode 100644 index 0000000000..f3e3adb50b --- /dev/null +++ b/src/libnm-core-impl/nm-setting-team-port.c @@ -0,0 +1,685 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + * Copyright (C) 2013 Jiri Pirko + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-team-port.h" + +#include +#include + +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-team-utils.h" + +/** + * SECTION:nm-setting-team-port + * @short_description: Describes connection properties for team ports + * + * The #NMSettingTeamPort object is a #NMSetting subclass that describes + * optional properties that apply to team ports. + **/ + +/*****************************************************************************/ + +static GParamSpec *obj_properties[_NM_TEAM_ATTRIBUTE_PORT_NUM] = { + NULL, +}; + +typedef struct { + NMTeamSetting *team_setting; +} NMSettingTeamPortPrivate; + +G_DEFINE_TYPE(NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING) + +#define NM_SETTING_TEAM_PORT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortPrivate)) + +/*****************************************************************************/ + +NMTeamSetting * +_nm_setting_team_port_get_team_setting(NMSettingTeamPort *setting) +{ + return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting; +} + +/*****************************************************************************/ + +#define _maybe_changed(self, changed) \ + nm_team_setting_maybe_changed(NM_SETTING(_NM_ENSURE_TYPE(NMSettingTeamPort *, self)), \ + (const GParamSpec *const *) obj_properties, \ + (changed)) + +#define _maybe_changed_with_assert(self, changed) \ + G_STMT_START \ + { \ + if (!_maybe_changed((self), (changed))) \ + nm_assert_not_reached(); \ + } \ + G_STMT_END + +/*****************************************************************************/ + +/** + * nm_setting_team_port_get_config: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:config property of the setting + **/ +const char * +nm_setting_team_port_get_config(NMSettingTeamPort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), NULL); + + return nm_team_setting_config_get(NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting); +} + +/** + * nm_setting_team_port_get_queue_id: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:queue_id property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_port_get_queue_id(NMSettingTeamPort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), -1); + + return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.queue_id; +} + +/** + * nm_setting_team_port_get_prio: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:prio property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_port_get_prio(NMSettingTeamPort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), 0); + + return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.prio; +} + +/** + * nm_setting_team_port_get_sticky: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:sticky property of the setting + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_port_get_sticky(NMSettingTeamPort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), FALSE); + + return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.sticky; +} + +/** + * nm_setting_team_port_get_lacp_prio: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:lacp-prio property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_port_get_lacp_prio(NMSettingTeamPort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), 0); + + return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.lacp_prio; +} + +/** + * nm_setting_team_port_get_lacp_key: + * @setting: the #NMSettingTeamPort + * + * Returns: the #NMSettingTeamPort:lacp-key property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_port_get_lacp_key(NMSettingTeamPort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), 0); + + return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.port.lacp_key; +} + +/** + * nm_setting_team_port_get_num_link_watchers: + * @setting: the #NMSettingTeamPort + * + * Returns: the number of configured link watchers + * + * Since: 1.12 + **/ +guint +nm_setting_team_port_get_num_link_watchers(NMSettingTeamPort *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), 0); + + return NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting->d.link_watchers->len; +} + +/** + * nm_setting_team_port_get_link_watcher: + * @setting: the #NMSettingTeamPort + * @idx: index number of the link watcher to return + * + * Returns: (transfer none): the link watcher at index @idx. + * + * Since: 1.12 + **/ +NMTeamLinkWatcher * +nm_setting_team_port_get_link_watcher(NMSettingTeamPort *setting, guint idx) +{ + NMSettingTeamPortPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), NULL); + + priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); + + g_return_val_if_fail(idx < priv->team_setting->d.link_watchers->len, NULL); + + return priv->team_setting->d.link_watchers->pdata[idx]; +} + +/** + * nm_setting_team_port_add_link_watcher: + * @setting: the #NMSettingTeamPort + * @link_watcher: the link watcher to add + * + * Appends a new link watcher to the setting. + * + * Returns: %TRUE if the link watcher is added; %FALSE if an identical link + * watcher was already there. + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_port_add_link_watcher(NMSettingTeamPort *setting, NMTeamLinkWatcher *link_watcher) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), FALSE); + g_return_val_if_fail(link_watcher != NULL, FALSE); + + return _maybe_changed(setting, + nm_team_setting_value_link_watchers_add( + NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting, + link_watcher)); +} + +/** + * nm_setting_team_port_remove_link_watcher: + * @setting: the #NMSettingTeamPort + * @idx: index number of the link watcher to remove + * + * Removes the link watcher at index #idx. + * + * Since: 1.12 + **/ +void +nm_setting_team_port_remove_link_watcher(NMSettingTeamPort *setting, guint idx) +{ + NMSettingTeamPortPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_TEAM_PORT(setting)); + + priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); + + g_return_if_fail(idx < priv->team_setting->d.link_watchers->len); + + _maybe_changed_with_assert(setting, + nm_team_setting_value_link_watchers_remove(priv->team_setting, idx)); +} + +/** + * nm_setting_team_port_remove_link_watcher_by_value: + * @setting: the #NMSettingTeamPort + * @link_watcher: the link watcher to remove + * + * Removes the link watcher entry matching link_watcher. + * + * Returns: %TRUE if the link watcher was found and removed, %FALSE otherwise. + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_port_remove_link_watcher_by_value(NMSettingTeamPort *setting, + NMTeamLinkWatcher *link_watcher) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM_PORT(setting), FALSE); + g_return_val_if_fail(link_watcher, FALSE); + + return _maybe_changed(setting, + nm_team_setting_value_link_watchers_remove_by_value( + NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting, + link_watcher)); +} + +/** + * nm_setting_team_port_clear_link_watchers: + * @setting: the #NMSettingTeamPort + * + * Removes all configured link watchers. + * + * Since: 1.12 + **/ +void +nm_setting_team_port_clear_link_watchers(NMSettingTeamPort *setting) +{ + g_return_if_fail(NM_IS_SETTING_TEAM_PORT(setting)); + + _maybe_changed(setting, + nm_team_setting_value_link_watchers_set_list( + NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting, + NULL, + 0)); +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); + + if (connection) { + NMSettingConnection *s_con; + const char * slave_type; + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + slave_type = nm_setting_connection_get_slave_type(s_con); + if (slave_type && strcmp(slave_type, NM_SETTING_TEAM_SETTING_NAME)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have the slave-type set to '%s'. " + "Instead it is '%s'"), + NM_SETTING_TEAM_PORT_SETTING_NAME, + NM_SETTING_TEAM_SETTING_NAME, + slave_type); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + } + + if (!nm_team_setting_verify(priv->team_setting, error)) + return FALSE; + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingTeamPortPrivate *a_priv; + NMSettingTeamPortPrivate *b_priv; + + if (nm_streq(sett_info->property_infos[property_idx].name, + NM_SETTING_TEAM_PORT_LINK_WATCHERS)) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) + return NM_TERNARY_DEFAULT; + if (!set_b) + return TRUE; + a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(set_a); + b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(set_b); + return nm_team_link_watchers_equal(a_priv->team_setting->d.link_watchers, + b_priv->team_setting->d.link_watchers, + TRUE); + } + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_PORT_CONFIG)) { + if (set_b) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) { + /* If we are trying to match a connection in order to assume it (and thus + * @flags contains INFERRABLE), use the "relaxed" matching for team + * configuration. Otherwise, for all other purposes (including connection + * comparison before an update), resort to the default string comparison. */ + return TRUE; + } + + a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(set_a); + b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(set_b); + + return nm_streq0(nm_team_setting_config_get(a_priv->team_setting), + nm_team_setting_config_get(b_priv->team_setting)); + } + + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_team_port_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +static void +duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) +{ + _maybe_changed(NM_SETTING_TEAM_PORT(dst), + nm_team_setting_reset(NM_SETTING_TEAM_PORT_GET_PRIVATE(dst)->team_setting, + NM_SETTING_TEAM_PORT_GET_PRIVATE(src)->team_setting)); +} + +static gboolean +init_from_dbus(NMSetting * setting, + GHashTable * keys, + GVariant * setting_dict, + GVariant * connection_dict, + guint /* NMSettingParseFlags */ parse_flags, + GError ** error) +{ + guint32 changed = 0; + gboolean success; + + success = + nm_team_setting_reset_from_dbus(NM_SETTING_TEAM_PORT_GET_PRIVATE(setting)->team_setting, + setting_dict, + keys, + &changed, + parse_flags, + error); + _maybe_changed(NM_SETTING_TEAM_PORT(setting), changed); + return success; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingTeamPort * setting = NM_SETTING_TEAM_PORT(object); + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); + + switch (prop_id) { + case NM_TEAM_ATTRIBUTE_CONFIG: + g_value_set_string(value, nm_team_setting_config_get(priv->team_setting)); + break; + case NM_TEAM_ATTRIBUTE_PORT_STICKY: + g_value_set_boolean(value, nm_team_setting_value_get_bool(priv->team_setting, prop_id)); + break; + case NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID: + case NM_TEAM_ATTRIBUTE_PORT_PRIO: + case NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO: + case NM_TEAM_ATTRIBUTE_PORT_LACP_KEY: + g_value_set_int(value, nm_team_setting_value_get_int32(priv->team_setting, prop_id)); + break; + case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: + g_value_take_boxed(value, + _nm_utils_copy_array(priv->team_setting->d.link_watchers, + (NMUtilsCopyFunc) _nm_team_link_watcher_ref, + (GDestroyNotify) nm_team_link_watcher_unref)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingTeamPort * setting = NM_SETTING_TEAM_PORT(object); + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); + guint32 changed; + const GPtrArray * v_ptrarr; + + switch (prop_id) { + case NM_TEAM_ATTRIBUTE_CONFIG: + changed = nm_team_setting_config_set(priv->team_setting, g_value_get_string(value)); + break; + case NM_TEAM_ATTRIBUTE_PORT_STICKY: + changed = + nm_team_setting_value_set_bool(priv->team_setting, prop_id, g_value_get_boolean(value)); + break; + case NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID: + case NM_TEAM_ATTRIBUTE_PORT_PRIO: + case NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO: + case NM_TEAM_ATTRIBUTE_PORT_LACP_KEY: + changed = + nm_team_setting_value_set_int32(priv->team_setting, prop_id, g_value_get_int(value)); + break; + case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: + v_ptrarr = g_value_get_boxed(value); + changed = nm_team_setting_value_link_watchers_set_list( + priv->team_setting, + v_ptrarr ? (const NMTeamLinkWatcher *const *) v_ptrarr->pdata : NULL, + v_ptrarr ? v_ptrarr->len : 0u); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + return; + } + + _maybe_changed(setting, changed & ~(((guint32) 1) << prop_id)); +} + +/*****************************************************************************/ + +static void +nm_setting_team_port_init(NMSettingTeamPort *setting) +{ + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(setting); + + priv->team_setting = nm_team_setting_new(TRUE, NULL); +} + +/** + * nm_setting_team_port_new: + * + * Creates a new #NMSettingTeamPort object with default values. + * + * Returns: (transfer full): the new empty #NMSettingTeamPort object + **/ +NMSetting * +nm_setting_team_port_new(void) +{ + return g_object_new(NM_TYPE_SETTING_TEAM_PORT, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE(object); + + nm_team_setting_free(priv->team_setting); + + G_OBJECT_CLASS(nm_setting_team_port_parent_class)->finalize(object); +} + +static void +nm_setting_team_port_class_init(NMSettingTeamPortClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingTeamPortPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + setting_class->duplicate_copy_properties = duplicate_copy_properties; + setting_class->init_from_dbus = init_from_dbus; + + /** + * NMSettingTeamPort:config: + * + * The JSON configuration for the team port. The property should contain raw + * JSON configuration data suitable for teamd, because the value is passed + * directly to teamd. If not specified, the default configuration is + * used. See man teamd.conf for the format details. + **/ + /* ---ifcfg-rh--- + * property: config + * variable: TEAM_PORT_CONFIG + * description: Team port configuration in JSON. See man teamd.conf for details. + * ---end--- + */ + obj_properties[NM_TEAM_ATTRIBUTE_CONFIG] = g_param_spec_string( + NM_SETTING_TEAM_PORT_CONFIG, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_CONFIG], + &nm_sett_info_propert_type_team_s); + + /** + * NMSettingTeamPort:queue-id: + * + * Corresponds to the teamd ports.PORTIFNAME.queue_id. + * When set to -1 means the parameter is skipped from the json config. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID] = + g_param_spec_int(NM_SETTING_TEAM_PORT_QUEUE_ID, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeamPort:prio: + * + * Corresponds to the teamd ports.PORTIFNAME.prio. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_PORT_PRIO] = + g_param_spec_int(NM_SETTING_TEAM_PORT_PRIO, + "", + "", + G_MININT32, + G_MAXINT32, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_PORT_PRIO], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeamPort:sticky: + * + * Corresponds to the teamd ports.PORTIFNAME.sticky. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_PORT_STICKY] = + g_param_spec_boolean(NM_SETTING_TEAM_PORT_STICKY, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_PORT_STICKY], + &nm_sett_info_propert_type_team_b); + + /** + * NMSettingTeamPort:lacp-prio: + * + * Corresponds to the teamd ports.PORTIFNAME.lacp_prio. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO] = + g_param_spec_int(NM_SETTING_TEAM_PORT_LACP_PRIO, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeamPort:lacp-key: + * + * Corresponds to the teamd ports.PORTIFNAME.lacp_key. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_KEY] = + g_param_spec_int(NM_SETTING_TEAM_PORT_LACP_KEY, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_KEY], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeamPort:link-watchers: (type GPtrArray(NMTeamLinkWatcher)) + * + * Link watchers configuration for the connection: each link watcher is + * defined by a dictionary, whose keys depend upon the selected link + * watcher. Available link watchers are 'ethtool', 'nsna_ping' and + * 'arp_ping' and it is specified in the dictionary with the key 'name'. + * Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; + * nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; + * arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', + * 'validate-inactive', 'send-always'. See teamd.conf man for more details. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS] = + g_param_spec_boxed(NM_SETTING_TEAM_PORT_LINK_WATCHERS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], + &nm_sett_info_propert_type_team_link_watchers); + + g_object_class_install_properties(object_class, G_N_ELEMENTS(obj_properties), obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_TEAM_PORT, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-team.c b/src/libnm-core-impl/nm-setting-team.c new file mode 100644 index 0000000000..d05f04cfab --- /dev/null +++ b/src/libnm-core-impl/nm-setting-team.c @@ -0,0 +1,1818 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + * Copyright (C) 2013 Jiri Pirko + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-team.h" + +#include + +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-team-utils.h" +#include "nm-connection-private.h" + +/** + * SECTION:nm-setting-team + * @short_description: Describes connection properties for teams + * + * The #NMSettingTeam object is a #NMSetting subclass that describes properties + * necessary for team connections. + **/ + +/***************************************************************************** + * NMTeamLinkWatcher + *****************************************************************************/ + +G_DEFINE_BOXED_TYPE(NMTeamLinkWatcher, + nm_team_link_watcher, + _nm_team_link_watcher_ref, + nm_team_link_watcher_unref) + +typedef enum { + LINK_WATCHER_ETHTOOL = 0, + LINK_WATCHER_NSNA_PING = 1, + LINK_WATCHER_ARP_PING = 2, +} LinkWatcherTypes; + +static const char *_link_watcher_name[] = {[LINK_WATCHER_ETHTOOL] = NM_TEAM_LINK_WATCHER_ETHTOOL, + [LINK_WATCHER_NSNA_PING] = + NM_TEAM_LINK_WATCHER_NSNA_PING, + [LINK_WATCHER_ARP_PING] = NM_TEAM_LINK_WATCHER_ARP_PING}; + +struct NMTeamLinkWatcher { + int ref_count; + + guint8 type; /* LinkWatcherTypes */ + + union { + struct { + int delay_up; + int delay_down; + } ethtool; + struct { + const char *target_host; + int init_wait; + int interval; + int missed_max; + } nsna_ping; + struct { + const char * target_host; + const char * source_host; + int init_wait; + int interval; + int missed_max; + int vlanid; + NMTeamLinkWatcherArpPingFlags flags; + } arp_ping; + }; +}; + +#define _CHECK_WATCHER_VOID(watcher) \ + G_STMT_START \ + { \ + g_return_if_fail(watcher != NULL); \ + g_return_if_fail(watcher->ref_count > 0); \ + nm_assert(watcher->type <= LINK_WATCHER_ARP_PING); \ + } \ + G_STMT_END + +#define _CHECK_WATCHER(watcher, err_val) \ + G_STMT_START \ + { \ + g_return_val_if_fail(watcher != NULL, err_val); \ + g_return_val_if_fail(watcher->ref_count > 0, err_val); \ + nm_assert(watcher->type <= LINK_WATCHER_ARP_PING); \ + } \ + G_STMT_END + +/** + * nm_team_link_watcher_new_ethtool: + * @delay_up: delay_up value + * @delay_down: delay_down value + * @error: this call never fails, so this var is not used but kept for format + * consistency with the link_watcher constructors of other type + * + * Creates a new ethtool #NMTeamLinkWatcher object + * + * Returns: (transfer full): the new #NMTeamLinkWatcher object + * + * Since: 1.12 + **/ +NMTeamLinkWatcher * +nm_team_link_watcher_new_ethtool(int delay_up, int delay_down, GError **error) +{ + NMTeamLinkWatcher *watcher; + const char * val_fail = NULL; + + if (delay_up < 0 || !_NM_INT_LE_MAXINT32(delay_up)) + val_fail = "delay-up"; + if (delay_down < 0 || !_NM_INT_LE_MAXINT32(delay_down)) + val_fail = "delay-down"; + if (val_fail) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("%s is out of range [0, %d]"), + val_fail, + G_MAXINT32); + return NULL; + } + + NM_PRAGMA_WARNING_DISABLE("-Warray-bounds") + + watcher = g_malloc(nm_offsetofend(NMTeamLinkWatcher, ethtool)); + + watcher->ref_count = 1; + watcher->type = LINK_WATCHER_ETHTOOL; + watcher->ethtool.delay_up = delay_up; + watcher->ethtool.delay_down = delay_down; + + NM_PRAGMA_WARNING_REENABLE + + return watcher; +} + +/** + * nm_team_link_watcher_new_nsna_ping: + * @init_wait: init_wait value + * @interval: interval value + * @missed_max: missed_max value + * @target_host: the host name or the ipv6 address that will be used as + * target address in the NS packet + * @error: (out) (allow-none): location to store the error on failure + * + * Creates a new nsna_ping #NMTeamLinkWatcher object + * + * Returns: (transfer full): the new #NMTeamLinkWatcher object, or %NULL on error + * + * Since: 1.12 + **/ +NMTeamLinkWatcher * +nm_team_link_watcher_new_nsna_ping(int init_wait, + int interval, + int missed_max, + const char *target_host, + GError ** error) +{ + NMTeamLinkWatcher *watcher; + const char * val_fail = NULL; + char * str; + gsize l_target_host; + + if (!target_host) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("Missing target-host in nsna_ping link watcher")); + return NULL; + } + + if (strpbrk(target_host, " \\/\t=\"\'")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("target-host '%s' contains invalid characters"), + target_host); + return NULL; + } + + if (init_wait < 0 || !_NM_INT_LE_MAXINT32(init_wait)) + val_fail = "init-wait"; + if (interval < 0 || !_NM_INT_LE_MAXINT32(interval)) + val_fail = "interval"; + if (missed_max < 0 || !_NM_INT_LE_MAXINT32(missed_max)) + val_fail = "missed-max"; + if (val_fail) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("%s is out of range [0, %d]"), + val_fail, + G_MAXINT32); + return NULL; + } + + l_target_host = strlen(target_host) + 1; + + watcher = g_malloc(nm_offsetofend(NMTeamLinkWatcher, nsna_ping) + l_target_host); + + watcher->ref_count = 1; + watcher->type = LINK_WATCHER_NSNA_PING; + watcher->nsna_ping.init_wait = init_wait; + watcher->nsna_ping.interval = interval; + watcher->nsna_ping.missed_max = missed_max; + + str = &((char *) watcher)[nm_offsetofend(NMTeamLinkWatcher, nsna_ping)]; + watcher->nsna_ping.target_host = str; + memcpy(str, target_host, l_target_host); + + return watcher; +} + +/** + * nm_team_link_watcher_new_arp_ping: + * @init_wait: init_wait value + * @interval: interval value + * @missed_max: missed_max value + * @target_host: the host name or the ip address that will be used as destination + * address in the arp request + * @source_host: the host name or the ip address that will be used as source + * address in the arp request + * @flags: the watcher #NMTeamLinkWatcherArpPingFlags + * @error: (out) (allow-none): location to store the error on failure + * + * Creates a new arp_ping #NMTeamLinkWatcher object + * + * Returns: (transfer full): the new #NMTeamLinkWatcher object, or %NULL on error + * + * Since: 1.12 + **/ +NMTeamLinkWatcher * +nm_team_link_watcher_new_arp_ping(int init_wait, + int interval, + int missed_max, + const char * target_host, + const char * source_host, + NMTeamLinkWatcherArpPingFlags flags, + GError ** error) +{ + return nm_team_link_watcher_new_arp_ping2(init_wait, + interval, + missed_max, + -1, + target_host, + source_host, + flags, + error); +} + +/** + * nm_team_link_watcher_new_arp_ping2: + * @init_wait: init_wait value + * @interval: interval value + * @missed_max: missed_max value + * @vlanid: vlanid value + * @target_host: the host name or the ip address that will be used as destination + * address in the arp request + * @source_host: the host name or the ip address that will be used as source + * address in the arp request + * @flags: the watcher #NMTeamLinkWatcherArpPingFlags + * @error: (out) (allow-none): location to store the error on failure + * + * Creates a new arp_ping #NMTeamLinkWatcher object + * + * Returns: (transfer full): the new #NMTeamLinkWatcher object, or %NULL on error + * + * Since: 1.16 + **/ +NMTeamLinkWatcher * +nm_team_link_watcher_new_arp_ping2(int init_wait, + int interval, + int missed_max, + int vlanid, + const char * target_host, + const char * source_host, + NMTeamLinkWatcherArpPingFlags flags, + GError ** error) +{ + NMTeamLinkWatcher *watcher; + const char * val_fail = NULL; + char * str; + gsize l_target_host; + gsize l_source_host; + + if (!target_host || !source_host) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("Missing %s in arp_ping link watcher"), + target_host ? "source-host" : "target-host"); + return NULL; + } + + if (strpbrk(target_host, " \\/\t=\"\'")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("target-host '%s' contains invalid characters"), + target_host); + return NULL; + } + + if (strpbrk(source_host, " \\/\t=\"\'")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("source-host '%s' contains invalid characters"), + source_host); + return NULL; + } + + else if (init_wait < 0 || !_NM_INT_LE_MAXINT32(init_wait)) + val_fail = "init-wait"; + else if (interval < 0 || !_NM_INT_LE_MAXINT32(interval)) + val_fail = "interval"; + else if (missed_max < 0 || !_NM_INT_LE_MAXINT32(missed_max)) + val_fail = "missed-max"; + if (val_fail) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("%s is out of range [0, %d]"), + val_fail, + G_MAXINT32); + return NULL; + } + + if (vlanid < -1 || vlanid > 4094) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("vlanid is out of range [-1, 4094]")); + return NULL; + } + + l_target_host = strlen(target_host) + 1; + l_source_host = strlen(source_host) + 1; + + watcher = g_malloc(nm_offsetofend(NMTeamLinkWatcher, arp_ping) + l_target_host + l_source_host); + + watcher->ref_count = 1; + watcher->type = LINK_WATCHER_ARP_PING; + watcher->arp_ping.init_wait = init_wait; + watcher->arp_ping.interval = interval; + watcher->arp_ping.missed_max = missed_max; + watcher->arp_ping.flags = flags; + watcher->arp_ping.vlanid = vlanid; + + str = &((char *) watcher)[nm_offsetofend(NMTeamLinkWatcher, arp_ping)]; + watcher->arp_ping.target_host = str; + memcpy(str, target_host, l_target_host); + + str += l_target_host; + watcher->arp_ping.source_host = str; + memcpy(str, source_host, l_source_host); + + return watcher; +} + +NMTeamLinkWatcher * +_nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, NULL); + + g_atomic_int_inc(&watcher->ref_count); + return watcher; +} + +/** + * nm_team_link_watcher_ref: + * @watcher: the #NMTeamLinkWatcher + * + * Increases the reference count of the object. + * + * Since: 1.12 + **/ +void +nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher) +{ + _nm_team_link_watcher_ref(watcher); +} + +/** + * nm_team_link_watcher_unref: + * @watcher: the #NMTeamLinkWatcher + * + * Decreases the reference count of the object. If the reference count + * reaches zero, the object will be destroyed. + * + * Since: 1.12 + **/ +void +nm_team_link_watcher_unref(NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER_VOID(watcher); + + if (g_atomic_int_dec_and_test(&watcher->ref_count)) + g_free(watcher); +} + +int +nm_team_link_watcher_cmp(const NMTeamLinkWatcher *watcher, const NMTeamLinkWatcher *other) +{ + NM_CMP_SELF(watcher, other); + + NM_CMP_FIELD(watcher, other, type); + + switch (watcher->type) { + case LINK_WATCHER_ETHTOOL: + NM_CMP_FIELD(watcher, other, ethtool.delay_up); + NM_CMP_FIELD(watcher, other, ethtool.delay_down); + break; + case LINK_WATCHER_NSNA_PING: + NM_CMP_FIELD_STR(watcher, other, nsna_ping.target_host); + NM_CMP_FIELD(watcher, other, nsna_ping.init_wait); + NM_CMP_FIELD(watcher, other, nsna_ping.interval); + NM_CMP_FIELD(watcher, other, nsna_ping.missed_max); + break; + case LINK_WATCHER_ARP_PING: + NM_CMP_FIELD_STR(watcher, other, arp_ping.target_host); + NM_CMP_FIELD_STR(watcher, other, arp_ping.source_host); + NM_CMP_FIELD(watcher, other, arp_ping.init_wait); + NM_CMP_FIELD(watcher, other, arp_ping.interval); + NM_CMP_FIELD(watcher, other, arp_ping.missed_max); + NM_CMP_FIELD(watcher, other, arp_ping.vlanid); + NM_CMP_FIELD(watcher, other, arp_ping.flags); + break; + } + return 0; +} + +/** + * nm_team_link_watcher_equal: + * @watcher: the #NMTeamLinkWatcher + * @other: the #NMTeamLinkWatcher to compare @watcher to. + * + * Determines if two #NMTeamLinkWatcher objects contain the same values + * in all the properties. + * + * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. + * + * Since: 1.12 + **/ +gboolean +nm_team_link_watcher_equal(const NMTeamLinkWatcher *watcher, const NMTeamLinkWatcher *other) +{ + return nm_team_link_watcher_cmp(watcher, other) == 0; +} + +static int +_team_link_watchers_cmp_p_with_data(gconstpointer data_a, gconstpointer data_b, gpointer user_data) +{ + return nm_team_link_watcher_cmp(*((const NMTeamLinkWatcher *const *) data_a), + *((const NMTeamLinkWatcher *const *) data_b)); +} + +int +nm_team_link_watchers_cmp(const NMTeamLinkWatcher *const *a, + const NMTeamLinkWatcher *const *b, + gsize len, + gboolean ignore_order) +{ + gs_free const NMTeamLinkWatcher **a_free = NULL; + gs_free const NMTeamLinkWatcher **b_free = NULL; + guint i; + + if (ignore_order && len > 1) { + a = nm_memdup_maybe_a(200, a, len * sizeof(*a), &a_free); + b = nm_memdup_maybe_a(200, b, len * sizeof(*b), &b_free); + g_qsort_with_data((gpointer) a, len, sizeof(*a), _team_link_watchers_cmp_p_with_data, NULL); + g_qsort_with_data((gpointer) b, len, sizeof(*b), _team_link_watchers_cmp_p_with_data, NULL); + } + for (i = 0; i < len; i++) { + NM_CMP_RETURN(nm_team_link_watcher_cmp(a[i], b[i])); + } + return 0; +} + +gboolean +nm_team_link_watchers_equal(const GPtrArray *a, const GPtrArray *b, gboolean ignore_order) +{ + return a == b + || (a && b && a->len == b->len + && (nm_team_link_watchers_cmp((const NMTeamLinkWatcher *const *) a->pdata, + (const NMTeamLinkWatcher *const *) b->pdata, + a->len, + ignore_order) + == 0)); +} + +/** + * nm_team_link_watcher_dup: + * @watcher: the #NMTeamLinkWatcher + * + * Creates a copy of @watcher + * + * Returns: (transfer full): a copy of @watcher + * + * Since: 1.12 + **/ +NMTeamLinkWatcher * +nm_team_link_watcher_dup(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, NULL); + + switch (watcher->type) { + case LINK_WATCHER_ETHTOOL: + return nm_team_link_watcher_new_ethtool(watcher->ethtool.delay_up, + watcher->ethtool.delay_down, + NULL); + break; + case LINK_WATCHER_NSNA_PING: + return nm_team_link_watcher_new_nsna_ping(watcher->nsna_ping.init_wait, + watcher->nsna_ping.interval, + watcher->nsna_ping.missed_max, + watcher->nsna_ping.target_host, + NULL); + break; + case LINK_WATCHER_ARP_PING: + return nm_team_link_watcher_new_arp_ping2(watcher->arp_ping.init_wait, + watcher->arp_ping.interval, + watcher->arp_ping.missed_max, + watcher->arp_ping.vlanid, + watcher->arp_ping.target_host, + watcher->arp_ping.source_host, + watcher->arp_ping.flags, + NULL); + default: + nm_assert_not_reached(); + return NULL; + } +} + +/** + * nm_team_link_watcher_get_name: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the name of the link watcher to be used. + * + * Since: 1.12 + **/ +const char * +nm_team_link_watcher_get_name(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, NULL); + + return _link_watcher_name[watcher->type]; +} + +/** + * nm_team_link_watcher_get_delay_up: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the delay_up interval (in milliseconds) that elapses between the link + * coming up and the runner being notified about it. + * + * Since: 1.12 + **/ +int +nm_team_link_watcher_get_delay_up(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, 0); + + if (watcher->type == LINK_WATCHER_ETHTOOL) + return watcher->ethtool.delay_up; + return -1; +} + +/** + * nm_team_link_watcher_get_delay_down: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the delay_down interval (in milliseconds) that elapses between the link + * going down and the runner being notified about it. + * + * Since: 1.12 + **/ +int +nm_team_link_watcher_get_delay_down(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, 0); + + if (watcher->type == LINK_WATCHER_ETHTOOL) + return watcher->ethtool.delay_down; + return -1; +} + +/** + * nm_team_link_watcher_get_init_wait: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the init_wait interval (in milliseconds) that the team slave should + * wait before sending the first packet to the target host. + * + * Since: 1.12 + **/ +int +nm_team_link_watcher_get_init_wait(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, 0); + + if (watcher->type == LINK_WATCHER_NSNA_PING) + return watcher->nsna_ping.init_wait; + if (watcher->type == LINK_WATCHER_ARP_PING) + return watcher->arp_ping.init_wait; + return -1; +} + +/** + * nm_team_link_watcher_get_interval: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the interval (in milliseconds) that the team slave should wait between + * sending two check packets to the target host. + * + * Since: 1.12 + **/ +int +nm_team_link_watcher_get_interval(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, 0); + + if (watcher->type == LINK_WATCHER_NSNA_PING) + return watcher->nsna_ping.interval; + if (watcher->type == LINK_WATCHER_ARP_PING) + return watcher->arp_ping.interval; + return -1; +} + +/** + * nm_team_link_watcher_get_missed_max: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the number of missed replies after which the link is considered down. + * + * Since: 1.12 + **/ +int +nm_team_link_watcher_get_missed_max(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, 0); + + if (watcher->type == LINK_WATCHER_NSNA_PING) + return watcher->nsna_ping.missed_max; + if (watcher->type == LINK_WATCHER_ARP_PING) + return watcher->arp_ping.missed_max; + return -1; +} + +/** + * nm_team_link_watcher_get_vlanid: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the VLAN tag ID to be used to outgoing link probes + * + * Since: 1.16 + **/ +int +nm_team_link_watcher_get_vlanid(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, -1); + + if (watcher->type == LINK_WATCHER_ARP_PING) + return watcher->arp_ping.vlanid; + return -1; +} + +/** + * nm_team_link_watcher_get_target_host: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the host name/ip address to be used as destination for the link probing + * packets. + * + * Since: 1.12 + **/ +const char * +nm_team_link_watcher_get_target_host(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, NULL); + + if (watcher->type == LINK_WATCHER_NSNA_PING) + return watcher->nsna_ping.target_host; + if (watcher->type == LINK_WATCHER_ARP_PING) + return watcher->arp_ping.target_host; + return NULL; +} + +/** + * nm_team_link_watcher_get_source_host: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the ip address to be used as source for the link probing packets. + * + * Since: 1.12 + **/ +const char * +nm_team_link_watcher_get_source_host(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, NULL); + + if (watcher->type == LINK_WATCHER_ARP_PING) + return watcher->arp_ping.source_host; + return NULL; +} + +/** + * nm_team_link_watcher_get_flags: + * @watcher: the #NMTeamLinkWatcher + * + * Gets the arp ping watcher flags. + * + * Since: 1.12 + **/ +NMTeamLinkWatcherArpPingFlags +nm_team_link_watcher_get_flags(const NMTeamLinkWatcher *watcher) +{ + _CHECK_WATCHER(watcher, 0); + + if (watcher->type == LINK_WATCHER_ARP_PING) + return watcher->arp_ping.flags; + return 0; +} + +/*****************************************************************************/ + +static GParamSpec *obj_properties[_NM_TEAM_ATTRIBUTE_MASTER_NUM] = { + NULL, +}; + +typedef struct { + NMTeamSetting *team_setting; +} NMSettingTeamPrivate; + +G_DEFINE_TYPE(NMSettingTeam, nm_setting_team, NM_TYPE_SETTING) + +#define NM_SETTING_TEAM_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_TEAM, NMSettingTeamPrivate)) + +/*****************************************************************************/ + +NMTeamSetting * +_nm_setting_team_get_team_setting(NMSettingTeam *setting) +{ + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting; +} + +/*****************************************************************************/ + +#define _maybe_changed(self, changed) \ + nm_team_setting_maybe_changed(NM_SETTING(_NM_ENSURE_TYPE(NMSettingTeam *, self)), \ + (const GParamSpec *const *) obj_properties, \ + (changed)) + +#define _maybe_changed_with_assert(self, changed) \ + G_STMT_START \ + { \ + if (!_maybe_changed((self), (changed))) \ + nm_assert_not_reached(); \ + } \ + G_STMT_END + +/** + * nm_setting_team_get_config: + * @setting: the #NMSettingTeam + * + * Returns: the #NMSettingTeam:config property of the setting + **/ +const char * +nm_setting_team_get_config(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); + + return nm_team_setting_config_get(NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting); +} + +/** + * nm_setting_team_get_notify_peers_count: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:notify-peers-count property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_get_notify_peers_count(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.notify_peers_count; +} + +/** + * nm_setting_team_get_notify_peers_interval: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:notify-peers-interval property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_get_notify_peers_interval(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.notify_peers_interval; +} + +/** + * nm_setting_team_get_mcast_rejoin_count: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:mcast-rejoin-count property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_get_mcast_rejoin_count(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.mcast_rejoin_count; +} + +/** + * nm_setting_team_get_mcast_rejoin_interval: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:mcast-rejoin-interval property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_get_mcast_rejoin_interval(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.mcast_rejoin_interval; +} + +/** + * nm_setting_team_get_runner: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner property of the setting + * + * Since: 1.12 + **/ +const char * +nm_setting_team_get_runner(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner; +} + +/** + * nm_setting_team_get_runner_hwaddr_policy: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner-hwaddr-policy property of the setting + * + * Since: 1.12 + **/ +const char * +nm_setting_team_get_runner_hwaddr_policy(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_hwaddr_policy; +} + +/** + * nm_setting_team_get_runner_tx_balancer: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner-tx-balancer property of the setting + * + * Since: 1.12 + **/ +const char * +nm_setting_team_get_runner_tx_balancer(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_tx_balancer; +} + +/** + * nm_setting_team_get_runner_tx_balancer_interval: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner-tx-balancer_interval property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_get_runner_tx_balancer_interval(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_tx_balancer_interval; +} + +/** + * nm_setting_team_get_runner_active: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner_active property of the setting + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_get_runner_active(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_active; +} + +/** + * nm_setting_team_get_runner_fast_rate: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner-fast-rate property of the setting + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_get_runner_fast_rate(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_fast_rate; +} + +/** + * nm_setting_team_get_runner_sys_prio: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner-sys-prio property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_get_runner_sys_prio(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_sys_prio; +} + +/** + * nm_setting_team_get_runner_min_ports: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner-min-ports property of the setting + * + * Since: 1.12 + **/ +int +nm_setting_team_get_runner_min_ports(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_min_ports; +} + +/** + * nm_setting_team_get_runner_agg_select_policy: + * @setting: the #NMSettingTeam + * + * Returns: the ##NMSettingTeam:runner-agg-select-policy property of the setting + * + * Since: 1.12 + **/ +const char * +nm_setting_team_get_runner_agg_select_policy(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_agg_select_policy; +} + +/** + * nm_setting_team_remove_runner_tx_hash_by_value: + * @setting: the #NMSetetingTeam + * @txhash: the txhash element to remove + * + * Removes the txhash element #txhash + * + * Returns: %TRUE if the txhash element was found and removed; %FALSE if it was not. + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_remove_runner_tx_hash_by_value(NMSettingTeam *setting, const char *txhash) +{ + NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(setting); + const GPtrArray * arr; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); + g_return_val_if_fail(txhash != NULL, FALSE); + + arr = priv->team_setting->d.master.runner_tx_hash; + if (arr) { + for (i = 0; i < arr->len; i++) { + if (nm_streq(txhash, arr->pdata[i])) { + _maybe_changed_with_assert( + setting, + nm_team_setting_value_master_runner_tx_hash_remove(priv->team_setting, i)); + return TRUE; + } + } + } + return FALSE; +} + +/** + * nm_setting_team_get_num_runner_tx_hash: + * @setting: the #NMSettingTeam + * + * Returns: the number of elements in txhash + * + * Since: 1.12 + **/ +guint +nm_setting_team_get_num_runner_tx_hash(NMSettingTeam *setting) +{ + const GPtrArray *arr; + + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + arr = NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_tx_hash; + return arr ? arr->len : 0u; +} + +/** + * nm_setting_team_get_runner_tx_hash + * @setting: the #NMSettingTeam + * @idx: index number of the txhash element to return + * + * Returns: the txhash element at index @idx + * + * Since: 1.12 + **/ +const char * +nm_setting_team_get_runner_tx_hash(NMSettingTeam *setting, guint idx) +{ + const GPtrArray *arr; + + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); + + arr = NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.master.runner_tx_hash; + + g_return_val_if_fail(arr, NULL); + g_return_val_if_fail(idx < arr->len, NULL); + + return arr->pdata[idx]; +} + +/** + * nm_setting_team_remove_runner_tx_hash: + * @setting: the #NMSettingTeam + * @idx: index number of the element to remove from txhash + * + * Removes the txhash element at index @idx. + * + * Since: 1.12 + **/ +void +nm_setting_team_remove_runner_tx_hash(NMSettingTeam *setting, guint idx) +{ + NMSettingTeamPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_TEAM(setting)); + + priv = NM_SETTING_TEAM_GET_PRIVATE(setting); + + g_return_if_fail(priv->team_setting->d.master.runner_tx_hash); + g_return_if_fail(idx < priv->team_setting->d.master.runner_tx_hash->len); + + _maybe_changed_with_assert( + setting, + nm_team_setting_value_master_runner_tx_hash_remove(priv->team_setting, idx)); +} + +/** + * nm_setting_team_add_runner_tx_hash: + * @setting: the #NMSettingTeam + * @txhash: the element to add to txhash + * + * Adds a new txhash element to the setting. + * + * Returns: %TRUE if the txhash element was added; %FALSE if the element + * was already knnown. + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_add_runner_tx_hash(NMSettingTeam *setting, const char *txhash) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); + g_return_val_if_fail(txhash, FALSE); + + return _maybe_changed(setting, + nm_team_setting_value_master_runner_tx_hash_add( + NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, + txhash)); +} + +/** + * nm_setting_team_get_num_link_watchers: + * @setting: the #NMSettingTeam + * + * Returns: the number of configured link watchers + * + * Since: 1.12 + **/ +guint +nm_setting_team_get_num_link_watchers(NMSettingTeam *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), 0); + + return NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.link_watchers->len; +} + +/** + * nm_setting_team_get_link_watcher: + * @setting: the #NMSettingTeam + * @idx: index number of the link watcher to return + * + * Returns: (transfer none): the link watcher at index @idx. + * + * Since: 1.12 + **/ +NMTeamLinkWatcher * +nm_setting_team_get_link_watcher(NMSettingTeam *setting, guint idx) +{ + const GPtrArray *arr; + + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), NULL); + + arr = NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting->d.link_watchers; + + g_return_val_if_fail(idx < arr->len, NULL); + + return arr->pdata[idx]; +} + +/** + * nm_setting_team_add_link_watcher: + * @setting: the #NMSettingTeam + * @link_watcher: the link watcher to add + * + * Appends a new link watcher to the setting. + * + * Returns: %TRUE if the link watcher is added; %FALSE if an identical link + * watcher was already there. + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_add_link_watcher(NMSettingTeam *setting, NMTeamLinkWatcher *link_watcher) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); + g_return_val_if_fail(link_watcher != NULL, FALSE); + + return _maybe_changed( + setting, + nm_team_setting_value_link_watchers_add(NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, + link_watcher)); +} + +/** + * nm_setting_team_remove_link_watcher: + * @setting: the #NMSettingTeam + * @idx: index number of the link watcher to remove + * + * Removes the link watcher at index #idx. + * + * Since: 1.12 + **/ +void +nm_setting_team_remove_link_watcher(NMSettingTeam *setting, guint idx) +{ + NMSettingTeamPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_TEAM(setting)); + + priv = NM_SETTING_TEAM_GET_PRIVATE(setting); + + g_return_if_fail(idx < priv->team_setting->d.link_watchers->len); + + _maybe_changed_with_assert(setting, + nm_team_setting_value_link_watchers_remove(priv->team_setting, idx)); +} + +/** + * nm_setting_team_remove_link_watcher_by_value: + * @setting: the #NMSettingTeam + * @link_watcher: the link watcher to remove + * + * Removes the link watcher entry matching link_watcher. + * + * Returns: %TRUE if the link watcher was found and removed, %FALSE otherwise. + * + * Since: 1.12 + **/ +gboolean +nm_setting_team_remove_link_watcher_by_value(NMSettingTeam * setting, + NMTeamLinkWatcher *link_watcher) +{ + g_return_val_if_fail(NM_IS_SETTING_TEAM(setting), FALSE); + g_return_val_if_fail(link_watcher, FALSE); + + return _maybe_changed(setting, + nm_team_setting_value_link_watchers_remove_by_value( + NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, + link_watcher)); +} + +/** + * nm_setting_team_clear_link_watchers: + * @setting: the #NMSettingTeam + * + * Removes all configured link watchers. + * + * Since: 1.12 + **/ +void +nm_setting_team_clear_link_watchers(NMSettingTeam *setting) +{ + g_return_if_fail(NM_IS_SETTING_TEAM(setting)); + + _maybe_changed(setting, + nm_team_setting_value_link_watchers_set_list( + NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, + NULL, + 0)); +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(setting); + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + if (!nm_team_setting_verify(priv->team_setting, error)) + return FALSE; + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingTeamPrivate *a_priv, *b_priv; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_LINK_WATCHERS)) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) + return NM_TERNARY_DEFAULT; + if (!set_b) + return TRUE; + a_priv = NM_SETTING_TEAM_GET_PRIVATE(set_a); + b_priv = NM_SETTING_TEAM_GET_PRIVATE(set_b); + return nm_team_link_watchers_equal(a_priv->team_setting->d.link_watchers, + b_priv->team_setting->d.link_watchers, + TRUE); + } + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_CONFIG)) { + if (set_b) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) { + /* If we are trying to match a connection in order to assume it (and thus + * @flags contains INFERRABLE), use the "relaxed" matching for team + * configuration. Otherwise, for all other purposes (including connection + * comparison before an update), resort to the default string comparison. */ + return TRUE; + } + + a_priv = NM_SETTING_TEAM_GET_PRIVATE(set_a); + b_priv = NM_SETTING_TEAM_GET_PRIVATE(set_b); + + return nm_streq0(nm_team_setting_config_get(a_priv->team_setting), + nm_team_setting_config_get(b_priv->team_setting)); + } + + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_team_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +static void +duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) +{ + _maybe_changed(NM_SETTING_TEAM(dst), + nm_team_setting_reset(NM_SETTING_TEAM_GET_PRIVATE(dst)->team_setting, + NM_SETTING_TEAM_GET_PRIVATE(src)->team_setting)); +} + +static gboolean +init_from_dbus(NMSetting * setting, + GHashTable * keys, + GVariant * setting_dict, + GVariant * connection_dict, + guint /* NMSettingParseFlags */ parse_flags, + GError ** error) +{ + guint32 changed = 0; + gboolean success; + + if (keys) + g_hash_table_remove(keys, "interface-name"); + + success = nm_team_setting_reset_from_dbus(NM_SETTING_TEAM_GET_PRIVATE(setting)->team_setting, + setting_dict, + keys, + &changed, + parse_flags, + error); + _maybe_changed(NM_SETTING_TEAM(setting), changed); + return success; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingTeam * setting = NM_SETTING_TEAM(object); + NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(setting); + const GPtrArray * v_ptrarr; + + switch (prop_id) { + case NM_TEAM_ATTRIBUTE_CONFIG: + g_value_set_string(value, nm_team_setting_config_get(priv->team_setting)); + break; + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE: + g_value_set_boolean(value, nm_team_setting_value_get_bool(priv->team_setting, prop_id)); + break; + case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT: + case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL: + case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT: + case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS: + g_value_set_int(value, nm_team_setting_value_get_int32(priv->team_setting, prop_id)); + break; + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY: + g_value_set_string(value, nm_team_setting_value_get_string(priv->team_setting, prop_id)); + break; + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH: + v_ptrarr = priv->team_setting->d.master.runner_tx_hash; + g_value_take_boxed(value, + v_ptrarr ? _nm_utils_ptrarray_to_strv((GPtrArray *) v_ptrarr) : NULL); + break; + case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: + g_value_take_boxed(value, + _nm_utils_copy_array(priv->team_setting->d.link_watchers, + (NMUtilsCopyFunc) _nm_team_link_watcher_ref, + (GDestroyNotify) nm_team_link_watcher_unref)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingTeam * setting = NM_SETTING_TEAM(object); + NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(object); + guint32 changed; + const GPtrArray * v_ptrarr; + + switch (prop_id) { + case NM_TEAM_ATTRIBUTE_CONFIG: + changed = nm_team_setting_config_set(priv->team_setting, g_value_get_string(value)); + break; + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE: + changed = + nm_team_setting_value_set_bool(priv->team_setting, prop_id, g_value_get_boolean(value)); + break; + case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT: + case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL: + case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT: + case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS: + changed = + nm_team_setting_value_set_int32(priv->team_setting, prop_id, g_value_get_int(value)); + break; + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY: + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY: + changed = nm_team_setting_value_set_string(priv->team_setting, + prop_id, + g_value_get_string(value)); + break; + case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH: + v_ptrarr = g_value_get_boxed(value); + changed = nm_team_setting_value_master_runner_tx_hash_set_list( + priv->team_setting, + v_ptrarr ? (const char *const *) v_ptrarr->pdata : NULL, + v_ptrarr ? v_ptrarr->len : 0u); + break; + case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: + v_ptrarr = g_value_get_boxed(value); + changed = nm_team_setting_value_link_watchers_set_list( + priv->team_setting, + v_ptrarr ? (const NMTeamLinkWatcher *const *) v_ptrarr->pdata : NULL, + v_ptrarr ? v_ptrarr->len : 0u); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + return; + } + + _maybe_changed(setting, changed & ~(((guint32) 1) << prop_id)); +} + +/*****************************************************************************/ + +static void +nm_setting_team_init(NMSettingTeam *setting) +{ + NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(setting); + + priv->team_setting = nm_team_setting_new(FALSE, NULL); +} + +/** + * nm_setting_team_new: + * + * Creates a new #NMSettingTeam object with default values. + * + * Returns: (transfer full): the new empty #NMSettingTeam object + **/ +NMSetting * +nm_setting_team_new(void) +{ + return g_object_new(NM_TYPE_SETTING_TEAM, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE(object); + + nm_team_setting_free(priv->team_setting); + + G_OBJECT_CLASS(nm_setting_team_parent_class)->finalize(object); +} + +static void +nm_setting_team_class_init(NMSettingTeamClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingTeamPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + setting_class->duplicate_copy_properties = duplicate_copy_properties; + setting_class->init_from_dbus = init_from_dbus; + + /** + * NMSettingTeam:config: + * + * The JSON configuration for the team network interface. The property + * should contain raw JSON configuration data suitable for teamd, because + * the value is passed directly to teamd. If not specified, the default + * configuration is used. See man teamd.conf for the format details. + **/ + /* ---ifcfg-rh--- + * property: config + * variable: TEAM_CONFIG + * description: Team configuration in JSON. See man teamd.conf for details. + * ---end--- + */ + obj_properties[NM_TEAM_ATTRIBUTE_CONFIG] = g_param_spec_string( + NM_SETTING_TEAM_CONFIG, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_CONFIG], + &nm_sett_info_propert_type_team_s); + + /** + * NMSettingTeam:notify-peers-count: + * + * Corresponds to the teamd notify_peers.count. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT] = + g_param_spec_int(NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeam:notify-peers-interval: + * + * Corresponds to the teamd notify_peers.interval. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL] = + g_param_spec_int(NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeam:mcast-rejoin-count: + * + * Corresponds to the teamd mcast_rejoin.count. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT] = + g_param_spec_int(NM_SETTING_TEAM_MCAST_REJOIN_COUNT, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeam:mcast-rejoin-interval: + * + * Corresponds to the teamd mcast_rejoin.interval. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL] = + g_param_spec_int(NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeam:runner: + * + * Corresponds to the teamd runner.name. + * Permitted values are: "roundrobin", "broadcast", "activebackup", + * "loadbalance", "lacp", "random". + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER] = + g_param_spec_string(NM_SETTING_TEAM_RUNNER, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER], + &nm_sett_info_propert_type_team_s); + + /** + * NMSettingTeam:runner-hwaddr-policy: + * + * Corresponds to the teamd runner.hwaddr_policy. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY] = + g_param_spec_string(NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY], + &nm_sett_info_propert_type_team_s); + + /** + * NMSettingTeam:runner-tx-hash: + * + * Corresponds to the teamd runner.tx_hash. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH] = g_param_spec_boxed( + NM_SETTING_TEAM_RUNNER_TX_HASH, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH], + &nm_sett_info_propert_type_team_as); + + /** + * NMSettingTeam:runner-tx-balancer: + * + * Corresponds to the teamd runner.tx_balancer.name. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER] = + g_param_spec_string(NM_SETTING_TEAM_RUNNER_TX_BALANCER, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER], + &nm_sett_info_propert_type_team_s); + + /** + * NMSettingTeam:runner-tx-balancer-interval: + * + * Corresponds to the teamd runner.tx_balancer.interval. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL] = + g_param_spec_int(NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeam:runner-active: + * + * Corresponds to the teamd runner.active. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE] = + g_param_spec_boolean(NM_SETTING_TEAM_RUNNER_ACTIVE, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE], + &nm_sett_info_propert_type_team_b); + + /** + * NMSettingTeam:runner-fast-rate: + * + * Corresponds to the teamd runner.fast_rate. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE] = + g_param_spec_boolean(NM_SETTING_TEAM_RUNNER_FAST_RATE, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE], + &nm_sett_info_propert_type_team_b); + + /** + * NMSettingTeam:runner-sys-prio: + * + * Corresponds to the teamd runner.sys_prio. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO] = + g_param_spec_int(NM_SETTING_TEAM_RUNNER_SYS_PRIO, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeam:runner-min-ports: + * + * Corresponds to the teamd runner.min_ports. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS] = + g_param_spec_int(NM_SETTING_TEAM_RUNNER_MIN_PORTS, + "", + "", + G_MININT32, + G_MAXINT32, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS], + &nm_sett_info_propert_type_team_i); + + /** + * NMSettingTeam:runner-agg-select-policy: + * + * Corresponds to the teamd runner.agg_select_policy. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY] = + g_param_spec_string(NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY], + &nm_sett_info_propert_type_team_s); + + /** + * NMSettingTeam:link-watchers: (type GPtrArray(NMTeamLinkWatcher)) + * + * Link watchers configuration for the connection: each link watcher is + * defined by a dictionary, whose keys depend upon the selected link + * watcher. Available link watchers are 'ethtool', 'nsna_ping' and + * 'arp_ping' and it is specified in the dictionary with the key 'name'. + * Available keys are: ethtool: 'delay-up', 'delay-down', 'init-wait'; + * nsna_ping: 'init-wait', 'interval', 'missed-max', 'target-host'; + * arp_ping: all the ones in nsna_ping and 'source-host', 'validate-active', + * 'validate-inactive', 'send-always'. See teamd.conf man for more details. + * + * Since: 1.12 + **/ + obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS] = + g_param_spec_boxed(NM_SETTING_TEAM_LINK_WATCHERS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], + &nm_sett_info_propert_type_team_link_watchers); + + /* ---dbus--- + * property: interface-name + * format: string + * description: Deprecated in favor of connection.interface-name, but can + * be used for backward-compatibility with older daemons, to set the + * team's interface name. + * ---end--- + */ + _nm_properties_override_dbus(properties_override, + "interface-name", + &nm_sett_info_propert_type_deprecated_interface_name); + + g_object_class_install_properties(object_class, G_N_ELEMENTS(obj_properties), obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_TEAM, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-tun.c b/src/libnm-core-impl/nm-setting-tun.c new file mode 100644 index 0000000000..412292a2e4 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-tun.c @@ -0,0 +1,397 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-tun.h" + +#include + +#include "nm-utils.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" +#include "nm-connection-private.h" + +/** + * SECTION:nm-setting-tun + * @short_description: Describes connection properties for TUN/TAP interfaces + * + * The #NMSettingTun object is a #NMSetting subclass that describes properties + * necessary for connection to TUN/TAP interfaces. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_MODE, + PROP_OWNER, + PROP_GROUP, + PROP_PI, + PROP_VNET_HDR, + PROP_MULTI_QUEUE, ); + +typedef struct { + char * owner; + char * group; + NMSettingTunMode mode; + bool pi : 1; + bool vnet_hdr : 1; + bool multi_queue : 1; +} NMSettingTunPrivate; + +G_DEFINE_TYPE(NMSettingTun, nm_setting_tun, NM_TYPE_SETTING) + +#define NM_SETTING_TUN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_TUN, NMSettingTunPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_tun_get_mode: + * @setting: the #NMSettingTun + * + * Returns: the #NMSettingTun:mode property of the setting + * + * Since: 1.2 + **/ +NMSettingTunMode +nm_setting_tun_get_mode(NMSettingTun *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TUN(setting), NM_SETTING_TUN_MODE_TUN); + return NM_SETTING_TUN_GET_PRIVATE(setting)->mode; +} + +/** + * nm_setting_tun_get_owner: + * @setting: the #NMSettingTun + * + * Returns: the #NMSettingTun:owner property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_tun_get_owner(NMSettingTun *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TUN(setting), NULL); + return NM_SETTING_TUN_GET_PRIVATE(setting)->owner; +} + +/** + * nm_setting_tun_get_group: + * @setting: the #NMSettingTun + * + * Returns: the #NMSettingTun:group property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_tun_get_group(NMSettingTun *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TUN(setting), NULL); + return NM_SETTING_TUN_GET_PRIVATE(setting)->group; +} + +/** + * nm_setting_tun_get_pi: + * @setting: the #NMSettingTun + * + * Returns: the #NMSettingTun:pi property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_tun_get_pi(NMSettingTun *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TUN(setting), FALSE); + return NM_SETTING_TUN_GET_PRIVATE(setting)->pi; +} + +/** + * nm_setting_tun_get_vnet_hdr: + * @setting: the #NMSettingTun + * + * Returns: the #NMSettingTun:vnet_hdr property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_tun_get_vnet_hdr(NMSettingTun *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TUN(setting), FALSE); + return NM_SETTING_TUN_GET_PRIVATE(setting)->vnet_hdr; +} + +/** + * nm_setting_tun_get_multi_queue: + * @setting: the #NMSettingTun + * + * Returns: the #NMSettingTun:multi-queue property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_tun_get_multi_queue(NMSettingTun *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_TUN(setting), FALSE); + return NM_SETTING_TUN_GET_PRIVATE(setting)->multi_queue; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(setting); + + if (!NM_IN_SET(priv->mode, NM_SETTING_TUN_MODE_TUN, NM_SETTING_TUN_MODE_TAP)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%u': invalid mode"), + (unsigned) priv->mode); + g_prefix_error(error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_MODE); + return FALSE; + } + + if (priv->owner) { + if (_nm_utils_ascii_str_to_int64(priv->owner, 10, 0, G_MAXINT32, -1) == -1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s': invalid user ID"), + priv->owner); + g_prefix_error(error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_OWNER); + return FALSE; + } + } + + if (priv->group) { + if (_nm_utils_ascii_str_to_int64(priv->group, 10, 0, G_MAXINT32, -1) == -1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s': invalid group ID"), + priv->group); + g_prefix_error(error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_GROUP); + return FALSE; + } + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingTun * setting = NM_SETTING_TUN(object); + NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_MODE: + g_value_set_uint(value, priv->mode); + break; + case PROP_OWNER: + g_value_set_string(value, priv->owner); + break; + case PROP_GROUP: + g_value_set_string(value, priv->group); + break; + case PROP_PI: + g_value_set_boolean(value, priv->pi); + break; + case PROP_VNET_HDR: + g_value_set_boolean(value, priv->vnet_hdr); + break; + case PROP_MULTI_QUEUE: + g_value_set_boolean(value, priv->multi_queue); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingTun * setting = NM_SETTING_TUN(object); + NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_MODE: + priv->mode = g_value_get_uint(value); + break; + case PROP_OWNER: + g_free(priv->owner); + priv->owner = g_value_dup_string(value); + break; + case PROP_GROUP: + g_free(priv->group); + priv->group = g_value_dup_string(value); + break; + case PROP_PI: + priv->pi = g_value_get_boolean(value); + break; + case PROP_VNET_HDR: + priv->vnet_hdr = g_value_get_boolean(value); + break; + case PROP_MULTI_QUEUE: + priv->multi_queue = g_value_get_boolean(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} +/*****************************************************************************/ + +static void +nm_setting_tun_init(NMSettingTun *self) +{ + NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(self); + + priv->mode = NM_SETTING_TUN_MODE_TUN; +} + +/** + * nm_setting_tun_new: + * + * Creates a new #NMSettingTun object with default values. + * + * Returns: (transfer full): the new empty #NMSettingTun object + * + * Since: 1.2 + **/ +NMSetting * +nm_setting_tun_new(void) +{ + return g_object_new(NM_TYPE_SETTING_TUN, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingTun * setting = NM_SETTING_TUN(object); + NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE(setting); + + g_free(priv->owner); + g_free(priv->group); + + G_OBJECT_CLASS(nm_setting_tun_parent_class)->finalize(object); +} + +static void +nm_setting_tun_class_init(NMSettingTunClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingTunPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingTun:mode: + * + * The operating mode of the virtual device. Allowed values are + * %NM_SETTING_TUN_MODE_TUN to create a layer 3 device and + * %NM_SETTING_TUN_MODE_TAP to create an Ethernet-like layer 2 + * one. + * + * Since: 1.2 + */ + obj_properties[PROP_MODE] = + g_param_spec_uint(NM_SETTING_TUN_MODE, + "", + "", + 0, + G_MAXUINT, + NM_SETTING_TUN_MODE_TUN, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingTun:owner: + * + * The user ID which will own the device. If set to %NULL everyone + * will be able to use the device. + * + * Since: 1.2 + */ + obj_properties[PROP_OWNER] = g_param_spec_string(NM_SETTING_TUN_OWNER, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingTun:group: + * + * The group ID which will own the device. If set to %NULL everyone + * will be able to use the device. + * + * Since: 1.2 + */ + obj_properties[PROP_GROUP] = g_param_spec_string(NM_SETTING_TUN_GROUP, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingTun:pi: + * + * If %TRUE the interface will prepend a 4 byte header describing the + * physical interface to the packets. + * + * Since: 1.2 + */ + obj_properties[PROP_PI] = g_param_spec_boolean(NM_SETTING_TUN_PI, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingTun:vnet-hdr: + * + * If %TRUE the IFF_VNET_HDR the tunnel packets will include a virtio + * network header. + * + * Since: 1.2 + */ + obj_properties[PROP_VNET_HDR] = g_param_spec_boolean( + NM_SETTING_TUN_VNET_HDR, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingTun:multi-queue: + * + * If the property is set to %TRUE, the interface will support + * multiple file descriptors (queues) to parallelize packet + * sending or receiving. Otherwise, the interface will only + * support a single queue. + * + * Since: 1.2 + */ + obj_properties[PROP_MULTI_QUEUE] = g_param_spec_boolean( + NM_SETTING_TUN_MULTI_QUEUE, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_TUN); +} diff --git a/src/libnm-core-impl/nm-setting-user.c b/src/libnm-core-impl/nm-setting-user.c new file mode 100644 index 0000000000..0f99baa221 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-user.c @@ -0,0 +1,594 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-user.h" + +#include "nm-setting.h" +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-user + * @short_description: Describes user properties + * + * The #NMSettingUser object is a #NMSetting subclass that allow to attach + * arbitrary user data to #NMConnection objects. + **/ + +#define MAX_NUM_KEYS 256 + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingUser, PROP_DATA, ); + +typedef struct { + GHashTable * data; + GHashTable * data_invalid; + const char **keys; +} NMSettingUserPrivate; + +/** + * NMSettingUser: + * + * General User Profile Settings + */ +struct _NMSettingUser { + NMSetting parent; + NMSettingUserPrivate _priv; +}; + +struct _NMSettingUserClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingUser, nm_setting_user, NM_TYPE_SETTING) + +#define NM_SETTING_USER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMSettingUser, NM_IS_SETTING_USER) + +/*****************************************************************************/ + +static gboolean +_key_char_is_regular(char ch) +{ + /* allow words of printable characters, plus some + * special characters, for example to support base64 encoding. */ + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') + || NM_IN_SET(ch, '-', '_', '+', '/', '='); +} + +/** + * nm_setting_user_check_key: + * @key: the key to check + * @error: a #GError, %NULL to ignore. + * + * Checks whether @key is a valid user data key. This means, + * key is not %NULL, not too large and valid ASCII. Also, + * only digits and numbers are allowed with a few special + * characters. The key must contain at least one '.' and + * look like a fully qualified DNS name. + * + * Since: 1.8 + * + * Returns: %TRUE if @key is a valid user data key. + */ +gboolean +nm_setting_user_check_key(const char *key, GError **error) +{ + gsize len; + gboolean has_dot; + char ch; + + g_return_val_if_fail(!error || !*error, FALSE); + + if (!key || !key[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("missing key")); + return FALSE; + } + len = strlen(key); + if (len > 255) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key is too long")); + return FALSE; + } + if (!g_utf8_validate(key, len, NULL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key must be UTF8")); + return FALSE; + } + + has_dot = FALSE; + while (TRUE) { + ch = (key++)[0]; + + /* Allow something that looks like a FQN, separating namespaces by a single '.' + * We want to print the keys nicely in nmcli requiring escaping. + * + * If a user really has to encode special values in the name, he may base64 encode it. */ + + if (!_key_char_is_regular(ch)) + break; + + while (_key_char_is_regular(key[0])) + key++; + + ch = key[0]; + if (ch == '\0') { + if (!has_dot) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key requires a '.' for a namespace")); + return FALSE; + } + return TRUE; + } + + if (ch != '.') + break; + + has_dot = TRUE; + ch = (++key)[0]; + if (ch == '.') { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key cannot contain \"..\"")); + return FALSE; + } + } + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key contains invalid characters")); + return FALSE; +} + +/** + * nm_setting_user_check_val: + * @val: the value to check + * @error: a #GError, %NULL to ignore. + * + * Checks whether @val is a valid user data value. This means, + * value is not %NULL, not too large and valid UTF-8. + * + * Since: 1.8 + * + * Returns: %TRUE if @val is a valid user data value. + */ +gboolean +nm_setting_user_check_val(const char *val, GError **error) +{ + gsize len; + + g_return_val_if_fail(!error || !*error, FALSE); + + if (!val) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value is missing")); + return FALSE; + } + + len = strlen(val); + if (len > 8 * 1024) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value is too large")); + return FALSE; + } + + if (!g_utf8_validate(val, len, NULL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value is not valid UTF8")); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static GHashTable * +_create_data_hash(void) +{ + return g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); +} + +/** + * nm_setting_user_get_keys: + * @setting: the #NMSettingUser + * @out_len: (out): the length of the returned array + * + * Returns: (array length=out_len) (transfer none): a + * %NULL-terminated array containing each key from the table. + **/ +const char *const * +nm_setting_user_get_keys(NMSettingUser *setting, guint *out_len) +{ + NMSettingUser * self = setting; + NMSettingUserPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_USER(self), NULL); + + priv = NM_SETTING_USER_GET_PRIVATE(self); + + if (priv->keys) { + NM_SET_OUT(out_len, g_hash_table_size(priv->data)); + return priv->keys; + } + + priv->keys = nm_utils_strdict_get_keys(priv->data, TRUE, out_len); + + /* don't return %NULL, but hijack the @keys fields as a pseudo + * empty strv array. */ + return priv->keys ?: ((const char **) &priv->keys); +} + +/*****************************************************************************/ + +/** + * nm_setting_user_get_data: + * @setting: the #NMSettingUser instance + * @key: the key to lookup + * + * Since: 1.8 + * + * Returns: (transfer none): the value associated with @key or %NULL if no such + * value exists. + */ +const char * +nm_setting_user_get_data(NMSettingUser *setting, const char *key) +{ + NMSettingUser * self = setting; + NMSettingUserPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_USER(self), NULL); + g_return_val_if_fail(key, NULL); + + priv = NM_SETTING_USER_GET_PRIVATE(self); + + if (!priv->data) + return NULL; + + return g_hash_table_lookup(priv->data, key); +} + +/** + * nm_setting_user_set_data: + * @setting: the #NMSettingUser instance + * @key: the key to set + * @val: (allow-none): the value to set or %NULL to clear a key. + * @error: (allow-none): optional error argument + * + * Since: 1.8 + * + * Returns: %TRUE if the operation was successful. The operation + * can fail if @key or @val are not valid strings according + * to nm_setting_user_check_key() and nm_setting_user_check_val(). + */ +gboolean +nm_setting_user_set_data(NMSettingUser *setting, const char *key, const char *val, GError **error) +{ + NMSettingUser * self = setting; + NMSettingUserPrivate *priv; + gboolean changed = FALSE; + + g_return_val_if_fail(NM_IS_SETTING_USER(self), FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + + if (!nm_setting_user_check_key(key, error)) + return FALSE; + + if (val && !nm_setting_user_check_val(val, error)) + return FALSE; + + priv = NM_SETTING_USER_GET_PRIVATE(self); + + if (!val) { + if (priv->data && g_hash_table_remove(priv->data, key)) { + nm_clear_g_free(&priv->keys); + changed = TRUE; + } + goto out; + } + + if (priv->data) { + const char *key2, *val2; + + if (g_hash_table_lookup_extended(priv->data, key, (gpointer *) &key2, (gpointer *) &val2)) { + if (nm_streq(val, val2)) + goto out; + } else { + if (g_hash_table_size(priv->data) >= MAX_NUM_KEYS) { + /* limit the number of valid keys */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("maximum number of user data entries reached")); + return FALSE; + } + + nm_clear_g_free(&priv->keys); + } + } else + priv->data = _create_data_hash(); + + g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); + changed = TRUE; + +out: + if (priv->data_invalid) { + /* setting a value purges all invalid values that were set + * via GObject property. */ + changed = TRUE; + nm_clear_pointer(&priv->data_invalid, g_hash_table_unref); + } + if (changed) + _notify(self, PROP_DATA); + return TRUE; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingUser * self = NM_SETTING_USER(setting); + NMSettingUserPrivate *priv = NM_SETTING_USER_GET_PRIVATE(self); + + if (priv->data_invalid) { + const char * key, *val; + GHashTableIter iter; + gs_free_error GError *local = NULL; + + g_hash_table_iter_init(&iter, priv->data_invalid); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + if (!nm_setting_user_check_key(key, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid key \"%s\": %s"), + key, + local->message); + } else if (!nm_setting_user_check_val(val, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid value for \"%s\": %s"), + key, + local->message); + } else { + nm_assert_not_reached(); + continue; + } + g_prefix_error(error, "%s.%s: ", NM_SETTING_USER_SETTING_NAME, NM_SETTING_USER_DATA); + return FALSE; + } + nm_assert_not_reached(); + } + + if (priv->data && g_hash_table_size(priv->data) > MAX_NUM_KEYS) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("maximum number of user data entries reached (%u instead of %u)"), + g_hash_table_size(priv->data), + (unsigned) MAX_NUM_KEYS); + g_prefix_error(error, "%s.%s: ", NM_SETTING_USER_SETTING_NAME, NM_SETTING_USER_DATA); + return FALSE; + } + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingUserPrivate *priv, *pri2; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_USER_DATA)) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) + return NM_TERNARY_DEFAULT; + + if (!set_b) + return TRUE; + + priv = NM_SETTING_USER_GET_PRIVATE(NM_SETTING_USER(set_a)); + pri2 = NM_SETTING_USER_GET_PRIVATE(NM_SETTING_USER(set_b)); + return nm_utils_hashtable_equal(priv->data, pri2->data, TRUE, g_str_equal) + && nm_utils_hashtable_equal(priv->data_invalid, + pri2->data_invalid, + TRUE, + g_str_equal); + } + + return NM_SETTING_CLASS(nm_setting_user_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingUser * self = NM_SETTING_USER(object); + NMSettingUserPrivate *priv = NM_SETTING_USER_GET_PRIVATE(self); + GHashTableIter iter; + GHashTable * data; + const char * key, *val; + + switch (prop_id) { + case PROP_DATA: + data = _create_data_hash(); + if (priv->data) { + g_hash_table_iter_init(&iter, priv->data); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert(data, g_strdup(key), g_strdup(val)); + } + if (priv->data_invalid) { + g_hash_table_iter_init(&iter, priv->data_invalid); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert(data, g_strdup(key), g_strdup(val)); + } + g_value_take_boxed(value, data); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingUser * self = NM_SETTING_USER(object); + NMSettingUserPrivate *priv = NM_SETTING_USER_GET_PRIVATE(self); + GHashTableIter iter; + GHashTable * data; + const char * key, *val; + + switch (prop_id) { + case PROP_DATA: + nm_clear_g_free(&priv->keys); + + data = g_value_get_boxed(value); + if (!data || !g_hash_table_size(data)) { + nm_clear_pointer(&priv->data, g_hash_table_unref); + nm_clear_pointer(&priv->data_invalid, g_hash_table_unref); + return; + } + + if (priv->data) + g_hash_table_remove_all(priv->data); + else + priv->data = _create_data_hash(); + + if (priv->data_invalid) + g_hash_table_remove_all(priv->data_invalid); + + g_hash_table_iter_init(&iter, data); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + if (nm_setting_user_check_key(key, NULL) && nm_setting_user_check_val(val, NULL)) + g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); + else { + if (!priv->data_invalid) + priv->data_invalid = _create_data_hash(); + g_hash_table_insert(priv->data_invalid, g_strdup(key), g_strdup(val)); + } + } + if (priv->data_invalid && !g_hash_table_size(priv->data_invalid)) + nm_clear_pointer(&priv->data_invalid, g_hash_table_unref); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_user_init(NMSettingUser *self) +{} + +/** + * nm_setting_user_new: + * + * Creates a new #NMSettingUser object with default values. + * + * Returns: the new empty #NMSettingUser object + **/ +NMSetting * +nm_setting_user_new(void) +{ + return g_object_new(NM_TYPE_SETTING_USER, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingUser * self = NM_SETTING_USER(object); + NMSettingUserPrivate *priv = NM_SETTING_USER_GET_PRIVATE(self); + + g_free(priv->keys); + if (priv->data) + g_hash_table_unref(priv->data); + if (priv->data_invalid) + g_hash_table_unref(priv->data_invalid); + + G_OBJECT_CLASS(nm_setting_user_parent_class)->finalize(object); +} + +static void +nm_setting_user_class_init(NMSettingUserClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + + /** + * NMSettingUser:data: (type GHashTable(utf8,utf8)) + * + * A dictionary of key/value pairs with user data. This data is ignored by NetworkManager + * and can be used at the users discretion. The keys only support a strict ascii format, + * but the values can be arbitrary UTF8 strings up to a certain length. + * + * Since: 1.8 + **/ + /* ---ifcfg-rh--- + * property: data + * variable: NM_USER_* + * description: each key/value pair is stored as a separate variable with + * name composed by concatenating NM_USER_ with the encoded key. The key is + * encoded by substituting lowercase letters with uppercase and prepending + * uppercase letters with an underscore. A dot is encoded as a double + * underscore. Remaining characters are encoded as underscore followed by a + * 3 digit octal representation of the character. + * example: NM_USER_FOO__BAR=something + * ---end--- + */ + obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_USER_DATA, + "", + "", + G_TYPE_HASH_TABLE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_DATA], + &nm_sett_info_propert_type_strdict); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_USER, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-veth.c b/src/libnm-core-impl/nm-setting-veth.c new file mode 100644 index 0000000000..70cfe50b42 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-veth.c @@ -0,0 +1,194 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-veth.h" + +#include + +#include "nm-utils.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" +#include "nm-connection-private.h" + +/** + * SECTION:nm-setting-veth + * @short_description: Describes connection properties for veth interfaces + * + * The #NMSettingVeth object is a #NMSetting subclass that describes properties + * necessary for connection to veth interfaces. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PEER, ); + +typedef struct { + char *peer; +} NMSettingVethPrivate; + +/** + * NMSettingVeth: + * + * Veth Settings + */ +struct _NMSettingVeth { + NMSetting parent; + NMSettingVethPrivate _priv; +}; + +struct _NMSettingVethClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingVeth, nm_setting_veth, NM_TYPE_SETTING) + +#define NM_SETTING_VETH_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingVeth, NM_IS_SETTING_VETH, NMSetting) + +/*****************************************************************************/ + +/** + * nm_setting_veth_get_peer: + * @setting: the #NMSettingVeth + * + * Returns: the #NMSettingVeth:peer property of the setting + * + * Since: 1.30 + **/ +const char * +nm_setting_veth_get_peer(NMSettingVeth *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VETH(setting), NULL); + return NM_SETTING_VETH_GET_PRIVATE(setting)->peer; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting); + + if (!priv->peer) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is not specified")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VETH_SETTING_NAME, NM_SETTING_VETH_PEER); + return FALSE; + } + + if (!nm_utils_ifname_valid(priv->peer, NMU_IFACE_KERNEL, NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid interface name"), + priv->peer); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VETH_SETTING_NAME, NM_SETTING_VETH_PEER); + return FALSE; + } + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingVeth * setting = NM_SETTING_VETH(object); + NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PEER: + g_value_set_string(value, priv->peer); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingVeth * setting = NM_SETTING_VETH(object); + NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PEER: + g_free(priv->peer); + priv->peer = g_value_dup_string(value); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_veth_init(NMSettingVeth *setting) +{} + +/** + * nm_setting_veth_new: + * + * Creates a new #NMSettingVeth object with default values. + * + * Returns: (transfer full): the new empty #NMSettingVeth object + * + * Since: 1.30 + **/ +NMSetting * +nm_setting_veth_new(void) +{ + return g_object_new(NM_TYPE_SETTING_VETH, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingVeth * setting = NM_SETTING_VETH(object); + NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting); + + g_free(priv->peer); + + G_OBJECT_CLASS(nm_setting_veth_parent_class)->finalize(object); +} + +static void +nm_setting_veth_class_init(NMSettingVethClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingVethPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingVeth:peer: + * + * This property specifies the peer interface name of the veth. This + * property is mandatory. + * + * Since: 1.30 + **/ + obj_properties[PROP_PEER] = g_param_spec_string(NM_SETTING_VETH_PEER, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_VETH); +} diff --git a/src/libnm-core-impl/nm-setting-vlan.c b/src/libnm-core-impl/nm-setting-vlan.c new file mode 100644 index 0000000000..e0cad6a614 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-vlan.c @@ -0,0 +1,983 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2014 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-vlan.h" + +#include + +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "nm-utils.h" +#include "libnm-core-intern/nm-core-types-internal.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" +#include "nm-setting-wired.h" +#include "nm-connection-private.h" + +/** + * SECTION:nm-setting-vlan + * @short_description: Describes connection properties for VLAN interfaces + * + * The #NMSettingVlan object is a #NMSetting subclass that describes properties + * necessary for connection to VLAN interfaces. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingVlan, + PROP_PARENT, + PROP_ID, + PROP_FLAGS, + PROP_INGRESS_PRIORITY_MAP, + PROP_EGRESS_PRIORITY_MAP, ); + +typedef struct { + GSList *ingress_priority_map; + GSList *egress_priority_map; + char * parent; + guint32 id; + guint32 flags; +} NMSettingVlanPrivate; + +G_DEFINE_TYPE(NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING) + +#define NM_SETTING_VLAN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_VLAN, NMSettingVlanPrivate)) + +/*****************************************************************************/ + +#define MAX_SKB_PRIO G_MAXUINT32 +#define MAX_8021P_PRIO 7 /* Max 802.1p priority */ + +/** + * nm_setting_vlan_get_parent: + * @setting: the #NMSettingVlan + * + * Returns: the #NMSettingVlan:parent property of the setting + **/ +const char * +nm_setting_vlan_get_parent(NMSettingVlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), NULL); + return NM_SETTING_VLAN_GET_PRIVATE(setting)->parent; +} + +/** + * nm_setting_vlan_get_id: + * @setting: the #NMSettingVlan + * + * Returns: the #NMSettingVlan:id property of the setting + **/ +guint32 +nm_setting_vlan_get_id(NMSettingVlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), 0); + return NM_SETTING_VLAN_GET_PRIVATE(setting)->id; +} + +/** + * nm_setting_vlan_get_flags: + * @setting: the #NMSettingVlan + * + * Returns: the #NMSettingVlan:flags property of the setting + **/ +guint32 +nm_setting_vlan_get_flags(NMSettingVlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), 0); + return NM_SETTING_VLAN_GET_PRIVATE(setting)->flags; +} + +static NMVlanQosMapping * +priority_map_new(guint32 from, guint32 to) +{ + NMVlanQosMapping *mapping; + + mapping = g_new(NMVlanQosMapping, 1); + *mapping = (NMVlanQosMapping){ + .from = from, + .to = to, + }; + return mapping; +} + +static NMVlanQosMapping * +priority_map_new_from_str(NMVlanPriorityMap map, const char *str) +{ + guint32 from, to; + + if (!nm_utils_vlan_priority_map_parse_str(map, str, FALSE, &from, &to, NULL)) + return NULL; + return priority_map_new(from, to); +} + +static void +priority_map_free(NMVlanQosMapping *map) +{ + nm_assert(map); + g_free(map); +} + +static GSList * +get_map(NMSettingVlan *self, NMVlanPriorityMap map) +{ + if (map == NM_VLAN_INGRESS_MAP) + return NM_SETTING_VLAN_GET_PRIVATE(self)->ingress_priority_map; + else if (map == NM_VLAN_EGRESS_MAP) + return NM_SETTING_VLAN_GET_PRIVATE(self)->egress_priority_map; + nm_assert_not_reached(); + return NULL; +} + +static int +prio_map_compare(gconstpointer p_a, gconstpointer p_b) +{ + const NMVlanQosMapping *a = p_a; + const NMVlanQosMapping *b = p_b; + + return a->from < b->from + ? -1 + : (a->from > b->from ? 1 : (a->to < b->to ? -1 : (a->to > b->to ? 1 : 0))); +} + +static void +set_map(NMSettingVlan *self, NMVlanPriorityMap map, GSList *list) +{ + /* Assert that the list is sorted */ +#if NM_MORE_ASSERTS >= 2 + { + GSList *iter, *last; + + last = list; + iter = list ? list->next : NULL; + while (iter) { + const NMVlanQosMapping *l = last->data; + const NMVlanQosMapping *m = iter->data; + + nm_assert(prio_map_compare(last->data, iter->data) < 0); + + /* Also reject duplicates (based on "from") */ + nm_assert(l->from < m->from); + + last = iter; + iter = iter->next; + } + } +#endif + + if (map == NM_VLAN_INGRESS_MAP) { + NM_SETTING_VLAN_GET_PRIVATE(self)->ingress_priority_map = list; + _notify(self, PROP_INGRESS_PRIORITY_MAP); + } else if (map == NM_VLAN_EGRESS_MAP) { + NM_SETTING_VLAN_GET_PRIVATE(self)->egress_priority_map = list; + _notify(self, PROP_EGRESS_PRIORITY_MAP); + } else + nm_assert_not_reached(); +} + +static gboolean +check_replace_duplicate_priority(GSList *list, guint32 from, guint32 to) +{ + GSList * iter; + NMVlanQosMapping *p; + + for (iter = list; iter; iter = g_slist_next(iter)) { + p = iter->data; + if (p->from == from) { + p->to = to; + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_vlan_add_priority_str: + * @setting: the #NMSettingVlan + * @map: the type of priority map + * @str: the string which contains a priority map, like "3:7" + * + * Adds a priority map entry into either the #NMSettingVlan:ingress_priority_map + * or the #NMSettingVlan:egress_priority_map properties. The priority map maps + * the Linux SKB priorities to 802.1p priorities. + * + * Returns: %TRUE if the entry was successfully added to the list, or it + * overwrote the old value, %FALSE if @str is not a valid mapping. + */ +gboolean +nm_setting_vlan_add_priority_str(NMSettingVlan *setting, NMVlanPriorityMap map, const char *str) +{ + GSList * list = NULL; + NMVlanQosMapping *item = NULL; + + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); + g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE); + g_return_val_if_fail(str && str[0], FALSE); + + item = priority_map_new_from_str(map, str); + if (!item) + return FALSE; + + list = get_map(setting, map); + + /* Duplicates get replaced */ + if (check_replace_duplicate_priority(list, item->from, item->to)) { + g_free(item); + if (map == NM_VLAN_INGRESS_MAP) + _notify(setting, PROP_INGRESS_PRIORITY_MAP); + else + _notify(setting, PROP_EGRESS_PRIORITY_MAP); + return TRUE; + } + + set_map(setting, map, g_slist_insert_sorted(list, item, prio_map_compare)); + return TRUE; +} + +/** + * nm_setting_vlan_get_num_priorities: + * @setting: the #NMSettingVlan + * @map: the type of priority map + * + * Returns the number of entries in the + * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map + * properties of this setting. + * + * Returns: return the number of ingress/egress priority entries. + **/ +gint32 +nm_setting_vlan_get_num_priorities(NMSettingVlan *setting, NMVlanPriorityMap map) +{ + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), -1); + g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, -1); + + return g_slist_length(get_map(setting, map)); +} + +/** + * nm_setting_vlan_get_priority: + * @setting: the #NMSettingVlan + * @map: the type of priority map + * @idx: the zero-based index of the ingress/egress priority map entry + * @out_from: (out) (allow-none): on return the value of the priority map's 'from' item + * @out_to: (out) (allow-none): on return the value of priority map's 'to' item + * + * Retrieve one of the entries of the #NMSettingVlan:ingress_priority_map + * or #NMSettingVlan:egress_priority_map properties of this setting. + * + * Returns: returns %TRUE if @idx is in range. Otherwise, %FALSE. + **/ +gboolean +nm_setting_vlan_get_priority(NMSettingVlan * setting, + NMVlanPriorityMap map, + guint32 idx, + guint32 * out_from, + guint32 * out_to) +{ + NMVlanQosMapping *item; + GSList * list; + + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); + g_return_val_if_fail(NM_IN_SET(map, NM_VLAN_INGRESS_MAP, NM_VLAN_EGRESS_MAP), FALSE); + + list = get_map(setting, map); + item = g_slist_nth_data(list, idx); + + if (!item) { + NM_SET_OUT(out_from, 0); + NM_SET_OUT(out_to, 0); + return FALSE; + } + + NM_SET_OUT(out_from, item->from); + NM_SET_OUT(out_to, item->to); + return TRUE; +} + +/** + * nm_setting_vlan_add_priority: + * @setting: the #NMSettingVlan + * @map: the type of priority map + * @from: the priority to map to @to + * @to: the priority to map @from to + * + * Adds a priority mapping to the #NMSettingVlan:ingress_priority_map or + * #NMSettingVlan:egress_priority_map properties of the setting. If @from is + * already in the given priority map, this function will overwrite the + * existing entry with the new @to. + * + * If @map is #NM_VLAN_INGRESS_MAP then @from is the incoming 802.1q VLAN + * Priority Code Point (PCP) value, and @to is the Linux SKB priority value. + * + * If @map is #NM_VLAN_EGRESS_MAP then @from is the Linux SKB priority value and + * @to is the outgoing 802.1q VLAN Priority Code Point (PCP) value. + * + * Returns: %TRUE. + */ +gboolean +nm_setting_vlan_add_priority(NMSettingVlan * setting, + NMVlanPriorityMap map, + guint32 from, + guint32 to) +{ + GSList * list = NULL; + NMVlanQosMapping *item; + + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); + g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE); + + list = get_map(setting, map); + if (check_replace_duplicate_priority(list, from, to)) { + if (map == NM_VLAN_INGRESS_MAP) + _notify(setting, PROP_INGRESS_PRIORITY_MAP); + else + _notify(setting, PROP_EGRESS_PRIORITY_MAP); + return TRUE; + } + + item = g_malloc0(sizeof(NMVlanQosMapping)); + item->from = from; + item->to = to; + set_map(setting, map, g_slist_insert_sorted(list, item, prio_map_compare)); + + return TRUE; +} + +gboolean +_nm_setting_vlan_set_priorities(NMSettingVlan * setting, + NMVlanPriorityMap map, + const NMVlanQosMapping *qos_map, + guint n_qos_map) +{ + gboolean has_changes = FALSE; + GSList * map_prev, *map_new; + guint i; + gint64 from_last; + + map_prev = get_map(setting, map); + + if (n_qos_map != g_slist_length(map_prev)) + has_changes = TRUE; + else { + const GSList *iter; + + iter = map_prev; + for (i = 0; i < n_qos_map; i++, iter = iter->next) { + const NMVlanQosMapping *m = iter->data; + + if (m->from != qos_map[i].from || m->to != qos_map[i].to) { + has_changes = TRUE; + break; + } + } + } + + if (!has_changes) + return FALSE; + + map_new = NULL; + from_last = G_MAXINT64; + for (i = n_qos_map; i > 0;) { + const NMVlanQosMapping *m = &qos_map[--i]; + NMVlanQosMapping * item; + + /* We require the array to be presorted. */ + if (m->from >= from_last) + g_return_val_if_reached(FALSE); + from_last = m->from; + + item = g_malloc0(sizeof(NMVlanQosMapping)); + item->from = m->from; + item->to = m->to; + map_new = g_slist_prepend(map_new, item); + } + + g_slist_free_full(map_prev, g_free); + set_map(setting, map, map_new); + + return TRUE; +} + +void +_nm_setting_vlan_get_priorities(NMSettingVlan * setting, + NMVlanPriorityMap map, + NMVlanQosMapping **out_qos_map, + guint * out_n_qos_map) +{ + GSList * list; + NMVlanQosMapping *qos_map = NULL; + guint n_qos_map, i; + + list = get_map(setting, map); + + n_qos_map = g_slist_length(list); + + if (n_qos_map > 0) { + qos_map = g_new(NMVlanQosMapping, n_qos_map); + + for (i = 0; list; i++, list = list->next) { + nm_assert(i < n_qos_map); + qos_map[i] = *((const NMVlanQosMapping *) list->data); + } + } + *out_qos_map = qos_map; + *out_n_qos_map = n_qos_map; +} + +/** + * nm_setting_vlan_remove_priority: + * @setting: the #NMSettingVlan + * @map: the type of priority map + * @idx: the zero-based index of the priority map to remove + * + * Removes the priority map at index @idx from the + * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map + * properties. + */ +void +nm_setting_vlan_remove_priority(NMSettingVlan *setting, NMVlanPriorityMap map, guint32 idx) +{ + GSList *list = NULL, *item = NULL; + + g_return_if_fail(NM_IS_SETTING_VLAN(setting)); + g_return_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP); + + list = get_map(setting, map); + g_return_if_fail(idx < g_slist_length(list)); + + item = g_slist_nth(list, idx); + priority_map_free((NMVlanQosMapping *) (item->data)); + set_map(setting, map, g_slist_delete_link(list, item)); +} + +static gboolean +priority_map_remove_by_value(NMSettingVlan * setting, + NMVlanPriorityMap map, + guint32 from, + guint32 to, + gboolean wildcard_to) +{ + GSList * list = NULL, *iter = NULL; + NMVlanQosMapping *item; + + nm_assert(NM_IS_SETTING_VLAN(setting)); + nm_assert(NM_IN_SET(map, NM_VLAN_INGRESS_MAP, NM_VLAN_EGRESS_MAP)); + + list = get_map(setting, map); + for (iter = list; iter; iter = g_slist_next(iter)) { + item = iter->data; + + if (item->from != from) + continue; + if (!wildcard_to && item->to != to) + continue; + + priority_map_free((NMVlanQosMapping *) (iter->data)); + set_map(setting, map, g_slist_delete_link(list, iter)); + return TRUE; + } + return FALSE; +} + +/** + * nm_setting_vlan_remove_priority_by_value: + * @setting: the #NMSettingVlan + * @map: the type of priority map + * @from: the priority to map to @to + * @to: the priority to map @from to + * + * Removes the priority map @form:@to from the #NMSettingVlan:ingress_priority_map + * or #NMSettingVlan:egress_priority_map (according to @map argument) + * properties. + * + * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not. + */ +gboolean +nm_setting_vlan_remove_priority_by_value(NMSettingVlan * setting, + NMVlanPriorityMap map, + guint32 from, + guint32 to) +{ + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); + g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE); + + return priority_map_remove_by_value(setting, map, from, to, FALSE); +} + +/** + * nm_setting_vlan_remove_priority_str_by_value: + * @setting: the #NMSettingVlan + * @map: the type of priority map + * @str: the string which contains a priority map, like "3:7" + * + * Removes the priority map @str from the #NMSettingVlan:ingress_priority_map + * or #NMSettingVlan:egress_priority_map (according to @map argument) + * properties. + * + * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not. + */ +gboolean +nm_setting_vlan_remove_priority_str_by_value(NMSettingVlan * setting, + NMVlanPriorityMap map, + const char * str) +{ + gboolean is_wildcard_to; + guint32 from, to; + + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), FALSE); + g_return_val_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE); + + if (!nm_utils_vlan_priority_map_parse_str(map, str, TRUE, &from, &to, &is_wildcard_to)) + return FALSE; + return priority_map_remove_by_value(setting, map, from, to, is_wildcard_to); +} + +/** + * nm_setting_vlan_clear_priorities: + * @setting: the #NMSettingVlan + * @map: the type of priority map + * + * Clear all the entries from #NMSettingVlan:ingress_priority_map or + * #NMSettingVlan:egress_priority_map properties. + */ +void +nm_setting_vlan_clear_priorities(NMSettingVlan *setting, NMVlanPriorityMap map) +{ + GSList *list = NULL; + + g_return_if_fail(NM_IS_SETTING_VLAN(setting)); + g_return_if_fail(map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP); + + list = get_map(setting, map); + g_slist_free_full(list, g_free); + set_map(setting, map, NULL); +} + +/*****************************************************************************/ + +static int +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(setting); + NMSettingConnection * s_con; + NMSettingWired * s_wired; + + if (connection) { + s_con = nm_connection_get_setting_connection(connection); + s_wired = nm_connection_get_setting_wired(connection); + } else { + s_con = NULL; + s_wired = NULL; + } + + if (priv->parent) { + if (nm_utils_is_uuid(priv->parent)) { + /* If we have an NMSettingConnection:master with slave-type="vlan", + * then it must be the same UUID. + */ + if (s_con) { + const char *master = NULL, *slave_type = NULL; + + slave_type = nm_setting_connection_get_slave_type(s_con); + if (!g_strcmp0(slave_type, NM_SETTING_VLAN_SETTING_NAME)) + master = nm_setting_connection_get_master(s_con); + + if (master && g_strcmp0(priv->parent, master) != 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' value doesn't match '%s=%s'"), + priv->parent, + NM_SETTING_CONNECTION_MASTER, + master); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_VLAN_SETTING_NAME, + NM_SETTING_VLAN_PARENT); + return FALSE; + } + } + } else if (!nm_utils_ifname_valid_kernel(priv->parent, NULL)) { + /* parent must be either a UUID or an interface name */ + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT); + return FALSE; + } + } else { + /* If parent is NULL, the parent must be specified via + * NMSettingWired:mac-address. + */ + if (connection && (!s_wired || !nm_setting_wired_get_mac_address(s_wired))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is not specified and neither is '%s:%s'"), + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_MAC_ADDRESS); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT); + return FALSE; + } + } + + if (priv->id >= 4095) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the vlan id must be in range 0-4094 but is %u"), + priv->id); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_ID); + return FALSE; + } + + if (priv->flags & ~NM_VLAN_FLAGS_ALL) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("flags are invalid")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_FLAGS); + return FALSE; + } + + if (connection && !s_wired) { + /* technically, a VLAN setting does not require an ethernet setting. However, + * the ifcfg-rh reader always adds a ethernet setting when reading a vlan setting. + * Thus, in order to be consistent, always add one via normalization. */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_SETTING_NOT_FOUND, + _("vlan setting should have a ethernet setting as well")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_FLAGS); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + return TRUE; +} + +static GVariant * +_override_flags_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + return g_variant_new_uint32(nm_setting_vlan_get_flags((NMSettingVlan *) setting)); +} + +static gboolean +_override_flags_not_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + NMSettingParseFlags parse_flags, + GError ** error) +{ + /* we changed the default value for FLAGS. When an older client + * doesn't serialize the property, we assume it is the old default. */ + g_object_set(G_OBJECT(setting), NM_SETTING_VLAN_FLAGS, (NMVlanFlags) 0, NULL); + return TRUE; +} + +static GSList * +priority_strv_to_maplist(NMVlanPriorityMap map, char **strv) +{ + GSList *list = NULL; + gsize i; + + for (i = 0; strv && strv[i]; i++) { + guint32 from, to; + + if (!nm_utils_vlan_priority_map_parse_str(map, strv[i], FALSE, &from, &to, NULL)) + continue; + if (check_replace_duplicate_priority(list, from, to)) + continue; + list = g_slist_prepend(list, priority_map_new(from, to)); + } + return g_slist_sort(list, prio_map_compare); +} + +static char ** +priority_maplist_to_strv(GSList *list) +{ + GSList * iter; + GPtrArray *strv; + + strv = g_ptr_array_new(); + + for (iter = list; iter; iter = g_slist_next(iter)) { + NMVlanQosMapping *item = iter->data; + + g_ptr_array_add(strv, g_strdup_printf("%d:%d", item->from, item->to)); + } + g_ptr_array_add(strv, NULL); + + return (char **) g_ptr_array_free(strv, FALSE); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingVlan * setting = NM_SETTING_VLAN(object); + NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string(value, priv->parent); + break; + case PROP_ID: + g_value_set_uint(value, priv->id); + break; + case PROP_FLAGS: + g_value_set_flags(value, priv->flags); + break; + case PROP_INGRESS_PRIORITY_MAP: + g_value_take_boxed(value, priority_maplist_to_strv(priv->ingress_priority_map)); + break; + case PROP_EGRESS_PRIORITY_MAP: + g_value_take_boxed(value, priority_maplist_to_strv(priv->egress_priority_map)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingVlan * setting = NM_SETTING_VLAN(object); + NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_free(priv->parent); + priv->parent = g_value_dup_string(value); + break; + case PROP_ID: + priv->id = g_value_get_uint(value); + break; + case PROP_FLAGS: + priv->flags = g_value_get_flags(value); + break; + case PROP_INGRESS_PRIORITY_MAP: + g_slist_free_full(priv->ingress_priority_map, g_free); + priv->ingress_priority_map = + priority_strv_to_maplist(NM_VLAN_INGRESS_MAP, g_value_get_boxed(value)); + break; + case PROP_EGRESS_PRIORITY_MAP: + g_slist_free_full(priv->egress_priority_map, g_free); + priv->egress_priority_map = + priority_strv_to_maplist(NM_VLAN_EGRESS_MAP, g_value_get_boxed(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_vlan_init(NMSettingVlan *self) +{ + NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(self); + + priv->flags = NM_VLAN_FLAG_REORDER_HEADERS; +} + +/** + * nm_setting_vlan_new: + * + * Creates a new #NMSettingVlan object with default values. + * + * Returns: (transfer full): the new empty #NMSettingVlan object + **/ +NMSetting * +nm_setting_vlan_new(void) +{ + return g_object_new(NM_TYPE_SETTING_VLAN, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingVlan * setting = NM_SETTING_VLAN(object); + NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE(setting); + + g_free(priv->parent); + g_slist_free_full(priv->ingress_priority_map, g_free); + g_slist_free_full(priv->egress_priority_map, g_free); + + G_OBJECT_CLASS(nm_setting_vlan_parent_class)->finalize(object); +} + +static void +nm_setting_vlan_class_init(NMSettingVlanClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingVlanPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingVlan:parent: + * + * If given, specifies the parent interface name or parent connection UUID + * from which this VLAN interface should be created. If this property is + * not specified, the connection must contain an #NMSettingWired setting + * with a #NMSettingWired:mac-address property. + **/ + /* ---ifcfg-rh--- + * property: parent + * variable: DEVICE or PHYSDEV + * description: Parent interface of the VLAN. + * ---end--- + */ + obj_properties[PROP_PARENT] = g_param_spec_string( + NM_SETTING_VLAN_PARENT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVlan:id: + * + * The VLAN identifier that the interface created by this connection should + * be assigned. The valid range is from 0 to 4094, without the reserved id 4095. + **/ + /* ---ifcfg-rh--- + * property: id + * variable: VLAN_ID or DEVICE + * description: VLAN identifier. + * ---end--- + */ + obj_properties[PROP_ID] = + g_param_spec_uint(NM_SETTING_VLAN_ID, + "", + "", + 0, + 4095, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVlan:flags: + * + * One or more flags which control the behavior and features of the VLAN + * interface. Flags include %NM_VLAN_FLAG_REORDER_HEADERS (reordering of + * output packet headers), %NM_VLAN_FLAG_GVRP (use of the GVRP protocol), + * and %NM_VLAN_FLAG_LOOSE_BINDING (loose binding of the interface to its + * master device's operating state). %NM_VLAN_FLAG_MVRP (use of the MVRP + * protocol). + * + * The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, + * but it used to be 0. To preserve backward compatibility, the default-value + * in the D-Bus API continues to be 0 and a missing property on D-Bus + * is still considered as 0. + **/ + /* ---ifcfg-rh--- + * property: flags + * variable: GVRP, MVRP, VLAN_FLAGS + * values: "yes or "no" for GVRP and MVRP; "LOOSE_BINDING" and "NO_REORDER_HDR" for VLAN_FLAGS + * description: VLAN flags. + * ---end--- + */ + obj_properties[PROP_FLAGS] = g_param_spec_flags(NM_SETTING_VLAN_FLAGS, + "", + "", + NM_TYPE_VLAN_FLAGS, + NM_VLAN_FLAG_REORDER_HEADERS, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_FLAGS], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT32, + .to_dbus_fcn = _override_flags_get, + .missing_from_dbus_fcn = _override_flags_not_set, )); + + /** + * NMSettingVlan:ingress-priority-map: + * + * For incoming packets, a list of mappings from 802.1p priorities to Linux + * SKB priorities. The mapping is given in the format "from:to" where both + * "from" and "to" are unsigned integers, ie "7:3". + **/ + /* ---ifcfg-rh--- + * property: ingress-priority-map + * variable: VLAN_INGRESS_PRIORITY_MAP + * description: Ingress priority mapping. + * example: VLAN_INGRESS_PRIORITY_MAP=4:2,3:5 + * ---end--- + */ + obj_properties[PROP_INGRESS_PRIORITY_MAP] = g_param_spec_boxed( + NM_SETTING_VLAN_INGRESS_PRIORITY_MAP, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVlan:egress-priority-map: + * + * For outgoing packets, a list of mappings from Linux SKB priorities to + * 802.1p priorities. The mapping is given in the format "from:to" where + * both "from" and "to" are unsigned integers, ie "7:3". + **/ + /* ---ifcfg-rh--- + * property: egress-priority-map + * variable: VLAN_EGRESS_PRIORITY_MAP + * description: Egress priority mapping. + * example: VLAN_EGRESS_PRIORITY_MAP=5:4,4:1,3:7 + * ---end--- + */ + obj_properties[PROP_EGRESS_PRIORITY_MAP] = g_param_spec_boxed( + NM_SETTING_VLAN_EGRESS_PRIORITY_MAP, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /* ---ifcfg-rh--- + * property: interface-name + * variable: PHYSDEV and VLAN_ID, or DEVICE + * description: VLAN interface name. + * If all variables are set, parent device from PHYSDEV takes precedence over DEVICE, + * but VLAN id from DEVICE takes precedence over VLAN_ID. + * example: PHYSDEV=eth0, VLAN_ID=12; or DEVICE=eth0.12 + * ---end--- + * ---dbus--- + * property: interface-name + * format: string + * description: Deprecated in favor of connection.interface-name, but can + * be used for backward-compatibility with older daemons, to set the + * vlan's interface name. + * ---end--- + */ + _nm_properties_override_dbus(properties_override, + "interface-name", + &nm_sett_info_propert_type_deprecated_interface_name); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_VLAN, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-vpn.c b/src/libnm-core-impl/nm-setting-vpn.c new file mode 100644 index 0000000000..19aafd4f19 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-vpn.c @@ -0,0 +1,1233 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-vpn.h" + +#include + +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-vpn + * @short_description: Describes connection properties for Virtual Private Networks + * + * The #NMSettingVpn object is a #NMSetting subclass that describes properties + * necessary for connection to Virtual Private Networks. NetworkManager uses + * a plugin architecture to allow easier use of new VPN types, and this + * setting abstracts the configuration for those plugins. Since the configuration + * options are only known to the VPN plugins themselves, the VPN configuration + * options are stored as key/value pairs of strings rather than GObject + * properties. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingVpn, + PROP_SERVICE_TYPE, + PROP_USER_NAME, + PROP_PERSISTENT, + PROP_DATA, + PROP_SECRETS, + PROP_TIMEOUT, ); + +typedef struct { + char *service_type; + + /* username of the user requesting this connection, thus + * it's really only valid for user connections, and it also + * should never be saved out to persistent config. + */ + char *user_name; + + /* Whether the VPN stays up across link changes, until the user + * explicitly disconnects it. + */ + gboolean persistent; + + /* The hash table is created at setting object + * init time and should not be replaced. It is + * a char * -> char * mapping, and both the key + * and value are owned by the hash table, and should + * be allocated with functions whose value can be + * freed with g_free(). Should not contain secrets. + */ + GHashTable *data; + + /* The hash table is created at setting object + * init time and should not be replaced. It is + * a char * -> char * mapping, and both the key + * and value are owned by the hash table, and should + * be allocated with functions whose value can be + * freed with g_free(). Should contain secrets only. + */ + GHashTable *secrets; + + /* Timeout for the VPN service to establish the connection */ + guint32 timeout; +} NMSettingVpnPrivate; + +G_DEFINE_TYPE(NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING) + +#define NM_SETTING_VPN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_VPN, NMSettingVpnPrivate)) + +/*****************************************************************************/ + +static GHashTable * +_ensure_strdict(GHashTable **p_hash, gboolean for_secrets) +{ + if (!*p_hash) { + *p_hash = g_hash_table_new_full(nm_str_hash, + g_str_equal, + g_free, + for_secrets ? (GDestroyNotify) nm_free_secret : g_free); + } + return *p_hash; +} + +/*****************************************************************************/ + +/** + * nm_setting_vpn_get_service_type: + * @setting: the #NMSettingVpn + * + * Returns the service name of the VPN, which identifies the specific VPN + * plugin that should be used to connect to this VPN. + * + * Returns: the VPN plugin's service name + **/ +const char * +nm_setting_vpn_get_service_type(NMSettingVpn *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); + + return NM_SETTING_VPN_GET_PRIVATE(setting)->service_type; +} + +/** + * nm_setting_vpn_get_user_name: + * @setting: the #NMSettingVpn + * + * Returns: the #NMSettingVpn:user-name property of the setting + **/ +const char * +nm_setting_vpn_get_user_name(NMSettingVpn *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); + + return NM_SETTING_VPN_GET_PRIVATE(setting)->user_name; +} + +/** + * nm_setting_vpn_get_persistent: + * @setting: the #NMSettingVpn + * + * Returns: the #NMSettingVpn:persistent property of the setting + **/ +gboolean +nm_setting_vpn_get_persistent(NMSettingVpn *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), FALSE); + + return NM_SETTING_VPN_GET_PRIVATE(setting)->persistent; +} + +/** + * nm_setting_vpn_get_num_data_items: + * @setting: the #NMSettingVpn + * + * Gets number of key/value pairs of VPN configuration data. + * + * Returns: the number of VPN plugin specific configuration data items + **/ +guint32 +nm_setting_vpn_get_num_data_items(NMSettingVpn *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), 0); + + return nm_g_hash_table_size(NM_SETTING_VPN_GET_PRIVATE(setting)->data); +} + +/** + * nm_setting_vpn_add_data_item: + * @setting: the #NMSettingVpn + * @key: a name that uniquely identifies the given value @item + * @item: (allow-none): the value to be referenced by @key + * + * Establishes a relationship between @key and @item internally in the + * setting which may be retrieved later. Should not be used to store passwords + * or other secrets, which is what nm_setting_vpn_add_secret() is for. + * + * Before 1.24, @item must not be %NULL and not an empty string. Since 1.24, + * @item can be set to an empty string. It can also be set to %NULL to unset + * the key. In that case, the behavior is as if calling nm_setting_vpn_remove_data_item(). + **/ +void +nm_setting_vpn_add_data_item(NMSettingVpn *setting, const char *key, const char *item) +{ + if (!item) { + nm_setting_vpn_remove_data_item(setting, key); + return; + } + + g_return_if_fail(NM_IS_SETTING_VPN(setting)); + g_return_if_fail(key && key[0]); + + g_hash_table_insert(_ensure_strdict(&NM_SETTING_VPN_GET_PRIVATE(setting)->data, FALSE), + g_strdup(key), + g_strdup(item)); + _notify(setting, PROP_DATA); +} + +/** + * nm_setting_vpn_get_data_item: + * @setting: the #NMSettingVpn + * @key: the name of the data item to retrieve + * + * Retrieves the data item of a key/value relationship previously established + * by nm_setting_vpn_add_data_item(). + * + * Returns: the data item, if any + **/ +const char * +nm_setting_vpn_get_data_item(NMSettingVpn *setting, const char *key) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); + g_return_val_if_fail(key && key[0], NULL); + + return nm_g_hash_table_lookup(NM_SETTING_VPN_GET_PRIVATE(setting)->data, key); +} + +/** + * nm_setting_vpn_get_data_keys: + * @setting: the #NMSettingVpn + * @out_length: (allow-none) (out): the length of the returned array + * + * Retrieves every data key inside @setting, as an array. + * + * Returns: (array length=out_length) (transfer container): a + * %NULL-terminated array containing each data key or %NULL if + * there are no data items. + * + * Since: 1.12 + */ +const char ** +nm_setting_vpn_get_data_keys(NMSettingVpn *setting, guint *out_length) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); + + return nm_utils_strdict_get_keys(NM_SETTING_VPN_GET_PRIVATE(setting)->data, TRUE, out_length); +} + +/** + * nm_setting_vpn_remove_data_item: + * @setting: the #NMSettingVpn + * @key: the name of the data item to remove + * + * Deletes a key/value relationship previously established by + * nm_setting_vpn_add_data_item(). + * + * Returns: %TRUE if the data item was found and removed from the internal list, + * %FALSE if it was not. + **/ +gboolean +nm_setting_vpn_remove_data_item(NMSettingVpn *setting, const char *key) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), FALSE); + g_return_val_if_fail(key && key[0], FALSE); + + if (nm_g_hash_table_remove(NM_SETTING_VPN_GET_PRIVATE(setting)->data, key)) { + _notify(setting, PROP_DATA); + return TRUE; + } + return FALSE; +} + +static void +foreach_item_helper(NMSettingVpn *self, GHashTable **p_hash, NMVpnIterFunc func, gpointer user_data) +{ + gs_unref_object NMSettingVpn *self_keep_alive = NULL; + gs_strfreev char ** keys = NULL; + guint i, len; + + nm_assert(NM_IS_SETTING_VPN(self)); + nm_assert(func); + + keys = nm_utils_strv_make_deep_copied(nm_utils_strdict_get_keys(*p_hash, TRUE, &len)); + if (len == 0u) { + nm_assert(!keys); + return; + } + + if (len > 1u) + self_keep_alive = g_object_ref(self); + + for (i = 0; i < len; i++) { + /* NOTE: note that we call the function with a clone of @key, + * not with the actual key from the dictionary. + * + * The @value on the other hand, is not cloned but retrieved before + * invoking @func(). That means, if @func() modifies the setting while + * being called, the values are as they currently are, but the + * keys (and their order) were pre-determined before starting to + * invoke the callbacks. + * + * The idea is to give some sensible, stable behavior in case the user + * modifies the settings. Whether this particular behavior is optimal + * is unclear. It's probably a bad idea to modify the settings while + * iterating the values. But at least, it's a safe thing to do and we + * do something sensible. */ + func(keys[i], nm_g_hash_table_lookup(*p_hash, keys[i]), user_data); + } +} + +/** + * nm_setting_vpn_foreach_data_item: + * @setting: a #NMSettingVpn + * @func: (scope call): an user provided function + * @user_data: data to be passed to @func + * + * Iterates all data items stored in this setting. It is safe to add, remove, + * and modify data items inside @func, though any additions or removals made + * during iteration will not be part of the iteration. + */ +void +nm_setting_vpn_foreach_data_item(NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data) +{ + g_return_if_fail(NM_IS_SETTING_VPN(setting)); + g_return_if_fail(func); + + foreach_item_helper(setting, &NM_SETTING_VPN_GET_PRIVATE(setting)->data, func, user_data); +} + +/** + * nm_setting_vpn_get_num_secrets: + * @setting: the #NMSettingVpn + * + * Gets number of VPN plugin specific secrets in the setting. + * + * Returns: the number of VPN plugin specific secrets + **/ +guint32 +nm_setting_vpn_get_num_secrets(NMSettingVpn *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), 0); + + return nm_g_hash_table_size(NM_SETTING_VPN_GET_PRIVATE(setting)->secrets); +} + +/** + * nm_setting_vpn_add_secret: + * @setting: the #NMSettingVpn + * @key: a name that uniquely identifies the given secret @secret + * @secret: (allow-none): the secret to be referenced by @key + * + * Establishes a relationship between @key and @secret internally in the + * setting which may be retrieved later. + * + * Before 1.24, @secret must not be %NULL and not an empty string. Since 1.24, + * @secret can be set to an empty string. It can also be set to %NULL to unset + * the key. In that case, the behavior is as if calling nm_setting_vpn_remove_secret(). + **/ +void +nm_setting_vpn_add_secret(NMSettingVpn *setting, const char *key, const char *secret) +{ + if (!secret) { + nm_setting_vpn_remove_secret(setting, key); + return; + } + + g_return_if_fail(NM_IS_SETTING_VPN(setting)); + g_return_if_fail(key && key[0]); + + g_hash_table_insert(_ensure_strdict(&NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, TRUE), + g_strdup(key), + g_strdup(secret)); + _notify(setting, PROP_SECRETS); +} + +/** + * nm_setting_vpn_get_secret: + * @setting: the #NMSettingVpn + * @key: the name of the secret to retrieve + * + * Retrieves the secret of a key/value relationship previously established + * by nm_setting_vpn_add_secret(). + * + * Returns: the secret, if any + **/ +const char * +nm_setting_vpn_get_secret(NMSettingVpn *setting, const char *key) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); + g_return_val_if_fail(key && key[0], NULL); + + return nm_g_hash_table_lookup(NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, key); +} + +/** + * nm_setting_vpn_get_secret_keys: + * @setting: the #NMSettingVpn + * @out_length: (allow-none) (out): the length of the returned array + * + * Retrieves every secret key inside @setting, as an array. + * + * Returns: (array length=out_length) (transfer container): a + * %NULL-terminated array containing each secret key or %NULL if + * there are no secrets. + * + * Since: 1.12 + */ +const char ** +nm_setting_vpn_get_secret_keys(NMSettingVpn *setting, guint *out_length) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), NULL); + + return nm_utils_strdict_get_keys(NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, + TRUE, + out_length); +} + +/** + * nm_setting_vpn_remove_secret: + * @setting: the #NMSettingVpn + * @key: the name of the secret to remove + * + * Deletes a key/value relationship previously established by + * nm_setting_vpn_add_secret(). + * + * Returns: %TRUE if the secret was found and removed from the internal list, + * %FALSE if it was not. + **/ +gboolean +nm_setting_vpn_remove_secret(NMSettingVpn *setting, const char *key) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), FALSE); + g_return_val_if_fail(key && key[0], FALSE); + + if (nm_g_hash_table_remove(NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, key)) { + _notify(setting, PROP_SECRETS); + return TRUE; + } + return FALSE; +} + +/** + * nm_setting_vpn_foreach_secret: + * @setting: a #NMSettingVpn + * @func: (scope call): an user provided function + * @user_data: data to be passed to @func + * + * Iterates all secrets stored in this setting. It is safe to add, remove, + * and modify secrets inside @func, though any additions or removals made during + * iteration will not be part of the iteration. + */ +void +nm_setting_vpn_foreach_secret(NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data) +{ + g_return_if_fail(NM_IS_SETTING_VPN(setting)); + g_return_if_fail(func); + + foreach_item_helper(setting, &NM_SETTING_VPN_GET_PRIVATE(setting)->secrets, func, user_data); +} + +static gboolean +aggregate(NMSetting *setting, int type_i, gpointer arg) +{ + NMSettingVpnPrivate * priv = NM_SETTING_VPN_GET_PRIVATE(setting); + NMConnectionAggregateType type = type_i; + NMSettingSecretFlags secret_flags; + const char * key_name; + GHashTableIter iter; + + switch (type) { + case NM_CONNECTION_AGGREGATE_ANY_SECRETS: + if (nm_g_hash_table_size(priv->secrets) > 0u) { + *((gboolean *) arg) = TRUE; + return TRUE; + } + return FALSE; + + case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: + + if (priv->secrets) { + g_hash_table_iter_init(&iter, priv->secrets); + while (g_hash_table_iter_next(&iter, (gpointer *) &key_name, NULL)) { + if (!nm_setting_get_secret_flags(NM_SETTING(setting), + key_name, + &secret_flags, + NULL)) + nm_assert_not_reached(); + if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { + *((gboolean *) arg) = TRUE; + return TRUE; + } + } + } + + /* OK, we have no secrets with system-secret flags. + * But do we have any secret-flags (without secrets) that indicate system secrets? */ + if (priv->data) { + g_hash_table_iter_init(&iter, priv->data); + while (g_hash_table_iter_next(&iter, (gpointer *) &key_name, NULL)) { + gs_free char *secret_name = NULL; + + if (!NM_STR_HAS_SUFFIX(key_name, "-flags")) + continue; + secret_name = g_strndup(key_name, strlen(key_name) - NM_STRLEN("-flags")); + if (secret_name[0] == '\0') + continue; + if (!nm_setting_get_secret_flags(NM_SETTING(setting), + secret_name, + &secret_flags, + NULL)) + nm_assert_not_reached(); + if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { + *((gboolean *) arg) = TRUE; + return TRUE; + } + } + } + + return FALSE; + } + + g_return_val_if_reached(FALSE); +} + +/** + * nm_setting_vpn_get_timeout: + * @setting: the #NMSettingVpn + * + * Returns: the #NMSettingVpn:timeout property of the setting + * + * Since: 1.2 + **/ +guint32 +nm_setting_vpn_get_timeout(NMSettingVpn *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VPN(setting), 0); + + return NM_SETTING_VPN_GET_PRIVATE(setting)->timeout; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); + NMSettingConnection *s_con; + + if (!priv->service_type) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE); + return FALSE; + } + if (!priv->service_type[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE); + return FALSE; + } + + /* default username can be NULL, but can't be zero-length */ + if (priv->user_name && !priv->user_name[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_USER_NAME); + return FALSE; + } + + if (connection && (s_con = nm_connection_get_setting_connection(connection)) + && nm_setting_connection_get_multi_connect(s_con) != NM_CONNECTION_MULTI_CONNECT_DEFAULT) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("cannot set connection.multi-connect for VPN setting")); + return FALSE; + } + + return TRUE; +} + +static NMSettingUpdateSecretResult +update_secret_string(NMSetting *setting, const char *key, const char *value, GError **error) +{ + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); + + g_return_val_if_fail(key && key[0], NM_SETTING_UPDATE_SECRET_ERROR); + g_return_val_if_fail(value, NM_SETTING_UPDATE_SECRET_ERROR); + + if (nm_streq0(nm_g_hash_table_lookup(priv->secrets, key), value)) + return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; + + g_hash_table_insert(_ensure_strdict(&priv->secrets, TRUE), g_strdup(key), g_strdup(value)); + return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; +} + +static NMSettingUpdateSecretResult +update_secret_dict(NMSetting *setting, GVariant *secrets, GError **error) +{ + NMSettingVpnPrivate * priv = NM_SETTING_VPN_GET_PRIVATE(setting); + GVariantIter iter; + const char * name, *value; + NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; + + g_return_val_if_fail(secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR); + + /* Make sure the items are valid */ + g_variant_iter_init(&iter, secrets); + while (g_variant_iter_next(&iter, "{&s&s}", &name, &value)) { + if (!name[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("setting contained a secret with an empty name")); + g_prefix_error(error, "%s: ", NM_SETTING_VPN_SETTING_NAME); + return NM_SETTING_UPDATE_SECRET_ERROR; + } + } + + /* Now add the items to the settings' secrets list */ + g_variant_iter_init(&iter, secrets); + while (g_variant_iter_next(&iter, "{&s&s}", &name, &value)) { + if (nm_streq0(nm_g_hash_table_lookup(priv->secrets, name), value)) + continue; + + g_hash_table_insert(_ensure_strdict(&priv->secrets, TRUE), g_strdup(name), g_strdup(value)); + result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; + } + + return result; +} + +static int +update_one_secret(NMSetting *setting, const char *key, GVariant *value, GError **error) +{ + NMSettingUpdateSecretResult success = NM_SETTING_UPDATE_SECRET_ERROR; + + g_return_val_if_fail(key != NULL, NM_SETTING_UPDATE_SECRET_ERROR); + g_return_val_if_fail(value != NULL, NM_SETTING_UPDATE_SECRET_ERROR); + + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + /* Passing the string properties individually isn't correct, and won't + * produce the correct result, but for some reason that's how it used + * to be done. So even though it's not correct, keep the code around + * for compatibility's sake. + */ + success = update_secret_string(setting, key, g_variant_get_string(value, NULL), error); + } else if (g_variant_is_of_type(value, G_VARIANT_TYPE("a{ss}"))) { + if (!nm_streq(key, NM_SETTING_VPN_SECRETS)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("not a secret property")); + g_prefix_error(error, "%s.%s ", NM_SETTING_VPN_SETTING_NAME, key); + } else + success = update_secret_dict(setting, value, error); + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("secret is not of correct type")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, key); + } + + if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) + _notify(NM_SETTING_VPN(setting), PROP_SECRETS); + + return success; +} + +static void +for_each_secret(NMSetting * setting, + const char * secret_name, + GVariant * val, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data, + GVariantBuilder * setting_builder) +{ + GVariantBuilder vpn_secrets_builder; + GVariantIter vpn_secrets_iter; + const char * vpn_secret_name; + const char * secret; + + if (!nm_streq(secret_name, NM_SETTING_VPN_SECRETS)) { + NM_SETTING_CLASS(nm_setting_vpn_parent_class) + ->for_each_secret(setting, + secret_name, + val, + remove_non_secrets, + callback, + callback_data, + setting_builder); + return; + } + + if (!g_variant_is_of_type(val, G_VARIANT_TYPE("a{ss}"))) { + /* invalid type. Silently ignore the secrets as we cannot find out the + * secret-flags. */ + return; + } + + /* Iterate through each secret from the VPN dict in the overall secrets dict */ + g_variant_builder_init(&vpn_secrets_builder, G_VARIANT_TYPE("a{ss}")); + g_variant_iter_init(&vpn_secrets_iter, val); + while (g_variant_iter_next(&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) { + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + /* we ignore the return value of get_secret_flags. The function may determine + * that this is not a secret, based on having not secret-flags and no secrets. + * But we have the secret at hand. We know it would be a valid secret, if we + * only add it to the VPN settings. */ + nm_setting_get_secret_flags(setting, vpn_secret_name, &secret_flags, NULL); + + if (callback(secret_flags, callback_data)) + g_variant_builder_add(&vpn_secrets_builder, "{ss}", vpn_secret_name, secret); + } + + g_variant_builder_add(setting_builder, + "{sv}", + secret_name, + g_variant_builder_end(&vpn_secrets_builder)); +} + +static gboolean +get_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags *out_flags, + GError ** error) +{ + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); + gs_free char * flags_key_free = NULL; + const char * flags_key; + const char * flags_val; + gint64 i64; + + nm_assert(secret_name); + + if (!secret_name[0]) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("secret name cannot be empty")); + return FALSE; + } + + flags_key = nm_construct_name_a("%s-flags", secret_name, &flags_key_free); + + if (!priv->data + || !g_hash_table_lookup_extended(priv->data, flags_key, NULL, (gpointer *) &flags_val)) { + NM_SET_OUT(out_flags, NM_SETTING_SECRET_FLAG_NONE); + + /* having no secret flag for the secret is fine, as long as there + * is the secret itself... */ + if (!nm_g_hash_table_lookup(priv->secrets, secret_name)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("secret flags property not found")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, flags_key); + return FALSE; + } + return TRUE; + } + + i64 = _nm_utils_ascii_str_to_int64(flags_val, 10, 0, NM_SETTING_SECRET_FLAG_ALL, -1); + if (i64 == -1 || !_nm_setting_secret_flags_valid(i64)) { + /* The flags keys is set to an unexpected value. That is a configuration + * error. Note that keys named "*-flags" are reserved for secrets. The user + * must not use this for anything but secret flags. Hence, we cannot fail + * to read the secret, we pretend that the secret flag is set to the default + * NM_SETTING_SECRET_FLAG_NONE. */ + NM_SET_OUT(out_flags, NM_SETTING_SECRET_FLAG_NONE); + return TRUE; + } + + NM_SET_OUT(out_flags, (NMSettingSecretFlags) i64); + return TRUE; +} + +static gboolean +set_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags flags, + GError ** error) +{ + nm_assert(secret_name); + + if (!secret_name[0]) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("secret name cannot be empty")); + return FALSE; + } + + g_hash_table_insert(_ensure_strdict(&NM_SETTING_VPN_GET_PRIVATE(setting)->data, FALSE), + g_strdup_printf("%s-flags", secret_name), + g_strdup_printf("%u", flags)); + _notify(NM_SETTING_VPN(setting), PROP_SECRETS); + return TRUE; +} + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + /* Assume that VPN connections need secrets since they almost always will */ + return g_ptr_array_sized_new(1); +} + +static NMTernary +compare_property_secrets(NMSettingVpn *a, NMSettingVpn *b, NMSettingCompareFlags flags) +{ + GHashTableIter iter; + const char * key, *val; + int run; + + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_FUZZY)) + return NM_TERNARY_DEFAULT; + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)) + return NM_TERNARY_DEFAULT; + + if (!b) + return TRUE; + + for (run = 0; run < 2; run++) { + NMSettingVpn * current_a = (run == 0) ? a : b; + NMSettingVpn * current_b = (run == 0) ? b : a; + NMSettingVpnPrivate *priv_a = NM_SETTING_VPN_GET_PRIVATE(current_a); + + if (!priv_a->secrets) + continue; + + g_hash_table_iter_init(&iter, priv_a->secrets); + while (g_hash_table_iter_next(&iter, (gpointer) &key, (gpointer) &val)) { + if (nm_streq0(val, nm_setting_vpn_get_secret(current_b, key))) + continue; + if (!_nm_setting_should_compare_secret_property(NM_SETTING(current_a), + NM_SETTING(current_b), + key, + flags)) + continue; + + return FALSE; + } + } + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_VPN_SECRETS)) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) + return NM_TERNARY_DEFAULT; + return compare_property_secrets(NM_SETTING_VPN(set_a), NM_SETTING_VPN(set_b), flags); + } + + return NM_SETTING_CLASS(nm_setting_vpn_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +static gboolean +clear_secrets(const NMSettInfoSetting * sett_info, + guint property_idx, + NMSetting * setting, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data) +{ + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); + GParamSpec * prop_spec = sett_info->property_infos[property_idx].param_spec; + GHashTableIter iter; + const char * secret; + gboolean changed = TRUE; + + if (!prop_spec || !NM_FLAGS_HAS(prop_spec->flags, NM_SETTING_PARAM_SECRET)) + return FALSE; + + nm_assert(nm_streq(prop_spec->name, NM_SETTING_VPN_SECRETS)); + + if (!priv->secrets) + return FALSE; + + g_hash_table_iter_init(&iter, priv->secrets); + while (g_hash_table_iter_next(&iter, (gpointer) &secret, NULL)) { + if (func) { + NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; + + if (!nm_setting_get_secret_flags(setting, secret, &flags, NULL)) + nm_assert_not_reached(); + + if (!func(setting, secret, flags, user_data)) + continue; + } else + nm_assert(nm_setting_get_secret_flags(setting, secret, NULL, NULL)); + + g_hash_table_iter_remove(&iter); + changed = TRUE; + } + + if (changed) + _notify(NM_SETTING_VPN(setting), PROP_SECRETS); + + return changed; +} + +static gboolean +vpn_secrets_from_dbus(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + NMSettingVpn * self = NM_SETTING_VPN(setting); + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(self); + gs_unref_hashtable GHashTable *hash_free = NULL; + GVariantIter iter; + const char * key; + const char * val; + + hash_free = g_steal_pointer(&priv->secrets); + + g_variant_iter_init(&iter, value); + while (g_variant_iter_next(&iter, "{&s&s}", &key, &val)) { + if (!key[0]) + continue; + g_hash_table_insert(_ensure_strdict(&priv->secrets, TRUE), g_strdup(key), g_strdup(val)); + } + + _notify(self, PROP_SECRETS); + return TRUE; +} + +static GVariant * +vpn_secrets_to_dbus(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); + GVariantBuilder builder; + gs_free const char **keys = NULL; + guint i, len; + + if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_NO_SECRETS)) + return NULL; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); + + keys = nm_utils_strdict_get_keys(priv->secrets, TRUE, &len); + for (i = 0; i < len; i++) { + const char * key = keys[i]; + NMSettingSecretFlags secret_flags; + + if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED)) { + if (!nm_setting_get_secret_flags(setting, key, &secret_flags, NULL) + || !NM_FLAGS_HAS(secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) + continue; + } + g_variant_builder_add(&builder, "{ss}", key, g_hash_table_lookup(priv->secrets, key)); + } + + return g_variant_builder_end(&builder); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingVpn * setting = NM_SETTING_VPN(object); + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_SERVICE_TYPE: + g_value_set_string(value, nm_setting_vpn_get_service_type(setting)); + break; + case PROP_USER_NAME: + g_value_set_string(value, nm_setting_vpn_get_user_name(setting)); + break; + case PROP_PERSISTENT: + g_value_set_boolean(value, priv->persistent); + break; + case PROP_DATA: + g_value_take_boxed(value, _nm_utils_copy_strdict(priv->data)); + break; + case PROP_SECRETS: + g_value_take_boxed(value, _nm_utils_copy_strdict(priv->secrets)); + break; + case PROP_TIMEOUT: + g_value_set_uint(value, nm_setting_vpn_get_timeout(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_SERVICE_TYPE: + g_free(priv->service_type); + priv->service_type = g_value_dup_string(value); + break; + case PROP_USER_NAME: + g_free(priv->user_name); + priv->user_name = g_value_dup_string(value); + break; + case PROP_PERSISTENT: + priv->persistent = g_value_get_boolean(value); + break; + case PROP_DATA: + case PROP_SECRETS: + { + gs_unref_hashtable GHashTable *hash_free = NULL; + GHashTable * src_hash = g_value_get_boxed(value); + GHashTable ** p_hash; + const gboolean is_secrets = (prop_id == PROP_SECRETS); + + if (is_secrets) + p_hash = &priv->secrets; + else + p_hash = &priv->data; + + hash_free = g_steal_pointer(p_hash); + + if (src_hash && g_hash_table_size(src_hash) > 0) { + GHashTableIter iter; + const char * key; + const char * val; + + g_hash_table_iter_init(&iter, src_hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + if (!key || !key[0] || !val) { + /* NULL keys/values and empty key are not allowed. Usually, we would reject them in verify(), but + * then our nm_setting_vpn_remove_data_item() also doesn't allow empty keys. So, if we failed + * it in verify(), it would be only fixable by setting PROP_DATA again. Instead, + * silently ignore them. */ + continue; + } + g_hash_table_insert(_ensure_strdict(p_hash, is_secrets), + g_strdup(key), + g_strdup(val)); + } + } + } break; + case PROP_TIMEOUT: + priv->timeout = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_vpn_init(NMSettingVpn *setting) +{} + +/** + * nm_setting_vpn_new: + * + * Creates a new #NMSettingVpn object with default values. + * + * Returns: (transfer full): the new empty #NMSettingVpn object + **/ +NMSetting * +nm_setting_vpn_new(void) +{ + return g_object_new(NM_TYPE_SETTING_VPN, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE(object); + + g_free(priv->service_type); + g_free(priv->user_name); + if (priv->data) + g_hash_table_unref(priv->data); + if (priv->secrets) + g_hash_table_unref(priv->secrets); + + G_OBJECT_CLASS(nm_setting_vpn_parent_class)->finalize(object); +} + +static void +nm_setting_vpn_class_init(NMSettingVpnClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingVpnPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->update_one_secret = update_one_secret; + setting_class->for_each_secret = for_each_secret; + setting_class->get_secret_flags = get_secret_flags; + setting_class->set_secret_flags = set_secret_flags; + setting_class->need_secrets = need_secrets; + setting_class->compare_property = compare_property; + setting_class->clear_secrets = clear_secrets; + setting_class->aggregate = aggregate; + + /** + * NMSettingVpn:service-type: + * + * D-Bus service name of the VPN plugin that this setting uses to connect to + * its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc + * plugin. + **/ + obj_properties[PROP_SERVICE_TYPE] = + g_param_spec_string(NM_SETTING_VPN_SERVICE_TYPE, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVpn:user-name: + * + * If the VPN connection requires a user name for authentication, that name + * should be provided here. If the connection is available to more than one + * user, and the VPN requires each user to supply a different name, then + * leave this property empty. If this property is empty, NetworkManager + * will automatically supply the username of the user which requested the + * VPN connection. + **/ + obj_properties[PROP_USER_NAME] = + g_param_spec_string(NM_SETTING_VPN_USER_NAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVpn:persistent: + * + * If the VPN service supports persistence, and this property is %TRUE, + * the VPN will attempt to stay connected across link changes and outages, + * until explicitly disconnected. + **/ + obj_properties[PROP_PERSISTENT] = + g_param_spec_boolean(NM_SETTING_VPN_PERSISTENT, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVpn:data: (type GHashTable(utf8,utf8)): + * + * Dictionary of key/value pairs of VPN plugin specific data. Both keys and + * values must be strings. + **/ + /* ---keyfile--- + * property: data + * variable: separate variables named after keys of the dictionary + * description: The keys of the data dictionary are used as variable names directly + * under [vpn] section. + * example: remote=ovpn.corp.com cipher=AES-256-CBC username=joe + * ---end--- + */ + obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_VPN_DATA, + "", + "", + G_TYPE_HASH_TABLE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_DATA], + &nm_sett_info_propert_type_strdict); + + /** + * NMSettingVpn:secrets: (type GHashTable(utf8,utf8)): + * + * Dictionary of key/value pairs of VPN plugin specific secrets like + * passwords or private keys. Both keys and values must be strings. + **/ + /* ---keyfile--- + * property: secrets + * variable: separate variables named after keys of the dictionary + * description: The keys of the secrets dictionary are used as variable names directly + * under [vpn-secrets] section. + * example: password=Popocatepetl + * ---end--- + */ + obj_properties[PROP_SECRETS] = + g_param_spec_boxed(NM_SETTING_VPN_SECRETS, + "", + "", + G_TYPE_HASH_TABLE, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET + | NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_SECRETS], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("a{ss}"), + .to_dbus_fcn = vpn_secrets_to_dbus, + .from_dbus_fcn = vpn_secrets_from_dbus, )); + + /** + * NMSettingVpn:timeout: + * + * Timeout for the VPN service to establish the connection. Some services + * may take quite a long time to connect. + * Value of 0 means a default timeout, which is 60 seconds (unless overridden + * by vpn.timeout in configuration file). Values greater than zero mean + * timeout in seconds. + * + * Since: 1.2 + **/ + obj_properties[PROP_TIMEOUT] = g_param_spec_uint(NM_SETTING_VPN_TIMEOUT, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_VPN, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-vrf.c b/src/libnm-core-impl/nm-setting-vrf.c new file mode 100644 index 0000000000..a5ee739592 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-vrf.c @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-vrf.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-vrf + * @short_description: Describes connection properties for vrf interfaces + * + * The #NMSettingVrf object is a #NMSetting subclass that describes properties + * necessary for connection to vrf devices + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_TABLE, ); + +/** + * NMSettingVrf: + * + * VRF settings + * + * Since: 1.24 + */ +struct _NMSettingVrf { + NMSetting parent; + guint32 table; +}; + +struct _NMSettingVrfClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingVrf, nm_setting_vrf, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_vrf_get_table: + * @setting: the #NMSettingVrf + * + * Returns: the routing table for the VRF + * + * Since: 1.24 + **/ +guint32 +nm_setting_vrf_get_table(NMSettingVrf *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VRF(setting), 0); + + return setting->table; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingVrf *self = NM_SETTING_VRF(setting); + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + if (self->table == 0) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("table cannot be zero")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VRF_SETTING_NAME, NM_SETTING_VRF_TABLE); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingVrf *self = NM_SETTING_VRF(object); + + switch (prop_id) { + case PROP_TABLE: + g_value_set_uint(value, self->table); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingVrf *self = NM_SETTING_VRF(object); + + switch (prop_id) { + case PROP_TABLE: + self->table = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_vrf_init(NMSettingVrf *setting) +{} + +/** + * nm_setting_vrf_new: + * + * Creates a new #NMSettingVrf object with default values. + * + * Returns: (transfer full): the new empty #NMSettingVrf object + * + * Since: 1.24 + **/ +NMSetting * +nm_setting_vrf_new(void) +{ + return g_object_new(NM_TYPE_SETTING_VRF, NULL); +} + +static void +nm_setting_vrf_class_init(NMSettingVrfClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + object_class->get_property = get_property; + object_class->set_property = set_property; + + setting_class->verify = verify; + + /** + * NMSettingVrf:table: + * + * The routing table for this VRF. + * + * Since: 1.24 + **/ + obj_properties[PROP_TABLE] = + g_param_spec_uint(NM_SETTING_VRF_TABLE, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_VRF); +} diff --git a/src/libnm-core-impl/nm-setting-vxlan.c b/src/libnm-core-impl/nm-setting-vxlan.c new file mode 100644 index 0000000000..ad7156f22f --- /dev/null +++ b/src/libnm-core-impl/nm-setting-vxlan.c @@ -0,0 +1,816 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-vxlan.h" + +#include + +#include "nm-utils.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-vxlan + * @short_description: Describes connection properties for VXLAN interfaces + * + * The #NMSettingVxlan object is a #NMSetting subclass that describes properties + * necessary for connection to VXLAN interfaces. + **/ + +#define DST_PORT_DEFAULT 8472 + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, + PROP_ID, + PROP_LOCAL, + PROP_REMOTE, + PROP_SOURCE_PORT_MIN, + PROP_SOURCE_PORT_MAX, + PROP_DESTINATION_PORT, + PROP_TOS, + PROP_TTL, + PROP_AGEING, + PROP_LIMIT, + PROP_LEARNING, + PROP_PROXY, + PROP_RSC, + PROP_L2_MISS, + PROP_L3_MISS, ); + +typedef struct { + char *parent; + char *local; + char *remote; + guint id; + guint source_port_min; + guint source_port_max; + guint destination_port; + guint tos; + guint ttl; + guint ageing; + guint limit; + bool learning : 1; + bool proxy : 1; + bool rsc : 1; + bool l2_miss : 1; + bool l3_miss : 1; +} NMSettingVxlanPrivate; + +G_DEFINE_TYPE(NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING) + +#define NM_SETTING_VXLAN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_VXLAN, NMSettingVxlanPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_vxlan_get_parent: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:parent property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_vxlan_get_parent(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), NULL); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->parent; +} + +/** + * nm_setting_vxlan_get_id: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:id property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_id(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->id; +} + +/** + * nm_setting_vxlan_get_local: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:local property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_vxlan_get_local(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), NULL); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->local; +} + +/** + * nm_setting_vxlan_get_remote: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:remote property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_vxlan_get_remote(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), NULL); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->remote; +} + +/** + * nm_setting_vxlan_get_source_port_min: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:source-port-min property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_source_port_min(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->source_port_min; +} + +/** + * nm_setting_vxlan_get_source_port_max: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:source-port-max property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_source_port_max(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->source_port_max; +} + +/** + * nm_setting_vxlan_get_destination_port: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:destination-port property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_destination_port(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), DST_PORT_DEFAULT); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->destination_port; +} + +/** + * nm_setting_vxlan_get_proxy: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:proxy property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_proxy(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->proxy; +} + +/** + * nm_setting_vxlan_get_ageing: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:ageing property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_ageing(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->ageing; +} + +/** + * nm_setting_vxlan_get_limit: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:limit property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_limit(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->limit; +} + +/** + * nm_setting_vxlan_get_tos: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:tos property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_tos(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->tos; +} + +/** + * nm_setting_vxlan_get_ttl: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:ttl property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_ttl(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->ttl; +} + +/** + * nm_setting_vxlan_get_learning: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:learning property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_learning(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->learning; +} + +/** + * nm_setting_vxlan_get_rsc: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:rsc property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_rsc(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->rsc; +} + +/** + * nm_setting_vxlan_get_l2_miss: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:l2_miss property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_l2_miss(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->l2_miss; +} + +/** + * nm_setting_vxlan_get_l3_miss: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:l3_miss property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_l3_miss(NMSettingVxlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VXLAN(setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE(setting)->l3_miss; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(setting); + int addr_family = AF_UNSPEC; + gboolean remote_is_valid = TRUE; + gboolean local_is_valid = TRUE; + + if (priv->remote && !nm_utils_parse_inaddr_bin(addr_family, priv->remote, &addr_family, NULL)) + remote_is_valid = FALSE; + if (priv->local && !nm_utils_parse_inaddr_bin(addr_family, priv->local, &addr_family, NULL)) + local_is_valid = FALSE; + + if (!remote_is_valid) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IP%s address"), + priv->remote, + addr_family == AF_UNSPEC ? "" : (addr_family == AF_INET ? "4" : "6")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VXLAN_SETTING_NAME, NM_SETTING_VXLAN_REMOTE); + return FALSE; + } + + if (!local_is_valid) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IP%s address"), + priv->local, + addr_family == AF_UNSPEC ? "" : (addr_family == AF_INET ? "4" : "6")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VXLAN_SETTING_NAME, NM_SETTING_VXLAN_LOCAL); + return FALSE; + } + + if (priv->parent && !nm_utils_ifname_valid_kernel(priv->parent, NULL) + && !nm_utils_is_uuid(priv->parent)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VXLAN_SETTING_NAME, NM_SETTING_VXLAN_PARENT); + return FALSE; + } + + if ((priv->source_port_min || priv->source_port_max) + && (priv->source_port_min > priv->source_port_max)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%d is greater than local port max %d"), + priv->source_port_min, + priv->source_port_max); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_VXLAN_SETTING_NAME, + NM_SETTING_VXLAN_SOURCE_PORT_MIN); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +_addrstr_set(char **dst, const char *src) +{ + gs_free char *old = NULL; + + old = *dst; + if (!src) + *dst = NULL; + else if (!nm_utils_parse_inaddr(AF_UNSPEC, src, dst)) + *dst = g_strdup(src); +} +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingVxlan * setting = NM_SETTING_VXLAN(object); + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string(value, priv->parent); + break; + case PROP_ID: + g_value_set_uint(value, priv->id); + break; + case PROP_LOCAL: + g_value_set_string(value, priv->local); + break; + case PROP_REMOTE: + g_value_set_string(value, priv->remote); + break; + case PROP_SOURCE_PORT_MIN: + g_value_set_uint(value, priv->source_port_min); + break; + case PROP_SOURCE_PORT_MAX: + g_value_set_uint(value, priv->source_port_max); + break; + case PROP_DESTINATION_PORT: + g_value_set_uint(value, priv->destination_port); + break; + case PROP_TOS: + g_value_set_uint(value, priv->tos); + break; + case PROP_AGEING: + g_value_set_uint(value, priv->ageing); + break; + case PROP_LIMIT: + g_value_set_uint(value, priv->limit); + break; + case PROP_PROXY: + g_value_set_boolean(value, priv->proxy); + break; + case PROP_TTL: + g_value_set_uint(value, priv->ttl); + break; + case PROP_LEARNING: + g_value_set_boolean(value, priv->learning); + break; + case PROP_RSC: + g_value_set_boolean(value, priv->rsc); + break; + case PROP_L2_MISS: + g_value_set_boolean(value, priv->l2_miss); + break; + case PROP_L3_MISS: + g_value_set_boolean(value, priv->l3_miss); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingVxlan * setting = NM_SETTING_VXLAN(object); + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_PARENT: + g_free(priv->parent); + priv->parent = g_value_dup_string(value); + break; + case PROP_ID: + priv->id = g_value_get_uint(value); + break; + case PROP_LOCAL: + _addrstr_set(&priv->local, g_value_get_string(value)); + break; + case PROP_REMOTE: + _addrstr_set(&priv->remote, g_value_get_string(value)); + break; + case PROP_SOURCE_PORT_MIN: + priv->source_port_min = g_value_get_uint(value); + break; + case PROP_SOURCE_PORT_MAX: + priv->source_port_max = g_value_get_uint(value); + break; + case PROP_DESTINATION_PORT: + priv->destination_port = g_value_get_uint(value); + break; + case PROP_TOS: + priv->tos = g_value_get_uint(value); + break; + case PROP_AGEING: + priv->ageing = g_value_get_uint(value); + break; + case PROP_LIMIT: + priv->limit = g_value_get_uint(value); + break; + case PROP_PROXY: + priv->proxy = g_value_get_boolean(value); + break; + case PROP_TTL: + priv->ttl = g_value_get_uint(value); + break; + case PROP_LEARNING: + priv->learning = g_value_get_boolean(value); + break; + case PROP_RSC: + priv->rsc = g_value_get_boolean(value); + break; + case PROP_L2_MISS: + priv->l2_miss = g_value_get_boolean(value); + break; + case PROP_L3_MISS: + priv->l3_miss = g_value_get_boolean(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_vxlan_init(NMSettingVxlan *self) +{ + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(self); + + priv->destination_port = DST_PORT_DEFAULT; + priv->ageing = 300; + priv->learning = TRUE; +} + +/** + * nm_setting_vxlan_new: + * + * Creates a new #NMSettingVxlan object with default values. + * + * Returns: (transfer full): the new empty #NMSettingVxlan object + * + * Since: 1.2 + **/ +NMSetting * +nm_setting_vxlan_new(void) +{ + return g_object_new(NM_TYPE_SETTING_VXLAN, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingVxlan * setting = NM_SETTING_VXLAN(object); + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE(setting); + + g_free(priv->parent); + g_free(priv->local); + g_free(priv->remote); + + G_OBJECT_CLASS(nm_setting_vxlan_parent_class)->finalize(object); +} + +static void +nm_setting_vxlan_class_init(NMSettingVxlanClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(klass, sizeof(NMSettingVxlanPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingVxlan:parent: + * + * If given, specifies the parent interface name or parent connection UUID. + * + * Since: 1.2 + **/ + obj_properties[PROP_PARENT] = g_param_spec_string( + NM_SETTING_VXLAN_PARENT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingVxlan:id: + * + * Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to + * use. + * + * Since: 1.2 + **/ + obj_properties[PROP_ID] = + g_param_spec_uint(NM_SETTING_VXLAN_ID, + "", + "", + 0, + (1 << 24) - 1, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:local: + * + * If given, specifies the source IP address to use in outgoing packets. + * + * Since: 1.2 + **/ + obj_properties[PROP_LOCAL] = g_param_spec_string(NM_SETTING_VXLAN_LOCAL, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:remote: + * + * Specifies the unicast destination IP address to use in outgoing packets + * when the destination link layer address is not known in the VXLAN device + * forwarding database, or the multicast IP address to join. + * + * Since: 1.2 + **/ + obj_properties[PROP_REMOTE] = g_param_spec_string( + NM_SETTING_VXLAN_REMOTE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:source-port-min: + * + * Specifies the minimum UDP source port to communicate to the remote VXLAN + * tunnel endpoint. + * + * Since: 1.2 + **/ + obj_properties[PROP_SOURCE_PORT_MIN] = + g_param_spec_uint(NM_SETTING_VXLAN_SOURCE_PORT_MIN, + "", + "", + 0, + G_MAXUINT16, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:source-port-max: + * + * Specifies the maximum UDP source port to communicate to the remote VXLAN + * tunnel endpoint. + * + * Since: 1.2 + **/ + obj_properties[PROP_SOURCE_PORT_MAX] = + g_param_spec_uint(NM_SETTING_VXLAN_SOURCE_PORT_MAX, + "", + "", + 0, + G_MAXUINT16, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:destination-port: + * + * Specifies the UDP destination port to communicate to the remote VXLAN + * tunnel endpoint. + * + * Since: 1.2 + **/ + obj_properties[PROP_DESTINATION_PORT] = + g_param_spec_uint(NM_SETTING_VXLAN_DESTINATION_PORT, + "", + "", + 0, + G_MAXUINT16, + DST_PORT_DEFAULT, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:ageing: + * + * Specifies the lifetime in seconds of FDB entries learnt by the kernel. + * + * Since: 1.2 + **/ + obj_properties[PROP_AGEING] = + g_param_spec_uint(NM_SETTING_VXLAN_AGEING, + "", + "", + 0, + G_MAXUINT32, + 300, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:limit: + * + * Specifies the maximum number of FDB entries. A value of zero means that + * the kernel will store unlimited entries. + * + * Since: 1.2 + **/ + obj_properties[PROP_LIMIT] = + g_param_spec_uint(NM_SETTING_VXLAN_LIMIT, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:tos: + * + * Specifies the TOS value to use in outgoing packets. + * + * Since: 1.2 + **/ + obj_properties[PROP_TOS] = + g_param_spec_uint(NM_SETTING_VXLAN_TOS, + "", + "", + 0, + 255, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:ttl: + * + * Specifies the time-to-live value to use in outgoing packets. + * + * Since: 1.2 + **/ + obj_properties[PROP_TTL] = + g_param_spec_uint(NM_SETTING_VXLAN_TTL, + "", + "", + 0, + 255, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:proxy: + * + * Specifies whether ARP proxy is turned on. + * + * Since: 1.2 + **/ + obj_properties[PROP_PROXY] = g_param_spec_boolean( + NM_SETTING_VXLAN_PROXY, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:learning: + * + * Specifies whether unknown source link layer addresses and IP addresses + * are entered into the VXLAN device forwarding database. + * + * Since: 1.2 + **/ + obj_properties[PROP_LEARNING] = g_param_spec_boolean( + NM_SETTING_VXLAN_LEARNING, + "", + "", + TRUE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingVxlan:rsc: + * + * Specifies whether route short circuit is turned on. + * + * Since: 1.2 + **/ + obj_properties[PROP_RSC] = g_param_spec_boolean(NM_SETTING_VXLAN_RSC, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + /** + * NMSettingVxlan:l2-miss: + * + * Specifies whether netlink LL ADDR miss notifications are generated. + * + * Since: 1.2 + **/ + obj_properties[PROP_L2_MISS] = g_param_spec_boolean( + NM_SETTING_VXLAN_L2_MISS, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingVxlan:l3-miss: + * + * Specifies whether netlink IP ADDR miss notifications are generated. + * + * Since: 1.2 + **/ + obj_properties[PROP_L3_MISS] = g_param_spec_boolean( + NM_SETTING_VXLAN_L3_MISS, + "", + "", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_VXLAN); +} diff --git a/src/libnm-core-impl/nm-setting-wifi-p2p.c b/src/libnm-core-impl/nm-setting-wifi-p2p.c new file mode 100644 index 0000000000..8f677479d3 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-wifi-p2p.c @@ -0,0 +1,304 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-wifi-p2p.h" + +#include + +#include "nm-utils.h" +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-wifi-p2p + * @short_description: Describes connection properties for 802.11 Wi-Fi P2P networks + * + * The #NMSettingWifiP2P object is a #NMSetting subclass that describes properties + * necessary for connection to 802.11 Wi-Fi P2P networks (aka Wi-Fi Direct). + **/ + +/** + * NMSettingWifiP2P: + * + * Wi-Fi P2P Settings + * + * Since: 1.16 + */ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PEER, PROP_WPS_METHOD, PROP_WFD_IES, ); + +typedef struct { + char * peer_mac_address; + GBytes *wfd_ies; + + NMSettingWirelessSecurityWpsMethod wps_method; +} NMSettingWifiP2PPrivate; + +struct _NMSettingWifiP2P { + NMSetting parent; + NMSettingWifiP2PPrivate _priv; +}; + +struct _NMSettingWifiP2PClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingWifiP2P, nm_setting_wifi_p2p, NM_TYPE_SETTING) + +#define NM_SETTING_WIFI_P2P_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingWifiP2P, NM_IS_SETTING_WIFI_P2P, NMSetting) + +/*****************************************************************************/ + +/** + * nm_setting_wifi_p2p_get_peer: + * @setting: the #NMSettingWifiP2P + * + * Returns: the #NMSettingWifiP2P:peer property of the setting + * + * Since: 1.16 + **/ +const char * +nm_setting_wifi_p2p_get_peer(NMSettingWifiP2P *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIFI_P2P(setting), NULL); + + return NM_SETTING_WIFI_P2P_GET_PRIVATE(setting)->peer_mac_address; +} + +/** + * nm_setting_wifi_p2p_get_wps_method: + * @setting: the #NMSettingWifiP2P + * + * Returns: the #NMSettingWifiP2P:wps-method property of the setting + * + * Since: 1.16 + **/ +NMSettingWirelessSecurityWpsMethod +nm_setting_wifi_p2p_get_wps_method(NMSettingWifiP2P *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIFI_P2P(setting), + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT); + + return NM_SETTING_WIFI_P2P_GET_PRIVATE(setting)->wps_method; +} + +/** + * nm_setting_wifi_p2p_get_wfd_ies: + * @setting: the #NMSettingWiFiP2P + * + * Returns: (transfer none): the #NMSettingWiFiP2P:wfd-ies property of the setting + * + * Since: 1.16 + **/ +GBytes * +nm_setting_wifi_p2p_get_wfd_ies(NMSettingWifiP2P *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIFI_P2P(setting), NULL); + + return NM_SETTING_WIFI_P2P_GET_PRIVATE(setting)->wfd_ies; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWifiP2PPrivate *priv = NM_SETTING_WIFI_P2P_GET_PRIVATE(setting); + + if (!priv->peer_mac_address) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIFI_P2P_SETTING_NAME, + NM_SETTING_WIFI_P2P_PEER); + return FALSE; + } + + if (!nm_utils_hwaddr_valid(priv->peer_mac_address, ETH_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIFI_P2P_SETTING_NAME, + NM_SETTING_WIFI_P2P_PEER); + return FALSE; + } + + if (!_nm_utils_wps_method_validate(priv->wps_method, + NM_SETTING_WIFI_P2P_SETTING_NAME, + NM_SETTING_WIFI_P2P_WPS_METHOD, + TRUE, + error)) + return FALSE; + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingWifiP2P *setting = NM_SETTING_WIFI_P2P(object); + + switch (prop_id) { + case PROP_PEER: + g_value_set_string(value, nm_setting_wifi_p2p_get_peer(setting)); + break; + case PROP_WPS_METHOD: + g_value_set_uint(value, nm_setting_wifi_p2p_get_wps_method(setting)); + break; + case PROP_WFD_IES: + g_value_set_boxed(value, nm_setting_wifi_p2p_get_wfd_ies(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingWifiP2PPrivate *priv = NM_SETTING_WIFI_P2P_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_PEER: + g_free(priv->peer_mac_address); + priv->peer_mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); + break; + case PROP_WPS_METHOD: + priv->wps_method = g_value_get_uint(value); + break; + case PROP_WFD_IES: + nm_clear_pointer(&priv->wfd_ies, g_bytes_unref); + priv->wfd_ies = g_value_dup_boxed(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_wifi_p2p_init(NMSettingWifiP2P *setting) +{} + +/** + * nm_setting_wifi_p2p_new: + * + * Creates a new #NMSettingWifiP2P object with default values. + * + * Returns: (transfer full): the new empty #NMSettingWifiP2P object + * + * Since: 1.16 + **/ +NMSetting * +nm_setting_wifi_p2p_new(void) +{ + return g_object_new(NM_TYPE_SETTING_WIFI_P2P, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingWifiP2PPrivate *priv = NM_SETTING_WIFI_P2P_GET_PRIVATE(object); + + g_free(priv->peer_mac_address); + g_bytes_unref(priv->wfd_ies); + + G_OBJECT_CLASS(nm_setting_wifi_p2p_parent_class)->finalize(object); +} + +static void +nm_setting_wifi_p2p_class_init(NMSettingWifiP2PClass *setting_wifi_p2p_class) +{ + GObjectClass * object_class = G_OBJECT_CLASS(setting_wifi_p2p_class); + NMSettingClass *setting_class = NM_SETTING_CLASS(setting_wifi_p2p_class); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingWifiP2P:peer: + * + * The P2P device that should be connected to. Currently, this is the only + * way to create or join a group. + * + * Since: 1.16 + */ + /* ---keyfile--- + * property: peer + * format: usual hex-digits-and-colons notation + * description: MAC address in traditional hex-digits-and-colons notation + * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) + * (e.g. 0;34;104;18;121;162). + * ---end--- + */ + obj_properties[PROP_PEER] = g_param_spec_string(NM_SETTING_WIFI_P2P_PEER, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWifiP2P:wps-method: + * + * Flags indicating which mode of WPS is to be used. + * + * There's little point in changing the default setting as NetworkManager will + * automatically determine the best method to use. + * + * Since: 1.16 + */ + obj_properties[PROP_WPS_METHOD] = g_param_spec_uint( + NM_SETTING_WIFI_P2P_WPS_METHOD, + "", + "", + 0, + G_MAXUINT32, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWifiP2P:wfd-ies: + * + * The Wi-Fi Display (WFD) Information Elements (IEs) to set. + * + * Wi-Fi Display requires a protocol specific information element to be + * set in certain Wi-Fi frames. These can be specified here for the + * purpose of establishing a connection. + * This setting is only useful when implementing a Wi-Fi Display client. + * + * Since: 1.16 + */ + obj_properties[PROP_WFD_IES] = g_param_spec_boxed( + NM_SETTING_WIFI_P2P_WFD_IES, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_WIFI_P2P); +} diff --git a/src/libnm-core-impl/nm-setting-wimax.c b/src/libnm-core-impl/nm-setting-wimax.c new file mode 100644 index 0000000000..3051405941 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-wimax.c @@ -0,0 +1,255 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2013 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-wimax.h" + +#include + +#include "nm-setting-private.h" +#include "nm-utils.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-wimax + * @short_description: Describes 802.16e Mobile WiMAX connection properties + * + * The #NMSettingWimax object is a #NMSetting subclass that describes properties + * necessary for connection to 802.16e Mobile WiMAX networks. + * + * NetworkManager no longer supports WiMAX; while this API remains available for + * backward-compatibility reasons, it serves no real purpose, since WiMAX + * connections cannot be activated. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_NETWORK_NAME, PROP_MAC_ADDRESS, ); + +typedef struct { + char *network_name; + char *mac_address; +} NMSettingWimaxPrivate; + +G_DEFINE_TYPE(NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING) + +#define NM_SETTING_WIMAX_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_wimax_get_network_name: + * @setting: the #NMSettingWimax + * + * Returns the WiMAX NSP name (ex "Sprint" or "CLEAR") which identifies the + * specific WiMAX network this setting describes a connection to. + * + * Returns: the WiMAX NSP name + * + * Deprecated: 1.2: WiMAX is no longer supported. + **/ +const char * +nm_setting_wimax_get_network_name(NMSettingWimax *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIMAX(setting), NULL); + + return NM_SETTING_WIMAX_GET_PRIVATE(setting)->network_name; +} + +/** + * nm_setting_wimax_get_mac_address: + * @setting: the #NMSettingWimax + * + * Returns the MAC address of a WiMAX device which this connection is locked + * to. + * + * Returns: the MAC address + * + * Deprecated: 1.2: WiMAX is no longer supported. + **/ +const char * +nm_setting_wimax_get_mac_address(NMSettingWimax *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIMAX(setting), NULL); + + return NM_SETTING_WIMAX_GET_PRIVATE(setting)->mac_address; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE(setting); + + if (!priv->network_name) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIMAX_SETTING_NAME, + NM_SETTING_WIMAX_NETWORK_NAME); + return FALSE; + } + + if (!strlen(priv->network_name)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIMAX_SETTING_NAME, + NM_SETTING_WIMAX_NETWORK_NAME); + return FALSE; + } + + if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, ETH_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIMAX_SETTING_NAME, + NM_SETTING_WIMAX_MAC_ADDRESS); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingWimax *setting = NM_SETTING_WIMAX(object); + + switch (prop_id) { + case PROP_NETWORK_NAME: + g_value_set_string(value, nm_setting_wimax_get_network_name(setting)); + break; + case PROP_MAC_ADDRESS: + g_value_set_string(value, nm_setting_wimax_get_mac_address(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_NETWORK_NAME: + g_free(priv->network_name); + priv->network_name = g_value_dup_string(value); + break; + case PROP_MAC_ADDRESS: + g_free(priv->mac_address); + priv->mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_wimax_init(NMSettingWimax *setting) +{} + +/** + * nm_setting_wimax_new: + * + * Creates a new #NMSettingWimax object with default values. + * + * Returns: the new empty #NMSettingWimax object + * + * Deprecated: 1.2: WiMAX is no longer supported. + **/ +NMSetting * +nm_setting_wimax_new(void) +{ + return g_object_new(NM_TYPE_SETTING_WIMAX, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE(object); + + g_free(priv->network_name); + g_free(priv->mac_address); + + G_OBJECT_CLASS(nm_setting_wimax_parent_class)->finalize(object); +} + +static void +nm_setting_wimax_class_init(NMSettingWimaxClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingWimaxPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingWimax:network-name: + * + * Network Service Provider (NSP) name of the WiMAX network this connection + * should use. + * + * Deprecated: 1.2: WiMAX is no longer supported. + **/ + obj_properties[PROP_NETWORK_NAME] = + g_param_spec_string(NM_SETTING_WIMAX_NETWORK_NAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWimax:mac-address: + * + * If specified, this connection will only apply to the WiMAX device whose + * MAC address matches. This property does not change the MAC address of the + * device (known as MAC spoofing). + * + * Deprecated: 1.2: WiMAX is no longer supported. + **/ + obj_properties[PROP_MAC_ADDRESS] = + g_param_spec_string(NM_SETTING_WIMAX_MAC_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_MAC_ADDRESS], + &nm_sett_info_propert_type_mac_address); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_WIMAX, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-wired.c b/src/libnm-core-impl/nm-setting-wired.c new file mode 100644 index 0000000000..f56ab8b4c8 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-wired.c @@ -0,0 +1,1647 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-wired.h" + +#include + +#include "nm-utils.h" +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-wired + * @short_description: Describes connection properties for Ethernet-based networks + * + * The #NMSettingWired object is a #NMSetting subclass that describes properties + * necessary for connection to Ethernet networks. + **/ + +/*****************************************************************************/ + +G_STATIC_ASSERT(NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS + == (NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT | NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE)); + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingWired, + PROP_PORT, + PROP_SPEED, + PROP_DUPLEX, + PROP_AUTO_NEGOTIATE, + PROP_MAC_ADDRESS, + PROP_CLONED_MAC_ADDRESS, + PROP_GENERATE_MAC_ADDRESS_MASK, + PROP_MAC_ADDRESS_BLACKLIST, + PROP_MTU, + PROP_S390_SUBCHANNELS, + PROP_S390_NETTYPE, + PROP_S390_OPTIONS, + PROP_WAKE_ON_LAN, + PROP_WAKE_ON_LAN_PASSWORD, ); + +typedef struct { + struct { + NMUtilsNamedValue *arr; + guint len; + guint n_alloc; + } s390_options; + GArray * mac_address_blacklist; + char ** s390_subchannels; + char * port; + char * duplex; + char * device_mac_address; + char * cloned_mac_address; + char * generate_mac_address_mask; + char * s390_nettype; + char * wol_password; + NMSettingWiredWakeOnLan wol; + guint32 speed; + guint32 mtu; + bool auto_negotiate : 1; +} NMSettingWiredPrivate; + +G_DEFINE_TYPE(NMSettingWired, nm_setting_wired, NM_TYPE_SETTING) + +#define NM_SETTING_WIRED_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate)) + +/*****************************************************************************/ + +static const char *valid_s390_opts[] = { + "broadcast_mode", + "buffer_count", + "canonical_macaddr", + "checksumming", + "ctcprot", + "fake_broadcast", + "inter", + "inter_jumbo", + "ipato_add4", + "ipato_add6", + "ipato_enable", + "ipato_invert4", + "ipato_invert6", + "isolation", + "lancmd_timeout", + "large_send", + "layer2", + "portname", + "portno", + "priority_queueing", + "protocol", + "route4", + "route6", + "rxip_add4", + "rxip_add6", + "sniffer", + "total", + "vipa_add4", + "vipa_add6", + NULL, +}; + +static gboolean +valid_s390_opts_check(const char *option) +{ +#if NM_MORE_ASSERTS > 5 + nm_assert(NM_PTRARRAY_LEN(valid_s390_opts) + 1 == G_N_ELEMENTS(valid_s390_opts)); + { + gsize i; + + for (i = 0; i < G_N_ELEMENTS(valid_s390_opts); i++) { + if (i == G_N_ELEMENTS(valid_s390_opts) - 1) + nm_assert(!valid_s390_opts[i]); + else { + nm_assert(valid_s390_opts[i]); + nm_assert(valid_s390_opts[i][0] != '\0'); + if (i > 0) + g_assert(strcmp(valid_s390_opts[i - 1], valid_s390_opts[i]) < 0); + } + } + } +#endif + + return option + && (nm_utils_array_find_binary_search(valid_s390_opts, + sizeof(const char *), + G_N_ELEMENTS(valid_s390_opts) - 1, + &option, + nm_strcmp_p_with_data, + NULL) + >= 0); +} + +/** + * nm_setting_wired_get_port: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:port property of the setting + **/ +const char * +nm_setting_wired_get_port(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->port; +} + +/** + * nm_setting_wired_get_speed: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:speed property of the setting + **/ +guint32 +nm_setting_wired_get_speed(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), 0); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->speed; +} + +/** + * nm_setting_wired_get_duplex: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:duplex property of the setting + **/ +const char * +nm_setting_wired_get_duplex(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->duplex; +} + +/** + * nm_setting_wired_get_auto_negotiate: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:auto-negotiate property of the setting + **/ +gboolean +nm_setting_wired_get_auto_negotiate(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->auto_negotiate; +} + +/** + * nm_setting_wired_get_mac_address: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:mac-address property of the setting + **/ +const char * +nm_setting_wired_get_mac_address(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->device_mac_address; +} + +/** + * nm_setting_wired_get_cloned_mac_address: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:cloned-mac-address property of the setting + **/ +const char * +nm_setting_wired_get_cloned_mac_address(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->cloned_mac_address; +} + +/** + * nm_setting_wired_get_generate_mac_address_mask: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:generate-mac-address-mask property of the setting + * + * Since: 1.4 + **/ +const char * +nm_setting_wired_get_generate_mac_address_mask(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->generate_mac_address_mask; +} + +/** + * nm_setting_wired_get_mac_address_blacklist: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:mac-address-blacklist property of the setting + **/ +const char *const * +nm_setting_wired_get_mac_address_blacklist(NMSettingWired *setting) +{ + NMSettingWiredPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + return (const char *const *) priv->mac_address_blacklist->data; +} + +/** + * nm_setting_wired_get_num_mac_blacklist_items: + * @setting: the #NMSettingWired + * + * Returns: the number of blacklisted MAC addresses + **/ +guint32 +nm_setting_wired_get_num_mac_blacklist_items(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), 0); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->mac_address_blacklist->len; +} + +/** + * nm_setting_wired_get_mac_blacklist_item: + * @setting: the #NMSettingWired + * @idx: the zero-based index of the MAC address entry + * + * Returns: the blacklisted MAC address string (hex-digits-and-colons notation) + * at index @idx + **/ +const char * +nm_setting_wired_get_mac_blacklist_item(NMSettingWired *setting, guint32 idx) +{ + NMSettingWiredPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + g_return_val_if_fail(idx <= priv->mac_address_blacklist->len, NULL); + + return g_array_index(priv->mac_address_blacklist, const char *, idx); +} + +/** + * nm_setting_wired_add_mac_blacklist_item: + * @setting: the #NMSettingWired + * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist + * + * Adds a new MAC address to the #NMSettingWired:mac-address-blacklist property. + * + * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address + * is invalid or was already present + **/ +gboolean +nm_setting_wired_add_mac_blacklist_item(NMSettingWired *setting, const char *mac) +{ + NMSettingWiredPrivate *priv; + const char * candidate; + int i; + + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); + g_return_val_if_fail(mac != NULL, FALSE); + + if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) + return FALSE; + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + for (i = 0; i < priv->mac_address_blacklist->len; i++) { + candidate = g_array_index(priv->mac_address_blacklist, char *, i); + if (nm_utils_hwaddr_matches(mac, -1, candidate, -1)) + return FALSE; + } + + mac = nm_utils_hwaddr_canonical(mac, ETH_ALEN); + g_array_append_val(priv->mac_address_blacklist, mac); + _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); + return TRUE; +} + +/** + * nm_setting_wired_remove_mac_blacklist_item: + * @setting: the #NMSettingWired + * @idx: index number of the MAC address + * + * Removes the MAC address at index @idx from the blacklist. + **/ +void +nm_setting_wired_remove_mac_blacklist_item(NMSettingWired *setting, guint32 idx) +{ + NMSettingWiredPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_WIRED(setting)); + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + g_return_if_fail(idx < priv->mac_address_blacklist->len); + + g_array_remove_index(priv->mac_address_blacklist, idx); + _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); +} + +/** + * nm_setting_wired_remove_mac_blacklist_item_by_value: + * @setting: the #NMSettingWired + * @mac: the MAC address string (hex-digits-and-colons notation) to remove from + * the blacklist + * + * Removes the MAC address @mac from the blacklist. + * + * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_wired_remove_mac_blacklist_item_by_value(NMSettingWired *setting, const char *mac) +{ + NMSettingWiredPrivate *priv; + const char * candidate; + int i; + + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); + g_return_val_if_fail(mac != NULL, FALSE); + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + for (i = 0; i < priv->mac_address_blacklist->len; i++) { + candidate = g_array_index(priv->mac_address_blacklist, char *, i); + if (!nm_utils_hwaddr_matches(mac, -1, candidate, -1)) { + g_array_remove_index(priv->mac_address_blacklist, i); + _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_wired_clear_mac_blacklist_items: + * @setting: the #NMSettingWired + * + * Removes all blacklisted MAC addresses. + **/ +void +nm_setting_wired_clear_mac_blacklist_items(NMSettingWired *setting) +{ + g_return_if_fail(NM_IS_SETTING_WIRED(setting)); + + g_array_set_size(NM_SETTING_WIRED_GET_PRIVATE(setting)->mac_address_blacklist, 0); + _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); +} + +/** + * nm_setting_wired_get_mtu: + * @setting: the #NMSettingWired + * + * Returns: the #NMSettingWired:mtu property of the setting + **/ +guint32 +nm_setting_wired_get_mtu(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), 0); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->mtu; +} + +/** + * nm_setting_wired_get_s390_subchannels: + * @setting: the #NMSettingWired + * + * Return the list of s390 subchannels that identify the device that this + * connection is applicable to. The connection should only be used in + * conjunction with that device. + * + * Returns: (transfer none) (element-type utf8): array of strings, each specifying + * one subchannel the s390 device uses to communicate to the host. + **/ +const char *const * +nm_setting_wired_get_s390_subchannels(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + return (const char *const *) NM_SETTING_WIRED_GET_PRIVATE(setting)->s390_subchannels; +} + +/** + * nm_setting_wired_get_s390_nettype: + * @setting: the #NMSettingWired + * + * Returns the s390 device type this connection should apply to. Will be one + * of 'qeth', 'lcs', or 'ctc'. + * + * Returns: the s390 device type + **/ +const char * +nm_setting_wired_get_s390_nettype(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->s390_nettype; +} + +/** + * nm_setting_wired_get_num_s390_options: + * @setting: the #NMSettingWired + * + * Returns the number of s390-specific options that should be set for this + * device when it is activated. This can be used to retrieve each s390 + * option individually using nm_setting_wired_get_s390_option(). + * + * Returns: the number of s390-specific device options + **/ +guint32 +nm_setting_wired_get_num_s390_options(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), 0); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->s390_options.len; +} + +/** + * nm_setting_wired_get_s390_option: + * @setting: the #NMSettingWired + * @idx: index of the desired option, from 0 to + * nm_setting_wired_get_num_s390_options() - 1 + * @out_key: (out) (transfer none): on return, the key name of the s390 specific + * option; this value is owned by the setting and should not be modified + * @out_value: (out) (transfer none): on return, the value of the key of the + * s390 specific option; this value is owned by the setting and should not be + * modified + * + * Given an index, return the value of the s390 option at that index. indexes + * are *not* guaranteed to be static across modifications to options done by + * nm_setting_wired_add_s390_option() and nm_setting_wired_remove_s390_option(), + * and should not be used to refer to options except for short periods of time + * such as during option iteration. + * + * Returns: %TRUE on success if the index was valid and an option was found, + * %FALSE if the index was invalid (ie, greater than the number of options + * currently held by the setting) + **/ +gboolean +nm_setting_wired_get_s390_option(NMSettingWired *setting, + guint32 idx, + const char ** out_key, + const char ** out_value) +{ + NMSettingWiredPrivate *priv; + + /* with LTO and optimization, the compiler complains that the + * output variables are not initialized. In practice, the function + * only sets the output on success. But make the compiler happy. + */ + NM_SET_OUT(out_key, NULL); + NM_SET_OUT(out_value, NULL); + + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + + g_return_val_if_fail(idx < priv->s390_options.len, FALSE); + + NM_SET_OUT(out_key, priv->s390_options.arr[idx].name); + NM_SET_OUT(out_value, priv->s390_options.arr[idx].value_str); + return TRUE; +} + +/** + * nm_setting_wired_get_s390_option_by_key: + * @setting: the #NMSettingWired + * @key: the key for which to retrieve the value + * + * Returns the value associated with the s390-specific option specified by + * @key, if it exists. + * + * Returns: the value, or %NULL if the key/value pair was never added to the + * setting; the value is owned by the setting and must not be modified + **/ +const char * +nm_setting_wired_get_s390_option_by_key(NMSettingWired *setting, const char *key) +{ + NMSettingWiredPrivate *priv; + gssize idx; + + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + g_return_val_if_fail(key && key[0], NULL); + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + + idx = nm_utils_named_value_list_find(priv->s390_options.arr, priv->s390_options.len, key, TRUE); + if (idx < 0) + return NULL; + return priv->s390_options.arr[idx].value_str; +} + +/** + * nm_setting_wired_add_s390_option: + * @setting: the #NMSettingWired + * @key: key name for the option + * @value: value for the option + * + * Add an option to the table. The option is compared to an internal list + * of allowed options. Key names may contain only alphanumeric characters + * (ie [a-zA-Z0-9]). Adding a new key replaces any existing key/value pair that + * may already exist. + * + * Returns: %TRUE if the option was valid and was added to the internal option + * list, %FALSE if it was not. + **/ +gboolean +nm_setting_wired_add_s390_option(NMSettingWired *setting, const char *key, const char *value) +{ + NMSettingWiredPrivate *priv; + gssize idx; + NMUtilsNamedValue * v; + + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); + g_return_val_if_fail(value, FALSE); + + if (!valid_s390_opts_check(key)) { + g_return_val_if_fail(key, FALSE); + return FALSE; + } + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + + idx = nm_utils_named_value_list_find(priv->s390_options.arr, priv->s390_options.len, key, TRUE); + if (idx < 0) { + gsize dst_idx = ~idx; + + if (priv->s390_options.n_alloc < priv->s390_options.len + 1) { + priv->s390_options.n_alloc = NM_MAX(4, (priv->s390_options.len + 1) * 2); + priv->s390_options.arr = + g_realloc(priv->s390_options.arr, + priv->s390_options.n_alloc * sizeof(NMUtilsNamedValue)); + } + if (dst_idx < priv->s390_options.len) { + memmove(&priv->s390_options.arr[dst_idx + 1], + &priv->s390_options.arr[dst_idx], + (priv->s390_options.len - dst_idx) * sizeof(NMUtilsNamedValue)); + } + priv->s390_options.arr[dst_idx] = (NMUtilsNamedValue){ + .name = g_strdup(key), + .value_str = g_strdup(value), + }; + priv->s390_options.len++; + } else { + v = &priv->s390_options.arr[idx]; + if (nm_streq(value, v->value_str)) + return TRUE; + g_free((char *) v->value_str); + v->value_str = g_strdup(value); + } + + _notify(setting, PROP_S390_OPTIONS); + return TRUE; +} + +/** + * nm_setting_wired_remove_s390_option: + * @setting: the #NMSettingWired + * @key: key name for the option to remove + * + * Remove the s390-specific option referenced by @key from the internal option + * list. + * + * Returns: %TRUE if the option was found and removed from the internal option + * list, %FALSE if it was not. + **/ +gboolean +nm_setting_wired_remove_s390_option(NMSettingWired *setting, const char *key) +{ + NMSettingWiredPrivate *priv; + gsize dst_idx; + gssize idx; + + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), FALSE); + g_return_val_if_fail(key, FALSE); + + priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + + idx = nm_utils_named_value_list_find(priv->s390_options.arr, priv->s390_options.len, key, TRUE); + if (idx < 0) + return FALSE; + + dst_idx = idx; + + g_free((char *) priv->s390_options.arr[dst_idx].name); + g_free((char *) priv->s390_options.arr[dst_idx].value_str); + if (dst_idx + 1 != priv->s390_options.len) { + memmove(&priv->s390_options.arr[dst_idx], + &priv->s390_options.arr[dst_idx + 1], + (priv->s390_options.len - dst_idx - 1) * sizeof(NMUtilsNamedValue)); + } + + priv->s390_options.len--; + + _notify(setting, PROP_S390_OPTIONS); + return TRUE; +} + +static void +_s390_options_clear(NMSettingWiredPrivate *priv) +{ + guint i; + + for (i = 0; i < priv->s390_options.len; i++) { + g_free((char *) priv->s390_options.arr[i].name); + g_free((char *) priv->s390_options.arr[i].value_str); + } + nm_clear_g_free(&priv->s390_options.arr); + priv->s390_options.len = 0; + priv->s390_options.n_alloc = 0; +} + +void +_nm_setting_wired_clear_s390_options(NMSettingWired *setting) +{ + g_return_if_fail(NM_IS_SETTING_WIRED(setting)); + + _s390_options_clear(NM_SETTING_WIRED_GET_PRIVATE(setting)); +} + +/** + * nm_setting_wired_get_valid_s390_options: + * @setting: (allow-none): the #NMSettingWired. This argument is unused + * and you may pass %NULL. + * + * Returns a list of valid s390 options. + * + * The @setting argument is unused and %NULL may be passed instead. + * + * Returns: (transfer none): a %NULL-terminated array of strings of valid s390 options. + **/ +const char ** +nm_setting_wired_get_valid_s390_options(NMSettingWired *setting) +{ + return valid_s390_opts; +} + +/** + * nm_setting_wired_get_wake_on_lan: + * @setting: the #NMSettingWired + * + * Returns the Wake-on-LAN options enabled for the connection + * + * Returns: the Wake-on-LAN options + * + * Since: 1.2 + */ +NMSettingWiredWakeOnLan +nm_setting_wired_get_wake_on_lan(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NM_SETTING_WIRED_WAKE_ON_LAN_NONE); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->wol; +} + +/** + * nm_setting_wired_get_wake_on_lan_password: + * @setting: the #NMSettingWired + * + * Returns the Wake-on-LAN password. This only applies to + * %NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC. + * + * Returns: the Wake-on-LAN setting password, or %NULL if there is no password. + * + * Since: 1.2 + */ +const char * +nm_setting_wired_get_wake_on_lan_password(NMSettingWired *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE(setting)->wol_password; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + GError * local = NULL; + guint i; + + if (!NM_IN_STRSET(priv->port, NULL, "tp", "aui", "bnc", "mii")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid Ethernet port value"), + priv->port); + g_prefix_error(error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_PORT); + return FALSE; + } + + if (!NM_IN_STRSET(priv->duplex, NULL, "half", "full")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid duplex value"), + priv->duplex); + g_prefix_error(error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_DUPLEX); + return FALSE; + } + + if (priv->device_mac_address && !nm_utils_hwaddr_valid(priv->device_mac_address, ETH_ALEN)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid MAC address"), + priv->device_mac_address); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_MAC_ADDRESS); + return FALSE; + } + + for (i = 0; i < priv->mac_address_blacklist->len; i++) { + const char *mac = g_array_index(priv->mac_address_blacklist, const char *, i); + + if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid MAC address"), + mac); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST); + return FALSE; + } + } + + if (priv->s390_subchannels) { + guint len = g_strv_length(priv->s390_subchannels); + + if (len != 2 && len != 3) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_SUBCHANNELS); + return FALSE; + } + } + + if (!NM_IN_STRSET(priv->s390_nettype, NULL, "qeth", "lcs", "ctc")) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_NETTYPE); + return FALSE; + } + + for (i = 0; i < priv->s390_options.len; i++) { + const NMUtilsNamedValue *v = &priv->s390_options.arr[i]; + + nm_assert(v->name); + + if (!valid_s390_opts_check(v->name) || v->value_str[0] == '\0' + || strlen(v->value_str) > 200) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid '%s' or its value '%s'"), + v->name, + v->value_str); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_OPTIONS); + return FALSE; + } + } + + if (priv->cloned_mac_address && !NM_CLONED_MAC_IS_SPECIAL(priv->cloned_mac_address) + && !nm_utils_hwaddr_valid(priv->cloned_mac_address, ETH_ALEN)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid MAC address"), + priv->cloned_mac_address); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_CLONED_MAC_ADDRESS); + return FALSE; + } + + /* generate-mac-address-mask only makes sense with cloned-mac-address "random" or + * "stable". Still, let's not be so strict about that and accept the value + * even if it is unused. */ + if (!_nm_utils_generate_mac_address_mask_parse(priv->generate_mac_address_mask, + NULL, + NULL, + NULL, + &local)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + local->message); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK); + g_error_free(local); + return FALSE; + } + + if (NM_FLAGS_ANY(priv->wol, NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS) + && !nm_utils_is_power_of_two(priv->wol)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Wake-on-LAN mode 'default' and 'ignore' are exclusive flags")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_WAKE_ON_LAN); + return FALSE; + } + + if (priv->wol_password && !NM_FLAGS_HAS(priv->wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Wake-on-LAN password can only be used with magic packet mode")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD); + return FALSE; + } + + if (priv->wol_password && !nm_utils_hwaddr_valid(priv->wol_password, ETH_ALEN)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid MAC address"), + priv->wol_password); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD); + return FALSE; + } + + /* Normalizable properties - just return NM_SETTING_VERIFY_NORMALIZABLE for compatibility + * with legacy nm-connection-editor which used to save "full" duplex connection as default + */ + + if (((priv->speed) && (!priv->duplex)) || ((!priv->speed) && (priv->duplex))) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + priv->auto_negotiate + ? _("both speed and duplex should have a valid value or both should be unset") + : _("both speed and duplex are required for static link configuration")); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + if (nm_streq(sett_info->property_infos[property_idx].name, + NM_SETTING_WIRED_CLONED_MAC_ADDRESS)) { + return !set_b + || nm_streq0(NM_SETTING_WIRED_GET_PRIVATE(set_a)->cloned_mac_address, + NM_SETTING_WIRED_GET_PRIVATE(set_b)->cloned_mac_address); + } + + return NM_SETTING_CLASS(nm_setting_wired_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +static GVariant * +_override_autoneg_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + return g_variant_new_boolean(nm_setting_wired_get_auto_negotiate((NMSettingWired *) setting)); +} + +/*****************************************************************************/ + +static void +clear_blacklist_item(char **item_p) +{ + g_free(*item_p); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingWired * setting = NM_SETTING_WIRED(object); + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + GHashTable * hash; + guint i; + + switch (prop_id) { + case PROP_PORT: + g_value_set_string(value, nm_setting_wired_get_port(setting)); + break; + case PROP_SPEED: + g_value_set_uint(value, nm_setting_wired_get_speed(setting)); + break; + case PROP_DUPLEX: + g_value_set_string(value, nm_setting_wired_get_duplex(setting)); + break; + case PROP_AUTO_NEGOTIATE: + g_value_set_boolean(value, nm_setting_wired_get_auto_negotiate(setting)); + break; + case PROP_MAC_ADDRESS: + g_value_set_string(value, nm_setting_wired_get_mac_address(setting)); + break; + case PROP_CLONED_MAC_ADDRESS: + g_value_set_string(value, nm_setting_wired_get_cloned_mac_address(setting)); + break; + case PROP_GENERATE_MAC_ADDRESS_MASK: + g_value_set_string(value, nm_setting_wired_get_generate_mac_address_mask(setting)); + break; + case PROP_MAC_ADDRESS_BLACKLIST: + g_value_set_boxed(value, (char **) priv->mac_address_blacklist->data); + break; + case PROP_MTU: + g_value_set_uint(value, nm_setting_wired_get_mtu(setting)); + break; + case PROP_S390_SUBCHANNELS: + g_value_set_boxed(value, priv->s390_subchannels); + break; + case PROP_S390_NETTYPE: + g_value_set_string(value, nm_setting_wired_get_s390_nettype(setting)); + break; + case PROP_S390_OPTIONS: + hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); + for (i = 0; i < priv->s390_options.len; i++) { + g_hash_table_insert(hash, + g_strdup(priv->s390_options.arr[i].name), + g_strdup(priv->s390_options.arr[i].value_str)); + } + g_value_take_boxed(value, hash); + break; + case PROP_WAKE_ON_LAN: + g_value_set_uint(value, priv->wol); + break; + case PROP_WAKE_ON_LAN_PASSWORD: + g_value_set_string(value, priv->wol_password); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(object); + const char *const * blacklist; + const char * mac; + + switch (prop_id) { + case PROP_PORT: + g_free(priv->port); + priv->port = g_value_dup_string(value); + break; + case PROP_SPEED: + priv->speed = g_value_get_uint(value); + break; + case PROP_DUPLEX: + g_free(priv->duplex); + priv->duplex = g_value_dup_string(value); + break; + case PROP_AUTO_NEGOTIATE: + priv->auto_negotiate = g_value_get_boolean(value); + break; + case PROP_MAC_ADDRESS: + g_free(priv->device_mac_address); + priv->device_mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); + break; + case PROP_CLONED_MAC_ADDRESS: + g_free(priv->cloned_mac_address); + priv->cloned_mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); + break; + case PROP_GENERATE_MAC_ADDRESS_MASK: + g_free(priv->generate_mac_address_mask); + priv->generate_mac_address_mask = g_value_dup_string(value); + break; + case PROP_MAC_ADDRESS_BLACKLIST: + blacklist = g_value_get_boxed(value); + g_array_set_size(priv->mac_address_blacklist, 0); + if (blacklist && *blacklist) { + guint i; + + for (i = 0; blacklist[i]; i++) { + mac = _nm_utils_hwaddr_canonical_or_invalid(blacklist[i], ETH_ALEN); + g_array_append_val(priv->mac_address_blacklist, mac); + } + } + break; + case PROP_MTU: + priv->mtu = g_value_get_uint(value); + break; + case PROP_S390_SUBCHANNELS: + if (priv->s390_subchannels) + g_strfreev(priv->s390_subchannels); + priv->s390_subchannels = g_value_dup_boxed(value); + break; + case PROP_S390_NETTYPE: + g_free(priv->s390_nettype); + priv->s390_nettype = g_value_dup_string(value); + break; + case PROP_S390_OPTIONS: + { + GHashTable *hash; + + _s390_options_clear(priv); + + hash = g_value_get_boxed(value); + + priv->s390_options.n_alloc = hash ? g_hash_table_size(hash) : 0u; + + if (priv->s390_options.n_alloc > 0) { + gboolean invalid_content = FALSE; + GHashTableIter iter; + const char * key; + const char * val; + guint i, j; + + priv->s390_options.arr = g_new(NMUtilsNamedValue, priv->s390_options.n_alloc); + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + if (!key || !val) { + invalid_content = TRUE; + continue; + } + nm_assert(priv->s390_options.len < priv->s390_options.n_alloc); + priv->s390_options.arr[priv->s390_options.len] = (NMUtilsNamedValue){ + .name = g_strdup(key), + .value_str = g_strdup(val), + }; + priv->s390_options.len++; + } + if (priv->s390_options.len > 1) { + nm_utils_named_value_list_sort(priv->s390_options.arr, + priv->s390_options.len, + NULL, + NULL); + /* prune duplicate keys. This is only possible if @hash does not use + * g_str_equal() as compare function (which would be a bug). + * Still, handle this, because we use later binary sort and rely + * on unique names. One bug here, should not bork the remainder + * of the program. */ + j = 1; + for (i = 1; i < priv->s390_options.len; i++) { + if (nm_streq(priv->s390_options.arr[j - 1].name, + priv->s390_options.arr[i].name)) { + g_free((char *) priv->s390_options.arr[i].name); + g_free((char *) priv->s390_options.arr[i].value_str); + invalid_content = TRUE; + continue; + } + priv->s390_options.arr[j++] = priv->s390_options.arr[i]; + } + priv->s390_options.len = j; + } + + g_return_if_fail(!invalid_content); + } + } break; + case PROP_WAKE_ON_LAN: + priv->wol = g_value_get_uint(value); + break; + case PROP_WAKE_ON_LAN_PASSWORD: + g_free(priv->wol_password); + priv->wol_password = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_wired_init(NMSettingWired *setting) +{ + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(setting); + + /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */ + priv->mac_address_blacklist = g_array_new(TRUE, FALSE, sizeof(char *)); + g_array_set_clear_func(priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item); + + priv->wol = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT; +} + +/** + * nm_setting_wired_new: + * + * Creates a new #NMSettingWired object with default values. + * + * Returns: (transfer full): the new empty #NMSettingWired object + **/ +NMSetting * +nm_setting_wired_new(void) +{ + return g_object_new(NM_TYPE_SETTING_WIRED, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE(object); + + g_free(priv->port); + g_free(priv->duplex); + g_free(priv->s390_nettype); + + _s390_options_clear(priv); + + g_free(priv->device_mac_address); + g_free(priv->cloned_mac_address); + g_free(priv->generate_mac_address_mask); + g_array_unref(priv->mac_address_blacklist); + + if (priv->s390_subchannels) + g_strfreev(priv->s390_subchannels); + + g_free(priv->wol_password); + + G_OBJECT_CLASS(nm_setting_wired_parent_class)->finalize(object); +} + +static void +nm_setting_wired_class_init(NMSettingWiredClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingWiredPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->compare_property = compare_property; + + /** + * NMSettingWired:port: + * + * Specific port type to use if the device supports multiple + * attachment methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit + * Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface). + * If the device supports only one port type, this setting is ignored. + **/ + /* ---ifcfg-rh--- + * property: port + * variable: (none) + * description: The property is not saved by the plugin. + * ---end--- + */ + obj_properties[PROP_PORT] = g_param_spec_string(NM_SETTING_WIRED_PORT, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:speed: + * + * When a value greater than 0 is set, configures the device to use + * the specified speed. If "auto-negotiate" is "yes" the specified + * speed will be the only one advertised during link negotiation: + * this works only for BASE-T 802.3 specifications and is useful for + * enforcing gigabit speeds, as in this case link negotiation is + * mandatory. + * If the value is unset (0, the default), the link configuration will be + * either skipped (if "auto-negotiate" is "no", the default) or will + * be auto-negotiated (if "auto-negotiate" is "yes") and the local device + * will advertise all the supported speeds. + * In Mbit/s, ie 100 == 100Mbit/s. + * Must be set together with the "duplex" property when non-zero. + * Before specifying a speed value be sure your device supports it. + **/ + /* ---ifcfg-rh--- + * property: speed + * variable: ETHTOOL_OPTS + * description: Fixed speed for the ethernet link. It is added as "speed" + * parameter in the ETHTOOL_OPTS variable. + * ---end--- + */ + obj_properties[PROP_SPEED] = g_param_spec_uint(NM_SETTING_WIRED_SPEED, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:duplex: + * + * When a value is set, either "half" or "full", configures the device + * to use the specified duplex mode. If "auto-negotiate" is "yes" the + * specified duplex mode will be the only one advertised during link + * negotiation: this works only for BASE-T 802.3 specifications and is + * useful for enforcing gigabits modes, as in these cases link negotiation + * is mandatory. + * If the value is unset (the default), the link configuration will be + * either skipped (if "auto-negotiate" is "no", the default) or will + * be auto-negotiated (if "auto-negotiate" is "yes") and the local device + * will advertise all the supported duplex modes. + * Must be set together with the "speed" property if specified. + * Before specifying a duplex mode be sure your device supports it. + **/ + /* ---ifcfg-rh--- + * property: duplex + * variable: ETHTOOL_OPTS + * description: Fixed duplex mode for the ethernet link. It is added as + * "duplex" parameter in the ETHOOL_OPTS variable. + * ---end--- + */ + obj_properties[PROP_DUPLEX] = g_param_spec_string(NM_SETTING_WIRED_DUPLEX, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:auto-negotiate: + * + * When %TRUE, enforce auto-negotiation of speed and duplex mode. + * If "speed" and "duplex" properties are both specified, only that + * single mode will be advertised and accepted during the link + * auto-negotiation process: this works only for BASE-T 802.3 specifications + * and is useful for enforcing gigabits modes, as in these cases link + * negotiation is mandatory. + * When %FALSE, "speed" and "duplex" properties should be both set or + * link configuration will be skipped. + **/ + /* ---ifcfg-rh--- + * property: auto-negotiate + * variable: ETHTOOL_OPTS + * description: Whether link speed and duplex autonegotiation is enabled. + * It is not saved only if disabled and no values are provided for the + * "speed" and "duplex" parameters (skips link configuration). + * ---end--- + */ + obj_properties[PROP_AUTO_NEGOTIATE] = + g_param_spec_boolean(NM_SETTING_WIRED_AUTO_NEGOTIATE, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_AUTO_NEGOTIATE], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BOOLEAN, + .to_dbus_fcn = _override_autoneg_get, )); + + /** + * NMSettingWired:mac-address: + * + * If specified, this connection will only apply to the Ethernet device + * whose permanent MAC address matches. This property does not change the + * MAC address of the device (i.e. MAC spoofing). + **/ + /* ---keyfile--- + * property: mac-address + * format: usual hex-digits-and-colons notation + * description: MAC address in traditional hex-digits-and-colons notation + * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) + * (e.g. 0;34;104;18;121;162) + * ---end--- + * ---ifcfg-rh--- + * property: mac-address + * variable: HWADDR + * description: Hardware address of the device in traditional hex-digits-and-colons + * notation (e.g. 00:22:68:14:5A:05). + * Note that for initscripts this is the current MAC address of the device as found + * during ifup. For NetworkManager this is the permanent MAC address. Or in case no + * permanent MAC address exists, the MAC address initially configured on the device. + * ---end--- + */ + obj_properties[PROP_MAC_ADDRESS] = g_param_spec_string( + NM_SETTING_WIRED_MAC_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_MAC_ADDRESS], + &nm_sett_info_propert_type_mac_address); + + /** + * NMSettingWired:cloned-mac-address: + * + * If specified, request that the device use this MAC address instead. + * This is known as MAC cloning or spoofing. + * + * Beside explicitly specifying a MAC address, the special values "preserve", "permanent", + * "random" and "stable" are supported. + * "preserve" means not to touch the MAC address on activation. + * "permanent" means to use the permanent hardware address if the device + * has one (otherwise this is treated as "preserve"). + * "random" creates a random MAC address on each connect. + * "stable" creates a hashed MAC address based on connection.stable-id and a + * machine dependent key. + * + * If unspecified, the value can be overwritten via global defaults, see manual + * of NetworkManager.conf. If still unspecified, it defaults to "preserve" + * (older versions of NetworkManager may use a different default value). + * + * On D-Bus, this field is expressed as "assigned-mac-address" or the deprecated + * "cloned-mac-address". + **/ + /* ---keyfile--- + * property: cloned-mac-address + * format: usual hex-digits-and-colons notation + * description: Cloned MAC address in traditional hex-digits-and-colons notation + * (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete) + * (e.g. 0;34;104;18;121;178). + * ---end--- + * ---ifcfg-rh--- + * property: cloned-mac-address + * variable: MACADDR + * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons + * notation (e.g. 00:22:68:14:5A:99). + * ---end--- + * ---dbus--- + * property: cloned-mac-address + * format: byte array + * description: This D-Bus field is deprecated in favor of "assigned-mac-address" + * which is more flexible and allows specifying special variants like "random". + * For libnm and nmcli, this field is called "cloned-mac-address". + * ---end--- + */ + obj_properties[PROP_CLONED_MAC_ADDRESS] = g_param_spec_string( + NM_SETTING_WIRED_CLONED_MAC_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_CLONED_MAC_ADDRESS], + &nm_sett_info_propert_type_cloned_mac_address); + + /* ---dbus--- + * property: assigned-mac-address + * format: string + * description: The new field for the cloned MAC address. It can be either + * a hardware address in ASCII representation, or one of the special values + * "preserve", "permanent", "random" or "stable". + * This field replaces the deprecated "cloned-mac-address" on D-Bus, which + * can only contain explicit hardware addresses. Note that this property + * only exists in D-Bus API. libnm and nmcli continue to call this property + * "cloned-mac-address". + * ---end--- + */ + _nm_properties_override_dbus(properties_override, + "assigned-mac-address", + &nm_sett_info_propert_type_assigned_mac_address); + + /** + * NMSettingWired:generate-mac-address-mask: + * + * With #NMSettingWired:cloned-mac-address setting "random" or "stable", + * by default all bits of the MAC address are scrambled and a locally-administered, + * unicast MAC address is created. This property allows to specify that certain bits + * are fixed. Note that the least significant bit of the first MAC address will + * always be unset to create a unicast MAC address. + * + * If the property is %NULL, it is eligible to be overwritten by a default + * connection setting. If the value is still %NULL or an empty string, the + * default is to create a locally-administered, unicast MAC address. + * + * If the value contains one MAC address, this address is used as mask. The set + * bits of the mask are to be filled with the current MAC address of the device, + * while the unset bits are subject to randomization. + * Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address + * and only randomize the lower 3 bytes using the "random" or "stable" algorithm. + * + * If the value contains one additional MAC address after the mask, + * this address is used instead of the current MAC address to fill the bits + * that shall not be randomized. For example, a value of + * "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address + * to 68:F7:28, while the lower bits are randomized. A value of + * "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled + * globally-administered, burned-in MAC address. + * + * If the value contains more than one additional MAC addresses, one of + * them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" + * will create a fully scrambled MAC address, randomly locally or globally + * administered. + **/ + /* ---ifcfg-rh--- + * property: generate-mac-address-mask + * variable: GENERATE_MAC_ADDRESS_MASK(+) + * description: the MAC address mask for generating randomized and stable + * cloned-mac-address. + * ---end--- + */ + obj_properties[PROP_GENERATE_MAC_ADDRESS_MASK] = g_param_spec_string( + NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:mac-address-blacklist: + * + * If specified, this connection will never apply to the Ethernet device + * whose permanent MAC address matches an address in the list. Each MAC + * address is in the standard hex-digits-and-colons notation + * (00:11:22:33:44:55). + **/ + /* ---keyfile--- + * property: mac-address-blacklist + * format: list of MACs (separated with semicolons) + * description: MAC address blacklist. + * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78 + * ---end--- + * ---ifcfg-rh--- + * property: mac-address-blacklist + * variable: HWADDR_BLACKLIST(+) + * description: It denies usage of the connection for any device whose address + * is listed. + * example: HWADDR_BLACKLIST="00:22:68:11:69:08 00:11:22:11:44:55" + * ---end--- + */ + obj_properties[PROP_MAC_ADDRESS_BLACKLIST] = g_param_spec_boxed( + NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple Ethernet frames. + **/ + /* ---ifcfg-rh--- + * property: mtu + * variable: MTU + * description: MTU of the interface. + * ---end--- + */ + obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_WIRED_MTU, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:s390-subchannels: + * + * Identifies specific subchannels that this network device uses for + * communication with z/VM or s390 host. Like the + * #NMSettingWired:mac-address property for non-z/VM devices, this property + * can be used to ensure this connection only applies to the network device + * that uses these subchannels. The list should contain exactly 3 strings, + * and each string may only be composed of hexadecimal characters and the + * period (.) character. + **/ + /* ---ifcfg-rh--- + * property: s390-subchannels + * variable: SUBCHANNELS + * description: Subchannels for IBM S390 hosts. + * example: SUBCHANNELS=0.0.b00a,0.0.b00b,0.0.b00c + * ---end--- + */ + obj_properties[PROP_S390_SUBCHANNELS] = g_param_spec_boxed( + NM_SETTING_WIRED_S390_SUBCHANNELS, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:s390-nettype: + * + * s390 network device type; one of "qeth", "lcs", or "ctc", representing + * the different types of virtual network devices available on s390 systems. + **/ + /* ---ifcfg-rh--- + * property: s390-nettype + * variable: NETTYPE + * values: "qeth", "lcs" or "ctc" + * description: Network type of the S390 host. + * example: NETTYPE=qeth + * ---end--- + */ + obj_properties[PROP_S390_NETTYPE] = g_param_spec_string( + NM_SETTING_WIRED_S390_NETTYPE, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:s390-options: (type GHashTable(utf8,utf8)): + * + * Dictionary of key/value pairs of s390-specific device options. Both keys + * and values must be strings. Allowed keys include "portno", "layer2", + * "portname", "protocol", among others. Key names must contain only + * alphanumeric characters (ie, [a-zA-Z0-9]). + **/ + /* ---ifcfg-rh--- + * property: s390-options + * variable: OPTIONS and PORTNAME, CTCPROTO, + * description: S390 device options. All options go to OPTIONS, except for + * "portname" and "ctcprot" that have their own variables. + * ---end--- + */ + obj_properties[PROP_S390_OPTIONS] = g_param_spec_boxed( + NM_SETTING_WIRED_S390_OPTIONS, + "", + "", + G_TYPE_HASH_TABLE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_S390_OPTIONS], + &nm_sett_info_propert_type_strdict); + + /** + * NMSettingWired:wake-on-lan: + * + * The #NMSettingWiredWakeOnLan options to enable. Not all devices support all options. + * May be any combination of %NM_SETTING_WIRED_WAKE_ON_LAN_PHY, + * %NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST, %NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST, + * %NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST, %NM_SETTING_WIRED_WAKE_ON_LAN_ARP, + * %NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC or the special values + * %NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (to use global settings) and + * %NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (to disable management of Wake-on-LAN in + * NetworkManager). + * + * Since: 1.2 + **/ + obj_properties[PROP_WAKE_ON_LAN] = + g_param_spec_uint(NM_SETTING_WIRED_WAKE_ON_LAN, + "", + "", + 0, + G_MAXUINT32, + NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWired:wake-on-lan-password: + * + * If specified, the password used with magic-packet-based + * Wake-on-LAN, represented as an Ethernet MAC address. If %NULL, + * no password will be required. + * + * Since: 1.2 + **/ + obj_properties[PROP_WAKE_ON_LAN_PASSWORD] = + g_param_spec_string(NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_WIRED, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-wireguard.c b/src/libnm-core-impl/nm-setting-wireguard.c new file mode 100644 index 0000000000..ea723a5b2e --- /dev/null +++ b/src/libnm-core-impl/nm-setting-wireguard.c @@ -0,0 +1,2591 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 - 2019 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-wireguard.h" + +#include "nm-setting-private.h" +#include "nm-utils-private.h" +#include "nm-connection-private.h" +#include "nm-glib-aux/nm-secret-utils.h" + +/*****************************************************************************/ + +/** + * SECTION:nm-setting-wireguard + * @short_description: Describes connection properties for wireguard related options + * + * The #NMSettingWireGuard object is a #NMSetting subclass that contains settings + * for configuring WireGuard. + **/ + +/*****************************************************************************/ + +static NMWireGuardPeer *_wireguard_peer_dup(const NMWireGuardPeer *self); + +G_DEFINE_BOXED_TYPE(NMWireGuardPeer, + nm_wireguard_peer, + _wireguard_peer_dup, + nm_wireguard_peer_unref) + +/* NMWireGuardPeer can also track invalid allowed-ip settings, and only reject + * them later during is_valid(). Such values are marked by a leading 'X' character + * in the @allowed_ips. It is expected, that such values are the exception, and + * commonly not present. */ +#define ALLOWED_IP_INVALID_X 'X' +#define ALLOWED_IP_INVALID_X_STR "X" + +/** + * NMWireGuardPeer: + * + * The settings of one WireGuard peer. + * + * Since: 1.16 + */ +struct _NMWireGuardPeer { + NMSockAddrEndpoint * endpoint; + char * public_key; + char * preshared_key; + GPtrArray * allowed_ips; + guint refcount; + NMSettingSecretFlags preshared_key_flags; + guint16 persistent_keepalive; + bool public_key_valid : 1; + bool preshared_key_valid : 1; + bool sealed : 1; +}; + +static gboolean +NM_IS_WIREGUARD_PEER(const NMWireGuardPeer *self, gboolean also_sealed) +{ + return self && self->refcount > 0 && (also_sealed || !self->sealed); +} + +/** + * nm_wireguard_peer_new: + * + * Returns: (transfer full): a new, default, unsealed #NMWireGuardPeer instance. + * + * Since: 1.16 + */ +NMWireGuardPeer * +nm_wireguard_peer_new(void) +{ + NMWireGuardPeer *self; + + self = g_slice_new(NMWireGuardPeer); + *self = (NMWireGuardPeer){ + .refcount = 1, + .preshared_key_flags = NM_SETTING_SECRET_FLAG_NOT_REQUIRED, + }; + return self; +} + +/** + * nm_wireguard_peer_new_clone: + * @self: the #NMWireGuardPeer instance to copy. + * @with_secrets: if %TRUE, the preshared-key secrets are copied + * as well. Otherwise, they will be removed. + * + * Returns: (transfer full): a clone of @self. This instance + * is always unsealed. + * + * Since: 1.16 + */ +NMWireGuardPeer * +nm_wireguard_peer_new_clone(const NMWireGuardPeer *self, gboolean with_secrets) +{ + NMWireGuardPeer *new; + guint i; + + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); + + new = g_slice_new(NMWireGuardPeer); + *new = (NMWireGuardPeer){ + .refcount = 1, + .public_key = g_strdup(self->public_key), + .public_key_valid = self->public_key_valid, + .preshared_key = with_secrets ? g_strdup(self->preshared_key) : NULL, + .preshared_key_valid = self->preshared_key_valid, + .preshared_key_flags = self->preshared_key_flags, + .endpoint = nm_sock_addr_endpoint_ref(self->endpoint), + .persistent_keepalive = self->persistent_keepalive, + }; + if (self->allowed_ips && self->allowed_ips->len > 0) { + new->allowed_ips = g_ptr_array_new_full(self->allowed_ips->len, g_free); + for (i = 0; i < self->allowed_ips->len; i++) { + g_ptr_array_add(new->allowed_ips, g_strdup(self->allowed_ips->pdata[i])); + } + } + return new; +} + +/** + * nm_wireguard_peer_ref: + * @self: (allow-none): the #NMWireGuardPeer instance + * + * This is not thread-safe. + * + * Returns: returns the input argument @self after incrementing + * the reference count. + * + * Since: 1.16 + */ +NMWireGuardPeer * +nm_wireguard_peer_ref(NMWireGuardPeer *self) +{ + if (!self) + return NULL; + + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); + + nm_assert(self->refcount < G_MAXUINT); + + self->refcount++; + return self; +} + +/** + * nm_wireguard_peer_unref: + * @self: (allow-none): the #NMWireGuardPeer instance + * + * Drop a reference to @self. If the last reference is dropped, + * the instance is freed and all associate data released. + * + * This is not thread-safe. + * + * Since: 1.16 + */ +void +nm_wireguard_peer_unref(NMWireGuardPeer *self) +{ + if (!self) + return; + + g_return_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE)); + + if (--self->refcount > 0) + return; + + nm_sock_addr_endpoint_unref(self->endpoint); + if (self->allowed_ips) + g_ptr_array_unref(self->allowed_ips); + g_free(self->public_key); + nm_free_secret(self->preshared_key); + g_slice_free(NMWireGuardPeer, self); +} + +/** + * _wireguard_peer_dup: + * @self: the #NMWireGuardPeer instance + * + * Duplicates the #NMWireGuardPeer instance. Note that if @self + * is already sealed, this increments the reference count and + * returns it. If the instance is still unsealed, it is copied. + * + * Returns: (transfer full): a duplicate of @self, or (if the + * instance is sealed and thus immutable) a reference to @self. + * As such, the instance will be sealed if and only if @self is + * sealed. + */ +static NMWireGuardPeer * +_wireguard_peer_dup(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); + + if (self->sealed) + return nm_wireguard_peer_ref((NMWireGuardPeer *) self); + return nm_wireguard_peer_new_clone(self, TRUE); +} + +/** + * nm_wireguard_peer_seal: + * @self: the #NMWireGuardPeer instance + * + * Seal the #NMWireGuardPeer instance. Afterwards, it is a bug + * to call all functions that modify the instance (except ref/unref). + * A sealed instance cannot be unsealed again, but you can create + * an unsealed copy with nm_wireguard_peer_new_clone(). + * + * Since: 1.16 + */ +void +nm_wireguard_peer_seal(NMWireGuardPeer *self) +{ + g_return_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE)); + + self->sealed = TRUE; + + if (self->allowed_ips) { + if (self->allowed_ips->len == 0) + nm_clear_pointer(&self->allowed_ips, g_ptr_array_unref); + } +} + +/** + * nm_wireguard_peer_is_sealed: + * @self: the #NMWireGuardPeer instance + * + * Returns: whether @self is sealed or not. + * + * Since: 1.16 + */ +gboolean +nm_wireguard_peer_is_sealed(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), FALSE); + + return self->sealed; +} + +/** + * nm_wireguard_peer_get_public_key: + * @self: the #NMWireGuardPeer instance + * + * Returns: (transfer none): the public key or %NULL if unset. + * + * Since: 1.16 + */ +const char * +nm_wireguard_peer_get_public_key(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); + + return self->public_key; +} + +/** + * nm_wireguard_peer_set_public_key: + * @self: the unsealed #NMWireGuardPeer instance + * @public_key: (allow-none) (transfer none): the new public + * key or %NULL to clear the public key. + * @accept_invalid: if %TRUE and @public_key is not %NULL and + * invalid, then do not modify the instance. + * + * Reset the public key. Note that if the public key is valid, it + * will be normalized (which may or may not modify the set value). + * + * It is a bug trying to modify a sealed #NMWireGuardPeer instance. + * + * Returns: %TRUE if the key was valid or %NULL. Returns + * %FALSE for invalid keys. Depending on @accept_invalid + * will an invalid key be set or not. + * + * Since: 1.16 + */ +gboolean +nm_wireguard_peer_set_public_key(NMWireGuardPeer *self, + const char * public_key, + gboolean accept_invalid) +{ + char * public_key_normalized = NULL; + gboolean is_valid; + + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); + + if (!public_key) { + nm_clear_g_free(&self->public_key); + return TRUE; + } + + is_valid = nm_utils_base64secret_normalize(public_key, + NM_WIREGUARD_PUBLIC_KEY_LEN, + &public_key_normalized); + nm_assert(is_valid == (public_key_normalized != NULL)); + + if (!is_valid && !accept_invalid) + return FALSE; + + self->public_key_valid = is_valid; + g_free(self->public_key); + self->public_key = public_key_normalized ?: g_strdup(public_key); + return is_valid; +} + +void +_nm_wireguard_peer_set_public_key_bin(NMWireGuardPeer *self, + const guint8 public_key[static NM_WIREGUARD_PUBLIC_KEY_LEN]) +{ + g_return_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE)); + + nm_clear_g_free(&self->public_key); + + if (!public_key) + return; + + self->public_key = g_base64_encode(public_key, NM_WIREGUARD_PUBLIC_KEY_LEN); + self->public_key_valid = TRUE; +} + +/** + * nm_wireguard_peer_get_preshared_key: + * @self: the #NMWireGuardPeer instance + * + * Returns: (transfer none): the preshared key or %NULL if unset. + * + * Since: 1.16 + */ +const char * +nm_wireguard_peer_get_preshared_key(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); + + return self->preshared_key; +} + +/** + * nm_wireguard_peer_set_preshared_key: + * @self: the unsealed #NMWireGuardPeer instance + * @preshared_key: (allow-none) (transfer none): the new preshared + * key or %NULL to clear the preshared key. + * @accept_invalid: whether to allow setting the key to an invalid + * value. If %FALSE, @self is unchanged if the key is invalid + * and if %FALSE is returned. + * + * Reset the preshared key. Note that if the preshared key is valid, it + * will be normalized (which may or may not modify the set value). + * + * Note that the preshared-key is a secret and consequently has corresponding + * preshared-key-flags property. This is so that secrets can be optional + * and requested on demand from a secret-agent. Also, an invalid preshared-key + * may optionally cause nm_wireguard_peer_is_valid() to fail or it may + * be accepted. + * + * It is a bug trying to modify a sealed #NMWireGuardPeer instance. + * + * Returns: %TRUE if the preshared-key is valid, otherwise %FALSE. + * %NULL is considered a valid value. + * If the key is invalid, it depends on @accept_invalid whether the + * previous value was reset. + * + * Since: 1.16 + */ +gboolean +nm_wireguard_peer_set_preshared_key(NMWireGuardPeer *self, + const char * preshared_key, + gboolean accept_invalid) +{ + char * preshared_key_normalized = NULL; + gboolean is_valid; + + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); + + if (!preshared_key) { + nm_clear_pointer(&self->preshared_key, nm_free_secret); + return TRUE; + } + + is_valid = nm_utils_base64secret_normalize(preshared_key, + NM_WIREGUARD_SYMMETRIC_KEY_LEN, + &preshared_key_normalized); + nm_assert(is_valid == (preshared_key_normalized != NULL)); + + if (!is_valid && !accept_invalid) + return FALSE; + + self->preshared_key_valid = is_valid; + nm_free_secret(self->preshared_key); + self->preshared_key = preshared_key_normalized ?: g_strdup(preshared_key); + return is_valid; +} + +/** + * nm_wireguard_peer_get_preshared_key_flags: + * @self: the #NMWireGuardPeer instance + * + * Returns: get the secret flags for the preshared-key. + * + * Since: 1.16 + */ +NMSettingSecretFlags +nm_wireguard_peer_get_preshared_key_flags(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), 0); + + return self->preshared_key_flags; +} + +/** + * nm_wireguard_peer_set_preshared_key_flags: + * @self: the unsealed #NMWireGuardPeer instance + * @preshared_key_flags: the secret flags to set. + * + * It is a bug trying to modify a sealed #NMWireGuardPeer instance. + * + * Since: 1.16 + */ +void +nm_wireguard_peer_set_preshared_key_flags(NMWireGuardPeer * self, + NMSettingSecretFlags preshared_key_flags) +{ + g_return_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE)); + + self->preshared_key_flags = preshared_key_flags; +} + +/** + * nm_wireguard_peer_get_persistent_keepalive: + * @self: the #NMWireGuardPeer instance + * + * Returns: get the persistent-keepalive setting in seconds. Set to zero to disable + * keep-alive. + * + * Since: 1.16 + */ +guint16 +nm_wireguard_peer_get_persistent_keepalive(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), 0); + + return self->persistent_keepalive; +} + +/** + * nm_wireguard_peer_set_persistent_keepalive: + * @self: the unsealed #NMWireGuardPeer instance + * @persistent_keepalive: the keep-alive value to set. + * + * It is a bug trying to modify a sealed #NMWireGuardPeer instance. + * + * Since: 1.16 + */ +void +nm_wireguard_peer_set_persistent_keepalive(NMWireGuardPeer *self, guint16 persistent_keepalive) +{ + g_return_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE)); + + self->persistent_keepalive = persistent_keepalive; +} + +NMSockAddrEndpoint * +_nm_wireguard_peer_get_endpoint(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); + + return self->endpoint; +} + +/** + * nm_wireguard_peer_get_endpoint: + * @self: the #NMWireGuardPeer instance + * + * Returns: (transfer none): the endpoint or %NULL if none was set. + * + * Since: 1.16 + */ +const char * +nm_wireguard_peer_get_endpoint(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); + + return self->endpoint ? nm_sock_addr_endpoint_get_endpoint(self->endpoint) : NULL; +} + +void +_nm_wireguard_peer_set_endpoint(NMWireGuardPeer *self, NMSockAddrEndpoint *endpoint) +{ + NMSockAddrEndpoint *old; + + nm_assert(NM_IS_WIREGUARD_PEER(self, FALSE)); + + old = self->endpoint; + self->endpoint = nm_sock_addr_endpoint_ref(endpoint); + nm_sock_addr_endpoint_unref(old); +} + +/** + * nm_wireguard_peer_set_endpoint: + * @self: the unsealed #NMWireGuardPeer instance + * @endpoint: the socket address endpoint to set or %NULL. + * @allow_invalid: if %TRUE, also invalid values are set. + * If %FALSE, the function does nothing for invalid @endpoint + * arguments. + * + * Sets or clears the endpoint of @self. + * + * It is a bug trying to modify a sealed #NMWireGuardPeer instance. + * + * Returns: %TRUE if the endpoint is %NULL or valid. For an + * invalid @endpoint argument, %FALSE is returned. Depending + * on @allow_invalid, the instance will be modified. + * + * Since: 1.16 + */ +gboolean +nm_wireguard_peer_set_endpoint(NMWireGuardPeer *self, const char *endpoint, gboolean allow_invalid) +{ + NMSockAddrEndpoint *old; + NMSockAddrEndpoint *new; + gboolean is_valid; + + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); + + if (!endpoint) { + nm_clear_pointer(&self->endpoint, nm_sock_addr_endpoint_unref); + return TRUE; + } + + new = nm_sock_addr_endpoint_new(endpoint); + + is_valid = (nm_sock_addr_endpoint_get_host(new) != NULL); + + if (!allow_invalid && !is_valid) { + nm_sock_addr_endpoint_unref(new); + return FALSE; + } + + old = self->endpoint; + self->endpoint = new; + nm_sock_addr_endpoint_unref(old); + return is_valid; +} + +/** + * nm_wireguard_peer_get_allowed_ips_len: + * @self: the #NMWireGuardPeer instance + * + * Returns: the number of allowed-ips entries. + * + * Since: 1.16 + */ +guint +nm_wireguard_peer_get_allowed_ips_len(const NMWireGuardPeer *self) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), 0); + + return self->allowed_ips ? self->allowed_ips->len : 0u; +} + +/** + * nm_wireguard_peer_get_allowed_ip: + * @self: the #NMWireGuardPeer instance + * @idx: the index from zero to (allowed-ips-len - 1) to + * retrieve. + * @out_is_valid: (allow-none): %TRUE if the returned value is a valid allowed-ip + * setting. + * + * Returns: (transfer none): the allowed-ip setting at index @idx. + * If @idx is out of range, %NULL will be returned. + * + * Since: 1.16 + */ +const char * +nm_wireguard_peer_get_allowed_ip(const NMWireGuardPeer *self, guint idx, gboolean *out_is_valid) +{ + const char *s; + + /* With LTO, the compiler might warn about the g_return_val_if_fail() + * code path not initializing the output argument. Workaround that by + * always setting the out argument. */ + NM_SET_OUT(out_is_valid, FALSE); + + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); + + if (!self->allowed_ips || idx >= self->allowed_ips->len) + return NULL; + + s = self->allowed_ips->pdata[idx]; + NM_SET_OUT(out_is_valid, s[0] != ALLOWED_IP_INVALID_X); + return s[0] == ALLOWED_IP_INVALID_X ? &s[1] : s; +} + +/** + * nm_wireguard_peer_clear_allowed_ips: + * @self: the unsealed #NMWireGuardPeer instance + * + * Removes all allowed-ip entries. + * + * It is a bug trying to modify a sealed #NMWireGuardPeer instance. + * + * Since: 1.16 + */ +void +nm_wireguard_peer_clear_allowed_ips(NMWireGuardPeer *self) +{ + g_return_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE)); + + if (self->allowed_ips) + g_ptr_array_set_size(self->allowed_ips, 0); +} + +static gboolean +_peer_append_allowed_ip(NMWireGuardPeer *self, const char *allowed_ip, gboolean accept_invalid) +{ + int addr_family; + int prefix; + NMIPAddr addrbin; + char * str; + gboolean is_valid = TRUE; + + nm_assert(NM_IS_WIREGUARD_PEER(self, FALSE)); + nm_assert(allowed_ip); + + /* normalize the address (if it is valid. Otherwise, take it + * as-is (it will render the instance invalid). */ + if (!nm_utils_parse_inaddr_prefix_bin(AF_UNSPEC, allowed_ip, &addr_family, &addrbin, &prefix)) { + if (!accept_invalid) + return FALSE; + /* mark the entry as invalid by having a "X" prefix. */ + str = g_strconcat(ALLOWED_IP_INVALID_X_STR, allowed_ip, NULL); + is_valid = FALSE; + } else { + char addrstr[NM_UTILS_INET_ADDRSTRLEN]; + + nm_assert_addr_family(addr_family); + + nm_utils_inet_ntop(addr_family, &addrbin, addrstr); + if (prefix >= 0) + str = g_strdup_printf("%s/%d", addrstr, prefix); + else + str = g_strdup(addrstr); + nm_assert(str[0] != ALLOWED_IP_INVALID_X); + } + + if (!self->allowed_ips) + self->allowed_ips = g_ptr_array_new_with_free_func(g_free); + + g_ptr_array_add(self->allowed_ips, str); + return is_valid; +} + +/** + * nm_wireguard_peer_append_allowed_ip: + * @self: the unsealed #NMWireGuardPeer instance + * @allowed_ip: the allowed-ip entry to set. + * @accept_invalid: if %TRUE, also invalid @allowed_ip value + * will be appended. Otherwise, the function does nothing + * in face of invalid values and returns %FALSE. + * + * Appends @allowed_ip setting to the list. This does not check + * for duplicates and always appends @allowed_ip to the end of the + * list. If @allowed_ip is valid, it will be normalized and a modified + * for might be appended. If @allowed_ip is invalid, it will still be + * appended, but later verification will fail. + * + * It is a bug trying to modify a sealed #NMWireGuardPeer instance. + * + * Returns: %TRUE if the value is a valid allowed-ips value, %FALSE otherwise. + * Depending on @accept_invalid, also invalid values are added. + * + * Since: 1.16 + */ +gboolean +nm_wireguard_peer_append_allowed_ip(NMWireGuardPeer *self, + const char * allowed_ip, + gboolean accept_invalid) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); + g_return_val_if_fail(allowed_ip, FALSE); + + return _peer_append_allowed_ip(self, allowed_ip, accept_invalid); +} + +/** + * nm_wireguard_peer_remove_allowed_ip: + * @self: the unsealed #NMWireGuardPeer instance + * @idx: the index from zero to (allowed-ips-len - 1) to + * retrieve. If the index is out of range, %FALSE is returned + * and nothing is done. + * + * Removes the allowed-ip at the given @idx. This shifts all + * following entries one index down. + * + * It is a bug trying to modify a sealed #NMWireGuardPeer instance. + * + * Returns: %TRUE if @idx was valid and the allowed-ip was removed. + * %FALSE otherwise, and the peer will not be changed. + * + * Since: 1.16 + */ +gboolean +nm_wireguard_peer_remove_allowed_ip(NMWireGuardPeer *self, guint idx) +{ + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, FALSE), FALSE); + + if (!self->allowed_ips || idx >= self->allowed_ips->len) + return FALSE; + + g_ptr_array_remove_index(self->allowed_ips, idx); + return TRUE; +} + +/** + * nm_wireguard_peer_is_valid: + * @self: the #NMWireGuardPeer instance + * @check_secrets: if %TRUE, non-secret properties are validated. + * Otherwise, they are ignored for this purpose. + * @check_non_secrets: if %TRUE, secret properties are validated. + * Otherwise, they are ignored for this purpose. + * @error: the #GError location for returning the failure reason. + * + * Returns: %TRUE if the peer is valid or fails with an error + * reason. + * + * Since: 1.16 + */ +gboolean +nm_wireguard_peer_is_valid(const NMWireGuardPeer *self, + gboolean check_non_secrets, + gboolean check_secrets, + GError ** error) +{ + guint i; + + g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + + if (check_non_secrets) { + if (!self->public_key) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("missing public-key for peer")); + return FALSE; + } else if (!self->public_key_valid) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid public-key for peer")); + return FALSE; + } + } + + if (check_secrets) { + if (self->preshared_key && !self->preshared_key_valid) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid preshared-key for peer")); + return FALSE; + } + } + + if (check_non_secrets) { + if (!_nm_utils_secret_flags_validate(self->preshared_key_flags, + NULL, + NULL, + NM_SETTING_SECRET_FLAG_NONE, + error)) + return FALSE; + } + + if (check_non_secrets) { + if (self->endpoint && !nm_sock_addr_endpoint_get_host(self->endpoint)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid endpoint for peer")); + return FALSE; + } + + if (self->allowed_ips) { + for (i = 0; i < self->allowed_ips->len; i++) { + const char *s = self->allowed_ips->pdata[i]; + + if (s[0] == ALLOWED_IP_INVALID_X) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid IP address \"%s\" for allowed-ip of peer"), + &s[1]); + return FALSE; + } + } + } + + if (!_nm_setting_secret_flags_valid(self->preshared_key_flags)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid preshared-key-flags for peer")); + return FALSE; + } + } + + return TRUE; +} + +/** + * nm_wireguard_peer_cmp: + * @a: (allow-none): the #NMWireGuardPeer to compare. + * @b: (allow-none): the other #NMWireGuardPeer to compare. + * @compare_flags: #NMSettingCompareFlags to affect the comparison. + * + * Returns: zero of the two instances are equivalent or + * a non-zero integer otherwise. This defines a total ordering + * over the peers. Whether a peer is sealed or not, does not + * affect the comparison. + * + * Since: 1.16 + */ +int +nm_wireguard_peer_cmp(const NMWireGuardPeer *a, + const NMWireGuardPeer *b, + NMSettingCompareFlags compare_flags) +{ + guint i, n; + + NM_CMP_SELF(a, b); + + /* regardless of the @compare_flags, the public-key is the ID of the peer. It must + * always be compared. */ + NM_CMP_FIELD_BOOL(a, b, public_key_valid); + NM_CMP_FIELD_STR0(a, b, public_key); + + if (NM_FLAGS_ANY(compare_flags, + NM_SETTING_COMPARE_FLAG_INFERRABLE | NM_SETTING_COMPARE_FLAG_FUZZY)) + return 0; + + NM_CMP_FIELD_BOOL(a, b, endpoint); + if (a->endpoint) { + NM_CMP_DIRECT_STRCMP0(nm_sock_addr_endpoint_get_endpoint(a->endpoint), + nm_sock_addr_endpoint_get_endpoint(b->endpoint)); + } + + NM_CMP_FIELD(a, b, persistent_keepalive); + + NM_CMP_DIRECT((n = (a->allowed_ips ? a->allowed_ips->len : 0u)), + (b->allowed_ips ? b->allowed_ips->len : 0u)); + for (i = 0; i < n; i++) + NM_CMP_DIRECT_STRCMP0(a->allowed_ips->pdata[i], b->allowed_ips->pdata[i]); + + NM_CMP_FIELD(a, b, preshared_key_flags); + + if (!NM_FLAGS_HAS(compare_flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)) { + if (NM_FLAGS_HAS(compare_flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) + && NM_FLAGS_HAS(a->preshared_key_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) { + /* pass */ + } else if (NM_FLAGS_HAS(compare_flags, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) + && NM_FLAGS_HAS(a->preshared_key_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)) { + /* pass */ + } else { + NM_CMP_FIELD_BOOL(a, b, preshared_key_valid); + NM_CMP_FIELD_STR0(a, b, preshared_key); + } + } + + return 0; +} + +/*****************************************************************************/ + +typedef struct { + const char * public_key; + NMWireGuardPeer *peer; + guint idx; +} PeerData; + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_FWMARK, + PROP_IP4_AUTO_DEFAULT_ROUTE, + PROP_IP6_AUTO_DEFAULT_ROUTE, + PROP_LISTEN_PORT, + PROP_MTU, + PROP_PEER_ROUTES, + PROP_PRIVATE_KEY, + PROP_PRIVATE_KEY_FLAGS, ); + +typedef struct { + char * private_key; + GPtrArray * peers_arr; + GHashTable * peers_hash; + NMSettingSecretFlags private_key_flags; + NMTernary ip4_auto_default_route; + NMTernary ip6_auto_default_route; + guint32 fwmark; + guint32 mtu; + guint16 listen_port; + bool private_key_valid : 1; + bool peer_routes : 1; +} NMSettingWireGuardPrivate; + +/** + * NMSettingWireGuard: + * + * WireGuard Settings + * + * Since: 1.16 + */ +struct _NMSettingWireGuard { + NMSetting parent; + NMSettingWireGuardPrivate _priv; +}; + +struct _NMSettingWireGuardClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingWireGuard, nm_setting_wireguard, NM_TYPE_SETTING) + +#define NM_SETTING_WIREGUARD_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingWireGuard, NM_IS_SETTING_WIREGUARD, NMSetting) + +/*****************************************************************************/ + +#define peers_psk_get_secret_name_a(public_key, to_free) \ + nm_construct_name_a(NM_SETTING_WIREGUARD_PEERS ".%s." NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, \ + (public_key), \ + (to_free)) + +#define peers_psk_get_secret_name_dup(public_key) \ + g_strdup_printf(NM_SETTING_WIREGUARD_PEERS ".%s." NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, \ + (public_key)) + +#define peers_psk_get_secret_parse_a(secret_public_key, public_key_free) \ + ({ \ + const char *_secret_public_key = (secret_public_key); \ + char ** _public_key_free = (public_key_free); \ + const char *_public_key = NULL; \ + \ + nm_assert(_public_key_free && !*_public_key_free); \ + \ + if (NM_STR_HAS_PREFIX(_secret_public_key, NM_SETTING_WIREGUARD_PEERS ".")) { \ + _secret_public_key += NM_STRLEN(NM_SETTING_WIREGUARD_PEERS "."); \ + if (NM_STR_HAS_SUFFIX(_secret_public_key, "." NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)) { \ + _public_key = \ + nm_strndup_a(300, \ + _secret_public_key, \ + strlen(_secret_public_key) \ + - NM_STRLEN("." NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY), \ + _public_key_free); \ + } \ + } \ + \ + _public_key; \ + }) + +/*****************************************************************************/ + +/** + * nm_setting_wireguard_get_private_key: + * @self: the #NMSettingWireGuard instance + * + * Returns: (transfer none): the set private-key or %NULL. + * + * Since: 1.16 + */ +const char * +nm_setting_wireguard_get_private_key(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NULL); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->private_key; +} + +/** + * nm_setting_wireguard_get_private_key_flags: + * @self: the #NMSettingWireGuard instance + * + * Returns: the secret-flags for #NMSettingWireGuard:private-key. + * + * Since: 1.16 + */ +NMSettingSecretFlags +nm_setting_wireguard_get_private_key_flags(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->private_key_flags; +} + +/** + * nm_setting_wireguard_get_fwmark: + * @self: the #NMSettingWireGuard instance + * + * Returns: the set firewall mark. + * + * Since: 1.16 + */ +guint32 +nm_setting_wireguard_get_fwmark(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->fwmark; +} + +/** + * nm_setting_wireguard_get_listen_port: + * @self: the #NMSettingWireGuard instance + * + * Returns: the set UDP listen port. + * + * Since: 1.16 + */ +guint16 +nm_setting_wireguard_get_listen_port(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->listen_port; +} + +/** + * nm_setting_wireguard_get_peer_routes: + * @self: the #NMSettingWireGuard instance + * + * Returns: whether automatically add peer routes. + * + * Since: 1.16 + */ +gboolean +nm_setting_wireguard_get_peer_routes(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), TRUE); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->peer_routes; +} + +/** + * nm_setting_wireguard_get_mtu: + * @self: the #NMSettingWireGuard instance + * + * Returns: the MTU of the setting. + * + * Since: 1.16 + */ +guint32 +nm_setting_wireguard_get_mtu(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->mtu; +} + +/** + * nm_setting_wireguard_get_ip4_auto_default_route: + * @self: the #NMSettingWireGuard setting. + * + * Returns: the "ip4-auto-default-route" property of the setting. + * + * Since: 1.20 + */ +NMTernary +nm_setting_wireguard_get_ip4_auto_default_route(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NM_TERNARY_DEFAULT); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->ip4_auto_default_route; +} + +/** + * nm_setting_wireguard_get_ip6_auto_default_route: + * @self: the #NMSettingWireGuard setting. + * + * Returns: the "ip6-auto-default-route" property of the setting. + * + * Since: 1.20 + */ +NMTernary +nm_setting_wireguard_get_ip6_auto_default_route(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NM_TERNARY_DEFAULT); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->ip6_auto_default_route; +} + +/*****************************************************************************/ + +static void +_peer_free(PeerData *pd) +{ + nm_assert(pd); + + nm_wireguard_peer_unref(pd->peer); + g_slice_free(PeerData, pd); +} + +/*****************************************************************************/ + +static void +_peers_notify(gpointer self) +{ + _nm_setting_emit_property_changed(self); +} + +static PeerData * +_peers_get(NMSettingWireGuardPrivate *priv, guint idx) +{ + PeerData *pd; + + nm_assert(priv); + nm_assert(idx < priv->peers_arr->len); + + pd = priv->peers_arr->pdata[idx]; + + nm_assert(pd); + nm_assert(pd->idx == idx); + nm_assert(NM_IS_WIREGUARD_PEER(pd->peer, TRUE)); + nm_assert(nm_wireguard_peer_is_sealed(pd->peer)); + nm_assert(pd->public_key == nm_wireguard_peer_get_public_key(pd->peer)); + nm_assert(g_hash_table_lookup(priv->peers_hash, pd) == pd); + + return pd; +} + +static PeerData * +_peers_get_by_public_key(NMSettingWireGuardPrivate *priv, + const char * public_key, + gboolean try_with_normalized_key) +{ + gs_free char *public_key_normalized = NULL; + PeerData * pd; + +again: + nm_assert(priv); + nm_assert(public_key); + + pd = g_hash_table_lookup(priv->peers_hash, &public_key); + if (pd) { + nm_assert(_peers_get(priv, pd->idx) == pd); + return pd; + } + if (try_with_normalized_key + && nm_utils_base64secret_normalize(public_key, + NM_WIREGUARD_PUBLIC_KEY_LEN, + &public_key_normalized)) { + public_key = public_key_normalized; + try_with_normalized_key = FALSE; + goto again; + } + return NULL; +} + +static void +_peers_remove(NMSettingWireGuardPrivate *priv, PeerData *pd, gboolean do_free) +{ + guint i; + + nm_assert(pd); + nm_assert(_peers_get(priv, pd->idx) == pd); + + for (i = pd->idx + 1; i < priv->peers_arr->len; i++) + _peers_get(priv, i)->idx--; + + g_ptr_array_remove_index(priv->peers_arr, pd->idx); + if (!g_hash_table_remove(priv->peers_hash, pd)) + nm_assert_not_reached(); + if (do_free) + _peer_free(pd); +} + +/** + * nm_setting_wireguard_get_peers_len: + * @self: the #NMSettingWireGuard instance + * + * Returns: the number of registered peers. + * + * Since: 1.16 + */ +guint +nm_setting_wireguard_get_peers_len(NMSettingWireGuard *self) +{ + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); + + return NM_SETTING_WIREGUARD_GET_PRIVATE(self)->peers_arr->len; +} + +/** + * nm_setting_wireguard_get_peer: + * @self: the #NMSettingWireGuard instance + * @idx: the index to lookup. + * + * Returns: (transfer none): the #NMWireGuardPeer entry at + * index @idx. If the index is out of range, %NULL is returned. + * + * Since: 1.16 + */ +NMWireGuardPeer * +nm_setting_wireguard_get_peer(NMSettingWireGuard *self, guint idx) +{ + NMSettingWireGuardPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NULL); + + priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); + + if (idx >= priv->peers_arr->len) + return NULL; + + return _peers_get(priv, idx)->peer; +} + +/** + * nm_setting_wireguard_get_peer_by_public_key: + * @self: the #NMSettingWireGuard instance + * @public_key: the public key for looking up the + * peer. + * @out_idx: (out) (allow-none): optional output argument + * for the index of the found peer. If no index is found, + * this is set to the nm_setting_wireguard_get_peers_len(). + * + * Returns: (transfer none): the #NMWireGuardPeer instance with a + * matching public key. If no such peer exists, %NULL is returned. + * + * Since: 1.16 + */ +NMWireGuardPeer * +nm_setting_wireguard_get_peer_by_public_key(NMSettingWireGuard *self, + const char * public_key, + guint * out_idx) +{ + NMSettingWireGuardPrivate *priv; + PeerData * pd; + + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), NULL); + g_return_val_if_fail(public_key, NULL); + + priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); + + pd = _peers_get_by_public_key(priv, public_key, TRUE); + if (!pd) { + NM_SET_OUT(out_idx, priv->peers_arr->len); + return NULL; + } + NM_SET_OUT(out_idx, pd->idx); + return pd->peer; +} + +static gboolean +_peers_set(NMSettingWireGuardPrivate *priv, + NMWireGuardPeer * peer, + guint idx, + gboolean check_same_key) +{ + PeerData * pd_same_key = NULL; + PeerData * pd_idx = NULL; + const char *public_key; + + nm_assert(idx <= priv->peers_arr->len); + + public_key = nm_wireguard_peer_get_public_key(peer); + + if (idx < priv->peers_arr->len) { + pd_idx = _peers_get(priv, idx); + + if (pd_idx->peer == peer) + return FALSE; + + if (check_same_key && nm_streq(public_key, nm_wireguard_peer_get_public_key(pd_idx->peer))) + check_same_key = FALSE; + } + + nm_wireguard_peer_seal(peer); + nm_wireguard_peer_ref(peer); + + if (check_same_key) { + pd_same_key = _peers_get_by_public_key(priv, public_key, FALSE); + if (pd_same_key) { + if (pd_idx) { + nm_assert(pd_same_key != pd_idx); + _peers_remove(priv, pd_same_key, TRUE); + pd_same_key = NULL; + } else { + if (pd_same_key->peer == peer && pd_same_key->idx == priv->peers_arr->len - 1) { + nm_wireguard_peer_unref(peer); + return FALSE; + } + _peers_remove(priv, pd_same_key, FALSE); + nm_wireguard_peer_unref(pd_same_key->peer); + } + } + } else + nm_assert(_peers_get_by_public_key(priv, public_key, FALSE) == pd_idx); + + if (pd_idx) { + g_hash_table_remove(priv->peers_hash, pd_idx); + nm_wireguard_peer_unref(pd_idx->peer); + pd_idx->public_key = public_key; + pd_idx->peer = peer; + g_hash_table_add(priv->peers_hash, pd_idx); + return TRUE; + } + + if (!pd_same_key) + pd_same_key = g_slice_new(PeerData); + + *pd_same_key = (PeerData){ + .peer = peer, + .public_key = public_key, + .idx = priv->peers_arr->len, + }; + + g_ptr_array_add(priv->peers_arr, pd_same_key); + if (!nm_g_hash_table_add(priv->peers_hash, pd_same_key)) + nm_assert_not_reached(); + + nm_assert(_peers_get(priv, pd_same_key->idx) == pd_same_key); + + return TRUE; +} + +static gboolean +_peers_append(NMSettingWireGuardPrivate *priv, NMWireGuardPeer *peer, gboolean check_same_key) +{ + return _peers_set(priv, peer, priv->peers_arr->len, check_same_key); +} + +/** + * nm_setting_wireguard_set_peer: + * @self: the #NMSettingWireGuard instance + * @peer: the #NMWireGuardPeer instance to set. + * This seals @peer and keeps a reference on the + * instance. + * @idx: the index, in the range of 0 to the number of + * peers (including). That means, if @idx is one past + * the end of the number of peers, this is the same as + * nm_setting_wireguard_append_peer(). Otherwise, the + * peer at this index is replaced. + * + * If @idx is one past the last peer, the behavior is the same + * as nm_setting_wireguard_append_peer(). + * Otherwise, the peer will be at @idx and replace the peer + * instance at that index. Note that if a peer with the same + * public-key exists on another index, then that peer will also + * be replaced. In that case, the number of peers will shrink + * by one (because the one at @idx got replace and then one + * with the same public-key got removed). This also means, + * that the resulting index afterwards may be one less than + * @idx (if another peer with a lower index was dropped). + * + * Since: 1.16 + */ +void +nm_setting_wireguard_set_peer(NMSettingWireGuard *self, NMWireGuardPeer *peer, guint idx) +{ + NMSettingWireGuardPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_WIREGUARD(self)); + g_return_if_fail(NM_IS_WIREGUARD_PEER(peer, TRUE)); + + priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); + + g_return_if_fail(idx <= priv->peers_arr->len); + + if (_peers_set(priv, peer, idx, TRUE)) + _peers_notify(self); +} + +/** + * nm_setting_wireguard_append_peer: + * @self: the #NMSettingWireGuard instance + * @peer: the #NMWireGuardPeer instance to append. + * This seals @peer and keeps a reference on the + * instance. + * + * If a peer with the same public-key already exists, that + * one is replaced by @peer. The new @peer is always appended + * (or moved to) the end, so in case a peer is replaced, the + * indexes are shifted and the number of peers stays unchanged. + * + * Since: 1.16 + */ +void +nm_setting_wireguard_append_peer(NMSettingWireGuard *self, NMWireGuardPeer *peer) +{ + g_return_if_fail(NM_IS_SETTING_WIREGUARD(self)); + g_return_if_fail(NM_IS_WIREGUARD_PEER(peer, TRUE)); + + if (_peers_append(NM_SETTING_WIREGUARD_GET_PRIVATE(self), peer, TRUE)) + _peers_notify(self); +} + +/** + * nm_setting_wireguard_remove_peer + * @self: the #NMSettingWireGuard instance + * @idx: the index to remove. + * + * Returns: %TRUE if @idx was in range and a peer + * was removed. Otherwise, @self is unchanged. + * + * Since: 1.16 + */ +gboolean +nm_setting_wireguard_remove_peer(NMSettingWireGuard *self, guint idx) +{ + NMSettingWireGuardPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), FALSE); + + priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); + + if (idx >= priv->peers_arr->len) + return FALSE; + + _peers_remove(priv, _peers_get(priv, idx), TRUE); + _peers_notify(self); + return TRUE; +} + +static guint +_peers_clear(NMSettingWireGuardPrivate *priv) +{ + guint l; + + l = priv->peers_arr->len; + while (priv->peers_arr->len > 0) { + _peers_remove(priv, _peers_get(priv, priv->peers_arr->len - 1), TRUE); + } + return l; +} + +/** + * nm_setting_wireguard_: + * @self: the #NMSettingWireGuard instance + * + * Returns: the number of cleared peers. + * + * Since: 1.16 + */ +guint +nm_setting_wireguard_clear_peers(NMSettingWireGuard *self) +{ + guint l; + + g_return_val_if_fail(NM_IS_SETTING_WIREGUARD(self), 0); + + l = _peers_clear(NM_SETTING_WIREGUARD_GET_PRIVATE(self)); + if (l > 0) + _peers_notify(self); + return l; +} + +/*****************************************************************************/ + +static GVariant * +_peers_dbus_only_synth(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + NMSettingWireGuard * self = NM_SETTING_WIREGUARD(setting); + NMSettingWireGuardPrivate *priv; + gboolean any_peers = FALSE; + GVariantBuilder peers_builder; + guint i_peer, n_peers; + guint i; + + n_peers = nm_setting_wireguard_get_peers_len(self); + if (n_peers == 0) + return NULL; + + priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); + + for (i_peer = 0; i_peer < n_peers; i_peer++) { + const NMWireGuardPeer *peer = _peers_get(priv, i_peer)->peer; + GVariantBuilder builder; + + if (!peer->public_key) + continue; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add(&builder, + "{sv}", + NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY, + g_variant_new_string(peer->public_key)); + + if (!NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS) && peer->endpoint) + g_variant_builder_add( + &builder, + "{sv}", + NM_WIREGUARD_PEER_ATTR_ENDPOINT, + g_variant_new_string(nm_sock_addr_endpoint_get_endpoint(peer->endpoint))); + + if (_nm_connection_serialize_secrets(flags, peer->preshared_key_flags) + && peer->preshared_key) + g_variant_builder_add(&builder, + "{sv}", + NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, + g_variant_new_string(peer->preshared_key)); + + if (!NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + && peer->preshared_key_flags != NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + g_variant_builder_add(&builder, + "{sv}", + NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS, + g_variant_new_uint32(peer->preshared_key_flags)); + + if (!NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + && peer->persistent_keepalive != 0) + g_variant_builder_add(&builder, + "{sv}", + NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE, + g_variant_new_uint32(peer->persistent_keepalive)); + + if (!NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS) && peer->allowed_ips + && peer->allowed_ips->len > 0) { + const char *const * strv = (const char *const *) peer->allowed_ips->pdata; + gs_free const char **strv_fixed = NULL; + + for (i = 0; i < peer->allowed_ips->len; i++) { + if (strv[i][0] != ALLOWED_IP_INVALID_X) + continue; + if (!strv_fixed) { + strv_fixed = nm_memdup(strv, sizeof(strv[0]) * peer->allowed_ips->len); + strv = strv_fixed; + } + ((const char **) strv)[i]++; + } + g_variant_builder_add(&builder, + "{sv}", + NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS, + g_variant_new_strv(strv, peer->allowed_ips->len)); + } + + if (!any_peers) { + g_variant_builder_init(&peers_builder, G_VARIANT_TYPE("aa{sv}")); + any_peers = TRUE; + } + g_variant_builder_add(&peers_builder, "a{sv}", &builder); + } + + return any_peers ? g_variant_builder_end(&peers_builder) : NULL; +} + +static gboolean +_peers_dbus_only_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + GVariantIter iter_peers; + GVariant * peer_var; + guint i_peer; + gboolean success = FALSE; + gboolean peers_changed = FALSE; + + nm_assert(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}"))); + + g_variant_iter_init(&iter_peers, value); + + i_peer = 0; + while (g_variant_iter_next(&iter_peers, "@a{sv}", &peer_var)) { + _nm_unused gs_unref_variant GVariant *peer_var_unref = peer_var; + nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; + const char * cstr; + guint32 u32; + GVariant * var; + + i_peer++; + + if (!g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY, "&s", &cstr)) { + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("peer #%u has no public-key"), + i_peer); + goto out; + } + continue; + } + + peer = nm_wireguard_peer_new(); + if (!nm_wireguard_peer_set_public_key(peer, cstr, TRUE)) { + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("peer #%u has invalid public-key"), + i_peer); + goto out; + } + continue; + } + + if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_ENDPOINT, "&s", &cstr)) { + nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL; + + ep = nm_sock_addr_endpoint_new(cstr); + if (!nm_sock_addr_endpoint_get_host(ep)) { + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("peer #%u has invalid endpoint"), + i_peer); + goto out; + } + } else + _nm_wireguard_peer_set_endpoint(peer, ep); + } + + if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, "&s", &cstr)) + nm_wireguard_peer_set_preshared_key(peer, cstr, TRUE); + + if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS, "u", &u32)) + nm_wireguard_peer_set_preshared_key_flags(peer, u32); + + if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE, "u", &u32)) + nm_wireguard_peer_set_persistent_keepalive(peer, u32); + + if (g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS, "@as", &var)) { + _nm_unused gs_unref_variant GVariant *var_free = var; + gs_free const char ** allowed_ips = NULL; + gsize i, l; + + allowed_ips = g_variant_get_strv(var, &l); + if (allowed_ips) { + for (i = 0; i < l; i++) { + if (_peer_append_allowed_ip(peer, allowed_ips[i], FALSE)) + continue; + if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) + continue; + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("peer #%u has invalid allowed-ips setting"), + i_peer); + goto out; + } + } + } + + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + gs_free_error GError *local = NULL; + + if (!nm_wireguard_peer_is_valid(peer, TRUE, FALSE, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("peer #%u is invalid: %s"), + i_peer, + local->message); + goto out; + } + } + + /* we could easily reject duplicate peers (by public-key) or duplicate GVariant attributes. + * However, don't do that. In case of duplicate values, the latter peer overwrite the earlier + * and GVariant attributes are ignored by g_variant_lookup() above. */ + if (_peers_append(NM_SETTING_WIREGUARD_GET_PRIVATE(setting), peer, TRUE)) + peers_changed = TRUE; + } + + success = TRUE; + +out: + if (peers_changed) + _peers_notify(setting); + return success; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWireGuard * s_wg = NM_SETTING_WIREGUARD(setting); + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + guint i; + + if (!_nm_connection_verify_required_interface_name(connection, error)) + return FALSE; + + if (!_nm_utils_secret_flags_validate(nm_setting_wireguard_get_private_key_flags(s_wg), + NM_SETTING_WIREGUARD_SETTING_NAME, + NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, + NM_SETTING_SECRET_FLAG_NOT_REQUIRED, + error)) + return FALSE; + + for (i = 0; i < priv->peers_arr->len; i++) { + NMWireGuardPeer *peer = _peers_get(priv, i)->peer; + + if (!nm_wireguard_peer_is_valid(peer, TRUE, FALSE, error)) { + g_prefix_error(error, + "%s.%s[%u]: ", + NM_SETTING_WIREGUARD_SETTING_NAME, + NM_SETTING_WIREGUARD_PEERS, + i); + return FALSE; + } + } + + if (connection) { + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + const char * method; + + /* WireGuard is Layer 3 only. For the moment, we only support a restricted set of + * IP methods. We may relax that later, once we fix the implementations so they + * actually work. */ + + if ((s_ip4 = nm_connection_get_setting_ip4_config(connection)) + && (method = nm_setting_ip_config_get_method(s_ip4)) + && !NM_IN_STRSET(method, + NM_SETTING_IP4_CONFIG_METHOD_DISABLED, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("method \"%s\" is not supported for WireGuard"), + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_METHOD); + return FALSE; + } + + if ((s_ip6 = nm_connection_get_setting_ip6_config(connection)) + && (method = nm_setting_ip_config_get_method(s_ip6)) + && !NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("method \"%s\" is not supported for WireGuard"), + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_METHOD); + return FALSE; + } + } + + /* private-key is a secret, hence we cannot verify it like a regular property. */ + return TRUE; +} + +static gboolean +verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + guint i; + + if (priv->private_key && !priv->private_key_valid) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("key must be 32 bytes base64 encoded")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIREGUARD_SETTING_NAME, + NM_SETTING_WIREGUARD_PRIVATE_KEY); + return FALSE; + } + + for (i = 0; i < priv->peers_arr->len; i++) { + NMWireGuardPeer *peer = _peers_get(priv, i)->peer; + + if (!nm_wireguard_peer_is_valid(peer, FALSE, TRUE, error)) { + g_prefix_error(error, + "%s.%s[%u]: ", + NM_SETTING_WIREGUARD_SETTING_NAME, + NM_SETTING_WIREGUARD_PEERS, + i); + return FALSE; + } + } + + return TRUE; +} + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + GPtrArray * secrets = NULL; + guint i; + + if (!priv->private_key || !priv->private_key_valid) { + secrets = g_ptr_array_new_full(1, g_free); + g_ptr_array_add(secrets, g_strdup(NM_SETTING_WIREGUARD_PRIVATE_KEY)); + } + + for (i = 0; i < priv->peers_arr->len; i++) { + NMWireGuardPeer *peer = _peers_get(priv, i)->peer; + + if (NM_FLAGS_HAS(peer->preshared_key_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) + continue; + + if (peer->preshared_key_valid) + continue; + + if (!peer->public_key_valid) + continue; + + if (!secrets) + secrets = g_ptr_array_new_full(1, g_free); + g_ptr_array_add(secrets, peers_psk_get_secret_name_dup(peer->public_key)); + } + + return secrets; +} + +static gboolean +clear_secrets(const NMSettInfoSetting * sett_info, + guint property_idx, + NMSetting * setting, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data) +{ + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_WIREGUARD_PEERS)) { + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + gboolean peers_changed = FALSE; + guint i, j; + + j = 0; + for (i = 0; i < priv->peers_arr->len; i++) { + NMWireGuardPeer *peer = _peers_get(priv, i)->peer; + + if (!peer->preshared_key) + continue; + + if (func) { + gs_free char *name_free = NULL; + const char * name; + + /* only stack-allocate (alloca) a few times. */ + if (j++ < 5) + name = peers_psk_get_secret_name_a(peer->public_key, &name_free); + else { + name_free = peers_psk_get_secret_name_dup(peer->public_key); + name = name_free; + } + + if (!func(setting, name, peer->preshared_key_flags, user_data)) + continue; + } + + { + nm_auto_unref_wgpeer NMWireGuardPeer *peer2 = NULL; + + peer2 = nm_wireguard_peer_new_clone(peer, FALSE); + + if (_peers_set(priv, peer2, i, FALSE)) + peers_changed = TRUE; + } + } + + if (peers_changed) + _peers_notify(setting); + return peers_changed; + } + + return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) + ->clear_secrets(sett_info, property_idx, setting, func, user_data); +} + +static int +update_one_secret(NMSetting *setting, const char *key, GVariant *value, GError **error) +{ + NMSettingWireGuard * self = NM_SETTING_WIREGUARD(setting); + NMSettingWireGuardPrivate *priv; + gboolean has_changes = FALSE; + gboolean has_error = FALSE; + GVariantIter iter_peers; + GVariant * peer_var; + guint i_peer; + + if (!nm_streq(key, NM_SETTING_WIREGUARD_PEERS)) { + return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) + ->update_one_secret(setting, key, value, error); + } + + if (!g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}"))) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("invalid peer secrets")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIREGUARD_SETTING_NAME, + NM_SETTING_WIREGUARD_PEERS); + return NM_SETTING_UPDATE_SECRET_ERROR; + } + + priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); + + g_variant_iter_init(&iter_peers, value); + + i_peer = 0; + while (g_variant_iter_next(&iter_peers, "@a{sv}", &peer_var)) { + _nm_unused gs_unref_variant GVariant *peer_var_unref = peer_var; + nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; + PeerData * pd; + const char * cstr; + + i_peer++; + + if (!g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY, "&s", &cstr)) { + if (!has_error) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("peer #%u lacks public-key"), + i_peer - 1); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIREGUARD_SETTING_NAME, + NM_SETTING_WIREGUARD_PEERS); + has_error = TRUE; + } + continue; + } + + pd = _peers_get_by_public_key(priv, cstr, TRUE); + if (!pd) { + if (!has_error) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, + _("non-existing peer '%s'"), + cstr); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIREGUARD_SETTING_NAME, + NM_SETTING_WIREGUARD_PEERS); + has_error = TRUE; + } + continue; + } + + if (!g_variant_lookup(peer_var, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, "&s", &cstr)) { + /* no preshared-key. Ignore the rest. + * + * In particular, we don't reject all unknown fields. */ + continue; + } + + if (nm_streq0(cstr, nm_wireguard_peer_get_preshared_key(pd->peer))) + continue; + + peer = nm_wireguard_peer_new_clone(pd->peer, FALSE); + nm_wireguard_peer_set_preshared_key(peer, cstr, TRUE); + + if (!_peers_set(priv, peer, pd->idx, FALSE)) + nm_assert_not_reached(); + has_changes = TRUE; + } + + if (has_error) + return NM_SETTING_UPDATE_SECRET_ERROR; + if (has_changes) + return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; + return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMSettingWireGuardPrivate *a_priv; + NMSettingWireGuardPrivate *b_priv; + guint i; + + if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_WIREGUARD_PEERS)) { + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) + return NM_TERNARY_DEFAULT; + + if (!set_b) + return TRUE; + + a_priv = NM_SETTING_WIREGUARD_GET_PRIVATE(set_a); + b_priv = NM_SETTING_WIREGUARD_GET_PRIVATE(set_b); + + if (a_priv->peers_arr->len != b_priv->peers_arr->len) + return FALSE; + for (i = 0; i < a_priv->peers_arr->len; i++) { + NMWireGuardPeer *a_peer = _peers_get(a_priv, i)->peer; + NMWireGuardPeer *b_peer = _peers_get(b_priv, i)->peer; + + if (nm_wireguard_peer_cmp(a_peer, b_peer, flags) != 0) + return FALSE; + } + + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +static void +duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) +{ + NMSettingWireGuardPrivate *priv_src = NM_SETTING_WIREGUARD_GET_PRIVATE(src); + NMSettingWireGuardPrivate *priv_dst = NM_SETTING_WIREGUARD_GET_PRIVATE(dst); + guint i; + gboolean peers_changed = FALSE; + + NM_SETTING_CLASS(nm_setting_wireguard_parent_class) + ->duplicate_copy_properties(sett_info, src, dst); + + /* We don't bother comparing the existing peers with what we are about to set. + * Always reset all. */ + if (_peers_clear(priv_dst) > 0) + peers_changed = TRUE; + for (i = 0; i < priv_src->peers_arr->len; i++) { + if (_peers_append(priv_dst, _peers_get(priv_src, i)->peer, FALSE)) + peers_changed = TRUE; + } + if (peers_changed) + _peers_notify(dst); +} + +static void +enumerate_values(const NMSettInfoProperty *property_info, + NMSetting * setting, + NMSettingValueIterFn func, + gpointer user_data) +{ + if (nm_streq(property_info->name, NM_SETTING_WIREGUARD_PEERS)) { + NMSettingWireGuardPrivate * priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + nm_auto_unset_gvalue GValue value = G_VALUE_INIT; + GPtrArray * ptr = NULL; + guint i; + + if (priv->peers_arr && priv->peers_arr->len > 0) { + ptr = g_ptr_array_new_with_free_func((GDestroyNotify) nm_wireguard_peer_unref); + for (i = 0; i < priv->peers_arr->len; i++) + g_ptr_array_add(ptr, nm_wireguard_peer_ref(_peers_get(priv, i)->peer)); + } + g_value_init(&value, G_TYPE_PTR_ARRAY); + g_value_take_boxed(&value, ptr); + func(setting, property_info->name, &value, 0, user_data); + return; + } + + NM_SETTING_CLASS(nm_setting_wireguard_parent_class) + ->enumerate_values(property_info, setting, func, user_data); +} + +static gboolean +aggregate(NMSetting *setting, int type_i, gpointer arg) +{ + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + NMConnectionAggregateType type = type_i; + NMSettingSecretFlags secret_flags; + guint i; + + nm_assert(NM_IN_SET(type, + NM_CONNECTION_AGGREGATE_ANY_SECRETS, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS)); + + switch (type) { + case NM_CONNECTION_AGGREGATE_ANY_SECRETS: + if (priv->private_key) + goto out_done; + for (i = 0; i < priv->peers_arr->len; i++) { + if (nm_wireguard_peer_get_preshared_key(_peers_get(priv, i)->peer)) + goto out_done; + } + break; + + case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: +#if NM_MORE_ASSERTS + if (!nm_setting_get_secret_flags(setting, + NM_SETTING_WIREGUARD_PRIVATE_KEY, + &secret_flags, + NULL)) + nm_assert_not_reached(); + nm_assert(secret_flags == priv->private_key_flags); +#endif + if (priv->private_key_flags == NM_SETTING_SECRET_FLAG_NONE) + goto out_done; + for (i = 0; i < priv->peers_arr->len; i++) { + secret_flags = nm_wireguard_peer_get_preshared_key_flags(_peers_get(priv, i)->peer); + if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) + goto out_done; + } + break; + } + + return FALSE; + +out_done: + *((gboolean *) arg) = TRUE; + return TRUE; +} + +static gboolean +get_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags *out_flags, + GError ** error) +{ + if (NM_STR_HAS_PREFIX(secret_name, NM_SETTING_WIREGUARD_PEERS ".")) { + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + gs_free char * public_key_free = NULL; + const char * public_key; + PeerData * pd; + + public_key = peers_psk_get_secret_parse_a(secret_name, &public_key_free); + if (public_key && (pd = _peers_get_by_public_key(priv, public_key, FALSE))) { + NM_SET_OUT(out_flags, nm_wireguard_peer_get_preshared_key_flags(pd->peer)); + return TRUE; + } + } + + return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) + ->get_secret_flags(setting, secret_name, out_flags, error); +} + +static gboolean +set_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags flags, + GError ** error) +{ + if (NM_STR_HAS_PREFIX(secret_name, NM_SETTING_WIREGUARD_PEERS ".")) { + NMSettingWireGuard * self = NM_SETTING_WIREGUARD(setting); + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(self); + gs_free char * public_key_free = NULL; + const char * public_key; + PeerData * pd; + + public_key = peers_psk_get_secret_parse_a(secret_name, &public_key_free); + if (public_key && (pd = _peers_get_by_public_key(priv, public_key, FALSE))) { + if (nm_wireguard_peer_get_preshared_key_flags(pd->peer) != flags) { + nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; + + peer = nm_wireguard_peer_new_clone(pd->peer, TRUE); + peer->preshared_key_flags = flags; + if (_peers_set(priv, peer, pd->idx, FALSE)) + _peers_notify(self); + } + + return TRUE; + } + } + + return NM_SETTING_CLASS(nm_setting_wireguard_parent_class) + ->set_secret_flags(setting, secret_name, flags, error); +} + +static void +for_each_secret(NMSetting * setting, + const char * data_key, + GVariant * data_val, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data, + GVariantBuilder * setting_builder) +{ + NMSettingWireGuard * s_wg; + NMSettingWireGuardPrivate *priv; + GVariantBuilder peers_builder; + GVariantIter * peer_iter; + GVariantIter data_iter; + const char * key; + + if (!nm_streq(data_key, NM_SETTING_WIREGUARD_PEERS)) { + NM_SETTING_CLASS(nm_setting_wireguard_parent_class) + ->for_each_secret(setting, + data_key, + data_val, + remove_non_secrets, + callback, + callback_data, + setting_builder); + return; + } + + if (!g_variant_is_of_type(data_val, G_VARIANT_TYPE("aa{sv}"))) { + /* invalid type. Silently ignore content as we cannot find secret-keys + * here. */ + return; + } + + s_wg = NM_SETTING_WIREGUARD(setting); + priv = NM_SETTING_WIREGUARD_GET_PRIVATE(s_wg); + + g_variant_builder_init(&peers_builder, G_VARIANT_TYPE("aa{sv}")); + g_variant_iter_init(&data_iter, data_val); + while (g_variant_iter_next(&data_iter, "a{sv}", &peer_iter)) { + _nm_unused nm_auto_free_variant_iter GVariantIter *peer_iter_free = peer_iter; + gs_unref_variant GVariant *preshared_key = NULL; + PeerData * pd = NULL; + NMSettingSecretFlags secret_flags; + GVariant * val; + GVariantBuilder peer_builder; + + g_variant_builder_init(&peer_builder, G_VARIANT_TYPE("a{sv}")); + + while (g_variant_iter_next(peer_iter, "{&sv}", &key, &val)) { + _nm_unused gs_unref_variant GVariant *val_free = val; + + if (nm_streq(key, NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)) { + if (!preshared_key && g_variant_is_of_type(val, G_VARIANT_TYPE_STRING)) + preshared_key = g_variant_ref(val); + continue; + } + + if (nm_streq(key, NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY)) { + if (!pd && g_variant_is_of_type(val, G_VARIANT_TYPE_STRING)) + pd = _peers_get_by_public_key(priv, g_variant_get_string(val, NULL), TRUE); + } else if (remove_non_secrets) + continue; + + g_variant_builder_add(&peer_builder, "{sv}", key, val); + } + + if (pd && preshared_key) { + /* without specifying a public-key of an existing peer, the secret is + * ignored. */ + secret_flags = nm_wireguard_peer_get_preshared_key_flags(pd->peer); + if (callback(secret_flags, callback_data)) + g_variant_builder_add(&peer_builder, + "{sv}", + NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY, + preshared_key); + } + + g_variant_builder_add(&peers_builder, "a{sv}", &peer_builder); + } + + g_variant_builder_add(setting_builder, + "{sv}", + NM_SETTING_WIREGUARD_PEERS, + g_variant_builder_end(&peers_builder)); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingWireGuard * setting = NM_SETTING_WIREGUARD(object); + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_FWMARK: + g_value_set_uint(value, priv->fwmark); + break; + case PROP_IP4_AUTO_DEFAULT_ROUTE: + g_value_set_enum(value, priv->ip4_auto_default_route); + break; + case PROP_IP6_AUTO_DEFAULT_ROUTE: + g_value_set_enum(value, priv->ip6_auto_default_route); + break; + case PROP_LISTEN_PORT: + g_value_set_uint(value, priv->listen_port); + break; + case PROP_MTU: + g_value_set_uint(value, priv->mtu); + break; + case PROP_PEER_ROUTES: + g_value_set_boolean(value, priv->peer_routes); + break; + case PROP_PRIVATE_KEY: + g_value_set_string(value, priv->private_key); + break; + case PROP_PRIVATE_KEY_FLAGS: + g_value_set_flags(value, priv->private_key_flags); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(object); + const char * str; + + switch (prop_id) { + case PROP_FWMARK: + priv->fwmark = g_value_get_uint(value); + break; + case PROP_IP4_AUTO_DEFAULT_ROUTE: + priv->ip4_auto_default_route = g_value_get_enum(value); + break; + case PROP_IP6_AUTO_DEFAULT_ROUTE: + priv->ip6_auto_default_route = g_value_get_enum(value); + break; + case PROP_LISTEN_PORT: + priv->listen_port = g_value_get_uint(value); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint(value); + break; + case PROP_PEER_ROUTES: + priv->peer_routes = g_value_get_boolean(value); + break; + case PROP_PRIVATE_KEY: + nm_clear_pointer(&priv->private_key, nm_free_secret); + str = g_value_get_string(value); + if (str) { + if (nm_utils_base64secret_normalize(str, + NM_WIREGUARD_PUBLIC_KEY_LEN, + &priv->private_key)) + priv->private_key_valid = TRUE; + else { + priv->private_key = g_strdup(str); + priv->private_key_valid = FALSE; + } + } + break; + case PROP_PRIVATE_KEY_FLAGS: + priv->private_key_flags = g_value_get_flags(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_wireguard_init(NMSettingWireGuard *setting) +{ + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); + + priv->peers_arr = g_ptr_array_new(); + priv->peers_hash = g_hash_table_new(nm_pstr_hash, nm_pstr_equal); + priv->peer_routes = TRUE; + priv->ip4_auto_default_route = NM_TERNARY_DEFAULT; + priv->ip6_auto_default_route = NM_TERNARY_DEFAULT; +} + +/** + * nm_setting_wireguard_new: + * + * Creates a new #NMSettingWireGuard object with default values. + * + * Returns: (transfer full): the new empty #NMSettingWireGuard object + * + * Since: 1.16 + **/ +NMSetting * +nm_setting_wireguard_new(void) +{ + return g_object_new(NM_TYPE_SETTING_WIREGUARD, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(object); + + nm_free_secret(priv->private_key); + + _peers_clear(priv); + g_ptr_array_unref(priv->peers_arr); + g_hash_table_unref(priv->peers_hash); + + G_OBJECT_CLASS(nm_setting_wireguard_parent_class)->finalize(object); +} + +static void +nm_setting_wireguard_class_init(NMSettingWireGuardClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; + setting_class->clear_secrets = clear_secrets; + setting_class->update_one_secret = update_one_secret; + setting_class->compare_property = compare_property; + setting_class->duplicate_copy_properties = duplicate_copy_properties; + setting_class->enumerate_values = enumerate_values; + setting_class->aggregate = aggregate; + setting_class->get_secret_flags = get_secret_flags; + setting_class->set_secret_flags = set_secret_flags; + setting_class->for_each_secret = for_each_secret; + + /** + * NMSettingWireGuard:private-key: + * + * The 256 bit private-key in base64 encoding. + * + * Since: 1.16 + **/ + obj_properties[PROP_PRIVATE_KEY] = + g_param_spec_string(NM_SETTING_WIREGUARD_PRIVATE_KEY, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireGuard:private-key-flags: + * + * Flags indicating how to handle the #NMSettingWirelessSecurity:private-key + * property. + * + * Since: 1.16 + **/ + obj_properties[PROP_PRIVATE_KEY_FLAGS] = + g_param_spec_flags(NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireGuard:fwmark: + * + * The use of fwmark is optional and is by default off. Setting it to 0 + * disables it. Otherwise, it is a 32-bit fwmark for outgoing packets. + * + * Note that "ip4-auto-default-route" or "ip6-auto-default-route" enabled, + * implies to automatically choose a fwmark. + * + * Since: 1.16 + **/ + obj_properties[PROP_FWMARK] = + g_param_spec_uint(NM_SETTING_WIREGUARD_FWMARK, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireGuard:listen-port: + * + * The listen-port. If listen-port is not specified, the port will be chosen + * randomly when the interface comes up. + * + * Since: 1.16 + **/ + obj_properties[PROP_LISTEN_PORT] = + g_param_spec_uint(NM_SETTING_WIREGUARD_LISTEN_PORT, + "", + "", + 0, + 65535, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireGuard:peer-routes: + * + * Whether to automatically add routes for the AllowedIPs ranges + * of the peers. If %TRUE (the default), NetworkManager will automatically + * add routes in the routing tables according to ipv4.route-table and + * ipv6.route-table. Usually you want this automatism enabled. + * If %FALSE, no such routes are added automatically. In this case, the + * user may want to configure static routes in ipv4.routes and ipv6.routes, + * respectively. + * + * Note that if the peer's AllowedIPs is "0.0.0.0/0" or "::/0" and the profile's + * ipv4.never-default or ipv6.never-default setting is enabled, the peer route for + * this peer won't be added automatically. + * + * Since: 1.16 + **/ + obj_properties[PROP_PEER_ROUTES] = g_param_spec_boolean( + NM_SETTING_WIREGUARD_PEER_ROUTES, + "", + "", + TRUE, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireGuard:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple fragments. + * + * If zero a default MTU is used. Note that contrary to wg-quick's MTU + * setting, this does not take into account the current routes at the + * time of activation. + * + * Since: 1.16 + **/ + obj_properties[PROP_MTU] = + g_param_spec_uint(NM_SETTING_WIREGUARD_MTU, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireGuard:ip4-auto-default-route: + * + * Whether to enable special handling of the IPv4 default route. + * If enabled, the IPv4 default route from wireguard.peer-routes + * will be placed to a dedicated routing-table and two policy routing rules + * will be added. The fwmark number is also used as routing-table for the default-route, + * and if fwmark is zero, an unused fwmark/table is chosen automatically. + * This corresponds to what wg-quick does with Table=auto and what WireGuard + * calls "Improved Rule-based Routing". + * + * Note that for this automatism to work, you usually don't want to set + * ipv4.gateway, because that will result in a conflicting default route. + * + * Leaving this at the default will enable this option automatically + * if ipv4.never-default is not set and there are any peers that use + * a default-route as allowed-ips. + * + * Since: 1.20 + **/ + obj_properties[PROP_IP4_AUTO_DEFAULT_ROUTE] = g_param_spec_enum( + NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE, + "", + "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireGuard:ip6-auto-default-route: + * + * Like ip4-auto-default-route, but for the IPv6 default route. + * + * Since: 1.20 + **/ + obj_properties[PROP_IP6_AUTO_DEFAULT_ROUTE] = g_param_spec_enum( + NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE, + "", + "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /* ---dbus--- + * property: peers + * format: array of 'a{sv}' + * description: Array of dictionaries for the WireGuard peers. + * ---end--- + */ + _nm_properties_override_dbus( + properties_override, + NM_SETTING_WIREGUARD_PEERS, + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = _peers_dbus_only_synth, + .from_dbus_fcn = _peers_dbus_only_set, )); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_WIREGUARD, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-wireless-security.c b/src/libnm-core-impl/nm-setting-wireless-security.c new file mode 100644 index 0000000000..f5bbe185f3 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-wireless-security.c @@ -0,0 +1,1967 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2017 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-wireless-security.h" + +#include "nm-setting-8021x.h" +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" +#include "nm-setting-wireless.h" +#include "nm-glib-aux/nm-secret-utils.h" + +/** + * SECTION:nm-setting-wireless-security + * @short_description: Describes connection properties for Wi-Fi networks that + * use WEP, LEAP, WPA or WPA2/RSN security + * + * The #NMSettingWirelessSecurity object is a #NMSetting subclass that describes + * properties necessary for connection to encrypted Wi-Fi networks. + * + * It's a good idea to read up on wpa_supplicant configuration before using this + * setting extensively, since most of the options here correspond closely with + * the relevant wpa_supplicant configuration options. To get a better overview + * of how Wi-Fi security works, you may want to get copies of the following books. + * + * 802.11 Wireless Networks: The Definitive Guide, Second Edition + * Author: Matthew Gast + * ISBN: 978-0596100520 + * + * Cisco Wireless LAN Security + * Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky + * ISBN: 978-1587051548 + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingWirelessSecurity, + PROP_KEY_MGMT, + PROP_WEP_TX_KEYIDX, + PROP_AUTH_ALG, + PROP_PROTO, + PROP_PAIRWISE, + PROP_GROUP, + PROP_PMF, + PROP_LEAP_USERNAME, + PROP_WEP_KEY0, + PROP_WEP_KEY1, + PROP_WEP_KEY2, + PROP_WEP_KEY3, + PROP_WEP_KEY_FLAGS, + PROP_WEP_KEY_TYPE, + PROP_PSK, + PROP_PSK_FLAGS, + PROP_LEAP_PASSWORD, + PROP_LEAP_PASSWORD_FLAGS, + PROP_WPS_METHOD, + PROP_FILS, ); + +typedef struct { + GSList * proto; /* GSList of strings */ + GSList * pairwise; /* GSList of strings */ + GSList * group; /* GSList of strings */ + char * key_mgmt; + char * auth_alg; + char * leap_username; + char * leap_password; + char * wep_key0; + char * wep_key1; + char * wep_key2; + char * wep_key3; + char * psk; + NMSettingSecretFlags leap_password_flags; + NMSettingSecretFlags wep_key_flags; + NMSettingSecretFlags psk_flags; + NMSettingWirelessSecurityPmf pmf; + NMWepKeyType wep_key_type; + NMSettingWirelessSecurityWpsMethod wps_method; + NMSettingWirelessSecurityFils fils; + guint32 wep_tx_keyidx; +} NMSettingWirelessSecurityPrivate; + +G_DEFINE_TYPE(NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING) + +#define NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + NM_TYPE_SETTING_WIRELESS_SECURITY, \ + NMSettingWirelessSecurityPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_wireless_security_get_key_mgmt: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:key-mgmt property of the setting + **/ +const char * +nm_setting_wireless_security_get_key_mgmt(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->key_mgmt; +} + +/** + * nm_setting_wireless_security_get_num_protos: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the number of security protocols this connection allows when + * connecting to secure Wi-Fi networks + **/ +guint32 +nm_setting_wireless_security_get_num_protos(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); + + return g_slist_length(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->proto); +} + +/** + * nm_setting_wireless_security_get_proto: + * @setting: the #NMSettingWirelessSecurity + * @i: an index into the protocol list + * + * Returns: the protocol at index @i + **/ +const char * +nm_setting_wireless_security_get_proto(NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + g_return_val_if_fail(i <= g_slist_length(priv->proto), NULL); + + return (const char *) g_slist_nth_data(priv->proto, i); +} + +/** + * nm_setting_wireless_security_add_proto: + * @setting: the #NMSettingWirelessSecurity + * @proto: the protocol to add, one of "wpa" or "rsn" + * + * Adds a Wi-Fi security protocol (one of "wpa" or "rsn") to the allowed list; + * only protocols in this list will be used when finding and connecting to + * the Wi-Fi network specified by this connection. For example, if the + * protocol list contains only "wpa" but the access point for the SSID specified + * by this connection only supports WPA2/RSN, the connection cannot be used + * with the access point. + * + * Returns: %TRUE if the protocol was new and was added to the allowed + * protocol list, or %FALSE if it was already in the list + **/ +gboolean +nm_setting_wireless_security_add_proto(NMSettingWirelessSecurity *setting, const char *proto) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); + g_return_val_if_fail(proto != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + for (iter = priv->proto; iter; iter = g_slist_next(iter)) { + if (g_ascii_strcasecmp(proto, (char *) iter->data) == 0) + return FALSE; + } + + priv->proto = g_slist_append(priv->proto, g_ascii_strdown(proto, -1)); + _notify(setting, PROP_PROTO); + return TRUE; +} + +/** + * nm_setting_wireless_security_remove_proto: + * @setting: the #NMSettingWirelessSecurity + * @i: index of the protocol to remove + * + * Removes a protocol from the allowed protocol list. + **/ +void +nm_setting_wireless_security_remove_proto(NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * elt; + + g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + elt = g_slist_nth(priv->proto, i); + g_return_if_fail(elt != NULL); + + g_free(elt->data); + priv->proto = g_slist_delete_link(priv->proto, elt); + _notify(setting, PROP_PROTO); +} + +/** + * nm_setting_wireless_security_remove_proto_by_value: + * @setting: the #NMSettingWirelessSecurity + * @proto: the protocol to remove, one of "wpa" or "rsn" + * + * Removes a protocol from the allowed protocol list. + * + * Returns: %TRUE if the protocol was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_wireless_security_remove_proto_by_value(NMSettingWirelessSecurity *setting, + const char * proto) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); + g_return_val_if_fail(proto != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + for (iter = priv->proto; iter; iter = g_slist_next(iter)) { + if (g_ascii_strcasecmp(proto, (char *) iter->data) == 0) { + priv->proto = g_slist_delete_link(priv->proto, iter); + _notify(setting, PROP_PROTO); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_wireless_security_clear_protos: + * @setting: the #NMSettingWirelessSecurity + * + * Removes all protocols from the allowed list. If there are no protocols + * specified then all protocols are allowed. + **/ +void +nm_setting_wireless_security_clear_protos(NMSettingWirelessSecurity *setting) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + g_slist_free_full(priv->proto, g_free); + priv->proto = NULL; + _notify(setting, PROP_PROTO); +} + +/** + * nm_setting_wireless_security_get_num_pairwise: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the number of pairwise encryption algorithms in the allowed list + **/ +guint32 +nm_setting_wireless_security_get_num_pairwise(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); + + return g_slist_length(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->pairwise); +} + +/** + * nm_setting_wireless_security_get_pairwise: + * @setting: the #NMSettingWirelessSecurity + * @i: index of an item in the allowed pairwise encryption algorithm list + * + * Returns the allowed pairwise encryption algorithm from allowed algorithm + * list. + * + * Returns: the pairwise encryption algorithm at index @i + **/ +const char * +nm_setting_wireless_security_get_pairwise(NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + g_return_val_if_fail(i <= g_slist_length(priv->pairwise), NULL); + + return (const char *) g_slist_nth_data(priv->pairwise, i); +} + +/** + * nm_setting_wireless_security_add_pairwise: + * @setting: the #NMSettingWirelessSecurity + * @pairwise: the encryption algorithm to add, one of "tkip" or "ccmp" + * + * Adds an encryption algorithm to the list of allowed pairwise encryption + * algorithms. If the list is not empty, then only access points that support + * one or more of the encryption algorithms in the list will be considered + * compatible with this connection. + * + * Returns: %TRUE if the algorithm was added to the list, %FALSE if it was + * already in the list + **/ +gboolean +nm_setting_wireless_security_add_pairwise(NMSettingWirelessSecurity *setting, const char *pairwise) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); + g_return_val_if_fail(pairwise != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + for (iter = priv->pairwise; iter; iter = g_slist_next(iter)) { + if (g_ascii_strcasecmp(pairwise, (char *) iter->data) == 0) + return FALSE; + } + + priv->pairwise = g_slist_append(priv->pairwise, g_ascii_strdown(pairwise, -1)); + _notify(setting, PROP_PAIRWISE); + return TRUE; +} + +/** + * nm_setting_wireless_security_remove_pairwise: + * @setting: the #NMSettingWirelessSecurity + * @i: the index of an item in the allowed pairwise encryption algorithm list + * + * Removes an encryption algorithm from the allowed pairwise encryption + * algorithm list. + **/ +void +nm_setting_wireless_security_remove_pairwise(NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * elt; + + g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + elt = g_slist_nth(priv->pairwise, i); + g_return_if_fail(elt != NULL); + + g_free(elt->data); + priv->pairwise = g_slist_delete_link(priv->pairwise, elt); + _notify(setting, PROP_PAIRWISE); +} + +/** + * nm_setting_wireless_security_remove_pairwise_by_value: + * @setting: the #NMSettingWirelessSecurity + * @pairwise: the encryption algorithm to remove, one of "tkip" or "ccmp" + * + * Removes an encryption algorithm from the allowed pairwise encryption + * algorithm list. + * + * Returns: %TRUE if the encryption algorithm was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_wireless_security_remove_pairwise_by_value(NMSettingWirelessSecurity *setting, + const char * pairwise) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); + g_return_val_if_fail(pairwise != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + for (iter = priv->pairwise; iter; iter = g_slist_next(iter)) { + if (g_ascii_strcasecmp(pairwise, (char *) iter->data) == 0) { + priv->pairwise = g_slist_delete_link(priv->pairwise, iter); + _notify(setting, PROP_PAIRWISE); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_wireless_security_clear_pairwise: + * @setting: the #NMSettingWirelessSecurity + * + * Removes all algorithms from the allowed list. If there are no algorithms + * specified then all pairwise encryption algorithms are allowed. + **/ +void +nm_setting_wireless_security_clear_pairwise(NMSettingWirelessSecurity *setting) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + g_slist_free_full(priv->pairwise, g_free); + priv->pairwise = NULL; + _notify(setting, PROP_PAIRWISE); +} + +/** + * nm_setting_wireless_security_get_num_groups: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the number of groupwise encryption algorithms in the allowed list + **/ +guint32 +nm_setting_wireless_security_get_num_groups(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); + + return g_slist_length(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->group); +} + +/** + * nm_setting_wireless_security_get_group: + * @setting: the #NMSettingWirelessSecurity + * @i: index of an item in the allowed groupwise encryption algorithm list + * + * Returns the allowed groupwise encryption algorithm from allowed algorithm + * list. + * + * Returns: the groupwise encryption algorithm at index @i + **/ +const char * +nm_setting_wireless_security_get_group(NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + g_return_val_if_fail(i <= g_slist_length(priv->group), NULL); + + return (const char *) g_slist_nth_data(priv->group, i); +} + +/** + * nm_setting_wireless_security_add_group: + * @setting: the #NMSettingWirelessSecurity + * @group: the encryption algorithm to add, one of "wep40", "wep104", + * "tkip", or "ccmp" + * + * Adds an encryption algorithm to the list of allowed groupwise encryption + * algorithms. If the list is not empty, then only access points that support + * one or more of the encryption algorithms in the list will be considered + * compatible with this connection. + * + * Returns: %TRUE if the algorithm was added to the list, %FALSE if it was + * already in the list + **/ +gboolean +nm_setting_wireless_security_add_group(NMSettingWirelessSecurity *setting, const char *group) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); + g_return_val_if_fail(group != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + for (iter = priv->group; iter; iter = g_slist_next(iter)) { + if (g_ascii_strcasecmp(group, (char *) iter->data) == 0) + return FALSE; + } + + priv->group = g_slist_append(priv->group, g_ascii_strdown(group, -1)); + _notify(setting, PROP_GROUP); + return TRUE; +} + +/** + * nm_setting_wireless_security_remove_group: + * @setting: the #NMSettingWirelessSecurity + * @i: the index of an item in the allowed groupwise encryption algorithm list + * + * Removes an encryption algorithm from the allowed groupwise encryption + * algorithm list. + **/ +void +nm_setting_wireless_security_remove_group(NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * elt; + + g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + elt = g_slist_nth(priv->group, i); + g_return_if_fail(elt != NULL); + + g_free(elt->data); + priv->group = g_slist_delete_link(priv->group, elt); + _notify(setting, PROP_GROUP); +} + +/** + * nm_setting_wireless_security_remove_group_by_value: + * @setting: the #NMSettingWirelessSecurity + * @group: the encryption algorithm to remove, one of "wep40", "wep104", + * "tkip", or "ccmp" + * + * Removes an encryption algorithm from the allowed groupwise encryption + * algorithm list. + * + * Returns: %TRUE if the algorithm was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_wireless_security_remove_group_by_value(NMSettingWirelessSecurity *setting, + const char * group) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList * iter; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), FALSE); + g_return_val_if_fail(group != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + for (iter = priv->group; iter; iter = g_slist_next(iter)) { + if (g_ascii_strcasecmp(group, (char *) iter->data) == 0) { + priv->group = g_slist_delete_link(priv->group, iter); + _notify(setting, PROP_GROUP); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_wireless_security_clear_groups: + * @setting: the #NMSettingWirelessSecurity + * + * Removes all algorithms from the allowed list. If there are no algorithms + * specified then all groupwise encryption algorithms are allowed. + **/ +void +nm_setting_wireless_security_clear_groups(NMSettingWirelessSecurity *setting) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + g_slist_free_full(priv->group, g_free); + priv->group = NULL; + _notify(setting, PROP_GROUP); +} + +/* + * nm_setting_wireless_security_get_pmf: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:pmf property of the setting + * + * Since: 1.10 + **/ +NMSettingWirelessSecurityPmf +nm_setting_wireless_security_get_pmf(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->pmf; +} + +/** + * nm_setting_wireless_security_get_psk: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:psk property of the setting + **/ +const char * +nm_setting_wireless_security_get_psk(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->psk; +} + +/** + * nm_setting_wireless_security_get_psk_flags: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSettingWirelessSecurity:psk + **/ +NMSettingSecretFlags +nm_setting_wireless_security_get_psk_flags(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->psk_flags; +} + +/** + * nm_setting_wireless_security_get_leap_username: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:leap-username property of the setting + **/ +const char * +nm_setting_wireless_security_get_leap_username(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->leap_username; +} + +/** + * nm_setting_wireless_security_get_leap_password: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:leap-password property of the setting + **/ +const char * +nm_setting_wireless_security_get_leap_password(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->leap_password; +} + +/** + * nm_setting_wireless_security_get_leap_password_flags: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingSecretFlags pertaining to the + * #NMSettingWirelessSecurity:leap-password + **/ +NMSettingSecretFlags +nm_setting_wireless_security_get_leap_password_flags(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->leap_password_flags; +} + +/** + * nm_setting_wireless_security_get_wep_key: + * @setting: the #NMSettingWirelessSecurity + * @idx: the WEP key index (0..3 inclusive) + * + * Returns: the WEP key at the given index + **/ +const char * +nm_setting_wireless_security_get_wep_key(NMSettingWirelessSecurity *setting, guint32 idx) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + g_return_val_if_fail(idx < 4, NULL); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + if (idx == 0) + return priv->wep_key0; + else if (idx == 1) + return priv->wep_key1; + else if (idx == 2) + return priv->wep_key2; + else if (idx == 3) + return priv->wep_key3; + + g_assert_not_reached(); + return NULL; +} + +/** + * nm_setting_wireless_security_set_wep_key: + * @setting: the #NMSettingWirelessSecurity + * @idx: the index of the key (0..3 inclusive) + * @key: the WEP key as a string, in either hexadecimal, ASCII, or passphrase + * form as determined by the value of the #NMSettingWirelessSecurity:wep-key-type + * property. + * + * Sets a WEP key in the given index. + **/ +void +nm_setting_wireless_security_set_wep_key(NMSettingWirelessSecurity *setting, + guint32 idx, + const char * key) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting)); + g_return_if_fail(idx < 4); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + switch (idx) { + case 0: + g_free(priv->wep_key0); + priv->wep_key0 = g_strdup(key); + _notify(setting, PROP_WEP_KEY0); + break; + case 1: + g_free(priv->wep_key1); + priv->wep_key1 = g_strdup(key); + _notify(setting, PROP_WEP_KEY1); + break; + case 2: + g_free(priv->wep_key2); + priv->wep_key2 = g_strdup(key); + _notify(setting, PROP_WEP_KEY2); + break; + case 3: + g_free(priv->wep_key3); + priv->wep_key3 = g_strdup(key); + _notify(setting, PROP_WEP_KEY3); + break; + default: + g_assert_not_reached(); + } +} + +/** + * nm_setting_wireless_security_get_wep_tx_keyidx: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:wep-tx-keyidx property of the setting + **/ +guint32 +nm_setting_wireless_security_get_wep_tx_keyidx(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wep_tx_keyidx; +} + +/** + * nm_setting_wireless_security_get_auth_alg: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:auth-alg property of the setting + **/ +const char * +nm_setting_wireless_security_get_auth_alg(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->auth_alg; +} + +/** + * nm_setting_wireless_security_get_wep_key_flags: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingSecretFlags pertaining to the all WEP keys + **/ +NMSettingSecretFlags +nm_setting_wireless_security_get_wep_key_flags(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), NM_SETTING_SECRET_FLAG_NONE); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wep_key_flags; +} + +/** + * nm_setting_wireless_security_get_wep_key_type: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:wep-key-type property of the setting + **/ +NMWepKeyType +nm_setting_wireless_security_get_wep_key_type(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wep_key_type; +} + +/** + * nm_setting_wireless_security_get_wps_method: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:wps-method property of the setting + * + * Since: 1.10 + **/ +NMSettingWirelessSecurityWpsMethod +nm_setting_wireless_security_get_wps_method(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wps_method; +} + +/* + * nm_setting_wireless_security_get_fils: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:fils property of the setting + * + * Since: 1.12 + **/ +NMSettingWirelessSecurityFils +nm_setting_wireless_security_get_fils(NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS_SECURITY(setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->fils; +} + +static GPtrArray * +need_secrets(NMSetting *setting) +{ + NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(setting); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); + GPtrArray * secrets; + + secrets = g_ptr_array_sized_new(4); + + g_assert(priv->key_mgmt); + + /* Static WEP */ + if (strcmp(priv->key_mgmt, "none") == 0) { + if ((priv->wep_tx_keyidx == 0) + && !nm_utils_wep_key_valid(priv->wep_key0, priv->wep_key_type)) { + g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0); + return secrets; + } + if ((priv->wep_tx_keyidx == 1) + && !nm_utils_wep_key_valid(priv->wep_key1, priv->wep_key_type)) { + g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1); + return secrets; + } + if ((priv->wep_tx_keyidx == 2) + && !nm_utils_wep_key_valid(priv->wep_key2, priv->wep_key_type)) { + g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2); + return secrets; + } + if ((priv->wep_tx_keyidx == 3) + && !nm_utils_wep_key_valid(priv->wep_key3, priv->wep_key_type)) { + g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3); + return secrets; + } + goto no_secrets; + } + + /* WPA-PSK infrastructure */ + if (strcmp(priv->key_mgmt, "wpa-psk") == 0) { + if (!nm_utils_wpa_psk_valid(priv->psk)) { + g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_PSK); + return secrets; + } + goto no_secrets; + } + + /* SAE, used in MESH and WPA3-Personal */ + if (strcmp(priv->key_mgmt, "sae") == 0) { + if (!priv->psk || !*priv->psk) { + g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_PSK); + return secrets; + } + goto no_secrets; + } + + /* LEAP */ + if (priv->auth_alg && !strcmp(priv->auth_alg, "leap") && !strcmp(priv->key_mgmt, "ieee8021x")) { + if (!priv->leap_password || !*priv->leap_password) { + g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD); + return secrets; + } + goto no_secrets; + } + + if (NM_IN_STRSET(priv->key_mgmt, "ieee8021x", "wpa-eap", "owe", "wpa-eap-suite-b-192")) { + /* Let caller check the 802.1x setting for secrets */ + goto no_secrets; + } + + g_assert_not_reached(); + return secrets; + +no_secrets: + if (secrets) + g_ptr_array_free(secrets, TRUE); + return NULL; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(setting); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); + const char * valid_key_mgmt[] = + {"none", "ieee8021x", "wpa-psk", "wpa-eap", "wpa-eap-suite-b-192", "sae", "owe", NULL}; + const char * valid_auth_algs[] = {"open", "shared", "leap", NULL}; + const char * valid_protos[] = {"wpa", "rsn", NULL}; + const char * valid_pairwise[] = {"tkip", "ccmp", NULL}; + const char * valid_groups[] = {"wep40", "wep104", "tkip", "ccmp", NULL}; + NMSettingWireless *s_wifi; + const char * wifi_mode; + + s_wifi = connection ? nm_connection_get_setting_wireless(connection) : NULL; + wifi_mode = s_wifi ? nm_setting_wireless_get_mode(s_wifi) : NULL; + + if (!priv->key_mgmt) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + return FALSE; + } + + if (g_strcmp0(wifi_mode, NM_SETTING_WIRELESS_MODE_MESH) == 0) { + if ((strcmp(priv->key_mgmt, "none") == 0) || (strcmp(priv->key_mgmt, "sae") == 0)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for '%s' mode connections"), + priv->key_mgmt, + NM_SETTING_WIRELESS_MODE_MESH); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + return FALSE; + } + } else { + if (!g_strv_contains(valid_key_mgmt, priv->key_mgmt)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid value for the property"), + priv->key_mgmt); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + return FALSE; + } + } + + if (priv->auth_alg && !strcmp(priv->auth_alg, "leap")) { + /* LEAP must use ieee8021x key management */ + if (strcmp(priv->key_mgmt, "ieee8021x")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' security requires '%s=%s'"), + "leap", + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "ieee8021x"); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; + } + if (!priv->leap_username) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME); + return FALSE; + } + } else { + if (nm_streq(priv->key_mgmt, "ieee8021x") || nm_streq(priv->key_mgmt, "wpa-eap") + || nm_streq(priv->key_mgmt, "wpa-eap-suite-b-192")) { + /* Need an 802.1x setting too */ + if (connection && !nm_connection_get_setting_802_1x(connection)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("'%s' security requires '%s' setting presence"), + priv->key_mgmt, + NM_SETTING_802_1X_SETTING_NAME); + g_prefix_error(error, "%s: ", NM_SETTING_802_1X_SETTING_NAME); + return FALSE; + } + } + } + + if (priv->leap_username && !strlen(priv->leap_username)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME); + return FALSE; + } + + if (priv->wep_tx_keyidx > 3) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%d' value is out of range <0-3>"), + priv->wep_tx_keyidx); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX); + return FALSE; + } + + if (priv->wep_key_type > NM_WEP_KEY_TYPE_LAST) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE); + return FALSE; + } + + if (priv->auth_alg && !g_strv_contains(valid_auth_algs, priv->auth_alg)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; + } + + if (priv->proto && !_nm_utils_string_slist_validate(priv->proto, valid_protos)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PROTO); + return FALSE; + } + + if (priv->pairwise) { + if (!_nm_utils_string_slist_validate(priv->pairwise, valid_pairwise)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PAIRWISE); + return FALSE; + } + } + + if (priv->group && !_nm_utils_string_slist_validate(priv->group, valid_groups)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_GROUP); + return FALSE; + } + + /* Shared Key auth can only be used with WEP */ + if (priv->auth_alg && !strcmp(priv->auth_alg, "shared")) { + if (priv->key_mgmt && strcmp(priv->key_mgmt, "none")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' can only be used with '%s=%s' (WEP)"), + "shared", + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "none"); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; + } + } + + G_STATIC_ASSERT_EXPR(((NMSettingWirelessSecurityPmf) -1) > 0); + if (priv->pmf > NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PMF); + return FALSE; + } + + if (NM_IN_SET(priv->pmf, + NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL, + NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) + && !NM_IN_STRSET(priv->key_mgmt, + "wpa-eap", + "wpa-eap-suite-b-192", + "wpa-psk", + "sae", + "owe")) { + g_set_error( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' can only be used with 'wpa-eap', 'wpa-eap-suite-b-192', 'wpa-psk' or 'sae' key " + "management "), + priv->pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL ? "optional" : "required"); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PMF); + return FALSE; + } + + if (!_nm_utils_wps_method_validate(priv->wps_method, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, + FALSE, + error)) + return FALSE; + + return TRUE; +} + +static gboolean +_verify_wep_key(const char * wep_key, + NMWepKeyType wep_key_type, + const char * property, + GError ** error) +{ + if (wep_key && !nm_utils_wep_key_valid(wep_key, wep_key_type)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, property); + return FALSE; + } + return TRUE; +} + +static gboolean +verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(setting); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); + + /* LEAP */ + if (priv->auth_alg && !strcmp(priv->auth_alg, "leap") && !strcmp(priv->key_mgmt, "ieee8021x")) { + if (!_nm_setting_verify_secret_string(priv->leap_password, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, + error)) + return FALSE; + } + + /* WEP */ + if (!_verify_wep_key(priv->wep_key0, + priv->wep_key_type, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + error)) + return FALSE; + if (!_verify_wep_key(priv->wep_key1, + priv->wep_key_type, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, + error)) + return FALSE; + if (!_verify_wep_key(priv->wep_key2, + priv->wep_key_type, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, + error)) + return FALSE; + if (!_verify_wep_key(priv->wep_key3, + priv->wep_key_type, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, + error)) + return FALSE; + + /* WPA-PSK */ + if (priv->psk && strcmp(priv->key_mgmt, "sae") != 0 && !nm_utils_wpa_psk_valid(priv->psk)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PSK); + return FALSE; + } + + return TRUE; +} + +static gboolean +get_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags *out_flags, + GError ** error) +{ + NMSettingSecretFlags flags; + + if (NM_IN_STRSET(secret_name, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY3)) { + /* There's only one 'flags' property for WEP keys, so alias all the WEP key + * property names to that flags property. */ + nm_assert(_nm_setting_property_is_regular_secret(setting, secret_name)); + nm_assert(_nm_setting_property_is_regular_secret_flags( + setting, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS)); + + g_object_get(G_OBJECT(setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, &flags, NULL); + NM_SET_OUT(out_flags, flags); + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_wireless_security_parent_class) + ->get_secret_flags(setting, secret_name, out_flags, error); +} + +static gboolean +set_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags flags, + GError ** error) +{ + if (NM_IN_STRSET(secret_name, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY3)) { + /* There's only one 'flags' property for WEP keys, so alias all the WEP key + * property names to that flags property. */ + nm_assert(_nm_setting_property_is_regular_secret(setting, secret_name)); + nm_assert(_nm_setting_property_is_regular_secret_flags( + setting, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS)); + + if (!nm_g_object_set_property_flags(G_OBJECT(setting), + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, + NM_TYPE_SETTING_SECRET_FLAGS, + flags, + error)) + g_return_val_if_reached(FALSE); + return TRUE; + } + + return NM_SETTING_CLASS(nm_setting_wireless_security_parent_class) + ->set_secret_flags(setting, secret_name, flags, error); +} + +/* NMSettingWirelessSecurity:wep-key-type is an enum, but needs to be marshalled + * as 'u', not 'i', for backward-compatibility. + */ +static GVariant * +wep_key_type_to_dbus(const GValue *from) +{ + return g_variant_new_uint32(g_value_get_enum(from)); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingWirelessSecurity * setting = NM_SETTING_WIRELESS_SECURITY(object); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + + switch (prop_id) { + case PROP_KEY_MGMT: + g_value_set_string(value, priv->key_mgmt); + break; + case PROP_WEP_TX_KEYIDX: + g_value_set_uint(value, priv->wep_tx_keyidx); + break; + case PROP_AUTH_ALG: + g_value_set_string(value, priv->auth_alg); + break; + case PROP_PROTO: + g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->proto, TRUE)); + break; + case PROP_PAIRWISE: + g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->pairwise, TRUE)); + break; + case PROP_GROUP: + g_value_take_boxed(value, _nm_utils_slist_to_strv(priv->group, TRUE)); + break; + case PROP_PMF: + g_value_set_int(value, nm_setting_wireless_security_get_pmf(setting)); + break; + case PROP_LEAP_USERNAME: + g_value_set_string(value, priv->leap_username); + break; + case PROP_WEP_KEY0: + g_value_set_string(value, priv->wep_key0); + break; + case PROP_WEP_KEY1: + g_value_set_string(value, priv->wep_key1); + break; + case PROP_WEP_KEY2: + g_value_set_string(value, priv->wep_key2); + break; + case PROP_WEP_KEY3: + g_value_set_string(value, priv->wep_key3); + break; + case PROP_WEP_KEY_FLAGS: + g_value_set_flags(value, priv->wep_key_flags); + break; + case PROP_PSK: + g_value_set_string(value, priv->psk); + break; + case PROP_PSK_FLAGS: + g_value_set_flags(value, priv->psk_flags); + break; + case PROP_LEAP_PASSWORD: + g_value_set_string(value, priv->leap_password); + break; + case PROP_LEAP_PASSWORD_FLAGS: + g_value_set_flags(value, priv->leap_password_flags); + break; + case PROP_WEP_KEY_TYPE: + g_value_set_enum(value, priv->wep_key_type); + break; + case PROP_WPS_METHOD: + g_value_set_uint(value, priv->wps_method); + break; + case PROP_FILS: + g_value_set_int(value, nm_setting_wireless_security_get_fils(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingWirelessSecurity * setting = NM_SETTING_WIRELESS_SECURITY(object); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting); + const char * str; + + switch (prop_id) { + case PROP_KEY_MGMT: + g_free(priv->key_mgmt); + str = g_value_get_string(value); + priv->key_mgmt = str ? g_ascii_strdown(str, -1) : NULL; + break; + case PROP_WEP_TX_KEYIDX: + priv->wep_tx_keyidx = g_value_get_uint(value); + break; + case PROP_AUTH_ALG: + g_free(priv->auth_alg); + str = g_value_get_string(value); + priv->auth_alg = str ? g_ascii_strdown(str, -1) : NULL; + break; + case PROP_PROTO: + g_slist_free_full(priv->proto, g_free); + priv->proto = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); + break; + case PROP_PAIRWISE: + g_slist_free_full(priv->pairwise, g_free); + priv->pairwise = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); + break; + case PROP_GROUP: + g_slist_free_full(priv->group, g_free); + priv->group = _nm_utils_strv_to_slist(g_value_get_boxed(value), TRUE); + break; + case PROP_PMF: + priv->pmf = g_value_get_int(value); + break; + case PROP_LEAP_USERNAME: + g_free(priv->leap_username); + priv->leap_username = g_value_dup_string(value); + break; + case PROP_WEP_KEY0: + nm_free_secret(priv->wep_key0); + priv->wep_key0 = g_value_dup_string(value); + break; + case PROP_WEP_KEY1: + nm_free_secret(priv->wep_key1); + priv->wep_key1 = g_value_dup_string(value); + break; + case PROP_WEP_KEY2: + nm_free_secret(priv->wep_key2); + priv->wep_key2 = g_value_dup_string(value); + break; + case PROP_WEP_KEY3: + nm_free_secret(priv->wep_key3); + priv->wep_key3 = g_value_dup_string(value); + break; + case PROP_WEP_KEY_FLAGS: + priv->wep_key_flags = g_value_get_flags(value); + break; + case PROP_PSK: + nm_free_secret(priv->psk); + priv->psk = g_value_dup_string(value); + break; + case PROP_PSK_FLAGS: + priv->psk_flags = g_value_get_flags(value); + break; + case PROP_LEAP_PASSWORD: + nm_free_secret(priv->leap_password); + priv->leap_password = g_value_dup_string(value); + break; + case PROP_LEAP_PASSWORD_FLAGS: + priv->leap_password_flags = g_value_get_flags(value); + break; + case PROP_WEP_KEY_TYPE: + priv->wep_key_type = g_value_get_enum(value); + break; + case PROP_WPS_METHOD: + priv->wps_method = g_value_get_uint(value); + break; + case PROP_FILS: + priv->fils = g_value_get_int(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_wireless_security_init(NMSettingWirelessSecurity *self) +{ + nm_assert(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self)->wep_key_type + == NM_WEP_KEY_TYPE_UNKNOWN); + nm_assert(NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self)->wps_method + == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT); +} + +/** + * nm_setting_wireless_security_new: + * + * Creates a new #NMSettingWirelessSecurity object with default values. + * + * Returns: (transfer full): the new empty #NMSettingWirelessSecurity object + **/ +NMSetting * +nm_setting_wireless_security_new(void) +{ + return g_object_new(NM_TYPE_SETTING_WIRELESS_SECURITY, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(object); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); + + g_free(priv->key_mgmt); + g_free(priv->auth_alg); + g_free(priv->leap_username); + nm_free_secret(priv->wep_key0); + nm_free_secret(priv->wep_key1); + nm_free_secret(priv->wep_key2); + nm_free_secret(priv->wep_key3); + nm_free_secret(priv->psk); + nm_free_secret(priv->leap_password); + + g_slist_free_full(priv->proto, g_free); + g_slist_free_full(priv->pairwise, g_free); + g_slist_free_full(priv->group, g_free); + + G_OBJECT_CLASS(nm_setting_wireless_security_parent_class)->finalize(object); +} + +static void +nm_setting_wireless_security_class_init(NMSettingWirelessSecurityClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingWirelessSecurityPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; + setting_class->get_secret_flags = get_secret_flags; + setting_class->set_secret_flags = set_secret_flags; + + /** + * NMSettingWirelessSecurity:key-mgmt: + * + * Key management used for the connection. One of "none" (WEP), + * "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" + * (SAE), "owe" (Opportunistic Wireless Encryption), "wpa-eap" + * (WPA-Enterprise) or "wpa-eap-suite-b-192" (WPA3-Enterprise Suite B). + * This property must be set for any Wi-Fi connection that uses security. + **/ + /* ---ifcfg-rh--- + * property: key-mgmt + * variable: KEY_MGMT(+) + * values: IEEE8021X, WPA-PSK, WPA-EAP, WPA-EAP-SUITE-B-192 + * description: Key management menthod. + * ---end--- + */ + obj_properties[PROP_KEY_MGMT] = + g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_REQUIRED | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:wep-tx-keyidx: + * + * When static WEP is used (ie, key-mgmt = "none") and a non-default WEP key + * index is used by the AP, put that WEP key index here. Valid values are 0 + * (default key) through 3. Note that some consumer access points (like the + * Linksys WRT54G) number the keys 1 - 4. + **/ + /* ---ifcfg-rh--- + * property: wep-tx-keyidx + * variable: DEFAULTKEY + * values: 1, 2, 3, 4 + * default: 1 + * description: Index of active WEP key. + * ---end--- + */ + obj_properties[PROP_WEP_TX_KEYIDX] = + g_param_spec_uint(NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, + "", + "", + 0, + 3, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:auth-alg: + * + * When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the + * 802.11 authentication algorithm required by the AP here. One of "open" + * for Open System, "shared" for Shared Key, or "leap" for Cisco LEAP. When + * using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the + * "leap-username" and "leap-password" properties must be specified. + **/ + /* ---ifcfg-rh--- + * property: auth-alg + * variable: SECURITYMODE(+) + * values: restricted, open, leap + * description: Authentication algorithm for WEP. + * ---end--- + */ + obj_properties[PROP_AUTH_ALG] = g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:proto: + * + * List of strings specifying the allowed WPA protocol versions to use. + * Each element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN). If + * not specified, both WPA and RSN connections are allowed. + **/ + /* ---ifcfg-rh--- + * property: proto + * variable: WPA_ALLOW_WPA(+), WPA_ALLOW_WPA2(+) + * values: yes, no + * default: no + * description: Allowed WPA protocols, WPA and WPA2 (RSN). + * ---end--- + */ + obj_properties[PROP_PROTO] = g_param_spec_boxed(NM_SETTING_WIRELESS_SECURITY_PROTO, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:pairwise: + * + * A list of pairwise encryption algorithms which prevents connections to + * Wi-Fi networks that do not utilize one of the algorithms in the list. + * For maximum compatibility leave this property empty. Each list element + * may be one of "tkip" or "ccmp". + **/ + /* ---ifcfg-rh--- + * property: pairwise + * variable: CIPHER_PAIRWISE(+) + * values: CCMP, TKIP + * description: Restrict pairwise encryption algorithms, specified as a space + * separated list. + * ---end--- + */ + obj_properties[PROP_PAIRWISE] = g_param_spec_boxed(NM_SETTING_WIRELESS_SECURITY_PAIRWISE, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:group: + * + * A list of group/broadcast encryption algorithms which prevents + * connections to Wi-Fi networks that do not utilize one of the algorithms + * in the list. For maximum compatibility leave this property empty. Each + * list element may be one of "wep40", "wep104", "tkip", or "ccmp". + **/ + /* ---ifcfg-rh--- + * property: group + * variable: CIPHER_GROUP(+) + * values: CCMP, TKIP, WEP40, WEP104 + * description: Restrict group/broadcast encryption algorithms, specified as a space + * separated list. + * ---end--- + */ + obj_properties[PROP_GROUP] = g_param_spec_boxed(NM_SETTING_WIRELESS_SECURITY_GROUP, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:pmf: + * + * Indicates whether Protected Management Frames (802.11w) must be enabled + * for the connection. One of %NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT + * (use global default value), %NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE + * (disable PMF), %NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (enable PMF if + * the supplicant and the access point support it) or + * %NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (enable PMF and fail if not + * supported). When set to %NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT and no + * global default is set, PMF will be optionally enabled. + * + * Since: 1.10 + **/ + /* ---ifcfg-rh--- + * property: pmf + * variable: PMF(+) + * values: default, disable, optional, required + * description: Enables or disables PMF (802.11w) + * example: PMF=required + * ---end--- + */ + obj_properties[PROP_PMF] = g_param_spec_int(NM_SETTING_WIRELESS_SECURITY_PMF, + "", + "", + G_MININT32, + G_MAXINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:leap-username: + * + * The login username for legacy LEAP connections (ie, key-mgmt = + * "ieee8021x" and auth-alg = "leap"). + **/ + /* ---ifcfg-rh--- + * property: leap-username + * variable: IEEE_8021X_IDENTITY(+) + * description: Login name for LEAP. + * ---end--- + */ + obj_properties[PROP_LEAP_USERNAME] = + g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:wep-key0: + * + * Index 0 WEP key. This is the WEP key used in most networks. See the + * "wep-key-type" property for a description of how this key is interpreted. + **/ + /* ---ifcfg-rh--- + * property: wep-key0 + * variable: KEY1, KEY_PASSPHRASE1(+) + * description: The first WEP key (used in most networks). See also DEFAULTKEY for key index. + * ---end--- + */ + obj_properties[PROP_WEP_KEY0] = + g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:wep-key1: + * + * Index 1 WEP key. This WEP index is not used by most networks. See the + * "wep-key-type" property for a description of how this key is interpreted. + **/ + /* ---ifcfg-rh--- + * property: wep-key1 + * variable: KEY2, KEY_PASSPHRASE2(+) + * description: WEP key with index 1. See also DEFAULTKEY for key index. + * ---end--- + */ + obj_properties[PROP_WEP_KEY1] = + g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:wep-key2: + * + * Index 2 WEP key. This WEP index is not used by most networks. See the + * "wep-key-type" property for a description of how this key is interpreted. + **/ + /* ---ifcfg-rh--- + * property: wep-key2 + * variable: KEY3, KEY_PASSPHRASE3(+) + * description: WEP key with index 2. See also DEFAULTKEY for key index. + * ---end--- + */ + obj_properties[PROP_WEP_KEY2] = + g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:wep-key3: + * + * Index 3 WEP key. This WEP index is not used by most networks. See the + * "wep-key-type" property for a description of how this key is interpreted. + **/ + /* ---ifcfg-rh--- + * property: wep-key3 + * variable: KEY4, KEY_PASSPHRASE4(+) + * description: WEP key with index 3. See also DEFAULTKEY for key index. + * ---end--- + */ + obj_properties[PROP_WEP_KEY3] = + g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:wep-key-flags: + * + * Flags indicating how to handle the #NMSettingWirelessSecurity:wep-key0, + * #NMSettingWirelessSecurity:wep-key1, #NMSettingWirelessSecurity:wep-key2, + * and #NMSettingWirelessSecurity:wep-key3 properties. + **/ + /* ---ifcfg-rh--- + * property: wep-key-flags + * variable: WEP_KEY_FLAGS(+) + * format: NMSettingSecretFlags + * description: Password flags for KEY, KEY_PASSPHRASE password. + * ---end--- + */ + obj_properties[PROP_WEP_KEY_FLAGS] = + g_param_spec_flags(NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:psk: + * + * Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII + * passphrase of 8 to 63 characters that is (as specified in the 802.11i + * standard) hashed to derive the actual key, or the key in form of 64 + * hexadecimal character. The WPA3-Personal networks use a passphrase + * of any length for SAE authentication. + **/ + /* ---ifcfg-rh--- + * property: psk + * variable: WPA_PSK + * description: Pre-Shared-Key for WPA networks. + * ---end--- + */ + obj_properties[PROP_PSK] = + g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_PSK, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:psk-flags: + * + * Flags indicating how to handle the #NMSettingWirelessSecurity:psk + * property. + **/ + /* ---ifcfg-rh--- + * property: psk-flags + * variable: WPA_PSK_FLAGS(+) + * format: NMSettingSecretFlags + * description: Password flags for WPA_PSK_FLAGS. + * example: WPA_PSK_FLAGS=user + * ---end--- + */ + obj_properties[PROP_PSK_FLAGS] = g_param_spec_flags(NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:leap-password: + * + * The login password for legacy LEAP connections (ie, key-mgmt = + * "ieee8021x" and auth-alg = "leap"). + **/ + /* ---ifcfg-rh--- + * property: leap-password + * variable: IEEE_8021X_PASSWORD(+) + * description: Password for LEAP. It can also go to "key-" + * lookaside file, or it can be owned by a secret agent. + * ---end--- + */ + obj_properties[PROP_LEAP_PASSWORD] = + g_param_spec_string(NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:leap-password-flags: + * + * Flags indicating how to handle the + * #NMSettingWirelessSecurity:leap-password property. + **/ + /* ---ifcfg-rh--- + * property: leap-password-flags + * variable: IEEE_8021X_PASSWORD_FLAGS(+) + * format: NMSettingSecretFlags + * description: Password flags for IEEE_8021X_PASSWORD_FLAGS. + * ---end--- + */ + obj_properties[PROP_LEAP_PASSWORD_FLAGS] = + g_param_spec_flags(NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, + "", + "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:wep-key-type: + * + * Controls the interpretation of WEP keys. Allowed values are + * %NM_WEP_KEY_TYPE_KEY, in which case the key is either a 10- or + * 26-character hexadecimal string, or a 5- or 13-character ASCII password; + * or %NM_WEP_KEY_TYPE_PASSPHRASE, in which case the passphrase is provided + * as a string and will be hashed using the de-facto MD5 method to derive + * the actual WEP key. + **/ + /* ---ifcfg-rh--- + * property: wep-key-type + * variable: KEY or KEY_PASSPHRASE(+); KEY_TYPE(+) + * description: KEY is used for "key" type (10 or 26 hexadecimal characters, + * or 5 or 13 character string prefixed with "s:"). KEY_PASSPHRASE is used + * for WEP passphrases. KEY_TYPE specifies the key type and can be either + * 'key' or 'passphrase'. KEY_TYPE is redundant and can be omitted. + * example: KEY1=s:ahoj, KEY1=0a1c45bc02, KEY_PASSPHRASE1=mysupersecretkey + * ---end--- + */ + obj_properties[PROP_WEP_KEY_TYPE] = + g_param_spec_enum(NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + "", + "", + NM_TYPE_WEP_KEY_TYPE, + NM_WEP_KEY_TYPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_WEP_KEY_TYPE], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT32, + .gprop_to_dbus_fcn = wep_key_type_to_dbus, )); + + /** + * NMSettingWirelessSecurity:wps-method: + * + * Flags indicating which mode of WPS is to be used if any. + * + * There's little point in changing the default setting as NetworkManager will + * automatically determine whether it's feasible to start WPS enrollment from + * the Access Point capabilities. + * + * WPS can be disabled by setting this property to a value of 1. + * + * Since: 1.10 + **/ + /* ---ifcfg-rh--- + * property: wps-method + * variable: WPS_METHOD + * description: Used to control the WPS methods to be used + * Valid values are "default", "auto", "disabled", "pin" and "pbc". + * If omitted, whatver the AP announces is used. + * example: WPS_METHOD=disabled, WPS_METHOD="pin pbc" + * ---end--- + */ + obj_properties[PROP_WPS_METHOD] = g_param_spec_uint( + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, + "", + "", + 0, + G_MAXUINT32, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWirelessSecurity:fils: + * + * Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for + * the connection. One of %NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (use + * global default value), %NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE + * (disable FILS), %NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (enable FILS + * if the supplicant and the access point support it) or + * %NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (enable FILS and fail if not + * supported). When set to %NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT and + * no global default is set, FILS will be optionally enabled. + * + * Since: 1.12 + **/ + /* ---ifcfg-rh--- + * property: fils + * variable: FILS(+) + * values: default, disable, optional, required + * description: Enables or disables FILS (802.11ai) + * example: FILS=required + * ---end--- + */ + obj_properties[PROP_FILS] = g_param_spec_int(NM_SETTING_WIRELESS_SECURITY_FILS, + "", + "", + G_MININT32, + G_MAXINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_WIRELESS_SECURITY, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-wireless.c b/src/libnm-core-impl/nm-setting-wireless.c new file mode 100644 index 0000000000..54c12c818a --- /dev/null +++ b/src/libnm-core-impl/nm-setting-wireless.c @@ -0,0 +1,1932 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-wireless.h" + +#include + +#include "nm-utils.h" +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-wireless + * @short_description: Describes connection properties for 802.11 Wi-Fi networks + * + * The #NMSettingWireless object is a #NMSetting subclass that describes properties + * necessary for connection to 802.11 Wi-Fi networks. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingWireless, + PROP_SSID, + PROP_MODE, + PROP_BAND, + PROP_CHANNEL, + PROP_BSSID, + PROP_RATE, + PROP_TX_POWER, + PROP_MAC_ADDRESS, + PROP_CLONED_MAC_ADDRESS, + PROP_GENERATE_MAC_ADDRESS_MASK, + PROP_MAC_ADDRESS_BLACKLIST, + PROP_MTU, + PROP_SEEN_BSSIDS, + PROP_HIDDEN, + PROP_POWERSAVE, + PROP_MAC_ADDRESS_RANDOMIZATION, + PROP_WAKE_ON_WLAN, + PROP_AP_ISOLATION, ); + +typedef struct { + GBytes * ssid; + GArray * mac_address_blacklist; + GPtrArray * seen_bssids; + char * mode; + char * band; + char * bssid; + char * device_mac_address; + char * cloned_mac_address; + char * generate_mac_address_mask; + NMSettingMacRandomization mac_address_randomization; + NMTernary ap_isolation; + guint32 channel; + guint32 rate; + guint32 tx_power; + guint32 mtu; + guint32 powersave; + guint32 wowl; + bool hidden : 1; +} NMSettingWirelessPrivate; + +G_DEFINE_TYPE(NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING) + +#define NM_SETTING_WIRELESS_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate)) + +/*****************************************************************************/ + +static gboolean +match_cipher(const char *cipher, + const char *expected, + guint32 wpa_flags, + guint32 rsn_flags, + guint32 flag) +{ + if (strcmp(cipher, expected) != 0) + return FALSE; + + if (!(wpa_flags & flag) && !(rsn_flags & flag)) + return FALSE; + + return TRUE; +} + +/** + * nm_setting_wireless_ap_security_compatible: + * @s_wireless: a #NMSettingWireless + * @s_wireless_sec: a #NMSettingWirelessSecurity or %NULL + * @ap_flags: the %NM80211ApFlags of the given access point + * @ap_wpa: the %NM80211ApSecurityFlags of the given access point's WPA + * capabilities + * @ap_rsn: the %NM80211ApSecurityFlags of the given access point's WPA2/RSN + * capabilities + * @ap_mode: the 802.11 mode of the AP, either Ad-Hoc or Infrastructure + * + * Given a #NMSettingWireless and an optional #NMSettingWirelessSecurity, + * determine if the configuration given by the settings is compatible with + * the security of an access point using that access point's capability flags + * and mode. Useful for clients that wish to filter a set of connections + * against a set of access points and determine which connections are + * compatible with which access points. + * + * Returns: %TRUE if the given settings are compatible with the access point's + * security flags and mode, %FALSE if they are not. + */ +gboolean +nm_setting_wireless_ap_security_compatible(NMSettingWireless * s_wireless, + NMSettingWirelessSecurity *s_wireless_sec, + NM80211ApFlags ap_flags, + NM80211ApSecurityFlags ap_wpa, + NM80211ApSecurityFlags ap_rsn, + NM80211Mode ap_mode) +{ + const char *key_mgmt = NULL, *cipher; + guint32 num, i; + gboolean found = FALSE; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(s_wireless), FALSE); + + if (!s_wireless_sec) { + if ((ap_flags & NM_802_11_AP_FLAGS_PRIVACY) || (ap_wpa != NM_802_11_AP_SEC_NONE) + || (ap_rsn != NM_802_11_AP_SEC_NONE)) + return FALSE; + return TRUE; + } + + key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wireless_sec); + if (!key_mgmt) + return FALSE; + + /* Static WEP */ + if (!strcmp(key_mgmt, "none")) { + if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY) || (ap_wpa != NM_802_11_AP_SEC_NONE) + || (ap_rsn != NM_802_11_AP_SEC_NONE)) + return FALSE; + return TRUE; + } + + /* Adhoc WPA2 (ie, RSN IBSS) */ + if (ap_mode == NM_802_11_MODE_ADHOC) { + if (strcmp(key_mgmt, "wpa-psk")) + return FALSE; + + /* Ensure the AP has RSN PSK capability */ + if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK)) + return FALSE; + + /* Fall through and check ciphers in generic WPA-PSK code */ + } + + /* Dynamic WEP or LEAP */ + if (!strcmp(key_mgmt, "ieee8021x")) { + if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + return FALSE; + + /* If the AP is advertising a WPA IE, make sure it supports WEP ciphers */ + if (ap_wpa != NM_802_11_AP_SEC_NONE) { + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + + /* quick check; can't use AP if it doesn't support at least one + * WEP cipher in both pairwise and group suites. + */ + if (!(ap_wpa & (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104)) + || !(ap_wpa & (NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104))) + return FALSE; + + /* Match at least one pairwise cipher with AP's capability if the + * wireless-security setting explicitly lists pairwise ciphers + */ + num = nm_setting_wireless_security_get_num_pairwise(s_wireless_sec); + for (i = 0, found = FALSE; i < num; i++) { + cipher = nm_setting_wireless_security_get_pairwise(s_wireless_sec, i); + if ((found = match_cipher(cipher, + "wep40", + ap_wpa, + ap_wpa, + NM_802_11_AP_SEC_PAIR_WEP40))) + break; + if ((found = match_cipher(cipher, + "wep104", + ap_wpa, + ap_wpa, + NM_802_11_AP_SEC_PAIR_WEP104))) + break; + } + if (!found && num) + return FALSE; + + /* Match at least one group cipher with AP's capability if the + * wireless-security setting explicitly lists group ciphers + */ + num = nm_setting_wireless_security_get_num_groups(s_wireless_sec); + for (i = 0, found = FALSE; i < num; i++) { + cipher = nm_setting_wireless_security_get_group(s_wireless_sec, i); + if ((found = match_cipher(cipher, + "wep40", + ap_wpa, + ap_wpa, + NM_802_11_AP_SEC_GROUP_WEP40))) + break; + if ((found = match_cipher(cipher, + "wep104", + ap_wpa, + ap_wpa, + NM_802_11_AP_SEC_GROUP_WEP104))) + break; + } + if (!found && num) + return FALSE; + } + return TRUE; + } + + /* WPA[2]-PSK and WPA[2] Enterprise */ + if (!strcmp(key_mgmt, "wpa-psk") || !strcmp(key_mgmt, "wpa-eap") || !strcmp(key_mgmt, "sae") + || !strcmp(key_mgmt, "owe")) { + if (!strcmp(key_mgmt, "wpa-psk")) { + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) + && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK)) + return FALSE; + } else if (!strcmp(key_mgmt, "wpa-eap")) { + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + } else if (!strcmp(key_mgmt, "sae")) { + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_SAE) + && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE)) + return FALSE; + } else if (!strcmp(key_mgmt, "owe")) { + if (!NM_FLAGS_ANY(ap_wpa, + NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM) + && !NM_FLAGS_ANY(ap_rsn, + NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) + return FALSE; + } + + // FIXME: should handle WPA and RSN separately here to ensure that + // if the Connection only uses WPA we don't match a cipher against + // the AP's RSN IE instead + + /* Match at least one pairwise cipher with AP's capability if the + * wireless-security setting explicitly lists pairwise ciphers + */ + num = nm_setting_wireless_security_get_num_pairwise(s_wireless_sec); + for (i = 0, found = FALSE; i < num; i++) { + cipher = nm_setting_wireless_security_get_pairwise(s_wireless_sec, i); + if ((found = match_cipher(cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_TKIP))) + break; + if ((found = match_cipher(cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_CCMP))) + break; + } + if (!found && num) + return FALSE; + + /* Match at least one group cipher with AP's capability if the + * wireless-security setting explicitly lists group ciphers + */ + num = nm_setting_wireless_security_get_num_groups(s_wireless_sec); + for (i = 0, found = FALSE; i < num; i++) { + cipher = nm_setting_wireless_security_get_group(s_wireless_sec, i); + + if ((found = + match_cipher(cipher, "wep40", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP40))) + break; + if ((found = + match_cipher(cipher, "wep104", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP104))) + break; + if ((found = match_cipher(cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_TKIP))) + break; + if ((found = match_cipher(cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_CCMP))) + break; + } + if (!found && num) + return FALSE; + + return TRUE; + } + + return FALSE; +} + +/** + * nm_setting_wireless_get_ssid: + * @setting: the #NMSettingWireless + * + * Returns: (transfer none): the #NMSettingWireless:ssid property of the setting + **/ +GBytes * +nm_setting_wireless_get_ssid(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->ssid; +} + +/** + * nm_setting_wireless_get_mode: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:mode property of the setting + **/ +const char * +nm_setting_wireless_get_mode(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mode; +} + +/** + * nm_setting_wireless_get_band: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:band property of the setting + **/ +const char * +nm_setting_wireless_get_band(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->band; +} + +/** + * nm_setting_wireless_get_channel: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:channel property of the setting + **/ +guint32 +nm_setting_wireless_get_channel(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->channel; +} + +/** + * nm_setting_wireless_get_bssid: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:bssid property of the setting + **/ +const char * +nm_setting_wireless_get_bssid(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->bssid; +} + +/** + * nm_setting_wireless_get_rate: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:rate property of the setting + **/ +guint32 +nm_setting_wireless_get_rate(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->rate; +} + +/** + * nm_setting_wireless_get_tx_power: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:tx-power property of the setting + **/ +guint32 +nm_setting_wireless_get_tx_power(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->tx_power; +} + +/** + * nm_setting_wireless_get_mac_address: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:mac-address property of the setting + **/ +const char * +nm_setting_wireless_get_mac_address(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->device_mac_address; +} + +/** + * nm_setting_wireless_get_cloned_mac_address: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:cloned-mac-address property of the setting + **/ +const char * +nm_setting_wireless_get_cloned_mac_address(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->cloned_mac_address; +} + +/** + * nm_setting_wireless_get_generate_mac_address_mask: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:generate-mac-address-mask property of the setting + * + * Since: 1.4 + **/ +const char * +nm_setting_wireless_get_generate_mac_address_mask(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->generate_mac_address_mask; +} + +/** + * nm_setting_wireless_get_mac_address_blacklist: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:mac-address-blacklist property of the setting + **/ +const char *const * +nm_setting_wireless_get_mac_address_blacklist(NMSettingWireless *setting) +{ + NMSettingWirelessPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + return (const char *const *) priv->mac_address_blacklist->data; +} + +/** + * nm_setting_wireless_get_num_mac_blacklist_items: + * @setting: the #NMSettingWireless + * + * Returns: the number of blacklisted MAC addresses + **/ +guint32 +nm_setting_wireless_get_num_mac_blacklist_items(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mac_address_blacklist->len; +} + +/** + * nm_setting_wireless_get_mac_blacklist_item: + * @setting: the #NMSettingWireless + * @idx: the zero-based index of the MAC address entry + * + * Returns: the blacklisted MAC address string (hex-digits-and-colons notation) + * at index @idx + **/ +const char * +nm_setting_wireless_get_mac_blacklist_item(NMSettingWireless *setting, guint32 idx) +{ + NMSettingWirelessPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + g_return_val_if_fail(idx <= priv->mac_address_blacklist->len, NULL); + + return g_array_index(priv->mac_address_blacklist, const char *, idx); +} + +/** + * nm_setting_wireless_add_mac_blacklist_item: + * @setting: the #NMSettingWireless + * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist + * + * Adds a new MAC address to the #NMSettingWireless:mac-address-blacklist property. + * + * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address + * is invalid or was already present + **/ +gboolean +nm_setting_wireless_add_mac_blacklist_item(NMSettingWireless *setting, const char *mac) +{ + NMSettingWirelessPrivate *priv; + const char * candidate; + int i; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), FALSE); + g_return_val_if_fail(mac != NULL, FALSE); + + if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) + return FALSE; + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + for (i = 0; i < priv->mac_address_blacklist->len; i++) { + candidate = g_array_index(priv->mac_address_blacklist, char *, i); + if (nm_utils_hwaddr_matches(mac, -1, candidate, -1)) + return FALSE; + } + + mac = nm_utils_hwaddr_canonical(mac, ETH_ALEN); + g_array_append_val(priv->mac_address_blacklist, mac); + _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); + return TRUE; +} + +/** + * nm_setting_wireless_remove_mac_blacklist_item: + * @setting: the #NMSettingWireless + * @idx: index number of the MAC address + * + * Removes the MAC address at index @idx from the blacklist. + **/ +void +nm_setting_wireless_remove_mac_blacklist_item(NMSettingWireless *setting, guint32 idx) +{ + NMSettingWirelessPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_WIRELESS(setting)); + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + g_return_if_fail(idx < priv->mac_address_blacklist->len); + + g_array_remove_index(priv->mac_address_blacklist, idx); + _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); +} + +/** + * nm_setting_wireless_remove_mac_blacklist_item_by_value: + * @setting: the #NMSettingWireless + * @mac: the MAC address string (hex-digits-and-colons notation) to remove from + * the blacklist + * + * Removes the MAC address @mac from the blacklist. + * + * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not. + **/ +gboolean +nm_setting_wireless_remove_mac_blacklist_item_by_value(NMSettingWireless *setting, const char *mac) +{ + NMSettingWirelessPrivate *priv; + const char * candidate; + int i; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), FALSE); + g_return_val_if_fail(mac != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + for (i = 0; i < priv->mac_address_blacklist->len; i++) { + candidate = g_array_index(priv->mac_address_blacklist, char *, i); + if (!nm_utils_hwaddr_matches(mac, -1, candidate, -1)) { + g_array_remove_index(priv->mac_address_blacklist, i); + _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_wireless_clear_mac_blacklist_items: + * @setting: the #NMSettingWireless + * + * Removes all blacklisted MAC addresses. + **/ +void +nm_setting_wireless_clear_mac_blacklist_items(NMSettingWireless *setting) +{ + g_return_if_fail(NM_IS_SETTING_WIRELESS(setting)); + + g_array_set_size(NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mac_address_blacklist, 0); + _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); +} + +/** + * nm_setting_wireless_get_mtu: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:mtu property of the setting + **/ +guint32 +nm_setting_wireless_get_mtu(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mtu; +} + +/** + * nm_setting_wireless_get_hidden: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:hidden property of the setting + **/ +gboolean +nm_setting_wireless_get_hidden(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), FALSE); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->hidden; +} + +/** + * nm_setting_wireless_get_powersave: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:powersave property of the setting + * + * Since: 1.2 + **/ +guint32 +nm_setting_wireless_get_powersave(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->powersave; +} + +/** + * nm_setting_wireless_get_mac_address_randomization: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:mac-address-randomization property of the + * setting + * + * Since: 1.2 + **/ +NMSettingMacRandomization +nm_setting_wireless_get_mac_address_randomization(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->mac_address_randomization; +} + +/** + * nm_setting_wireless_add_seen_bssid: + * @setting: the #NMSettingWireless + * @bssid: the new BSSID to add to the list + * + * Adds a new Wi-Fi AP's BSSID to the previously seen BSSID list of the setting. + * NetworkManager now tracks previously seen BSSIDs internally so this function + * no longer has much use. Actually, changes you make using this function will + * not be preserved. + * + * Returns: %TRUE if @bssid was already known, %FALSE if not + **/ +gboolean +nm_setting_wireless_add_seen_bssid(NMSettingWireless *setting, const char *bssid) +{ + NMSettingWirelessPrivate *priv; + gs_free char * lower_bssid = NULL; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), FALSE); + g_return_val_if_fail(bssid != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + + lower_bssid = g_ascii_strdown(bssid, -1); + + if (!priv->seen_bssids) { + priv->seen_bssids = g_ptr_array_new_with_free_func(g_free); + } else { + if (nm_utils_strv_find_first((char **) priv->seen_bssids->pdata, + priv->seen_bssids->len, + lower_bssid) + >= 0) + return FALSE; + } + + g_ptr_array_add(priv->seen_bssids, g_steal_pointer(&lower_bssid)); + _notify(setting, PROP_SEEN_BSSIDS); + return TRUE; +} + +/** + * nm_setting_wireless_get_num_seen_bssids: + * @setting: the #NMSettingWireless + * + * Returns: the number of BSSIDs in the previously seen BSSID list + **/ +guint32 +nm_setting_wireless_get_num_seen_bssids(NMSettingWireless *setting) +{ + NMSettingWirelessPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + + return priv->seen_bssids ? priv->seen_bssids->len : 0u; +} + +/** + * nm_setting_wireless_get_seen_bssid: + * @setting: the #NMSettingWireless + * @i: index of a BSSID in the previously seen BSSID list + * + * Returns: the BSSID at index @i + **/ +const char * +nm_setting_wireless_get_seen_bssid(NMSettingWireless *setting, guint32 i) +{ + NMSettingWirelessPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), 0); + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + + if (!priv->seen_bssids || i >= priv->seen_bssids->len) + return NULL; + + return priv->seen_bssids->pdata[i]; +} + +static GVariant * +_to_dbus_fcn_seen_bssids(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + NMSettingWirelessPrivate *priv; + + if (options && options->seen_bssids) { + return options->seen_bssids[0] ? g_variant_new_strv(options->seen_bssids, -1) : NULL; + } + + priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + + if (!priv->seen_bssids || priv->seen_bssids->len == 0) + return NULL; + + return g_variant_new_strv((const char *const *) priv->seen_bssids->pdata, + priv->seen_bssids->len); +} + +/** + * nm_setting_wireless_get_ap_isolation: + * @setting: the #NMSettingWireless + * + * Returns: the #NMSettingWireless:ap-isolation property of the setting + * + * Since: 1.28 + */ +NMTernary +nm_setting_wireless_get_ap_isolation(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NM_TERNARY_DEFAULT); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->ap_isolation; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + const char * valid_modes[] = {NM_SETTING_WIRELESS_MODE_INFRA, + NM_SETTING_WIRELESS_MODE_ADHOC, + NM_SETTING_WIRELESS_MODE_AP, + NM_SETTING_WIRELESS_MODE_MESH, + NULL}; + const char * valid_bands[] = {"a", "bg", NULL}; + guint i; + gsize length; + GError * local = NULL; + + if (!priv->ssid) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID); + return FALSE; + } + + length = g_bytes_get_size(priv->ssid); + if (length == 0 || length > 32) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("SSID length is out of range <1-32> bytes")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID); + return FALSE; + } + + if (priv->mode && !g_strv_contains(valid_modes, priv->mode)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid Wi-Fi mode"), + priv->mode); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MODE); + return FALSE; + } + + if (priv->band && !g_strv_contains(valid_bands, priv->band)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid band"), + priv->band); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_BAND); + return FALSE; + } + + if (priv->channel && !priv->band) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("'%s' requires setting '%s' property"), + NM_SETTING_WIRELESS_CHANNEL, + NM_SETTING_WIRELESS_BAND); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_BAND); + return FALSE; + } + + if (priv->channel) { + if (!nm_utils_wifi_is_channel_valid(priv->channel, priv->band)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%d' is not a valid channel"), + priv->channel); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_CHANNEL); + return FALSE; + } + } + + if ((g_strcmp0(priv->mode, NM_SETTING_WIRELESS_MODE_MESH) == 0) + && !(priv->channel && priv->band)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("'%s' requires '%s' and '%s' property"), + priv->mode, + NM_SETTING_WIRELESS_BAND, + NM_SETTING_WIRELESS_CHANNEL); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MODE); + return FALSE; + } + + if (priv->bssid && !nm_utils_hwaddr_valid(priv->bssid, ETH_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_BSSID); + return FALSE; + } + + if (priv->device_mac_address && !nm_utils_hwaddr_valid(priv->device_mac_address, ETH_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MAC_ADDRESS); + return FALSE; + } + + if (priv->cloned_mac_address && !NM_CLONED_MAC_IS_SPECIAL(priv->cloned_mac_address) + && !nm_utils_hwaddr_valid(priv->cloned_mac_address, ETH_ALEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS); + return FALSE; + } + + /* generate-mac-address-mask only makes sense with cloned-mac-address "random" or + * "stable". Still, let's not be so strict about that and accept the value + * even if it is unused. */ + if (!_nm_utils_generate_mac_address_mask_parse(priv->generate_mac_address_mask, + NULL, + NULL, + NULL, + &local)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + local->message); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK); + g_error_free(local); + return FALSE; + } + + for (i = 0; i < priv->mac_address_blacklist->len; i++) { + const char *mac = g_array_index(priv->mac_address_blacklist, const char *, i); + + if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid MAC address"), + mac); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST); + return FALSE; + } + } + + if (priv->seen_bssids) { + for (i = 0; i < priv->seen_bssids->len; i++) { + const char *b; + + b = priv->seen_bssids->pdata[i]; + if (!nm_utils_hwaddr_valid(b, ETH_ALEN)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid MAC address"), + b); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SEEN_BSSIDS); + return FALSE; + } + } + } + + if (!NM_IN_SET(priv->mac_address_randomization, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + NM_SETTING_MAC_RANDOMIZATION_NEVER, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid value")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION); + return FALSE; + } + + if (NM_FLAGS_ANY(priv->wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS)) { + if (!nm_utils_is_power_of_two(priv->wowl)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Wake-on-WLAN mode 'default' and 'ignore' are exclusive flags")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_WAKE_ON_WLAN); + return FALSE; + } + } else if (NM_FLAGS_ANY(priv->wowl, ~NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Wake-on-WLAN trying to set unknown flag")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_WAKE_ON_WLAN); + return FALSE; + } + + if (priv->ap_isolation != NM_TERNARY_DEFAULT + && !nm_streq0(priv->mode, NM_SETTING_WIRELESS_MODE_AP)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("AP isolation can be set only in AP mode")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_AP_ISOLATION); + return FALSE; + } + + /* from here on, check for NM_SETTING_VERIFY_NORMALIZABLE conditions. */ + + if (priv->cloned_mac_address) { + if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS + && nm_streq(priv->cloned_mac_address, "random")) + goto mac_addr_rand_ok; + if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_NEVER + && nm_streq(priv->cloned_mac_address, "permanent")) + goto mac_addr_rand_ok; + if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) + goto mac_addr_rand_ok; + } else if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) + goto mac_addr_rand_ok; + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("conflicting value of mac-address-randomization and cloned-mac-address")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS); + return NM_SETTING_VERIFY_NORMALIZABLE; +mac_addr_rand_ok: + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + if (nm_streq(sett_info->property_infos[property_idx].name, + NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) { + return !set_b + || nm_streq0(NM_SETTING_WIRELESS_GET_PRIVATE(set_a)->cloned_mac_address, + NM_SETTING_WIRELESS_GET_PRIVATE(set_b)->cloned_mac_address); + } + + return NM_SETTING_CLASS(nm_setting_wireless_parent_class) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); +} + +/*****************************************************************************/ + +static GVariant * +nm_setting_wireless_get_security(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + return NULL; + + if (!connection) + return NULL; + + if (!nm_connection_get_setting_wireless_security(connection)) + return NULL; + + return g_variant_new_string(NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); +} + +/** + * nm_setting_wireless_get_wake_on_wlan: + * @setting: the #NMSettingWireless + * + * Returns the Wake-on-WLAN options enabled for the connection + * + * Returns: the Wake-on-WLAN options + * + * Since: 1.12 + */ +NMSettingWirelessWakeOnWLan +nm_setting_wireless_get_wake_on_wlan(NMSettingWireless *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE); + + return NM_SETTING_WIRELESS_GET_PRIVATE(setting)->wowl; +} + +static void +clear_blacklist_item(char **item_p) +{ + g_free(*item_p); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingWireless * setting = NM_SETTING_WIRELESS(object); + NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_SSID: + g_value_set_boxed(value, nm_setting_wireless_get_ssid(setting)); + break; + case PROP_MODE: + g_value_set_string(value, nm_setting_wireless_get_mode(setting)); + break; + case PROP_BAND: + g_value_set_string(value, nm_setting_wireless_get_band(setting)); + break; + case PROP_CHANNEL: + g_value_set_uint(value, nm_setting_wireless_get_channel(setting)); + break; + case PROP_BSSID: + g_value_set_string(value, nm_setting_wireless_get_bssid(setting)); + break; + case PROP_RATE: + g_value_set_uint(value, nm_setting_wireless_get_rate(setting)); + break; + case PROP_TX_POWER: + g_value_set_uint(value, nm_setting_wireless_get_tx_power(setting)); + break; + case PROP_MAC_ADDRESS: + g_value_set_string(value, nm_setting_wireless_get_mac_address(setting)); + break; + case PROP_CLONED_MAC_ADDRESS: + g_value_set_string(value, nm_setting_wireless_get_cloned_mac_address(setting)); + break; + case PROP_GENERATE_MAC_ADDRESS_MASK: + g_value_set_string(value, nm_setting_wireless_get_generate_mac_address_mask(setting)); + break; + case PROP_MAC_ADDRESS_BLACKLIST: + g_value_set_boxed(value, (char **) priv->mac_address_blacklist->data); + break; + case PROP_MTU: + g_value_set_uint(value, nm_setting_wireless_get_mtu(setting)); + break; + case PROP_SEEN_BSSIDS: + g_value_take_boxed(value, + priv->seen_bssids ? nm_utils_strv_dup((char **) priv->seen_bssids->pdata, + priv->seen_bssids->len, + TRUE) + : NULL); + break; + case PROP_HIDDEN: + g_value_set_boolean(value, nm_setting_wireless_get_hidden(setting)); + break; + case PROP_POWERSAVE: + g_value_set_uint(value, nm_setting_wireless_get_powersave(setting)); + break; + case PROP_MAC_ADDRESS_RANDOMIZATION: + g_value_set_uint(value, nm_setting_wireless_get_mac_address_randomization(setting)); + break; + case PROP_WAKE_ON_WLAN: + g_value_set_uint(value, nm_setting_wireless_get_wake_on_wlan(setting)); + break; + case PROP_AP_ISOLATION: + g_value_set_enum(value, priv->ap_isolation); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(object); + const char *const * blacklist; + const char * mac; + gboolean bool_val; + + switch (prop_id) { + case PROP_SSID: + if (priv->ssid) + g_bytes_unref(priv->ssid); + priv->ssid = g_value_dup_boxed(value); + break; + case PROP_MODE: + g_free(priv->mode); + priv->mode = g_value_dup_string(value); + break; + case PROP_BAND: + g_free(priv->band); + priv->band = g_value_dup_string(value); + break; + case PROP_CHANNEL: + priv->channel = g_value_get_uint(value); + break; + case PROP_BSSID: + g_free(priv->bssid); + priv->bssid = g_value_dup_string(value); + break; + case PROP_RATE: + priv->rate = g_value_get_uint(value); + break; + case PROP_TX_POWER: + priv->tx_power = g_value_get_uint(value); + break; + case PROP_MAC_ADDRESS: + g_free(priv->device_mac_address); + priv->device_mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); + break; + case PROP_CLONED_MAC_ADDRESS: + bool_val = !!priv->cloned_mac_address; + g_free(priv->cloned_mac_address); + priv->cloned_mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); + if (bool_val && !priv->cloned_mac_address) { + /* cloned-mac-address was set before but was now explicitly cleared. + * In this case, we also clear mac-address-randomization flag */ + if (priv->mac_address_randomization != NM_SETTING_MAC_RANDOMIZATION_DEFAULT) { + priv->mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_DEFAULT; + _notify(NM_SETTING_WIRELESS(object), PROP_MAC_ADDRESS_RANDOMIZATION); + } + } + break; + case PROP_GENERATE_MAC_ADDRESS_MASK: + g_free(priv->generate_mac_address_mask); + priv->generate_mac_address_mask = g_value_dup_string(value); + break; + case PROP_MAC_ADDRESS_BLACKLIST: + blacklist = g_value_get_boxed(value); + g_array_set_size(priv->mac_address_blacklist, 0); + if (blacklist && blacklist[0]) { + gsize i; + + for (i = 0; blacklist[i]; i++) { + mac = _nm_utils_hwaddr_canonical_or_invalid(blacklist[i], ETH_ALEN); + g_array_append_val(priv->mac_address_blacklist, mac); + } + } + break; + case PROP_MTU: + priv->mtu = g_value_get_uint(value); + break; + case PROP_SEEN_BSSIDS: + { + gs_unref_ptrarray GPtrArray *arr_old = NULL; + const char *const * strv; + + arr_old = g_steal_pointer(&priv->seen_bssids); + + strv = g_value_get_boxed(value); + if (strv && strv[0]) { + gsize i, l; + + l = NM_PTRARRAY_LEN(strv); + priv->seen_bssids = g_ptr_array_new_full(l, g_free); + for (i = 0; i < l; i++) + g_ptr_array_add(priv->seen_bssids, g_strdup(strv[i])); + } + break; + } + case PROP_HIDDEN: + priv->hidden = g_value_get_boolean(value); + break; + case PROP_POWERSAVE: + priv->powersave = g_value_get_uint(value); + break; + case PROP_MAC_ADDRESS_RANDOMIZATION: + priv->mac_address_randomization = g_value_get_uint(value); + break; + case PROP_WAKE_ON_WLAN: + priv->wowl = g_value_get_uint(value); + break; + case PROP_AP_ISOLATION: + priv->ap_isolation = g_value_get_enum(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_wireless_init(NMSettingWireless *setting) +{ + NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); + + /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */ + priv->mac_address_blacklist = g_array_new(TRUE, FALSE, sizeof(char *)); + g_array_set_clear_func(priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item); + + priv->wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT; + priv->ap_isolation = NM_TERNARY_DEFAULT; +} + +/** + * nm_setting_wireless_new: + * + * Creates a new #NMSettingWireless object with default values. + * + * Returns: (transfer full): the new empty #NMSettingWireless object + **/ +NMSetting * +nm_setting_wireless_new(void) +{ + return g_object_new(NM_TYPE_SETTING_WIRELESS, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE(object); + + g_free(priv->mode); + g_free(priv->band); + + if (priv->ssid) + g_bytes_unref(priv->ssid); + g_free(priv->bssid); + g_free(priv->device_mac_address); + g_free(priv->cloned_mac_address); + g_free(priv->generate_mac_address_mask); + g_array_unref(priv->mac_address_blacklist); + nm_clear_pointer(&priv->seen_bssids, g_ptr_array_unref); + + G_OBJECT_CLASS(nm_setting_wireless_parent_class)->finalize(object); +} + +static void +nm_setting_wireless_class_init(NMSettingWirelessClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray * properties_override = _nm_sett_info_property_override_create_array(); + + g_type_class_add_private(klass, sizeof(NMSettingWirelessPrivate)); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + setting_class->compare_property = compare_property; + + /** + * NMSettingWireless:ssid: + * + * SSID of the Wi-Fi network. Must be specified. + **/ + /* ---keyfile--- + * property: ssid + * format: string (or decimal-byte list - obsolete) + * description: SSID of Wi-Fi network. + * example: ssid=Quick Net + * ---end--- + * ---ifcfg-rh--- + * property: ssid + * variable: ESSID + * description: SSID of Wi-Fi network. + * example: ESSID="Quick Net" + * ---end--- + */ + obj_properties[PROP_SSID] = g_param_spec_boxed(NM_SETTING_WIRELESS_SSID, + "", + "", + G_TYPE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:mode: + * + * Wi-Fi network mode; one of "infrastructure", "mesh", "adhoc" or "ap". If blank, + * infrastructure is assumed. + **/ + /* ---ifcfg-rh--- + * property: mode + * variable: MODE + * values: Ad-Hoc, Managed (Auto) [case insensitive] + * description: Wi-Fi network mode. + * ---end--- + */ + obj_properties[PROP_MODE] = g_param_spec_string(NM_SETTING_WIRELESS_MODE, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:band: + * + * 802.11 frequency band of the network. One of "a" for 5GHz 802.11a or + * "bg" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network + * to the specific band, i.e. if "a" is specified, the device will not + * associate with the same network in the 2.4GHz band even if the network's + * settings are compatible. This setting depends on specific driver + * capability and may not work with all drivers. + **/ + /* ---ifcfg-rh--- + * property: band + * variable: BAND(+) + * values: a, bg + * description: BAND alone is honored, but CHANNEL overrides BAND since it + * implies a band. + * example: BAND=bg + * ---end--- + */ + obj_properties[PROP_BAND] = g_param_spec_string(NM_SETTING_WIRELESS_BAND, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:channel: + * + * Wireless channel to use for the Wi-Fi connection. The device will only + * join (or create for Ad-Hoc networks) a Wi-Fi network on the specified + * channel. Because channel numbers overlap between bands, this property + * also requires the "band" property to be set. + **/ + /* ---ifcfg-rh--- + * property: channel + * variable: CHANNEL + * description: Channel used for the Wi-Fi communication. + * Channels greater than 14 mean "a" band, otherwise the + * band is "bg". + * example: CHANNEL=6 + * ---end--- + */ + obj_properties[PROP_CHANNEL] = g_param_spec_uint(NM_SETTING_WIRELESS_CHANNEL, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:bssid: + * + * If specified, directs the device to only associate with the given access + * point. This capability is highly driver dependent and not supported by + * all devices. Note: this property does not control the BSSID used when + * creating an Ad-Hoc network and is unlikely to in the future. + **/ + /* ---ifcfg-rh--- + * property: bssid + * variable: BSSID(+) + * description: Restricts association only to a single AP. + * example: BSSID=00:1E:BD:64:83:21 + * ---end--- + */ + obj_properties[PROP_BSSID] = g_param_spec_string(NM_SETTING_WIRELESS_BSSID, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_BSSID], + &nm_sett_info_propert_type_mac_address); + + /** + * NMSettingWireless:rate: + * + * If non-zero, directs the device to only use the specified bitrate for + * communication with the access point. Units are in Kb/s, ie 5500 = 5.5 + * Mbit/s. This property is highly driver dependent and not all devices + * support setting a static bitrate. + **/ + /* ---ifcfg-rh--- + * property: rate + * variable: (none) + * description: This property is not handled by ifcfg-rh plugin. + * ---end--- + */ + obj_properties[PROP_RATE] = g_param_spec_uint(NM_SETTING_WIRELESS_RATE, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:tx-power: + * + * If non-zero, directs the device to use the specified transmit power. + * Units are dBm. This property is highly driver dependent and not all + * devices support setting a static transmit power. + **/ + /* ---ifcfg-rh--- + * property: tx-power + * variable: (none) + * description: This property is not handled by ifcfg-rh plugin. + * ---end--- + */ + obj_properties[PROP_TX_POWER] = g_param_spec_uint( + NM_SETTING_WIRELESS_TX_POWER, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:mac-address: + * + * If specified, this connection will only apply to the Wi-Fi device whose + * permanent MAC address matches. This property does not change the MAC + * address of the device (i.e. MAC spoofing). + **/ + /* ---keyfile--- + * property: mac-address + * format: usual hex-digits-and-colons notation + * description: MAC address in traditional hex-digits-and-colons notation + * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) + * (e.g. 0;34;104;18;121;162). + * ---end--- + * ---ifcfg-rh--- + * property: mac-address + * variable: HWADDR + * description: Hardware address of the device in traditional hex-digits-and-colons + * notation (e.g. 00:22:68:14:5A:05). + * Note that for initscripts this is the current MAC address of the device as found + * during ifup. For NetworkManager this is the permanent MAC address. Or in case no + * permanent MAC address exists, the MAC address initially configured on the device. + * ---end--- + */ + obj_properties[PROP_MAC_ADDRESS] = + g_param_spec_string(NM_SETTING_WIRELESS_MAC_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_MAC_ADDRESS], + &nm_sett_info_propert_type_mac_address); + + /** + * NMSettingWireless:cloned-mac-address: + * + * If specified, request that the device use this MAC address instead. + * This is known as MAC cloning or spoofing. + * + * Beside explicitly specifying a MAC address, the special values "preserve", "permanent", + * "random" and "stable" are supported. + * "preserve" means not to touch the MAC address on activation. + * "permanent" means to use the permanent hardware address of the device. + * "random" creates a random MAC address on each connect. + * "stable" creates a hashed MAC address based on connection.stable-id and a + * machine dependent key. + * + * If unspecified, the value can be overwritten via global defaults, see manual + * of NetworkManager.conf. If still unspecified, it defaults to "preserve" + * (older versions of NetworkManager may use a different default value). + * + * On D-Bus, this field is expressed as "assigned-mac-address" or the deprecated + * "cloned-mac-address". + **/ + /* ---keyfile--- + * property: cloned-mac-address + * format: usual hex-digits-and-colons notation + * description: Cloned MAC address in traditional hex-digits-and-colons notation + * (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete) + * (e.g. 0;34;104;18;121;178). + * ---end--- + * ---ifcfg-rh--- + * property: cloned-mac-address + * variable: MACADDR + * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons + * notation (e.g. 00:22:68:14:5A:99). + * ---end--- + * ---dbus--- + * property: cloned-mac-address + * format: byte array + * description: This D-Bus field is deprecated in favor of "assigned-mac-address" + * which is more flexible and allows specifying special variants like "random". + * For libnm and nmcli, this field is called "cloned-mac-address". + * ---end--- + */ + obj_properties[PROP_CLONED_MAC_ADDRESS] = g_param_spec_string( + NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj(properties_override, + obj_properties[PROP_CLONED_MAC_ADDRESS], + &nm_sett_info_propert_type_cloned_mac_address); + + /* ---dbus--- + * property: assigned-mac-address + * format: string + * description: The new field for the cloned MAC address. It can be either + * a hardware address in ASCII representation, or one of the special values + * "preserve", "permanent", "random" or "stable". + * This field replaces the deprecated "cloned-mac-address" on D-Bus, which + * can only contain explicit hardware addresses. Note that this property + * only exists in D-Bus API. libnm and nmcli continue to call this property + * "cloned-mac-address". + * ---end--- + */ + _nm_properties_override_dbus(properties_override, + "assigned-mac-address", + &nm_sett_info_propert_type_assigned_mac_address); + + /** + * NMSettingWireless:generate-mac-address-mask: + * + * With #NMSettingWireless:cloned-mac-address setting "random" or "stable", + * by default all bits of the MAC address are scrambled and a locally-administered, + * unicast MAC address is created. This property allows to specify that certain bits + * are fixed. Note that the least significant bit of the first MAC address will + * always be unset to create a unicast MAC address. + * + * If the property is %NULL, it is eligible to be overwritten by a default + * connection setting. If the value is still %NULL or an empty string, the + * default is to create a locally-administered, unicast MAC address. + * + * If the value contains one MAC address, this address is used as mask. The set + * bits of the mask are to be filled with the current MAC address of the device, + * while the unset bits are subject to randomization. + * Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address + * and only randomize the lower 3 bytes using the "random" or "stable" algorithm. + * + * If the value contains one additional MAC address after the mask, + * this address is used instead of the current MAC address to fill the bits + * that shall not be randomized. For example, a value of + * "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address + * to 68:F7:28, while the lower bits are randomized. A value of + * "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled + * globally-administered, burned-in MAC address. + * + * If the value contains more than one additional MAC addresses, one of + * them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" + * will create a fully scrambled MAC address, randomly locally or globally + * administered. + **/ + /* ---ifcfg-rh--- + * property: generate-mac-address-mask + * variable: GENERATE_MAC_ADDRESS_MASK(+) + * description: the MAC address mask for generating randomized and stable + * cloned-mac-address. + * ---end--- + */ + obj_properties[PROP_GENERATE_MAC_ADDRESS_MASK] = g_param_spec_string( + NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK, + "", + "", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:mac-address-blacklist: + * + * A list of permanent MAC addresses of Wi-Fi devices to which this + * connection should never apply. Each MAC address should be given in the + * standard hex-digits-and-colons notation (eg "00:11:22:33:44:55"). + **/ + /* ---keyfile--- + * property: mac-address-blacklist + * format: list of MACs (separated with semicolons) + * description: MAC address blacklist. + * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78 + * ---end--- + * ---ifcfg-rh--- + * property: mac-address-blacklist + * variable: HWADDR_BLACKLIST(+) + * description: It denies usage of the connection for any device whose address + * is listed. + * ---end--- + */ + obj_properties[PROP_MAC_ADDRESS_BLACKLIST] = g_param_spec_boxed( + NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:seen-bssids: + * + * A list of BSSIDs (each BSSID formatted as a MAC address like + * "00:11:22:33:44:55") that have been detected as part of the Wi-Fi + * network. NetworkManager internally tracks previously seen BSSIDs. The + * property is only meant for reading and reflects the BSSID list of + * NetworkManager. The changes you make to this property will not be + * preserved. + **/ + /* ---ifcfg-rh--- + * property: seen-bssids + * variable: (none) + * description: This property is not handled by ifcfg-rh plugin. + * ---end--- + */ + obj_properties[PROP_SEEN_BSSIDS] = g_param_spec_boxed( + NM_SETTING_WIRELESS_SEEN_BSSIDS, + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_SEEN_BSSIDS], + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING_ARRAY, + .to_dbus_fcn = _to_dbus_fcn_seen_bssids, )); + + /** + * NMSettingWireless:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple Ethernet frames. + **/ + /* ---ifcfg-rh--- + * property: mtu + * variable: MTU + * description: MTU of the wireless interface. + * ---end--- + */ + obj_properties[PROP_MTU] = g_param_spec_uint(NM_SETTING_WIRELESS_MTU, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE + | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:hidden: + * + * If %TRUE, indicates that the network is a non-broadcasting network that + * hides its SSID. This works both in infrastructure and AP mode. + * + * In infrastructure mode, various workarounds are used for a more reliable + * discovery of hidden networks, such as probe-scanning the SSID. However, + * these workarounds expose inherent insecurities with hidden SSID networks, + * and thus hidden SSID networks should be used with caution. + * + * In AP mode, the created network does not broadcast its SSID. + * + * Note that marking the network as hidden may be a privacy issue for you + * (in infrastructure mode) or client stations (in AP mode), as the explicit + * probe-scans are distinctly recognizable on the air. + * + **/ + /* ---ifcfg-rh--- + * property: hidden + * variable: SSID_HIDDEN(+) + * description: Whether the network hides the SSID. + * ---end--- + */ + obj_properties[PROP_HIDDEN] = g_param_spec_boolean(NM_SETTING_WIRELESS_HIDDEN, + "", + "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:powersave: + * + * One of %NM_SETTING_WIRELESS_POWERSAVE_DISABLE (disable Wi-Fi power + * saving), %NM_SETTING_WIRELESS_POWERSAVE_ENABLE (enable Wi-Fi power + * saving), %NM_SETTING_WIRELESS_POWERSAVE_IGNORE (don't touch currently + * configure setting) or %NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (use the + * globally configured value). All other values are reserved. + * + * Since: 1.2 + **/ + /* ---ifcfg-rh--- + * property: powersave + * variable: POWERSAVE(+) + * values: default, ignore, enable, disable + * description: Enables or disables Wi-Fi power saving. + * example: POWERSAVE=enable + * ---end--- + */ + obj_properties[PROP_POWERSAVE] = g_param_spec_uint(NM_SETTING_WIRELESS_POWERSAVE, + "", + "", + 0, + G_MAXUINT32, + NM_SETTING_WIRELESS_POWERSAVE_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:mac-address-randomization: + * + * One of %NM_SETTING_MAC_RANDOMIZATION_DEFAULT (never randomize unless + * the user has set a global default to randomize and the supplicant + * supports randomization), %NM_SETTING_MAC_RANDOMIZATION_NEVER (never + * randomize the MAC address), or %NM_SETTING_MAC_RANDOMIZATION_ALWAYS + * (always randomize the MAC address). This property is deprecated for + * 'cloned-mac-address'. + * + * Since: 1.2 + * Deprecated: 1.4: Deprecated by NMSettingWireless:cloned-mac-address property. + **/ + /* ---ifcfg-rh--- + * property: mac-address-randomization + * variable: MAC_ADDRESS_RANDOMIZATION(+) + * values: default, never, always + * description: Enables or disables Wi-Fi MAC address randomization. + * example: MAC_ADDRESS_RANDOMIZATION=always + * ---end--- + */ + obj_properties[PROP_MAC_ADDRESS_RANDOMIZATION] = + g_param_spec_uint(NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, + "", + "", + 0, + G_MAXUINT32, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /* Compatibility for deprecated property */ + /* ---ifcfg-rh--- + * property: security + * variable: (none) + * description: This property is deprecated and not handled by ifcfg-rh-plugin. + * ---end--- + * ---dbus--- + * property: security + * description: This property is deprecated, but can be set to the value + * '802-11-wireless-security' when a wireless security setting is also + * present in the connection dictionary, for compatibility with very old + * NetworkManager daemons. + * ---end--- + */ + _nm_properties_override_dbus( + properties_override, + "security", + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING, + .to_dbus_fcn = nm_setting_wireless_get_security, )); + + /** + * NMSettingWireless:wake-on-wlan: + * + * The #NMSettingWirelessWakeOnWLan options to enable. Not all devices support all options. + * May be any combination of %NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY, + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT, + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC, + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE, + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST, + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE, + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE, + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP or the special values + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT (to use global settings) and + * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE (to disable management of Wake-on-LAN in + * NetworkManager). + * + * Since: 1.12 + **/ + obj_properties[PROP_WAKE_ON_WLAN] = + g_param_spec_uint(NM_SETTING_WIRELESS_WAKE_ON_WLAN, + "", + "", + 0, + G_MAXUINT32, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWireless:ap-isolation + * + * Configures AP isolation, which prevents communication between + * wireless devices connected to this AP. This property can be set + * to a value different from %NM_TERNARY_DEFAULT only when the + * interface is configured in AP mode. + * + * If set to %NM_TERNARY_TRUE, devices are not able to communicate + * with each other. This increases security because it protects + * devices against attacks from other clients in the network. At + * the same time, it prevents devices to access resources on the + * same wireless networks as file shares, printers, etc. + * + * If set to %NM_TERNARY_FALSE, devices can talk to each other. + * + * When set to %NM_TERNARY_DEFAULT, the global default is used; in + * case the global default is unspecified it is assumed to be + * %NM_TERNARY_FALSE. + * + * Since: 1.28 + **/ + /* ---ifcfg-rh--- + * property: ap-isolation + * variable: AP_ISOLATION(+) + * values: "yes", "no" + * default: missing variable means global default + * description: Whether AP isolation is enabled + * ---end--- + */ + obj_properties[PROP_AP_ISOLATION] = g_param_spec_enum( + NM_SETTING_WIRELESS_AP_ISOLATION, + "", + "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit_full(setting_class, + NM_META_SETTING_TYPE_WIRELESS, + NULL, + properties_override); +} diff --git a/src/libnm-core-impl/nm-setting-wpan.c b/src/libnm-core-impl/nm-setting-wpan.c new file mode 100644 index 0000000000..28a6478f16 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-wpan.c @@ -0,0 +1,393 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Lubomir Rintel + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-wpan.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-wpan + * @short_description: Describes connection properties for IEEE 802.15.4 (WPAN) MAC + * + * The #NMSettingWpan object is a #NMSetting subclass that describes properties + * necessary for configuring IEEE 802.15.4 (WPAN) MAC layer devices. + **/ + +/* Ideally we'll be able to get these from a public header. */ +#ifndef IEEE802154_ADDR_LEN + #define IEEE802154_ADDR_LEN 8 +#endif + +#ifndef IEEE802154_MAX_PAGE + #define IEEE802154_MAX_PAGE 31 +#endif + +#ifndef IEEE802154_MAX_CHANNEL + #define IEEE802154_MAX_CHANNEL 26 +#endif + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_MAC_ADDRESS, + PROP_PAN_ID, + PROP_SHORT_ADDRESS, + PROP_PAGE, + PROP_CHANNEL, ); + +typedef struct { + char * mac_address; + guint16 pan_id; + guint16 short_address; + gint16 page; + gint16 channel; +} NMSettingWpanPrivate; + +/** + * NMSettingWpan: + * + * IEEE 802.15.4 (WPAN) MAC Settings + */ +struct _NMSettingWpan { + NMSetting parent; +}; + +struct _NMSettingWpanClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingWpan, nm_setting_wpan, NM_TYPE_SETTING) + +#define NM_SETTING_WPAN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_WPAN, NMSettingWpanPrivate)) + +/*****************************************************************************/ + +/** + * nm_setting_wpan_get_mac_address: + * @setting: the #NMSettingWpan + * + * Returns: the #NMSettingWpan:mac-address property of the setting + * + * Since: 1.14 + **/ +const char * +nm_setting_wpan_get_mac_address(NMSettingWpan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), NULL); + + return NM_SETTING_WPAN_GET_PRIVATE(setting)->mac_address; +} + +/** + * nm_setting_wpan_get_pan_id: + * @setting: the #NMSettingWpan + * + * Returns: the #NMSettingWpan:pan-id property of the setting + * + * Since: 1.14 + **/ +guint16 +nm_setting_wpan_get_pan_id(NMSettingWpan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), G_MAXUINT16); + + return NM_SETTING_WPAN_GET_PRIVATE(setting)->pan_id; +} + +/** + * nm_setting_wpan_get_short_address: + * @setting: the #NMSettingWpan + * + * Returns: the #NMSettingWpan:short-address property of the setting + * + * Since: 1.14 + **/ +guint16 +nm_setting_wpan_get_short_address(NMSettingWpan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), G_MAXUINT16); + + return NM_SETTING_WPAN_GET_PRIVATE(setting)->short_address; +} + +/** + * nm_setting_wpan_get_page: + * @setting: the #NMSettingWpan + * + * Returns: the #NMSettingWpan:page property of the setting + * + * Since: 1.16 + **/ +gint16 +nm_setting_wpan_get_page(NMSettingWpan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), NM_SETTING_WPAN_PAGE_DEFAULT); + + return NM_SETTING_WPAN_GET_PRIVATE(setting)->page; +} + +/** + * nm_setting_wpan_get_channel: + * @setting: the #NMSettingWpan + * + * Returns: the #NMSettingWpan:channel property of the setting + * + * Since: 1.16 + **/ +gint16 +nm_setting_wpan_get_channel(NMSettingWpan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_WPAN(setting), NM_SETTING_WPAN_CHANNEL_DEFAULT); + + return NM_SETTING_WPAN_GET_PRIVATE(setting)->channel; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE(setting); + + if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, IEEE802154_ADDR_LEN)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_MAC_ADDRESS); + return FALSE; + } + + if ((priv->page == NM_SETTING_WPAN_PAGE_DEFAULT) + != (priv->channel == NM_SETTING_WPAN_CHANNEL_DEFAULT)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("page must be defined along with a channel")); + g_prefix_error(error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_PAGE); + return FALSE; + } + + if (priv->page < NM_SETTING_WPAN_PAGE_DEFAULT || priv->page > IEEE802154_MAX_PAGE) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("page must be between %d and %d"), + NM_SETTING_WPAN_PAGE_DEFAULT, + IEEE802154_MAX_PAGE); + g_prefix_error(error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_PAGE); + return FALSE; + } + + if (priv->channel < NM_SETTING_WPAN_CHANNEL_DEFAULT || priv->channel > IEEE802154_MAX_CHANNEL) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("channel must not be between %d and %d"), + NM_SETTING_WPAN_CHANNEL_DEFAULT, + IEEE802154_MAX_CHANNEL); + g_prefix_error(error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_CHANNEL); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingWpan *setting = NM_SETTING_WPAN(object); + + switch (prop_id) { + case PROP_MAC_ADDRESS: + g_value_set_string(value, nm_setting_wpan_get_mac_address(setting)); + break; + case PROP_PAN_ID: + g_value_set_uint(value, nm_setting_wpan_get_pan_id(setting)); + break; + case PROP_SHORT_ADDRESS: + g_value_set_uint(value, nm_setting_wpan_get_short_address(setting)); + break; + case PROP_PAGE: + g_value_set_int(value, nm_setting_wpan_get_page(setting)); + break; + case PROP_CHANNEL: + g_value_set_int(value, nm_setting_wpan_get_channel(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_MAC_ADDRESS: + g_free(priv->mac_address); + priv->mac_address = + _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), IEEE802154_ADDR_LEN); + break; + case PROP_PAN_ID: + priv->pan_id = g_value_get_uint(value); + break; + case PROP_SHORT_ADDRESS: + priv->short_address = g_value_get_uint(value); + break; + case PROP_PAGE: + priv->page = g_value_get_int(value); + break; + case PROP_CHANNEL: + priv->channel = g_value_get_int(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_wpan_init(NMSettingWpan *setting) +{ + NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE(setting); + + priv->pan_id = G_MAXUINT16; + priv->short_address = G_MAXUINT16; + priv->page = NM_SETTING_WPAN_PAGE_DEFAULT; + priv->channel = NM_SETTING_WPAN_CHANNEL_DEFAULT; +} + +/** + * nm_setting_wpan_new: + * + * Creates a new #NMSettingWpan object with default values. + * + * Returns: (transfer full): the new empty #NMSettingWpan object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_wpan_new(void) +{ + return g_object_new(NM_TYPE_SETTING_WPAN, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE(object); + + g_free(priv->mac_address); + + G_OBJECT_CLASS(nm_setting_wpan_parent_class)->finalize(object); +} + +static void +nm_setting_wpan_class_init(NMSettingWpanClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + + g_type_class_add_private(setting_class, sizeof(NMSettingWpanPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingWpan:mac-address: + * + * If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) + * MAC layer device whose permanent MAC address matches. + **/ + /* ---keyfile--- + * property: mac-address + * format: usual hex-digits-and-colons notation + * description: MAC address in hex-digits-and-colons notation + * (e.g. 76:d8:9b:87:66:60:84:ee). + * ---end--- + */ + obj_properties[PROP_MAC_ADDRESS] = + g_param_spec_string(NM_SETTING_WPAN_MAC_ADDRESS, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWpan:pan-id: + * + * IEEE 802.15.4 Personal Area Network (PAN) identifier. + **/ + obj_properties[PROP_PAN_ID] = g_param_spec_uint(NM_SETTING_WPAN_PAN_ID, + "", + "", + 0, + G_MAXUINT16, + G_MAXUINT16, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWpan:short-address: + * + * Short IEEE 802.15.4 address to be used within a restricted environment. + **/ + obj_properties[PROP_SHORT_ADDRESS] = + g_param_spec_uint(NM_SETTING_WPAN_SHORT_ADDRESS, + "", + "", + 0, + G_MAXUINT16, + G_MAXUINT16, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWpan:page: + * + * IEEE 802.15.4 channel page. A positive integer or -1, meaning "do not + * set, use whatever the device is already set to". + * + * Since: 1.16 + **/ + obj_properties[PROP_PAGE] = g_param_spec_int(NM_SETTING_WPAN_PAGE, + "", + "", + G_MININT16, + G_MAXINT16, + NM_SETTING_WPAN_PAGE_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMSettingWpan:channel: + * + * IEEE 802.15.4 channel. A positive integer or -1, meaning "do not + * set, use whatever the device is already set to". + * + * Since: 1.16 + **/ + obj_properties[PROP_CHANNEL] = g_param_spec_int(NM_SETTING_WPAN_CHANNEL, + "", + "", + G_MININT16, + G_MAXINT16, + NM_SETTING_WPAN_CHANNEL_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_WPAN); +} diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c new file mode 100644 index 0000000000..22ec0f6d34 --- /dev/null +++ b/src/libnm-core-impl/nm-setting.c @@ -0,0 +1,2834 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2011 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting.h" + +#include "nm-setting-private.h" +#include "nm-utils.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "nm-utils-private.h" +#include "nm-property-compare.h" + +/** + * SECTION:nm-setting + * @short_description: Describes related configuration information + * + * Each #NMSetting contains properties that describe configuration that applies + * to a specific network layer (like IPv4 or IPv6 configuration) or device type + * (like Ethernet, or Wi-Fi). A collection of individual settings together + * make up an #NMConnection. Each property is strongly typed and usually has + * a number of allowed values. See each #NMSetting subclass for a description + * of properties and allowed values. + */ + +/*****************************************************************************/ + +typedef struct { + GHashTable * hash; + const char **names; + GVariant ** values; +} GenData; + +typedef struct { + const char * name; + GType type; + NMSettingPriority priority; +} SettingInfo; + +NM_GOBJECT_PROPERTIES_DEFINE(NMSetting, PROP_NAME, ); + +typedef struct { + GenData *gendata; +} NMSettingPrivate; + +G_DEFINE_ABSTRACT_TYPE(NMSetting, nm_setting, G_TYPE_OBJECT) + +#define NM_SETTING_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING, NMSettingPrivate)) + +/*****************************************************************************/ + +static GenData *_gendata_hash(NMSetting *setting, gboolean create_if_necessary); + +/*****************************************************************************/ + +NMSettingPriority +_nm_setting_get_setting_priority(NMSetting *setting) +{ + const NMMetaSettingInfo *setting_info; + + g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_PRIORITY_INVALID); + + setting_info = NM_SETTING_GET_CLASS(setting)->setting_info; + return setting_info ? setting_info->setting_priority : NM_SETTING_PRIORITY_INVALID; +} + +NMSettingPriority +_nm_setting_get_base_type_priority(NMSetting *setting) +{ + g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_PRIORITY_INVALID); + + return nm_meta_setting_info_get_base_type_priority(NM_SETTING_GET_CLASS(setting)->setting_info, + G_OBJECT_TYPE(setting)); +} + +/** + * nm_setting_lookup_type: + * @name: a setting name + * + * Returns the #GType of the setting's class for a given setting name. + * + * Returns: the #GType of the setting's class, or %G_TYPE_INVALID if + * @name is not recognized. + **/ +GType +nm_setting_lookup_type(const char *name) +{ + const NMMetaSettingInfo *setting_info; + + g_return_val_if_fail(name, G_TYPE_INVALID); + + setting_info = nm_meta_setting_infos_by_name(name); + return setting_info ? setting_info->get_setting_gtype() : G_TYPE_INVALID; +} + +int +_nm_setting_compare_priority(gconstpointer a, gconstpointer b) +{ + NMSettingPriority prio_a, prio_b; + + prio_a = _nm_setting_get_setting_priority((NMSetting *) a); + prio_b = _nm_setting_get_setting_priority((NMSetting *) b); + + if (prio_a < prio_b) + return -1; + else if (prio_a == prio_b) + return 0; + return 1; +} + +/*****************************************************************************/ + +gboolean +_nm_setting_slave_type_is_valid(const char *slave_type, const char **out_port_type) +{ + const char *port_type = NULL; + gboolean found = TRUE; + + if (!slave_type) + found = FALSE; + else if (NM_IN_STRSET(slave_type, NM_SETTING_BOND_SETTING_NAME, NM_SETTING_VRF_SETTING_NAME)) { + /* pass */ + } else if (nm_streq(slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) + port_type = NM_SETTING_BRIDGE_PORT_SETTING_NAME; + else if (nm_streq(slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) + port_type = NM_SETTING_OVS_PORT_SETTING_NAME; + else if (nm_streq(slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) + port_type = NM_SETTING_OVS_INTERFACE_SETTING_NAME; + else if (nm_streq(slave_type, NM_SETTING_TEAM_SETTING_NAME)) + port_type = NM_SETTING_TEAM_PORT_SETTING_NAME; + else + found = FALSE; + + if (out_port_type) + *out_port_type = port_type; + return found; +} + +/*****************************************************************************/ + +static const NMSettInfoProperty * +_nm_sett_info_property_find_in_array(const NMSettInfoProperty *properties, + guint len, + const char * name) +{ + guint i; + + for (i = 0; i < len; i++) { + if (nm_streq(name, properties[i].name)) + return &properties[i]; + } + return NULL; +} + +static GVariant * +_gprop_to_dbus_fcn_bytes(const GValue *val) +{ + nm_assert(G_VALUE_HOLDS(val, G_TYPE_BYTES)); + return nm_utils_gbytes_to_variant_ay(g_value_get_boxed(val)); +} + +static GVariant * +_gprop_to_dbus_fcn_enum(const GValue *val) +{ + return g_variant_new_int32(g_value_get_enum(val)); +} + +static GVariant * +_gprop_to_dbus_fcn_flags(const GValue *val) +{ + return g_variant_new_uint32(g_value_get_flags(val)); +} + +gboolean +_nm_properties_override_assert(const NMSettInfoProperty *prop_info) +{ + nm_assert(prop_info); + nm_assert((!!prop_info->name) != (!!prop_info->param_spec)); + nm_assert(!prop_info->param_spec || !prop_info->name + || nm_streq0(prop_info->name, prop_info->param_spec->name)); + +#define _PROPERT_EXTRA(prop_info, member) \ + ({ \ + const NMSettInfoProperty *_prop_info = (prop_info); \ + \ + (_prop_info->property_type ? _prop_info->property_type->member : 0); \ + }) + + nm_assert(!_PROPERT_EXTRA(prop_info, gprop_from_dbus_fcn) + || _PROPERT_EXTRA(prop_info, dbus_type)); + nm_assert(!_PROPERT_EXTRA(prop_info, from_dbus_fcn) || _PROPERT_EXTRA(prop_info, dbus_type)); + nm_assert(!_PROPERT_EXTRA(prop_info, to_dbus_fcn) || _PROPERT_EXTRA(prop_info, dbus_type)); + + nm_assert(!_PROPERT_EXTRA(prop_info, to_dbus_fcn) + || !_PROPERT_EXTRA(prop_info, gprop_to_dbus_fcn)); + nm_assert(!_PROPERT_EXTRA(prop_info, from_dbus_fcn) + || !_PROPERT_EXTRA(prop_info, gprop_from_dbus_fcn)); + + nm_assert(!_PROPERT_EXTRA(prop_info, gprop_to_dbus_fcn) || prop_info->param_spec); + nm_assert(!_PROPERT_EXTRA(prop_info, gprop_from_dbus_fcn) || prop_info->param_spec); + +#undef _PROPERT_EXTRA + + return TRUE; +} + +static NMSettInfoSetting _sett_info_settings[_NM_META_SETTING_TYPE_NUM]; + +const NMSettInfoSetting * +nmtst_sett_info_settings(void) +{ + return _sett_info_settings; +} + +static int +_property_infos_sort_cmp_setting_connection(gconstpointer p_a, + gconstpointer p_b, + gpointer user_data) +{ + const NMSettInfoProperty *a = *((const NMSettInfoProperty *const *) p_a); + const NMSettInfoProperty *b = *((const NMSettInfoProperty *const *) p_b); + int c_name; + + c_name = strcmp(a->name, b->name); + nm_assert(c_name != 0); + +#define CMP_AND_RETURN(n_a, n_b, name) \ + G_STMT_START \ + { \ + gboolean _is = nm_streq(n_a, "" name); \ + \ + if (_is || nm_streq(n_b, "" name)) \ + return _is ? -1 : 1; \ + } \ + G_STMT_END + + /* for [connection], report first id, uuid, type in that order. */ + if (c_name != 0) { + CMP_AND_RETURN(a->name, b->name, NM_SETTING_CONNECTION_ID); + CMP_AND_RETURN(a->name, b->name, NM_SETTING_CONNECTION_UUID); + CMP_AND_RETURN(a->name, b->name, NM_SETTING_CONNECTION_TYPE); + } + +#undef CMP_AND_RETURN + + return c_name; +} + +static const NMSettInfoProperty *const * +_property_infos_sort(const NMSettInfoProperty *property_infos, + guint property_infos_len, + NMSettingClass * setting_class) +{ + const NMSettInfoProperty **arr; + guint i; + +#if NM_MORE_ASSERTS > 5 + /* assert that the property names are all unique and sorted. */ + for (i = 0; i < property_infos_len; i++) { + if (property_infos[i].param_spec) + nm_assert(nm_streq(property_infos[i].name, property_infos[i].param_spec->name)); + if (i > 0) + nm_assert(strcmp(property_infos[i - 1].name, property_infos[i].name) < 0); + } +#endif + + if (property_infos_len <= 1) + return NULL; + if (G_TYPE_FROM_CLASS(setting_class) != NM_TYPE_SETTING_CONNECTION) { + /* we only do something special for certain setting types. This one, + * has just alphabetical sorting. */ + return NULL; + } + + arr = g_new(const NMSettInfoProperty *, property_infos_len); + for (i = 0; i < property_infos_len; i++) + arr[i] = &property_infos[i]; + + g_qsort_with_data(arr, + property_infos_len, + sizeof(const NMSettInfoProperty *), + _property_infos_sort_cmp_setting_connection, + NULL); + return arr; +} + +void +_nm_setting_class_commit_full(NMSettingClass * setting_class, + NMMetaSettingType meta_type, + const NMSettInfoSettDetail *detail, + GArray * properties_override) +{ + NMSettInfoSetting *sett_info; + gs_free GParamSpec **property_specs = NULL; + guint i, n_property_specs, override_len; + + nm_assert(NM_IS_SETTING_CLASS(setting_class)); + nm_assert(!setting_class->setting_info); + + nm_assert(meta_type < G_N_ELEMENTS(_sett_info_settings)); + + sett_info = &_sett_info_settings[meta_type]; + + nm_assert(!sett_info->setting_class); + nm_assert(!sett_info->property_infos_len); + nm_assert(!sett_info->property_infos); + + if (!properties_override) { + override_len = 0; + properties_override = _nm_sett_info_property_override_create_array(); + } else + override_len = properties_override->len; + + property_specs = + g_object_class_list_properties(G_OBJECT_CLASS(setting_class), &n_property_specs); + + for (i = 0; i < properties_override->len; i++) { + NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); + + nm_assert((!!p->name) != (!!p->param_spec)); + + if (!p->name) { + nm_assert(p->param_spec); + p->name = p->param_spec->name; + } else + nm_assert(!p->param_spec); + } + +#if NM_MORE_ASSERTS > 10 + /* assert that properties_override is constructed consistently. */ + for (i = 0; i < override_len; i++) { + const NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); + gboolean found = FALSE; + guint j; + + nm_assert( + !_nm_sett_info_property_find_in_array((NMSettInfoProperty *) properties_override->data, + i, + p->name)); + for (j = 0; j < n_property_specs; j++) { + if (!nm_streq(property_specs[j]->name, p->name)) + continue; + nm_assert(!found); + found = TRUE; + nm_assert(p->param_spec == property_specs[j]); + } + nm_assert(found == (p->param_spec != NULL)); + } +#endif + + for (i = 0; i < n_property_specs; i++) { + const char * name = property_specs[i]->name; + NMSettInfoProperty *p; + + if (_nm_sett_info_property_find_in_array((NMSettInfoProperty *) properties_override->data, + override_len, + name)) + continue; + + g_array_set_size(properties_override, properties_override->len + 1); + p = &g_array_index(properties_override, NMSettInfoProperty, properties_override->len - 1); + memset(p, 0, sizeof(*p)); + p->name = name; + p->param_spec = property_specs[i]; + } + + for (i = 0; i < properties_override->len; i++) { + NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); + GType vtype; + + if (p->property_type) + goto has_property_type; + + nm_assert(p->param_spec); + + vtype = p->param_spec->value_type; + if (vtype == G_TYPE_BOOLEAN) + p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BOOLEAN); + else if (vtype == G_TYPE_UCHAR) + p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BYTE); + else if (vtype == G_TYPE_INT) + p->property_type = &nm_sett_info_propert_type_plain_i; + else if (vtype == G_TYPE_UINT) + p->property_type = &nm_sett_info_propert_type_plain_u; + else if (vtype == G_TYPE_INT64) + p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_INT64); + else if (vtype == G_TYPE_UINT64) + p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT64); + else if (vtype == G_TYPE_STRING) + p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING); + else if (vtype == G_TYPE_DOUBLE) + p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_DOUBLE); + else if (vtype == G_TYPE_STRV) + p->property_type = NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING_ARRAY); + else if (vtype == G_TYPE_BYTES) { + p->property_type = + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_BYTESTRING, + .gprop_to_dbus_fcn = _gprop_to_dbus_fcn_bytes); + } else if (g_type_is_a(vtype, G_TYPE_ENUM)) { + p->property_type = + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_INT32, + .gprop_to_dbus_fcn = _gprop_to_dbus_fcn_enum); + } else if (g_type_is_a(vtype, G_TYPE_FLAGS)) { + p->property_type = + NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_UINT32, + .gprop_to_dbus_fcn = _gprop_to_dbus_fcn_flags); + } else + nm_assert_not_reached(); + +has_property_type: + nm_assert(p->property_type); + nm_assert(p->property_type->dbus_type); + nm_assert(g_variant_type_string_is_valid((const char *) p->property_type->dbus_type)); + } + + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMSettInfoProperty, name) == 0); + g_array_sort(properties_override, nm_strcmp_p); + + setting_class->setting_info = &nm_meta_setting_infos[meta_type]; + sett_info->setting_class = setting_class; + if (detail) + sett_info->detail = *detail; + nm_assert(properties_override->len > 0); + sett_info->property_infos_len = properties_override->len; + sett_info->property_infos = + nm_memdup(properties_override->data, sizeof(NMSettInfoProperty) * properties_override->len); + + sett_info->property_infos_sorted = _property_infos_sort(sett_info->property_infos, + sett_info->property_infos_len, + setting_class); + + g_array_free(properties_override, TRUE); +} + +const NMSettInfoProperty * +_nm_sett_info_setting_get_property_info(const NMSettInfoSetting *sett_info, + const char * property_name) +{ + const NMSettInfoProperty *property; + gssize idx; + + nm_assert(property_name); + + if (!sett_info) + return NULL; + + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMSettInfoProperty, name) == 0); + idx = nm_utils_array_find_binary_search(sett_info->property_infos, + sizeof(NMSettInfoProperty), + sett_info->property_infos_len, + &property_name, + nm_strcmp_p_with_data, + NULL); + + if (idx < 0) + return NULL; + + property = &sett_info->property_infos[idx]; + + nm_assert(idx == 0 || strcmp(property[-1].name, property[0].name) < 0); + nm_assert(idx == sett_info->property_infos_len - 1 + || strcmp(property[0].name, property[1].name) < 0); + + return property; +} + +const NMSettInfoSetting * +_nm_setting_class_get_sett_info(NMSettingClass *setting_class) +{ + const NMSettInfoSetting *sett_info; + + if (!NM_IS_SETTING_CLASS(setting_class) || !setting_class->setting_info) + return NULL; + + nm_assert(setting_class->setting_info->meta_type < G_N_ELEMENTS(_sett_info_settings)); + sett_info = &_sett_info_settings[setting_class->setting_info->meta_type]; + nm_assert(sett_info->setting_class == setting_class); + return sett_info; +} + +/*****************************************************************************/ + +void +_nm_setting_emit_property_changed(NMSetting *setting) +{ + /* Some settings have "properties" that are not implemented as GObject properties. + * + * For example: + * + * - gendata-base settings like NMSettingEthtool. Here properties are just + * GVariant values in the gendata hash. + * + * - NMSettingWireGuard's peers are not backed by a GObject property. Instead + * there is C-API to access/modify peers. + * + * We still want to emit property-changed notifications for such properties, + * in particular because NMConnection registers to such signals to re-emit + * it as NM_CONNECTION_CHANGED signal. In fact, there are unlikely any other + * uses of such a property-changed signal, because generally it doesn't make + * too much sense. + * + * So, instead of adding yet another (artificial) signal "setting-changed", + * hijack the "notify" signal and just notify about changes of the "name". + * Of course, the "name" doesn't really ever change, because it's tied to + * the GObject's type. + */ + _notify(setting, PROP_NAME); +} + +/*****************************************************************************/ + +gboolean +_nm_setting_use_legacy_property(NMSetting * setting, + GVariant * connection_dict, + const char *legacy_property, + const char *new_property) +{ + GVariant *setting_dict, *value; + + setting_dict = g_variant_lookup_value(connection_dict, + nm_setting_get_name(NM_SETTING(setting)), + NM_VARIANT_TYPE_SETTING); + g_return_val_if_fail(setting_dict != NULL, FALSE); + + /* If the new property isn't set, we have to use the legacy property. */ + value = g_variant_lookup_value(setting_dict, new_property, NULL); + if (!value) { + g_variant_unref(setting_dict); + return TRUE; + } + g_variant_unref(value); + + /* Otherwise, clients always prefer new properties sent from the daemon. */ + if (!_nm_utils_is_manager_process) { + g_variant_unref(setting_dict); + return FALSE; + } + + /* The daemon prefers the legacy property if it exists. */ + value = g_variant_lookup_value(setting_dict, legacy_property, NULL); + g_variant_unref(setting_dict); + + if (value) { + g_variant_unref(value); + return TRUE; + } else + return FALSE; +} + +/*****************************************************************************/ + +static GVariant * +property_to_dbus(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options, + gboolean ignore_flags, + gboolean ignore_default) +{ + const NMSettInfoProperty *property = &sett_info->property_infos[property_idx]; + GVariant * variant; + + nm_assert(property->property_type->dbus_type); + + if (!property->param_spec) { + if (!property->property_type->to_dbus_fcn) + return NULL; + } else if (!ignore_flags + && !NM_FLAGS_HAS(property->param_spec->flags, + NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS)) { + if (!NM_FLAGS_HAS(property->param_spec->flags, G_PARAM_WRITABLE)) + return NULL; + + if (NM_FLAGS_HAS(property->param_spec->flags, NM_SETTING_PARAM_LEGACY) + && !_nm_utils_is_manager_process) + return NULL; + + if (NM_FLAGS_HAS(property->param_spec->flags, NM_SETTING_PARAM_SECRET)) { + if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_NO_SECRETS)) + return NULL; + + if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED)) { + NMSettingSecretFlags f; + + /* see also _nm_connection_serialize_secrets() */ + if (!nm_setting_get_secret_flags(setting, property->param_spec->name, &f, NULL)) + return NULL; + if (!NM_FLAGS_HAS(f, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) + return NULL; + } + } else { + if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_ONLY_SECRETS)) + return NULL; + } + } + + if (property->property_type->to_dbus_fcn) { + variant = property->property_type + ->to_dbus_fcn(sett_info, property_idx, connection, setting, flags, options); + nm_g_variant_take_ref(variant); + } else { + nm_auto_unset_gvalue GValue prop_value = { + 0, + }; + + nm_assert(property->param_spec); + + g_value_init(&prop_value, property->param_spec->value_type); + + g_object_get_property(G_OBJECT(setting), property->param_spec->name, &prop_value); + + if (ignore_default && g_param_value_defaults(property->param_spec, &prop_value)) + return NULL; + + if (property->property_type->gprop_to_dbus_fcn) { + variant = property->property_type->gprop_to_dbus_fcn(&prop_value); + nm_g_variant_take_ref(variant); + } else + variant = g_dbus_gvalue_to_gvariant(&prop_value, property->property_type->dbus_type); + } + + nm_assert(!variant || !g_variant_is_floating(variant)); + nm_assert(!variant || g_variant_is_of_type(variant, property->property_type->dbus_type)); + + return variant; +} + +static gboolean +set_property_from_dbus(const NMSettInfoProperty *property, GVariant *src_value, GValue *dst_value) +{ + nm_assert(property->param_spec); + nm_assert(property->property_type->dbus_type); + + if (property->property_type->gprop_from_dbus_fcn) { + if (!g_variant_type_equal(g_variant_get_type(src_value), + property->property_type->dbus_type)) + return FALSE; + property->property_type->gprop_from_dbus_fcn(src_value, dst_value); + } else if (dst_value->g_type == G_TYPE_BYTES) { + if (!g_variant_is_of_type(src_value, G_VARIANT_TYPE_BYTESTRING)) + return FALSE; + + _nm_utils_bytes_from_dbus(src_value, dst_value); + } else { + GValue tmp = G_VALUE_INIT; + + g_dbus_gvariant_to_gvalue(src_value, &tmp); + if (G_VALUE_TYPE(&tmp) == G_VALUE_TYPE(dst_value)) + *dst_value = tmp; + else { + gboolean success; + + success = g_value_transform(&tmp, dst_value); + g_value_unset(&tmp); + if (!success) + return FALSE; + } + } + + return TRUE; +} + +/** + * _nm_setting_to_dbus: + * @setting: the #NMSetting + * @connection: the #NMConnection containing @setting + * @flags: hash flags, e.g. %NM_CONNECTION_SERIALIZE_ALL + * @options: the #NMConnectionSerializationOptions options to control + * what/how gets serialized. + * + * Converts the #NMSetting into a #GVariant of type #NM_VARIANT_TYPE_SETTING + * mapping each setting property name to a value describing that property, + * suitable for marshalling over D-Bus or serializing. + * + * Returns: (transfer none): a new floating #GVariant describing the setting's + * properties + **/ +GVariant * +_nm_setting_to_dbus(NMSetting * setting, + NMConnection * connection, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + NMSettingPrivate * priv; + GVariantBuilder builder; + const NMSettInfoSetting *sett_info; + guint n_properties, i; + const char *const * gendata_keys; + + g_return_val_if_fail(NM_IS_SETTING(setting), NULL); + + priv = NM_SETTING_GET_PRIVATE(setting); + + g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); + + n_properties = _nm_setting_option_get_all(setting, &gendata_keys, NULL); + for (i = 0; i < n_properties; i++) { + g_variant_builder_add(&builder, + "{sv}", + gendata_keys[i], + g_hash_table_lookup(priv->gendata->hash, gendata_keys[i])); + } + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); + for (i = 0; i < sett_info->property_infos_len; i++) { + gs_unref_variant GVariant *dbus_value = NULL; + + dbus_value = + property_to_dbus(sett_info, i, connection, setting, flags, options, FALSE, TRUE); + if (dbus_value) { + g_variant_builder_add(&builder, "{sv}", sett_info->property_infos[i].name, dbus_value); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * _nm_setting_new_from_dbus: + * @setting_type: the #NMSetting type which the hash contains properties for + * @setting_dict: the #GVariant containing an %NM_VARIANT_TYPE_SETTING dictionary + * mapping property names to values + * @connection_dict: the #GVariant containing an %NM_VARIANT_TYPE_CONNECTION + * dictionary mapping setting names to dictionaries. + * @parse_flags: flags to determine behavior during parsing. + * @error: location to store error, or %NULL + * + * Creates a new #NMSetting object and populates that object with the properties + * contained in @setting_dict, using each key as the property to set, and each + * value as the value to set that property to. Setting properties are strongly + * typed, thus the #GVariantType of the dict value must be correct. See the + * documentation on each #NMSetting object subclass for the correct property + * names and value types. + * + * Returns: a new #NMSetting object populated with the properties from the + * hash table, or %NULL if @setting_hash could not be deserialized. + **/ +NMSetting * +_nm_setting_new_from_dbus(GType setting_type, + GVariant * setting_dict, + GVariant * connection_dict, + NMSettingParseFlags parse_flags, + GError ** error) +{ + gs_unref_ptrarray GPtrArray *keys_keep_variant = NULL; + gs_unref_object NMSetting *setting = NULL; + gs_unref_hashtable GHashTable *keys = NULL; + + g_return_val_if_fail(G_TYPE_IS_INSTANTIATABLE(setting_type), NULL); + g_return_val_if_fail(g_variant_is_of_type(setting_dict, NM_VARIANT_TYPE_SETTING), NULL); + + nm_assert(!NM_FLAGS_ANY(parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL)); + nm_assert(!NM_FLAGS_ALL(parse_flags, + NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT)); + + /* connection_dict is not technically optional, but some tests in test-general + * don't bother with it in cases where they know it's not needed. + */ + if (connection_dict) + g_return_val_if_fail(g_variant_is_of_type(connection_dict, NM_VARIANT_TYPE_CONNECTION), + NULL); + + /* Build the setting object from the properties we know about; we assume + * that any propreties in @setting_dict that we don't know about can + * either be ignored or else has a backward-compatibility equivalent + * that we do know about. + */ + setting = g_object_new(setting_type, NULL); + + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + GVariantIter iter; + GVariant * entry, *entry_key; + const char * key; + + keys_keep_variant = g_ptr_array_new_with_free_func((GDestroyNotify) g_variant_unref); + keys = g_hash_table_new(nm_str_hash, g_str_equal); + + g_variant_iter_init(&iter, setting_dict); + while ((entry = g_variant_iter_next_value(&iter))) { + entry_key = g_variant_get_child_value(entry, 0); + g_ptr_array_add(keys_keep_variant, entry_key); + g_variant_unref(entry); + + key = g_variant_get_string(entry_key, NULL); + if (!g_hash_table_add(keys, (char *) key)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("duplicate property")); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), key); + return NULL; + } + } + } + + if (!NM_SETTING_GET_CLASS(setting) + ->init_from_dbus(setting, keys, setting_dict, connection_dict, parse_flags, error)) + return NULL; + + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT) && g_hash_table_size(keys) > 0) { + GHashTableIter iter; + const char * key; + + g_hash_table_iter_init(&iter, keys); + if (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unknown property")); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), key); + return NULL; + } + } + + return g_steal_pointer(&setting); +} + +static gboolean +init_from_dbus(NMSetting * setting, + GHashTable * keys, + GVariant * setting_dict, + GVariant * connection_dict, + guint /* NMSettingParseFlags */ parse_flags, + GError ** error) +{ + const NMSettInfoSetting *sett_info; + + guint i; + + nm_assert(NM_IS_SETTING(setting)); + nm_assert(!NM_FLAGS_ANY(parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL)); + nm_assert(!NM_FLAGS_ALL(parse_flags, + NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT)); + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); + + if (sett_info->detail.gendata_info) { + GHashTable * hash; + GVariantIter iter; + char * key; + GVariant * val; + + hash = _gendata_hash(setting, TRUE)->hash; + + g_variant_iter_init(&iter, setting_dict); + while (g_variant_iter_next(&iter, "{sv}", &key, &val)) { + g_hash_table_insert(hash, key, val); + if (keys) + g_hash_table_remove(keys, key); + } + + _nm_setting_option_notify(setting, TRUE); + + /* Currently, only NMSettingEthtool supports gendata based options, and + * that one has no other properties (except "name"). That means, we + * consumed all options above. + * + * In the future it may be interesting to have settings that are both + * based on gendata and regular properties. In that case, we would need + * to handle this case differently. */ + nm_assert(nm_streq(G_OBJECT_TYPE_NAME(setting), "NMSettingEthtool")); + nm_assert(sett_info->property_infos_len == 1); + + return TRUE; + } + + for (i = 0; i < sett_info->property_infos_len; i++) { + const NMSettInfoProperty *property_info = &sett_info->property_infos[i]; + gs_unref_variant GVariant *value = NULL; + gs_free_error GError *local = NULL; + + if (property_info->param_spec && !(property_info->param_spec->flags & G_PARAM_WRITABLE)) + continue; + + value = g_variant_lookup_value(setting_dict, property_info->name, NULL); + + if (value && keys) + g_hash_table_remove(keys, property_info->name); + + if (value && property_info->property_type->from_dbus_fcn) { + if (!g_variant_type_equal(g_variant_get_type(value), + property_info->property_type->dbus_type)) { + /* for backward behavior, fail unless best-effort is chosen. */ + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) + continue; + g_set_error( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can't set property of type '%s' from value of type '%s'"), + property_info->property_type->dbus_type + ? g_variant_type_peek_string(property_info->property_type->dbus_type) + : property_info->param_spec ? g_type_name(property_info->param_spec->value_type) + : "(unknown)", + g_variant_get_type_string(value)); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); + return FALSE; + } + + if (!property_info->property_type->from_dbus_fcn(setting, + connection_dict, + property_info->name, + value, + parse_flags, + &local)) { + if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) + continue; + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("failed to set property: %s"), + local->message); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); + return FALSE; + } + } else if (!value && property_info->property_type->missing_from_dbus_fcn) { + if (!property_info->property_type->missing_from_dbus_fcn(setting, + connection_dict, + property_info->name, + parse_flags, + &local)) { + if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) + continue; + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("failed to set property: %s"), + local->message); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); + return FALSE; + } + } else if (value && property_info->param_spec) { + nm_auto_unset_gvalue GValue object_value = G_VALUE_INIT; + + g_value_init(&object_value, property_info->param_spec->value_type); + if (!set_property_from_dbus(property_info, value, &object_value)) { + /* for backward behavior, fail unless best-effort is chosen. */ + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) + continue; + g_set_error( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can't set property of type '%s' from value of type '%s'"), + property_info->property_type->dbus_type + ? g_variant_type_peek_string(property_info->property_type->dbus_type) + : (property_info->param_spec + ? g_type_name(property_info->param_spec->value_type) + : "(unknown)"), + g_variant_get_type_string(value)); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); + return FALSE; + } + + if (!nm_g_object_set_property(G_OBJECT(setting), + property_info->param_spec->name, + &object_value, + &local)) { + if (!NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) + continue; + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can not set property: %s"), + local->message); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), property_info->name); + return FALSE; + } + } + } + + return TRUE; +} + +/** + * nm_setting_get_dbus_property_type: + * @setting: an #NMSetting + * @property_name: the property of @setting to get the type of + * + * Gets the D-Bus marshalling type of a property. @property_name is a D-Bus + * property name, which may not necessarily be a #GObject property. + * + * Returns: the D-Bus marshalling type of @property on @setting. + */ +const GVariantType * +nm_setting_get_dbus_property_type(NMSetting *setting, const char *property_name) +{ + const NMSettInfoProperty *property; + + g_return_val_if_fail(NM_IS_SETTING(setting), NULL); + g_return_val_if_fail(property_name != NULL, NULL); + + property = _nm_setting_class_get_property_info(NM_SETTING_GET_CLASS(setting), property_name); + + g_return_val_if_fail(property != NULL, NULL); + + nm_assert(property->property_type); + nm_assert(g_variant_type_string_is_valid((const char *) property->property_type->dbus_type)); + + return property->property_type->dbus_type; +} + +gboolean +_nm_setting_get_property(NMSetting *setting, const char *property_name, GValue *value) +{ + const NMSettInfoSetting * sett_info; + const NMSettInfoProperty *property_info; + + g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); + g_return_val_if_fail(property_name, FALSE); + g_return_val_if_fail(value, FALSE); + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); + + if (sett_info->detail.gendata_info) { + GVariant *variant; + GenData * gendata = _gendata_hash(setting, FALSE); + + variant = gendata ? g_hash_table_lookup(gendata->hash, property_name) : NULL; + + if (!variant) { + g_value_unset(value); + return FALSE; + } + + g_value_init(value, G_TYPE_VARIANT); + g_value_set_variant(value, variant); + return TRUE; + } + + property_info = _nm_sett_info_setting_get_property_info(sett_info, property_name); + if (!property_info || !property_info->param_spec) { + g_value_unset(value); + return FALSE; + } + + g_value_init(value, property_info->param_spec->value_type); + g_object_get_property(G_OBJECT(setting), property_name, value); + return TRUE; +} + +static void +_gobject_copy_property(GObject *src, GObject *dst, const char *property_name, GType gtype) +{ + nm_auto_unset_gvalue GValue value = G_VALUE_INIT; + + nm_assert(G_IS_OBJECT(src)); + nm_assert(G_IS_OBJECT(dst)); + + g_value_init(&value, gtype); + g_object_get_property(src, property_name, &value); + g_object_set_property(dst, property_name, &value); +} + +static void +duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) +{ + if (sett_info->detail.gendata_info) { + GenData *gendata = _gendata_hash(src, FALSE); + + nm_assert(!_gendata_hash(dst, FALSE)); + + if (gendata && g_hash_table_size(gendata->hash) > 0) { + GHashTableIter iter; + GHashTable * h = _gendata_hash(dst, TRUE)->hash; + const char * key; + GVariant * val; + + g_hash_table_iter_init(&iter, gendata->hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + g_hash_table_insert(h, g_strdup(key), g_variant_ref(val)); + } + } + } + + if (sett_info->property_infos_len > 0) { + gboolean frozen = FALSE; + guint i; + + for (i = 0; i < sett_info->property_infos_len; i++) { + const NMSettInfoProperty *property_info = &sett_info->property_infos[i]; + + if (property_info->param_spec) { + if ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) + != G_PARAM_WRITABLE) + continue; + + if (!frozen) { + g_object_freeze_notify(G_OBJECT(dst)); + frozen = TRUE; + } + _gobject_copy_property(G_OBJECT(src), + G_OBJECT(dst), + property_info->param_spec->name, + G_PARAM_SPEC_VALUE_TYPE(property_info->param_spec)); + continue; + } + } + + if (frozen) + g_object_thaw_notify(G_OBJECT(dst)); + } +} + +/** + * nm_setting_duplicate: + * @setting: the #NMSetting to duplicate + * + * Duplicates a #NMSetting. + * + * Returns: (transfer full): a new #NMSetting containing the same properties and values as the + * source #NMSetting + **/ +NMSetting * +nm_setting_duplicate(NMSetting *setting) +{ + const NMSettInfoSetting *sett_info; + NMSettingClass * klass; + NMSetting * dst; + + g_return_val_if_fail(NM_IS_SETTING(setting), NULL); + + klass = NM_SETTING_GET_CLASS(setting); + nm_assert(NM_IS_SETTING_CLASS(klass)); + nm_assert(klass->duplicate_copy_properties); + + dst = g_object_new(G_TYPE_FROM_CLASS(klass), NULL); + + sett_info = _nm_setting_class_get_sett_info(klass); + nm_assert(sett_info); + + klass->duplicate_copy_properties(sett_info, setting, dst); + return dst; +} + +/** + * nm_setting_get_name: + * @setting: the #NMSetting + * + * Returns the type name of the #NMSetting object + * + * Returns: a string containing the type name of the #NMSetting object, + * like 'ppp' or 'wireless' or 'wired'. + **/ +const char * +nm_setting_get_name(NMSetting *setting) +{ + const NMMetaSettingInfo *setting_info; + + g_return_val_if_fail(NM_IS_SETTING(setting), NULL); + + setting_info = NM_SETTING_GET_CLASS(setting)->setting_info; + return setting_info ? setting_info->setting_name : NULL; +} + +/** + * nm_setting_verify: + * @setting: the #NMSetting to verify + * @connection: (allow-none): the #NMConnection that @setting came from, or + * %NULL if @setting is being verified in isolation. + * @error: location to store error, or %NULL + * + * Validates the setting. Each setting's properties have allowed values, and + * some are dependent on other values (hence the need for @connection). The + * returned #GError contains information about which property of the setting + * failed validation, and in what way that property failed validation. + * + * Returns: %TRUE if the setting is valid, %FALSE if it is not + **/ +gboolean +nm_setting_verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingVerifyResult result = _nm_setting_verify(setting, connection, error); + + if (result == NM_SETTING_VERIFY_NORMALIZABLE) + g_clear_error(error); + + return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE; +} + +NMSettingVerifyResult +_nm_setting_verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_VERIFY_ERROR); + g_return_val_if_fail(!connection || NM_IS_CONNECTION(connection), NM_SETTING_VERIFY_ERROR); + g_return_val_if_fail(!error || *error == NULL, NM_SETTING_VERIFY_ERROR); + + if (NM_SETTING_GET_CLASS(setting)->verify) + return NM_SETTING_GET_CLASS(setting)->verify(setting, connection, error); + + return NM_SETTING_VERIFY_SUCCESS; +} + +/** + * nm_setting_verify_secrets: + * @setting: the #NMSetting to verify secrets in + * @connection: (allow-none): the #NMConnection that @setting came from, or + * %NULL if @setting is being verified in isolation. + * @error: location to store error, or %NULL + * + * Verifies the secrets in the setting. + * The returned #GError contains information about which secret of the setting + * failed validation, and in what way that secret failed validation. + * The secret validation is done separately from main setting validation, because + * in some cases connection failure is not desired just for the secrets. + * + * Returns: %TRUE if the setting secrets are valid, %FALSE if they are not + * + * Since: 1.2 + **/ +gboolean +nm_setting_verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) +{ + g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_VERIFY_ERROR); + g_return_val_if_fail(!connection || NM_IS_CONNECTION(connection), NM_SETTING_VERIFY_ERROR); + g_return_val_if_fail(!error || *error == NULL, NM_SETTING_VERIFY_ERROR); + + if (NM_SETTING_GET_CLASS(setting)->verify_secrets) + return NM_SETTING_GET_CLASS(setting)->verify_secrets(setting, connection, error); + + return NM_SETTING_VERIFY_SUCCESS; +} + +gboolean +_nm_setting_verify_secret_string(const char *str, + const char *setting_name, + const char *property, + GError ** error) +{ + if (str && !*str) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is empty")); + g_prefix_error(error, "%s.%s: ", setting_name, property); + return FALSE; + } + return TRUE; +} + +gboolean +_nm_setting_should_compare_secret_property(NMSetting * setting, + NMSetting * other, + const char * secret_name, + NMSettingCompareFlags flags) +{ + NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE; + NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + nm_assert(NM_IS_SETTING(setting)); + nm_assert(!other || G_OBJECT_TYPE(setting) == G_OBJECT_TYPE(other)); + + /* secret_name must be a valid secret for @setting. */ + nm_assert(nm_setting_get_secret_flags(setting, secret_name, NULL, NULL)); + + if (!NM_FLAGS_ANY(flags, + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS + | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) + return TRUE; + + nm_setting_get_secret_flags(setting, secret_name, &a_secret_flags, NULL); + if (other) { + if (!nm_setting_get_secret_flags(other, secret_name, &b_secret_flags, NULL)) { + /* secret-name may not be a valid secret for @other. That is fine, we ignore that + * and treat @b_secret_flags as NM_SETTING_SECRET_FLAG_NONE. + * + * This can happen with VPN secrets, where the caller knows that @secret_name + * is a secret for setting, but it may not be a secret for @other. Accept that. + * + * Mark @other as missing. */ + other = NULL; + } + } + + /* when @setting has the secret-flags that should be ignored, + * we skip the comparison if: + * + * - @other is not present, + * - @other does not have a secret named @secret_name + * - @other also has the secret flat to be ignored. + * + * This makes the check symmetric (aside the fact that @setting must + * have the secret while @other may not -- which is asymmetric). */ + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) + && NM_FLAGS_HAS(a_secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED) + && (!other || NM_FLAGS_HAS(b_secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED))) + return FALSE; + + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) + && NM_FLAGS_HAS(a_secret_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED) + && (!other || NM_FLAGS_HAS(b_secret_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED))) + return FALSE; + + return TRUE; +} + +static NMTernary +compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + const NMSettInfoProperty *property_info = &sett_info->property_infos[property_idx]; + const GParamSpec * param_spec = property_info->param_spec; + + if (!param_spec) + return NM_TERNARY_DEFAULT; + + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_FUZZY) + && NM_FLAGS_ANY(param_spec->flags, NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)) + return NM_TERNARY_DEFAULT; + + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE) + && !NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_INFERRABLE)) + return NM_TERNARY_DEFAULT; + + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY) + && NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_REAPPLY_IMMEDIATELY)) + return NM_TERNARY_DEFAULT; + + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) + && NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_SECRET)) + return NM_TERNARY_DEFAULT; + + if (nm_streq(param_spec->name, NM_SETTING_NAME)) + return NM_TERNARY_DEFAULT; + + if (NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_SECRET) + && !_nm_setting_should_compare_secret_property(set_a, set_b, param_spec->name, flags)) + return NM_TERNARY_DEFAULT; + + if (set_b) { + gs_unref_variant GVariant *value1 = NULL; + gs_unref_variant GVariant *value2 = NULL; + + value1 = property_to_dbus(sett_info, + property_idx, + con_a, + set_a, + NM_CONNECTION_SERIALIZE_ALL, + NULL, + TRUE, + TRUE); + value2 = property_to_dbus(sett_info, + property_idx, + con_b, + set_b, + NM_CONNECTION_SERIALIZE_ALL, + NULL, + TRUE, + TRUE); + if (nm_property_compare(value1, value2) != 0) + return NM_TERNARY_FALSE; + } + + return NM_TERNARY_TRUE; +} + +static NMTernary +_compare_property(const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags) +{ + NMTernary compare_result; + + nm_assert(sett_info); + nm_assert(NM_IS_SETTING_CLASS(sett_info->setting_class)); + nm_assert(property_idx < sett_info->property_infos_len); + nm_assert(NM_SETTING_GET_CLASS(set_a) == sett_info->setting_class); + nm_assert(!set_b || NM_SETTING_GET_CLASS(set_b) == sett_info->setting_class); + + compare_result = + NM_SETTING_GET_CLASS(set_a) + ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); + + nm_assert(NM_IN_SET(compare_result, NM_TERNARY_DEFAULT, NM_TERNARY_FALSE, NM_TERNARY_TRUE)); + + /* check that the inferable flag and the GObject property flag corresponds. */ + nm_assert(!NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE) + || !sett_info->property_infos[property_idx].param_spec + || NM_FLAGS_HAS(sett_info->property_infos[property_idx].param_spec->flags, + NM_SETTING_PARAM_INFERRABLE) + || compare_result == NM_TERNARY_DEFAULT); + +#if NM_MORE_ASSERTS > 10 + /* assert that compare_property() is symeric. */ + nm_assert(!set_b + || compare_result + == NM_SETTING_GET_CLASS(set_a)->compare_property(sett_info, + property_idx, + con_b, + set_b, + con_a, + set_a, + flags)); +#endif + + return compare_result; +} + +/** + * nm_setting_compare: + * @a: a #NMSetting + * @b: a second #NMSetting to compare with the first + * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT + * + * Compares two #NMSetting objects for similarity, with comparison behavior + * modified by a set of flags. See the documentation for #NMSettingCompareFlags + * for a description of each flag's behavior. + * + * Returns: %TRUE if the comparison succeeds, %FALSE if it does not + **/ +gboolean +nm_setting_compare(NMSetting *a, NMSetting *b, NMSettingCompareFlags flags) +{ + return _nm_setting_compare(NULL, a, NULL, b, flags); +} + +gboolean +_nm_setting_compare(NMConnection * con_a, + NMSetting * a, + NMConnection * con_b, + NMSetting * b, + NMSettingCompareFlags flags) +{ + const NMSettInfoSetting *sett_info; + guint i; + + g_return_val_if_fail(NM_IS_SETTING(a), FALSE); + g_return_val_if_fail(NM_IS_SETTING(b), FALSE); + + nm_assert(!con_a || NM_IS_CONNECTION(con_a)); + nm_assert(!con_b || NM_IS_CONNECTION(con_b)); + + /* First check that both have the same type */ + if (G_OBJECT_TYPE(a) != G_OBJECT_TYPE(b)) + return FALSE; + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(a)); + + if (sett_info->detail.gendata_info) { + GenData *a_gendata = _gendata_hash(a, FALSE); + GenData *b_gendata = _gendata_hash(b, FALSE); + + return nm_utils_hashtable_equal(a_gendata ? a_gendata->hash : NULL, + b_gendata ? b_gendata->hash : NULL, + TRUE, + g_variant_equal); + } + + for (i = 0; i < sett_info->property_infos_len; i++) { + if (_compare_property(sett_info, i, con_a, a, con_b, b, flags) == NM_TERNARY_FALSE) + return FALSE; + } + + return TRUE; +} + +static void +_setting_diff_add_result(GHashTable *results, const char *prop_name, NMSettingDiffResult r) +{ + void *p; + + if (r == NM_SETTING_DIFF_RESULT_UNKNOWN) + return; + + if (g_hash_table_lookup_extended(results, prop_name, NULL, &p)) { + if (!NM_FLAGS_ALL((guint) r, GPOINTER_TO_UINT(p))) + g_hash_table_insert(results, + g_strdup(prop_name), + GUINT_TO_POINTER(((guint) r) | GPOINTER_TO_UINT(p))); + } else + g_hash_table_insert(results, g_strdup(prop_name), GUINT_TO_POINTER(r)); +} + +/** + * nm_setting_diff: + * @a: a #NMSetting + * @b: a second #NMSetting to compare with the first + * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT + * @invert_results: this parameter is used internally by libnm and should + * be set to %FALSE. If %TRUE inverts the meaning of the #NMSettingDiffResult. + * @results: (inout) (transfer full) (element-type utf8 guint32): if the + * settings differ, on return a hash table mapping the differing keys to one or + * more %NMSettingDiffResult values OR-ed together. If the settings do not + * differ, any hash table passed in is unmodified. If no hash table is passed + * in and the settings differ, a new one is created and returned. + * + * Compares two #NMSetting objects for similarity, with comparison behavior + * modified by a set of flags. See the documentation for #NMSettingCompareFlags + * for a description of each flag's behavior. If the settings differ, the keys + * of each setting that differ from the other are added to @results, mapped to + * one or more #NMSettingDiffResult values. + * + * Returns: %TRUE if the settings contain the same values, %FALSE if they do not + **/ +gboolean +nm_setting_diff(NMSetting * a, + NMSetting * b, + NMSettingCompareFlags flags, + gboolean invert_results, + GHashTable ** results) +{ + return _nm_setting_diff(NULL, a, NULL, b, flags, invert_results, results); +} + +gboolean +_nm_setting_diff(NMConnection * con_a, + NMSetting * a, + NMConnection * con_b, + NMSetting * b, + NMSettingCompareFlags flags, + gboolean invert_results, + GHashTable ** results) +{ + const NMSettInfoSetting *sett_info; + guint i; + NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A; + NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B; + NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; + NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; + gboolean results_created = FALSE; + gboolean compared_any = FALSE; + gboolean diff_found = FALSE; + + g_return_val_if_fail(results != NULL, FALSE); + g_return_val_if_fail(NM_IS_SETTING(a), FALSE); + if (b) { + g_return_val_if_fail(NM_IS_SETTING(b), FALSE); + g_return_val_if_fail(G_OBJECT_TYPE(a) == G_OBJECT_TYPE(b), FALSE); + } + + nm_assert(!con_a || NM_IS_CONNECTION(con_a)); + nm_assert(!con_b || NM_IS_CONNECTION(con_b)); + + if ((flags + & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT + | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) + == (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT + | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) { + /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */ + flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT; + } + + /* If the caller is calling this function in a pattern like this to get + * complete diffs: + * + * nm_setting_diff (A, B, FALSE, &results); + * nm_setting_diff (B, A, TRUE, &results); + * + * and wants us to invert the results so that the second invocation comes + * out correctly, do that here. + */ + if (invert_results) { + a_result = NM_SETTING_DIFF_RESULT_IN_B; + b_result = NM_SETTING_DIFF_RESULT_IN_A; + a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; + b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; + } + + if (*results == NULL) { + *results = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, NULL); + results_created = TRUE; + } + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(a)); + + if (sett_info->detail.gendata_info) { + const char * key; + GVariant * val, *val2; + GHashTableIter iter; + GenData * a_gendata = _gendata_hash(a, FALSE); + GenData * b_gendata = b ? _gendata_hash(b, FALSE) : NULL; + + if (!a_gendata || !b_gendata) { + if (a_gendata || b_gendata) { + NMSettingDiffResult one_sided_result; + + one_sided_result = a_gendata ? a_result : b_result; + g_hash_table_iter_init(&iter, a_gendata ? a_gendata->hash : b_gendata->hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) { + diff_found = TRUE; + _setting_diff_add_result(*results, key, one_sided_result); + } + } + } else { + g_hash_table_iter_init(&iter, a_gendata->hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + val2 = g_hash_table_lookup(b_gendata->hash, key); + compared_any = TRUE; + if (!val2 || !g_variant_equal(val, val2)) { + diff_found = TRUE; + _setting_diff_add_result(*results, key, a_result); + } + } + g_hash_table_iter_init(&iter, b_gendata->hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + val2 = g_hash_table_lookup(a_gendata->hash, key); + compared_any = TRUE; + if (!val2 || !g_variant_equal(val, val2)) { + diff_found = TRUE; + _setting_diff_add_result(*results, key, b_result); + } + } + } + } else { + for (i = 0; i < sett_info->property_infos_len; i++) { + NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; + const NMSettInfoProperty *property_info; + NMTernary compare_result; + GParamSpec * prop_spec; + + compare_result = _compare_property(sett_info, i, con_a, a, con_b, b, flags); + if (compare_result == NM_TERNARY_DEFAULT) + continue; + + if (NM_FLAGS_ANY(flags, + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS + | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) + && b && compare_result == NM_TERNARY_FALSE) { + /* we have setting @b and the property is not the same. But we also are instructed + * to ignore secrets based on the flags. + * + * Note that compare_property() called with two settings will ignore secrets + * based on the flags, but it will do so if *both* settings have the flag we + * look for. So that is symmetric behavior and good. + * + * But for the purpose of diff(), we do a asymmetric comparison because and + * we want to skip testing the property if setting @a alone indicates to do + * so. + * + * We need to double-check whether the property should be ignored by + * looking at @a alone. */ + if (_compare_property(sett_info, i, con_a, a, NULL, NULL, flags) + == NM_TERNARY_DEFAULT) + continue; + } + + compared_any = TRUE; + + property_info = &sett_info->property_infos[i]; + prop_spec = property_info->param_spec; + + if (b) { + if (compare_result == NM_TERNARY_FALSE) { + if (prop_spec) { + gboolean a_is_default, b_is_default; + GValue value = G_VALUE_INIT; + + g_value_init(&value, prop_spec->value_type); + g_object_get_property(G_OBJECT(a), prop_spec->name, &value); + a_is_default = g_param_value_defaults(prop_spec, &value); + + g_value_reset(&value); + g_object_get_property(G_OBJECT(b), prop_spec->name, &value); + b_is_default = g_param_value_defaults(prop_spec, &value); + + g_value_unset(&value); + if (!NM_FLAGS_HAS(flags, + NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)) { + if (!a_is_default) + r |= a_result; + if (!b_is_default) + r |= b_result; + } else { + r |= a_result | b_result; + if (a_is_default) + r |= a_result_default; + if (b_is_default) + r |= b_result_default; + } + } else + r |= a_result | b_result; + } + } else if ((flags + & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT + | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) + == 0) + r = a_result; /* only in A */ + else { + if (prop_spec) { + GValue value = G_VALUE_INIT; + + g_value_init(&value, prop_spec->value_type); + g_object_get_property(G_OBJECT(a), prop_spec->name, &value); + if (!g_param_value_defaults(prop_spec, &value)) + r |= a_result; + else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) + r |= a_result | a_result_default; + + g_value_unset(&value); + } else + r |= a_result; + } + + if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { + diff_found = TRUE; + _setting_diff_add_result(*results, property_info->name, r); + } + } + } + + if (!compared_any && !b) { + /* special case: the setting has no properties, and the opposite + * setting @b is not given. The settings differ, and we signal that + * by returning an empty results hash. */ + diff_found = TRUE; + } + + if (diff_found) { + /* if there is a difference, we always return FALSE. It also means, we might + * have allocated a new @results hash, and return it to the caller. */ + return FALSE; + } else { + if (results_created) { + /* the allocated hash is unused. Clear it again. */ + g_hash_table_destroy(*results); + *results = NULL; + } else { + /* we found no diff, and return false. However, the input + * @result is returned unmodified. */ + } + return TRUE; + } +} + +static void +enumerate_values(const NMSettInfoProperty *property_info, + NMSetting * setting, + NMSettingValueIterFn func, + gpointer user_data) +{ + GValue value = G_VALUE_INIT; + + if (!property_info->param_spec) + return; + + g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(property_info->param_spec)); + g_object_get_property(G_OBJECT(setting), property_info->param_spec->name, &value); + func(setting, + property_info->param_spec->name, + &value, + property_info->param_spec->flags, + user_data); + g_value_unset(&value); +} + +/** + * nm_setting_enumerate_values: + * @setting: the #NMSetting + * @func: (scope call): user-supplied function called for each property of the setting + * @user_data: user data passed to @func at each invocation + * + * Iterates over each property of the #NMSetting object, calling the supplied + * user function for each property. + **/ +void +nm_setting_enumerate_values(NMSetting *setting, NMSettingValueIterFn func, gpointer user_data) +{ + const NMSettInfoSetting *sett_info; + guint i; + + g_return_if_fail(NM_IS_SETTING(setting)); + g_return_if_fail(func != NULL); + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); + + if (sett_info->detail.gendata_info) { + const char *const *names; + guint n_properties; + + /* the properties of this setting are not real GObject properties. + * Hence, this API makes little sense (or does it?). Still, call + * @func with each value. */ + n_properties = _nm_setting_option_get_all(setting, &names, NULL); + if (n_properties > 0) { + gs_strfreev char **keys = g_strdupv((char **) names); + GHashTable * h = _gendata_hash(setting, FALSE)->hash; + + for (i = 0; i < n_properties; i++) { + GValue value = G_VALUE_INIT; + GVariant *val = g_hash_table_lookup(h, keys[i]); + + if (!val) { + /* was deleted in the meantime? Skip */ + continue; + } + + g_value_init(&value, G_TYPE_VARIANT); + g_value_set_variant(&value, val); + /* call it will GParamFlags 0. It shall indicate that this + * is not a "real" GObject property. */ + func(setting, keys[i], &value, 0, user_data); + g_value_unset(&value); + } + } + return; + } + + for (i = 0; i < sett_info->property_infos_len; i++) { + NM_SETTING_GET_CLASS(setting)->enumerate_values( + _nm_sett_info_property_info_get_sorted(sett_info, i), + setting, + func, + user_data); + } +} + +static gboolean +aggregate(NMSetting *setting, int type_i, gpointer arg) +{ + NMConnectionAggregateType type = type_i; + const NMSettInfoSetting * sett_info; + guint i; + + nm_assert(NM_IN_SET(type, + NM_CONNECTION_AGGREGATE_ANY_SECRETS, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS)); + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); + for (i = 0; i < sett_info->property_infos_len; i++) { + const NMSettInfoProperty * property_info = &sett_info->property_infos[i]; + GParamSpec * prop_spec = property_info->param_spec; + nm_auto_unset_gvalue GValue value = G_VALUE_INIT; + NMSettingSecretFlags secret_flags; + + if (!prop_spec || !NM_FLAGS_HAS(prop_spec->flags, NM_SETTING_PARAM_SECRET)) { + nm_assert(!nm_setting_get_secret_flags(setting, property_info->name, NULL, NULL)); + continue; + } + + /* for the moment, all aggregate types only care about secrets. */ + nm_assert(nm_setting_get_secret_flags(setting, property_info->name, NULL, NULL)); + + switch (type) { + case NM_CONNECTION_AGGREGATE_ANY_SECRETS: + g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(prop_spec)); + g_object_get_property(G_OBJECT(setting), prop_spec->name, &value); + if (!g_param_value_defaults(prop_spec, &value)) { + *((gboolean *) arg) = TRUE; + return TRUE; + } + break; + + case NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS: + if (!nm_setting_get_secret_flags(setting, prop_spec->name, &secret_flags, NULL)) + nm_assert_not_reached(); + if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) { + *((gboolean *) arg) = TRUE; + return TRUE; + } + break; + } + } + + return FALSE; +} + +/** + * _nm_setting_aggregate: + * @setting: the #NMSetting to aggregate. + * @type: the #NMConnectionAggregateType aggregate type. + * @arg: the in/out arguments for aggregation. They depend on @type. + * + * This is the implementation detail of _nm_connection_aggregate(). It + * makes no sense to call this function directly outside of _nm_connection_aggregate(). + * + * Returns: %TRUE if afterwards the aggregation is complete. That means, + * the only caller _nm_connection_aggregate() will not visit other settings + * after a setting returns %TRUE (indicating that there is nothing further + * to aggregate). Note that is very different from the boolean return + * argument of _nm_connection_aggregate(), which serves a different purpose. + */ +gboolean +_nm_setting_aggregate(NMSetting *setting, NMConnectionAggregateType type, gpointer arg) +{ + g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); + g_return_val_if_fail(arg, FALSE); + g_return_val_if_fail(NM_IN_SET(type, + NM_CONNECTION_AGGREGATE_ANY_SECRETS, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS), + FALSE); + + return NM_SETTING_GET_CLASS(setting)->aggregate(setting, type, arg); +} + +static gboolean +clear_secrets(const NMSettInfoSetting * sett_info, + guint property_idx, + NMSetting * setting, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data) +{ + NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; + GParamSpec * param_spec = sett_info->property_infos[property_idx].param_spec; + + if (!param_spec) + return FALSE; + + if (!NM_FLAGS_HAS(param_spec->flags, NM_SETTING_PARAM_SECRET)) + return FALSE; + + if (func) { + if (!nm_setting_get_secret_flags(setting, param_spec->name, &flags, NULL)) + nm_assert_not_reached(); + if (!func(setting, param_spec->name, flags, user_data)) + return FALSE; + } else + nm_assert(nm_setting_get_secret_flags(setting, param_spec->name, NULL, NULL)); + + { + nm_auto_unset_gvalue GValue value = G_VALUE_INIT; + + g_value_init(&value, param_spec->value_type); + g_object_get_property(G_OBJECT(setting), param_spec->name, &value); + if (g_param_value_defaults(param_spec, &value)) + return FALSE; + + g_param_value_set_default(param_spec, &value); + g_object_set_property(G_OBJECT(setting), param_spec->name, &value); + } + + return TRUE; +} + +/** + * _nm_setting_clear_secrets: + * @setting: the #NMSetting + * @func: (scope call): function to be called to determine whether a + * specific secret should be cleared or not + * @user_data: caller-supplied data passed to @func + * + * Clears and frees secrets determined by @func. + * + * Returns: %TRUE if the setting changed at all + **/ +gboolean +_nm_setting_clear_secrets(NMSetting * setting, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data) +{ + const NMSettInfoSetting *sett_info; + gboolean changed = FALSE; + guint i; + gboolean (*my_clear_secrets)(const struct _NMSettInfoSetting *sett_info, + guint property_idx, + NMSetting * setting, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data); + + g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); + + my_clear_secrets = NM_SETTING_GET_CLASS(setting)->clear_secrets; + + sett_info = _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting)); + for (i = 0; i < sett_info->property_infos_len; i++) { + changed |= my_clear_secrets(sett_info, i, setting, func, user_data); + } + return changed; +} + +/** + * _nm_setting_need_secrets: + * @setting: the #NMSetting + * + * Returns an array of property names for each secret which may be required + * to make a successful connection. The returned hints are only intended as a + * guide to what secrets may be required, because in some circumstances, there + * is no way to conclusively determine exactly which secrets are needed. + * + * Returns: (transfer container) (element-type utf8): a #GPtrArray containing + * the property names of secrets of the #NMSetting which may be required; the + * caller owns the array and must free it with g_ptr_array_free(), but must not + * free the elements. + **/ +GPtrArray * +_nm_setting_need_secrets(NMSetting *setting) +{ + GPtrArray *secrets = NULL; + + g_return_val_if_fail(NM_IS_SETTING(setting), NULL); + + if (NM_SETTING_GET_CLASS(setting)->need_secrets) + secrets = NM_SETTING_GET_CLASS(setting)->need_secrets(setting); + + return secrets; +} + +static int +update_one_secret(NMSetting *setting, const char *key, GVariant *value, GError **error) +{ + const NMSettInfoProperty *property; + GParamSpec * prop_spec; + GValue prop_value = { + 0, + }; + + property = _nm_setting_class_get_property_info(NM_SETTING_GET_CLASS(setting), key); + if (!property) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND, + _("secret not found")); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), key); + return NM_SETTING_UPDATE_SECRET_ERROR; + } + + /* Silently ignore non-secrets */ + prop_spec = property->param_spec; + if (!prop_spec || !(prop_spec->flags & NM_SETTING_PARAM_SECRET)) + return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; + + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING) && G_IS_PARAM_SPEC_STRING(prop_spec)) { + /* String is expected to be a common case. Handle it specially and check + * whether the value is already set. Otherwise, we just reset the + * property and assume the value got modified. + */ + char *v; + + g_object_get(G_OBJECT(setting), prop_spec->name, &v, NULL); + if (g_strcmp0(v, g_variant_get_string(value, NULL)) == 0) { + g_free(v); + return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; + } + g_free(v); + } + + g_value_init(&prop_value, prop_spec->value_type); + set_property_from_dbus(property, value, &prop_value); + g_object_set_property(G_OBJECT(setting), prop_spec->name, &prop_value); + g_value_unset(&prop_value); + + return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; +} + +/** + * _nm_setting_update_secrets: + * @setting: the #NMSetting + * @secrets: a #GVariant of type #NM_VARIANT_TYPE_SETTING, mapping property + * names to secrets. + * @error: location to store error, or %NULL + * + * Update the setting's secrets, given a dictionary of secrets intended for that + * setting (deserialized from D-Bus for example). + * + * Returns: an #NMSettingUpdateSecretResult + **/ +NMSettingUpdateSecretResult +_nm_setting_update_secrets(NMSetting *setting, GVariant *secrets, GError **error) +{ + GVariantIter iter; + const char * secret_key; + GVariant * secret_value; + GError * tmp_error = NULL; + NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; + + g_return_val_if_fail(NM_IS_SETTING(setting), NM_SETTING_UPDATE_SECRET_ERROR); + g_return_val_if_fail(g_variant_is_of_type(secrets, NM_VARIANT_TYPE_SETTING), + NM_SETTING_UPDATE_SECRET_ERROR); + if (error) + g_return_val_if_fail(*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR); + + g_variant_iter_init(&iter, secrets); + while (g_variant_iter_next(&iter, "{&sv}", &secret_key, &secret_value)) { + int success; + + success = NM_SETTING_GET_CLASS(setting)->update_one_secret(setting, + secret_key, + secret_value, + &tmp_error); + nm_assert(!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error))); + + g_variant_unref(secret_value); + + if (success == NM_SETTING_UPDATE_SECRET_ERROR) { + g_propagate_error(error, tmp_error); + return NM_SETTING_UPDATE_SECRET_ERROR; + } + + if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) + result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; + } + + return result; +} + +static void +for_each_secret(NMSetting * setting, + const char * secret_name, + GVariant * val, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data, + GVariantBuilder * setting_builder) +{ + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + + if (!nm_setting_get_secret_flags(setting, secret_name, &secret_flags, NULL)) { + if (!remove_non_secrets) + g_variant_builder_add(setting_builder, "{sv}", secret_name, val); + return; + } + if (callback(secret_flags, callback_data)) + g_variant_builder_add(setting_builder, "{sv}", secret_name, val); +} + +static void +_set_error_secret_property_not_found(GError **error, NMSetting *setting, const char *secret_name) +{ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND, + _("not a secret property")); + g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), secret_name); +} + +gboolean +_nm_setting_property_is_regular_secret(NMSetting *setting, const char *secret_name) +{ + const NMSettInfoProperty *property; + + nm_assert(NM_IS_SETTING(setting)); + nm_assert(secret_name); + + property = _nm_setting_class_get_property_info(NM_SETTING_GET_CLASS(setting), secret_name); + return property && property->param_spec + && NM_FLAGS_HAS(property->param_spec->flags, NM_SETTING_PARAM_SECRET); +} + +gboolean +_nm_setting_property_is_regular_secret_flags(NMSetting *setting, const char *secret_flags_name) +{ + const NMSettInfoProperty *property; + + nm_assert(NM_IS_SETTING(setting)); + nm_assert(secret_flags_name); + + property = + _nm_setting_class_get_property_info(NM_SETTING_GET_CLASS(setting), secret_flags_name); + return property && property->param_spec + && !NM_FLAGS_HAS(property->param_spec->flags, NM_SETTING_PARAM_SECRET) + && G_PARAM_SPEC_VALUE_TYPE(property->param_spec) == NM_TYPE_SETTING_SECRET_FLAGS; +} + +static gboolean +get_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags *out_flags, + GError ** error) +{ + gs_free char * secret_flags_name_free = NULL; + const char * secret_flags_name; + NMSettingSecretFlags flags; + + if (!_nm_setting_property_is_regular_secret(setting, secret_name)) { + _set_error_secret_property_not_found(error, setting, secret_name); + NM_SET_OUT(out_flags, NM_SETTING_SECRET_FLAG_NONE); + return FALSE; + } + + secret_flags_name = nm_construct_name_a("%s-flags", secret_name, &secret_flags_name_free); + + nm_assert(_nm_setting_property_is_regular_secret_flags(setting, secret_flags_name)); + + g_object_get(G_OBJECT(setting), secret_flags_name, &flags, NULL); + NM_SET_OUT(out_flags, flags); + return TRUE; +} + +/** + * nm_setting_get_secret_flags: + * @setting: the #NMSetting + * @secret_name: the secret key name to get flags for + * @out_flags: on success, the #NMSettingSecretFlags for the secret + * @error: location to store error, or %NULL + * + * For a given secret, retrieves the #NMSettingSecretFlags describing how to + * handle that secret. + * + * Returns: %TRUE on success (if the given secret name was a valid property of + * this setting, and if that property is secret), %FALSE if not + **/ +gboolean +nm_setting_get_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags *out_flags, + GError ** error) +{ + g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); + g_return_val_if_fail(secret_name != NULL, FALSE); + + return NM_SETTING_GET_CLASS(setting)->get_secret_flags(setting, secret_name, out_flags, error); +} + +static gboolean +set_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags flags, + GError ** error) +{ + gs_free char *secret_flags_name_free = NULL; + const char * secret_flags_name; + + if (!_nm_setting_property_is_regular_secret(setting, secret_name)) { + _set_error_secret_property_not_found(error, setting, secret_name); + return FALSE; + } + + secret_flags_name = nm_construct_name_a("%s-flags", secret_name, &secret_flags_name_free); + + nm_assert(_nm_setting_property_is_regular_secret_flags(setting, secret_flags_name)); + + if (!nm_g_object_set_property_flags(G_OBJECT(setting), + secret_flags_name, + NM_TYPE_SETTING_SECRET_FLAGS, + flags, + error)) + g_return_val_if_reached(FALSE); + return TRUE; +} + +/** + * nm_setting_set_secret_flags: + * @setting: the #NMSetting + * @secret_name: the secret key name to set flags for + * @flags: the #NMSettingSecretFlags for the secret + * @error: location to store error, or %NULL + * + * For a given secret, stores the #NMSettingSecretFlags describing how to + * handle that secret. + * + * Returns: %TRUE on success (if the given secret name was a valid property of + * this setting, and if that property is secret), %FALSE if not + **/ +gboolean +nm_setting_set_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags flags, + GError ** error) +{ + g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); + g_return_val_if_fail(secret_name != NULL, FALSE); + g_return_val_if_fail(_nm_setting_secret_flags_valid(flags), FALSE); + + return NM_SETTING_GET_CLASS(setting)->set_secret_flags(setting, secret_name, flags, error); +} + +/** + * nm_setting_to_string: + * @setting: the #NMSetting + * + * Convert the setting (including secrets!) into a string. For debugging + * purposes ONLY, should NOT be used for serialization of the setting, + * or machine-parsed in any way. The output format is not guaranteed to + * be stable and may change at any time. + * + * Returns: an allocated string containing a textual representation of the + * setting's properties and values, which the caller should + * free with g_free() + **/ +char * +nm_setting_to_string(NMSetting *setting) +{ + GString * string; + gs_unref_variant GVariant *variant = NULL; + GVariant * child; + GVariantIter iter; + + string = g_string_new(nm_setting_get_name(setting)); + g_string_append_c(string, '\n'); + + variant = _nm_setting_to_dbus(setting, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); + + g_variant_iter_init(&iter, variant); + while ((child = g_variant_iter_next_value(&iter))) { + gs_free char * name = NULL; + gs_free char * value_str = NULL; + gs_unref_variant GVariant *value = NULL; + + g_variant_get(child, "{sv}", &name, &value); + value_str = g_variant_print(value, FALSE); + + g_string_append_printf(string, "\t%s : %s\n", name, value_str); + } + + return g_string_free(string, FALSE); +} + +static GVariant * +_nm_setting_get_deprecated_virtual_interface_name(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + NMSettingConnection *s_con; + + if (!connection) + return NULL; + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) + return NULL; + + if (nm_setting_connection_get_interface_name(s_con)) + return g_variant_new_string(nm_setting_connection_get_interface_name(s_con)); + else + return NULL; +} + +const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_interface_name = { + .dbus_type = G_VARIANT_TYPE_STRING, + .to_dbus_fcn = _nm_setting_get_deprecated_virtual_interface_name, +}; + +const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_i = { + .dbus_type = G_VARIANT_TYPE_INT32, + /* No functions set. This property type is to silently ignore the value on D-Bus. */ +}; + +const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_u = { + .dbus_type = G_VARIANT_TYPE_UINT32, + /* No functions set. This property type is to silently ignore the value on D-Bus. */ +}; + +const NMSettInfoPropertType nm_sett_info_propert_type_plain_i = { + .dbus_type = G_VARIANT_TYPE_INT32, +}; + +const NMSettInfoPropertType nm_sett_info_propert_type_plain_u = { + .dbus_type = G_VARIANT_TYPE_UINT32, +}; + +/*****************************************************************************/ + +static GenData * +_gendata_hash(NMSetting *setting, gboolean create_if_necessary) +{ + NMSettingPrivate *priv; + + nm_assert(NM_IS_SETTING(setting)); + + priv = NM_SETTING_GET_PRIVATE(setting); + + if (G_UNLIKELY(!priv->gendata)) { + if (!create_if_necessary) + return NULL; + priv->gendata = g_slice_new(GenData); + priv->gendata->hash = g_hash_table_new_full(nm_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_variant_unref); + priv->gendata->names = NULL; + priv->gendata->values = NULL; + } + + return priv->gendata; +} + +GHashTable * +_nm_setting_option_hash(NMSetting *setting, gboolean create_if_necessary) +{ + GenData *gendata; + + gendata = _gendata_hash(setting, create_if_necessary); + return gendata ? gendata->hash : NULL; +} + +void +_nm_setting_option_notify(NMSetting *setting, gboolean names_changed) +{ + GenData *gendata; + + gendata = _gendata_hash(setting, FALSE); + if (!gendata) + goto out; + + nm_clear_g_free(&gendata->values); + + if (names_changed) { + /* if only the values changed, it's sufficient to invalidate the + * values cache. Otherwise, the names cache must be invalidated too. */ + nm_clear_g_free(&gendata->names); + } + + /* Note, currently there is no way to notify the subclass when gendata changed. + * gendata is only changed in two situations: + * 1) from within NMSetting itself, for example when creating a NMSetting instance + * from keyfile or a D-Bus GVariant. + * 2) actively from the subclass itself + * For 2), we don't need the notification, because the subclass knows that something + * changed. + * For 1), we currently don't need the notification either, because all that the subclass + * currently would do, is emit a g_object_notify() signal. However, 1) only happens when + * the setting instance is newly created, at that point, nobody listens to the signal. + * + * If we ever need it, then we would need to call a virtual function to notify the subclass + * that gendata changed. */ + +out: + _nm_setting_emit_property_changed(setting); +} + +guint +_nm_setting_option_get_all(NMSetting * setting, + const char *const **out_names, + GVariant *const ** out_values) +{ + GenData * gendata; + GHashTable *hash; + guint i, len; + + nm_assert(NM_IS_SETTING(setting)); + + gendata = _gendata_hash(setting, FALSE); + if (!gendata) + goto out_zero; + + hash = gendata->hash; + len = g_hash_table_size(hash); + if (len == 0) + goto out_zero; + + if (!out_names && !out_values) + return len; + + if (G_UNLIKELY(!gendata->names)) { + gendata->names = nm_utils_strdict_get_keys(hash, TRUE, NULL); + } + + if (out_values) { + if (G_UNLIKELY(!gendata->values)) { + gendata->values = g_new(GVariant *, len + 1); + for (i = 0; i < len; i++) + gendata->values[i] = g_hash_table_lookup(hash, gendata->names[i]); + gendata->values[i] = NULL; + } + *out_values = gendata->values; + } + + NM_SET_OUT(out_names, (const char *const *) gendata->names); + return len; + +out_zero: + NM_SET_OUT(out_names, NULL); + NM_SET_OUT(out_values, NULL); + return 0; +} + +/** + * nm_setting_option_get_all_names: + * @setting: the #NMSetting + * @out_len: (allow-none) (out): + * + * Gives the name of all set options. + * + * Returns: (array length=out_len zero-terminated=1) (transfer none): + * A %NULL terminated array of key names. If no names are present, this returns + * %NULL. The returned array and the names are owned by %NMSetting and might be invalidated + * by the next operation. + * + * Since: 1.26 + **/ +const char *const * +nm_setting_option_get_all_names(NMSetting *setting, guint *out_len) +{ + const char *const *names; + guint len; + + g_return_val_if_fail(NM_IS_SETTING(setting), NULL); + + len = _nm_setting_option_get_all(setting, &names, NULL); + NM_SET_OUT(out_len, len); + return names; +} + +gboolean +_nm_setting_option_clear(NMSetting *setting, const char *optname) +{ + GHashTable *ht; + + nm_assert(NM_IS_SETTING(setting)); + nm_assert(nm_str_not_empty(optname)); + + ht = _nm_setting_option_hash(setting, FALSE); + if (!ht) + return FALSE; + + return g_hash_table_remove(ht, optname); +} + +/** + * nm_setting_option_clear_by_name: + * @setting: the #NMSetting + * @predicate: (allow-none) (scope call): the predicate for which names + * should be clear. + * If the predicate returns %TRUE for an option name, the option + * gets removed. If %NULL, all options will be removed. + * + * Since: 1.26 + */ +void +nm_setting_option_clear_by_name(NMSetting *setting, NMUtilsPredicateStr predicate) +{ + GHashTable * hash; + GHashTableIter iter; + const char * name; + gboolean changed = FALSE; + + g_return_if_fail(NM_IS_SETTING(setting)); + + hash = _nm_setting_option_hash(NM_SETTING(setting), FALSE); + if (!hash) + return; + + if (!predicate) { + changed = (g_hash_table_size(hash) > 0); + if (changed) + g_hash_table_remove_all(hash); + } else { + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &name, NULL)) { + if (predicate(name)) { + g_hash_table_iter_remove(&iter); + changed = TRUE; + } + } + } + + if (changed) + _nm_setting_option_notify(setting, TRUE); +} + +/*****************************************************************************/ + +/** + * nm_setting_option_get: + * @setting: the #NMSetting + * @opt_name: the option name to request. + * + * Returns: (transfer none): the #GVariant or %NULL if the option + * is not set. + * + * Since: 1.26. + */ +GVariant * +nm_setting_option_get(NMSetting *setting, const char *opt_name) +{ + GenData *gendata; + + g_return_val_if_fail(NM_IS_SETTING(setting), FALSE); + g_return_val_if_fail(opt_name, FALSE); + + gendata = _gendata_hash(setting, FALSE); + return gendata ? g_hash_table_lookup(gendata->hash, opt_name) : NULL; +} + +/** + * nm_setting_option_get_boolean: + * @setting: the #NMSetting + * @opt_name: the option to get + * @out_value: (allow-none) (out): the optional output value. + * If the option is unset, %FALSE will be returned. + * + * Returns: %TRUE if @opt_name is set to a boolean variant. + * + * Since: 1.26 + */ +gboolean +nm_setting_option_get_boolean(NMSetting *setting, const char *opt_name, gboolean *out_value) +{ + GVariant *v; + + v = nm_setting_option_get(NM_SETTING(setting), opt_name); + if (v && g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) { + NM_SET_OUT(out_value, g_variant_get_boolean(v)); + return TRUE; + } + NM_SET_OUT(out_value, FALSE); + return FALSE; +} + +/** + * nm_setting_option_get_uint32: + * @setting: the #NMSetting + * @opt_name: the option to get + * @out_value: (allow-none) (out): the optional output value. + * If the option is unset, 0 will be returned. + * + * Returns: %TRUE if @opt_name is set to a uint32 variant. + * + * Since: 1.26 + */ +gboolean +nm_setting_option_get_uint32(NMSetting *setting, const char *opt_name, guint32 *out_value) +{ + GVariant *v; + + v = nm_setting_option_get(NM_SETTING(setting), opt_name); + if (v && g_variant_is_of_type(v, G_VARIANT_TYPE_UINT32)) { + NM_SET_OUT(out_value, g_variant_get_uint32(v)); + return TRUE; + } + NM_SET_OUT(out_value, 0); + return FALSE; +} + +/** + * nm_setting_option_set: + * @setting: the #NMSetting + * @opt_name: the option name to set + * @variant: (allow-none): the variant to set. + * + * If @variant is %NULL, this clears the option if it is set. + * Otherwise, @variant is set as the option. If @variant is + * a floating reference, it will be consumed. + * + * Note that not all setting types support options. It is a bug + * setting a variant to a setting that doesn't support it. + * Currently, only #NMSettingEthtool supports it. + * + * Since: 1.26 + */ +void +nm_setting_option_set(NMSetting *setting, const char *opt_name, GVariant *variant) +{ + GVariant * old_variant; + gboolean changed_name; + gboolean changed_value; + GHashTable *hash; + + g_return_if_fail(NM_IS_SETTING(setting)); + g_return_if_fail(opt_name); + + hash = _nm_setting_option_hash(setting, variant != NULL); + + if (!variant) { + if (hash) { + if (g_hash_table_remove(hash, opt_name)) + _nm_setting_option_notify(setting, TRUE); + } + return; + } + + /* Currently, it is a bug setting any option, unless the setting type supports it. + * And currently, only NMSettingEthtool supports it. + * + * In the future, more setting types may support it. Or we may relax this so + * that options can be attached to all setting types (to indicate "unsupported" + * settings for forward compatibility). + * + * As it is today, internal code will only add gendata options to NMSettingEthtool, + * and there exists not public API to add such options. Still, it is permissible + * to call get(), clear() and set(variant=NULL) also on settings that don't support + * it, as these operations don't add options. + */ + g_return_if_fail( + _nm_setting_class_get_sett_info(NM_SETTING_GET_CLASS(setting))->detail.gendata_info); + + old_variant = g_hash_table_lookup(hash, opt_name); + + changed_name = (old_variant == NULL); + changed_value = changed_name || !g_variant_equal(old_variant, variant); + + /* We always want to replace the variant, even if it has + * the same value according to g_variant_equal(). The reason + * is that we want to take a reference on @variant, because + * that is what the user might expect. */ + g_hash_table_insert(hash, g_strdup(opt_name), g_variant_ref_sink(variant)); + + if (changed_value) + _nm_setting_option_notify(setting, !changed_name); +} + +/** + * nm_setting_option_set_boolean: + * @setting: the #NMSetting + * @value: the value to set. + * + * Like nm_setting_option_set() to set a boolean GVariant. + * + * Since: 1.26 + */ +void +nm_setting_option_set_boolean(NMSetting *setting, const char *opt_name, gboolean value) +{ + GVariant * old_variant; + gboolean changed_name; + gboolean changed_value; + GHashTable *hash; + + g_return_if_fail(NM_IS_SETTING(setting)); + g_return_if_fail(opt_name); + + value = (!!value); + + hash = _nm_setting_option_hash(setting, TRUE); + + old_variant = g_hash_table_lookup(hash, opt_name); + + changed_name = (old_variant == NULL); + changed_value = changed_name + || (!g_variant_is_of_type(old_variant, G_VARIANT_TYPE_BOOLEAN) + || g_variant_get_boolean(old_variant) != value); + + g_hash_table_insert(hash, g_strdup(opt_name), g_variant_ref_sink(g_variant_new_boolean(value))); + + if (changed_value) + _nm_setting_option_notify(setting, !changed_name); +} + +/** + * nm_setting_option_set_uint32: + * @setting: the #NMSetting + * @value: the value to set. + * + * Like nm_setting_option_set() to set a uint32 GVariant. + * + * Since: 1.26 + */ +void +nm_setting_option_set_uint32(NMSetting *setting, const char *opt_name, guint32 value) +{ + GVariant * old_variant; + gboolean changed_name; + gboolean changed_value; + GHashTable *hash; + + g_return_if_fail(NM_IS_SETTING(setting)); + g_return_if_fail(opt_name); + + hash = _nm_setting_option_hash(setting, TRUE); + + old_variant = g_hash_table_lookup(hash, opt_name); + + changed_name = (old_variant == NULL); + changed_value = changed_name + || (!g_variant_is_of_type(old_variant, G_VARIANT_TYPE_UINT32) + || g_variant_get_uint32(old_variant) != value); + + g_hash_table_insert(hash, g_strdup(opt_name), g_variant_ref_sink(g_variant_new_uint32(value))); + + if (changed_value) + _nm_setting_option_notify(setting, !changed_name); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSetting *setting = NM_SETTING(object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string(value, nm_setting_get_name(setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_init(NMSetting *setting) +{} + +static void +finalize(GObject *object) +{ + NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE(object); + + if (priv->gendata) { + g_free(priv->gendata->names); + g_free(priv->gendata->values); + g_hash_table_unref(priv->gendata->hash); + g_slice_free(GenData, priv->gendata); + } + + G_OBJECT_CLASS(nm_setting_parent_class)->finalize(object); +} + +static void +nm_setting_class_init(NMSettingClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(setting_class); + + g_type_class_add_private(setting_class, sizeof(NMSettingPrivate)); + + object_class->get_property = get_property; + object_class->finalize = finalize; + + setting_class->update_one_secret = update_one_secret; + setting_class->get_secret_flags = get_secret_flags; + setting_class->set_secret_flags = set_secret_flags; + setting_class->compare_property = compare_property; + setting_class->clear_secrets = clear_secrets; + setting_class->for_each_secret = for_each_secret; + setting_class->duplicate_copy_properties = duplicate_copy_properties; + setting_class->enumerate_values = enumerate_values; + setting_class->aggregate = aggregate; + setting_class->init_from_dbus = init_from_dbus; + + /** + * NMSetting:name: + * + * The setting's name, which uniquely identifies the setting within the + * connection. Each setting type has a name unique to that type, for + * example "ppp" or "802-11-wireless" or "802-3-ethernet". + **/ + obj_properties[PROP_NAME] = g_param_spec_string(NM_SETTING_NAME, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} diff --git a/src/libnm-core-impl/nm-simple-connection.c b/src/libnm-core-impl/nm-simple-connection.c new file mode 100644 index 0000000000..6834c41e23 --- /dev/null +++ b/src/libnm-core-impl/nm-simple-connection.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2014 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-simple-connection.h" + +#include "nm-setting-private.h" + +/** + * SECTION:nm-simple-connection + * @short_description: An unmanaged connection + * + * An #NMSimpleConnection does not directly represent a D-Bus-exported connection, + * but might be used in the process of creating a new one. + **/ + +/*****************************************************************************/ + +static void nm_simple_connection_interface_init(NMConnectionInterface *iface); + +G_DEFINE_TYPE_WITH_CODE(NMSimpleConnection, + nm_simple_connection, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(NM_TYPE_CONNECTION, + nm_simple_connection_interface_init);) + +/*****************************************************************************/ + +static void +nm_simple_connection_init(NMSimpleConnection *self) +{} + +/** + * nm_simple_connection_new: + * + * Creates a new #NMSimpleConnection object with no #NMSetting objects. + * + * Returns: (transfer full): the new empty #NMConnection object + **/ +NMConnection * +nm_simple_connection_new(void) +{ + return g_object_new(NM_TYPE_SIMPLE_CONNECTION, NULL); +} + +/** + * _nm_simple_connection_new_from_dbus: + * @dict: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION describing the connection + * @error: on unsuccessful return, an error + * + * Creates a new #NMSimpleConnection from a hash table describing the + * connection. See nm_connection_to_dbus() for a description of the expected + * hash table. + * + * Returns: (transfer full): the new #NMSimpleConnection object, populated with + * settings created from the values in the hash table, or %NULL if there was + * an error. + **/ +NMConnection * +_nm_simple_connection_new_from_dbus(GVariant *dict, NMSettingParseFlags parse_flags, GError **error) +{ + NMConnection *connection; + + g_return_val_if_fail(dict != NULL, NULL); + g_return_val_if_fail(g_variant_is_of_type(dict, NM_VARIANT_TYPE_CONNECTION), NULL); + g_return_val_if_fail(!NM_FLAGS_ANY(parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL), NULL); + g_return_val_if_fail( + !NM_FLAGS_ALL(parse_flags, + NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT), + NULL); + + connection = nm_simple_connection_new(); + if (!_nm_connection_replace_settings(connection, dict, parse_flags, error)) + g_clear_object(&connection); + return connection; +} + +/** + * nm_simple_connection_new_from_dbus: + * @dict: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION describing the connection + * @error: on unsuccessful return, an error + * + * Creates a new #NMSimpleConnection from a hash table describing the + * connection and normalize the connection. See nm_connection_to_dbus() for a + * description of the expected hash table. + * + * Returns: (transfer full): the new #NMSimpleConnection object, populated with + * settings created from the values in the hash table, or %NULL if the + * connection failed to normalize. + **/ +NMConnection * +nm_simple_connection_new_from_dbus(GVariant *dict, GError **error) +{ + return _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, error); +} + +/** + * nm_simple_connection_new_clone: + * @connection: the #NMConnection to clone + * + * Clones an #NMConnection as an #NMSimpleConnection. + * + * Returns: (transfer full): a new #NMConnection containing the same settings + * and properties as the source #NMConnection + **/ +NMConnection * +nm_simple_connection_new_clone(NMConnection *connection) +{ + NMConnection *clone; + const char * path; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + + clone = nm_simple_connection_new(); + + path = nm_connection_get_path(connection); + if (path) + nm_connection_set_path(clone, path); + + nm_connection_replace_settings_from_connection(clone, connection); + + return clone; +} + +static void +dispose(GObject *object) +{ +#if NM_MORE_ASSERTS + g_signal_handlers_disconnect_by_data(object, + (gpointer) &_nmtst_connection_unchanging_user_data); +#endif + + nm_connection_clear_secrets(NM_CONNECTION(object)); + + G_OBJECT_CLASS(nm_simple_connection_parent_class)->dispose(object); +} + +static void +nm_simple_connection_class_init(NMSimpleConnectionClass *simple_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(simple_class); + + object_class->dispose = dispose; +} + +static void +nm_simple_connection_interface_init(NMConnectionInterface *iface) +{} diff --git a/src/libnm-core-impl/nm-team-utils.c b/src/libnm-core-impl/nm-team-utils.c new file mode 100644 index 0000000000..9546ababfd --- /dev/null +++ b/src/libnm-core-impl/nm-team-utils.c @@ -0,0 +1,2866 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#define NM_VALUE_TYPE_DEFINE_FUNCTIONS + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-team-utils.h" + +#include "nm-errors.h" +#include "nm-utils-private.h" +#include "nm-glib-aux/nm-json-aux.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "nm-setting-team.h" +#include "nm-setting-team-port.h" + +/*****************************************************************************/ + +typedef enum { + SET_FIELD_MODE_UNSET = 0, + SET_FIELD_MODE_SET = 1, + + /* Sets the field as set, unless the field is at the default. + * This is the case for API that is called from NMSettingTeam/NMSettingTeamPort. + * This means, using libnm API to reset the value of a NMSetting to the default, + * will mark the field as unset. + * This is different from initializing the field when parsing JSON/GVariant. In + * that case an explicitly set field (even set to the default value) will be remembered + * to be set. */ + SET_FIELD_MODE_SET_UNLESS_DEFAULT = 2, +} SetFieldModeEnum; + +typedef enum { + RESET_JSON_NO = FALSE, + RESET_JSON_YES = TRUE, +} ResetJsonEnum; + +/* we rely on "config" being the first. At various places we iterate over attribute types, + * starting after "config".*/ +G_STATIC_ASSERT(_NM_TEAM_ATTRIBUTE_0 == 0); +G_STATIC_ASSERT(NM_TEAM_ATTRIBUTE_CONFIG == 1); + +static const char *const _valid_names_runner[] = { + NM_SETTING_TEAM_RUNNER_BROADCAST, + NM_SETTING_TEAM_RUNNER_ROUNDROBIN, + NM_SETTING_TEAM_RUNNER_RANDOM, + NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP, + NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NM_SETTING_TEAM_RUNNER_LACP, + NULL, +}; + +static const char *const _valid_names_runner_hwaddr_policy[] = { + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL, + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE, + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE, + NULL, +}; + +static const char *const _valid_names_runner_tx_balancer[] = { + "basic", + NULL, +}; + +static const char *const _valid_names_runner_tx_hash[] = { + "eth", + "vlan", + "ipv4", + "ipv6", + "ip", + "l3", + "l4", + "tcp", + "udp", + "sctp", + NULL, +}; + +static const char *const _valid_names_runner_agg_select_policy[] = { + "lacp_prio", + "lacp_prio_stable", + "bandwidth", + "count", + "port_config", + NULL, +}; + +typedef struct { + NMTeamAttribute team_attr; + const char *const *valid_runners; +} RunnerCompatElem; + +static const RunnerCompatElem _runner_compat_lst[] = { + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP), + }, + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LOADBALANCE, NM_SETTING_TEAM_RUNNER_LACP), + }, + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LOADBALANCE, NM_SETTING_TEAM_RUNNER_LACP), + }, + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LOADBALANCE, NM_SETTING_TEAM_RUNNER_LACP), + }, + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), + }, + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), + }, + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), + }, + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), + }, + { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, + NM_MAKE_STRV(NM_SETTING_TEAM_RUNNER_LACP), + }, +}; + +typedef struct { + const char *const *js_keys; + const char * property_name; + NMValueTypUnion default_val; + union { + struct { + gint32 min; + gint32 max; + } r_int32; + struct { + const char *const *valid_names; + } r_string; + } range; + NMTeamAttribute team_attr; + NMValueType value_type; + guint8 field_offset; + guint8 js_keys_len; + bool for_master : 1; + bool for_port : 1; + bool has_range : 1; +} TeamAttrData; + +#define TEAM_ATTR_IDX(_is_port, _team_attr) \ + (((!(_is_port) || (_team_attr) < _NM_TEAM_ATTRIBUTE_START) \ + ? (int) (_team_attr) \ + : (((int) (_NM_TEAM_ATTRIBUTE_MASTER_NUM - _NM_TEAM_ATTRIBUTE_START)) \ + + ((int) (_team_attr)))) \ + - 1) + +#define TEAM_ATTR_IDX_CONFIG (TEAM_ATTR_IDX(FALSE, NM_TEAM_ATTRIBUTE_CONFIG)) + +static const TeamAttrData team_attr_datas[] = { + +#define _JS_KEYS(...) .js_keys = NM_MAKE_STRV(__VA_ARGS__), .js_keys_len = NM_NARG(__VA_ARGS__) + +#define _VAL_BOOL(_default) .default_val.v_bool = (_default) + +#define _VAL_INT32(_default) .default_val.v_int32 = (_default) + +#define _VAL_INT32_RANGE(_default, _min, _max) \ + _VAL_INT32(_default), .has_range = TRUE, \ + .range.r_int32 = { \ + .min = _min, \ + .max = _max, \ + } + +#define _VAL_STRING() .default_val.v_string = NULL + +#define _VAL_STRING_RANGE(_valid_names) \ + _VAL_STRING(), .has_range = TRUE, \ + .range.r_string = { \ + .valid_names = (_valid_names), \ + } + +#define _VAL_UNSPEC() .default_val.v_string = (NULL) + +#define _INIT(_is_port, _team_attr, field, _value_type, _property_name, ...) \ + [TEAM_ATTR_IDX(_is_port, _team_attr)] = { \ + .for_master = (_team_attr) < _NM_TEAM_ATTRIBUTE_START || !(_is_port), \ + .for_port = (_team_attr) < _NM_TEAM_ATTRIBUTE_START || (_is_port), \ + .team_attr = (_team_attr), \ + .field_offset = G_STRUCT_OFFSET(NMTeamSetting, _data_priv.field), \ + .value_type = (_value_type), \ + .property_name = ""_property_name \ + "", \ + __VA_ARGS__} + + _INIT(0, NM_TEAM_ATTRIBUTE_CONFIG, _js_str, NM_VALUE_TYPE_UNSPEC, NM_SETTING_TEAM_CONFIG, ), + + _INIT(0, + NM_TEAM_ATTRIBUTE_LINK_WATCHERS, + link_watchers, + NM_VALUE_TYPE_UNSPEC, + NM_SETTING_TEAM_LINK_WATCHERS, + _JS_KEYS("link_watch"), + _VAL_UNSPEC(), ), + + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT, + master.notify_peers_count, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, + _JS_KEYS("notify_peers", "count"), + _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, + master.notify_peers_interval, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, + _JS_KEYS("notify_peers", "interval"), + _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, + master.mcast_rejoin_count, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_MCAST_REJOIN_COUNT, + _JS_KEYS("mcast_rejoin", "count"), + _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, + master.mcast_rejoin_interval, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, + _JS_KEYS("mcast_rejoin", "interval"), + _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER, + master.runner, + NM_VALUE_TYPE_STRING, + NM_SETTING_TEAM_RUNNER, + _JS_KEYS("runner", "name"), + _VAL_STRING_RANGE(_valid_names_runner), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, + master.runner_hwaddr_policy, + NM_VALUE_TYPE_STRING, + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, + _JS_KEYS("runner", "hwaddr_policy"), + _VAL_STRING_RANGE(_valid_names_runner_hwaddr_policy), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, + master.runner_tx_hash, + NM_VALUE_TYPE_UNSPEC, + NM_SETTING_TEAM_RUNNER_TX_HASH, + _JS_KEYS("runner", "tx_hash"), + _VAL_UNSPEC(), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, + master.runner_tx_balancer, + NM_VALUE_TYPE_STRING, + NM_SETTING_TEAM_RUNNER_TX_BALANCER, + _JS_KEYS("runner", "tx_balancer", "name"), + _VAL_STRING_RANGE(_valid_names_runner_tx_balancer), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, + master.runner_tx_balancer_interval, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, + _JS_KEYS("runner", "tx_balancer", "balancing_interval"), + _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, + master.runner_active, + NM_VALUE_TYPE_BOOL, + NM_SETTING_TEAM_RUNNER_ACTIVE, + _JS_KEYS("runner", "active"), + _VAL_BOOL(TRUE), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, + master.runner_fast_rate, + NM_VALUE_TYPE_BOOL, + NM_SETTING_TEAM_RUNNER_FAST_RATE, + _JS_KEYS("runner", "fast_rate"), + _VAL_BOOL(FALSE), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, + master.runner_sys_prio, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_RUNNER_SYS_PRIO, + _JS_KEYS("runner", "sys_prio"), + _VAL_INT32_RANGE(-1, 0, USHRT_MAX + 1), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, + master.runner_min_ports, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_RUNNER_MIN_PORTS, + _JS_KEYS("runner", "min_ports"), + _VAL_INT32_RANGE(-1, 1, UCHAR_MAX + 1), ), + _INIT(0, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, + master.runner_agg_select_policy, + NM_VALUE_TYPE_STRING, + NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, + _JS_KEYS("runner", "agg_select_policy"), + _VAL_STRING_RANGE(_valid_names_runner_agg_select_policy), ), + + _INIT(1, + NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID, + port.queue_id, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_PORT_QUEUE_ID, + _JS_KEYS("queue_id"), + _VAL_INT32_RANGE(-1, 0, G_MAXINT32), ), + _INIT(1, + NM_TEAM_ATTRIBUTE_PORT_PRIO, + port.prio, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_PORT_PRIO, + _JS_KEYS("prio"), + _VAL_INT32(0), ), + _INIT(1, + NM_TEAM_ATTRIBUTE_PORT_STICKY, + port.sticky, + NM_VALUE_TYPE_BOOL, + NM_SETTING_TEAM_PORT_STICKY, + _JS_KEYS("sticky"), + _VAL_BOOL(FALSE), ), + _INIT(1, + NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, + port.lacp_prio, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_PORT_LACP_PRIO, + _JS_KEYS("lacp_prio"), + _VAL_INT32_RANGE(-1, 0, USHRT_MAX + 1), ), + _INIT(1, + NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, + port.lacp_key, + NM_VALUE_TYPE_INT32, + NM_SETTING_TEAM_PORT_LACP_KEY, + _JS_KEYS("lacp_key"), + _VAL_INT32_RANGE(-1, 0, USHRT_MAX + 1), ), + +#undef _INIT +}; + +/*****************************************************************************/ + +typedef enum { + LINK_WATCHER_ATTRIBUTE_NAME, + LINK_WATCHER_ATTRIBUTE_DELAY_UP, + LINK_WATCHER_ATTRIBUTE_DELAY_DOWN, + LINK_WATCHER_ATTRIBUTE_INTERVAL, + LINK_WATCHER_ATTRIBUTE_INIT_WAIT, + LINK_WATCHER_ATTRIBUTE_MISSED_MAX, + LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, + LINK_WATCHER_ATTRIBUTE_TARGET_HOST, + LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, + LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, + LINK_WATCHER_ATTRIBUTE_VLANID, + LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS, +} LinkWatcherAttribute; + +#define _EXPECTED_LINK_WATCHER_ATTRIBUTES_ETHTOOL \ + LINK_WATCHER_ATTRIBUTE_NAME, LINK_WATCHER_ATTRIBUTE_DELAY_UP, LINK_WATCHER_ATTRIBUTE_DELAY_DOWN +#define _EXPECTED_LINK_WATCHER_ATTRIBUTES_NSNA_PING \ + LINK_WATCHER_ATTRIBUTE_NAME, LINK_WATCHER_ATTRIBUTE_INTERVAL, \ + LINK_WATCHER_ATTRIBUTE_INIT_WAIT, LINK_WATCHER_ATTRIBUTE_MISSED_MAX, \ + LINK_WATCHER_ATTRIBUTE_TARGET_HOST +#define _EXPECTED_LINK_WATCHER_ATTRIBUTES_ARP_PING \ + LINK_WATCHER_ATTRIBUTE_NAME, LINK_WATCHER_ATTRIBUTE_INTERVAL, \ + LINK_WATCHER_ATTRIBUTE_INIT_WAIT, LINK_WATCHER_ATTRIBUTE_MISSED_MAX, \ + LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, LINK_WATCHER_ATTRIBUTE_TARGET_HOST, \ + LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, \ + LINK_WATCHER_ATTRIBUTE_VLANID, LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS + +typedef struct { + const char * js_key; + const char * dbus_name; + NMValueTypUnion default_val; + LinkWatcherAttribute link_watcher_attr; + NMValueType value_type; +} LinkWatcherAttrData; + +static const LinkWatcherAttrData link_watcher_attr_datas[] = { +#define _INIT(_link_watcher_attr, _js_key, _dbus_name, _value_type, ...) \ + [_link_watcher_attr] = {.link_watcher_attr = (_link_watcher_attr), \ + .value_type = (_value_type), \ + .js_key = (""_js_key \ + ""), \ + .dbus_name = (""_dbus_name \ + ""), \ + __VA_ARGS__} + _INIT(LINK_WATCHER_ATTRIBUTE_NAME, "name", "name", NM_VALUE_TYPE_STRING, ), + _INIT(LINK_WATCHER_ATTRIBUTE_DELAY_UP, "delay_up", "delay-up", NM_VALUE_TYPE_INT, ), + _INIT(LINK_WATCHER_ATTRIBUTE_DELAY_DOWN, "delay_down", "delay-down", NM_VALUE_TYPE_INT, ), + _INIT(LINK_WATCHER_ATTRIBUTE_INTERVAL, "interval", "interval", NM_VALUE_TYPE_INT, ), + _INIT(LINK_WATCHER_ATTRIBUTE_INIT_WAIT, "init_wait", "init-wait", NM_VALUE_TYPE_INT, ), + _INIT(LINK_WATCHER_ATTRIBUTE_MISSED_MAX, + "missed_max", + "missed-max", + NM_VALUE_TYPE_INT, + .default_val.v_int = 3, ), + _INIT(LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, "source_host", "source-host", NM_VALUE_TYPE_STRING, ), + _INIT(LINK_WATCHER_ATTRIBUTE_TARGET_HOST, "target_host", "target-host", NM_VALUE_TYPE_STRING, ), + _INIT(LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, + "validate_active", + "validate-active", + NM_VALUE_TYPE_BOOL, ), + _INIT(LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, + "validate_inactive", + "validate-inactive", + NM_VALUE_TYPE_BOOL, ), + _INIT(LINK_WATCHER_ATTRIBUTE_VLANID, + "vlanid", + "vlanid", + NM_VALUE_TYPE_INT, + .default_val.v_int = -1, ), + _INIT(LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS, "send_always", "send-always", NM_VALUE_TYPE_BOOL, ), +#undef _INIT +}; + +/*****************************************************************************/ + +static const TeamAttrData *_team_attr_data_get(gboolean is_port, NMTeamAttribute team_attr); +static gpointer _team_setting_get_field(const NMTeamSetting *self, const TeamAttrData *attr_data); +static void _link_watcher_to_json(const NMTeamLinkWatcher *link_watcher, GString *gstr); + +/*****************************************************************************/ + +static void +_team_attr_data_ASSERT(const TeamAttrData *attr_data) +{ +#if NM_MORE_ASSERTS > 5 + nm_assert(attr_data); + if (attr_data->for_port) + nm_assert(attr_data == _team_attr_data_get(TRUE, attr_data->team_attr)); + if (attr_data->for_master) + nm_assert(attr_data == _team_attr_data_get(FALSE, attr_data->team_attr)); + nm_assert((attr_data - team_attr_datas) + == TEAM_ATTR_IDX(attr_data->for_port, attr_data->team_attr)); + nm_assert(attr_data->value_type > 0); + nm_assert(attr_data->field_offset < sizeof(NMTeamSetting)); + nm_assert(attr_data->js_keys_len == NM_PTRARRAY_LEN(attr_data->js_keys)); + nm_assert(attr_data->property_name); + { + static int checked = 0; + + if (checked == 0) { + checked = 1; + + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; + attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) + _team_attr_data_ASSERT(attr_data); + } + } +#endif +} + +static gboolean +_team_attr_data_is_relevant(const TeamAttrData *attr_data, gboolean is_port) +{ + return is_port ? attr_data->for_port : attr_data->for_master; +} + +static const TeamAttrData * +_team_attr_data_get(gboolean is_port, NMTeamAttribute team_attr) +{ + const int idx = TEAM_ATTR_IDX(is_port, team_attr); + + nm_assert(idx >= 0 && idx < G_N_ELEMENTS(team_attr_datas)); + nm_assert(team_attr_datas[idx].team_attr == team_attr); + nm_assert(_team_attr_data_is_relevant(&team_attr_datas[idx], is_port)); + + return &team_attr_datas[idx]; +} + +static const TeamAttrData * +_team_attr_data_find_for_property_name(gboolean is_port, const char *property_name) +{ + const TeamAttrData *attr_data; + + for (attr_data = team_attr_datas; attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) { + if (_team_attr_data_is_relevant(attr_data, is_port) + && nm_streq(property_name, attr_data->property_name)) + return attr_data; + } + return NULL; +} + +static int +_team_attr_data_cmp(const TeamAttrData *attr_data, + gboolean is_port, + gconstpointer val_a, + gconstpointer val_b) +{ + const GPtrArray *v_ptrarray_a; + const GPtrArray *v_ptrarray_b; + guint len; + + _team_attr_data_ASSERT(attr_data); + nm_assert(val_a); + nm_assert(val_b); + + if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) + NM_CMP_RETURN(nm_value_type_cmp(attr_data->value_type, val_a, val_b)); + else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { + v_ptrarray_a = *((const GPtrArray *const *) val_a); + v_ptrarray_b = *((const GPtrArray *const *) val_b); + len = v_ptrarray_a ? v_ptrarray_a->len : 0u; + NM_CMP_DIRECT(len, (v_ptrarray_b ? v_ptrarray_b->len : 0u)); + if (len > 0) { + NM_CMP_RETURN( + nm_team_link_watchers_cmp((const NMTeamLinkWatcher *const *) v_ptrarray_a->pdata, + (const NMTeamLinkWatcher *const *) v_ptrarray_b->pdata, + len, + FALSE)); + } + } else if (!is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + v_ptrarray_a = *((const GPtrArray *const *) val_a); + v_ptrarray_b = *((const GPtrArray *const *) val_b); + NM_CMP_RETURN( + nm_utils_strv_cmp_n(v_ptrarray_a ? (const char *const *) v_ptrarray_a->pdata : NULL, + v_ptrarray_a ? v_ptrarray_a->len : 0u, + v_ptrarray_b ? (const char *const *) v_ptrarray_b->pdata : NULL, + v_ptrarray_b ? v_ptrarray_b->len : 0u)); + } else + nm_assert_not_reached(); + return 0; +} + +static gboolean +_team_attr_data_equal(const TeamAttrData *attr_data, + gboolean is_port, + gconstpointer val_a, + gconstpointer val_b) +{ + return _team_attr_data_cmp(attr_data, is_port, val_a, val_b) == 0; +} + +static void +_team_attr_data_copy(const TeamAttrData *attr_data, + gboolean is_port, + gpointer dst, + gconstpointer src) +{ + GPtrArray * v_ptrarray_dst; + const GPtrArray *v_ptrarray_src; + GPtrArray * dst_array; + guint i, len; + + if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) + nm_value_type_copy(attr_data->value_type, dst, src); + else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { + v_ptrarray_src = *((const GPtrArray *const *) src); + v_ptrarray_dst = *((GPtrArray **) dst); + len = (v_ptrarray_src ? v_ptrarray_src->len : 0u); + + if (len == 0) { + if (v_ptrarray_dst) + g_ptr_array_set_size(v_ptrarray_dst, 0); + } else { + dst_array = g_ptr_array_new_full(len, (GDestroyNotify) nm_team_link_watcher_unref); + for (i = 0; i < len; i++) { + if (v_ptrarray_src->pdata[i]) { + nm_team_link_watcher_ref(v_ptrarray_src->pdata[i]); + g_ptr_array_add(dst_array, v_ptrarray_src->pdata[i]); + } + } + if (v_ptrarray_dst) + g_ptr_array_unref(v_ptrarray_dst); + *((GPtrArray **) dst) = dst_array; + } + } else if (!is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + v_ptrarray_src = *((const GPtrArray *const *) src); + v_ptrarray_dst = *((GPtrArray **) dst); + len = (v_ptrarray_src ? v_ptrarray_src->len : 0u); + + if (v_ptrarray_src && v_ptrarray_src->len > 0) { + dst_array = g_ptr_array_new_full(v_ptrarray_src->len, g_free); + for (i = 0; i < v_ptrarray_src->len; i++) + g_ptr_array_add(dst_array, g_strdup(v_ptrarray_src->pdata[i])); + } else + dst_array = NULL; + if (v_ptrarray_dst) + g_ptr_array_unref(v_ptrarray_dst); + *((GPtrArray **) dst) = dst_array; + } else + nm_assert_not_reached(); +} + +static void +_team_attr_data_to_json(const TeamAttrData *attr_data, + gboolean is_port, + GString * gstr, + gconstpointer p_field) +{ + guint i; + + _team_attr_data_ASSERT(attr_data); + nm_assert(p_field); + + nm_json_gstr_append_obj_name(gstr, attr_data->js_keys[attr_data->js_keys_len - 1], '\0'); + + if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) { + nm_value_type_to_json(attr_data->value_type, gstr, p_field); + return; + } + + if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { + const GPtrArray *v_ptrarray = *((const GPtrArray *const *) p_field); + + if (!v_ptrarray) + g_string_append(gstr, "null"); + else if (v_ptrarray->len == 0) + g_string_append(gstr, "[ ]"); + else if (v_ptrarray->len == 1) + _link_watcher_to_json(v_ptrarray->pdata[0], gstr); + else { + g_string_append(gstr, "[ "); + for (i = 0; i < v_ptrarray->len; i++) { + if (i > 0) + nm_json_gstr_append_delimiter(gstr); + _link_watcher_to_json(v_ptrarray->pdata[i], gstr); + } + g_string_append(gstr, " ]"); + } + return; + } + + if (!is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + const GPtrArray *v_ptrarray = *((const GPtrArray *const *) p_field); + + if (!v_ptrarray) + g_string_append(gstr, "null"); + else { + g_string_append(gstr, "[ "); + for (i = 0; i < v_ptrarray->len; i++) { + if (i > 0) + nm_json_gstr_append_delimiter(gstr); + nm_json_gstr_append_string(gstr, v_ptrarray->pdata[i]); + } + g_string_append(gstr, i > 0 ? " ]" : "]"); + } + return; + } + + nm_assert_not_reached(); +} + +/*****************************************************************************/ + +static void +_team_setting_ASSERT(const NMTeamSetting *self) +{ + nm_assert(self); + nm_assert(!self->d._js_str_need_synthetize || !self->d._js_str); +#if NM_MORE_ASSERTS > 2 + if (!self->d.strict_validated) { + nm_assert(!self->d._js_str_need_synthetize); + nm_assert(self->d._js_str); + } + nm_assert(self->d.link_watchers); + nm_assert(self->d.is_port || !self->d.master.runner_tx_hash + || self->d.master.runner_tx_hash->len > 0); +#endif +} + +static gboolean +_team_setting_has_field(const NMTeamSetting *self, const TeamAttrData *attr_data) +{ + _team_setting_ASSERT(self); + return NM_FLAGS_ALL(self->d.has_fields_mask, nm_team_attribute_to_flags(attr_data->team_attr)); +} + +static gboolean +_team_setting_has_fields_any_v(const NMTeamSetting * self, + const NMTeamAttribute *team_attrs, + gsize n_team_attrs) +{ + gsize i; + + for (i = 0; i < n_team_attrs; i++) { + const TeamAttrData *attr_data = _team_attr_data_get(self->d.is_port, team_attrs[i]); + + if (_team_setting_has_field(self, attr_data)) + return TRUE; + } + return FALSE; +} + +#define _team_setting_has_fields_any(self, ...) \ + _team_setting_has_fields_any_v((self), \ + ((const NMTeamAttribute[]){__VA_ARGS__}), \ + NM_NARG(__VA_ARGS__)) + +static void +_team_setting_has_field_set(NMTeamSetting * self, + const TeamAttrData *attr_data, + SetFieldModeEnum set_field_mode) +{ + guint32 mask = nm_team_attribute_to_flags(attr_data->team_attr); + + _team_setting_ASSERT(self); + + switch (set_field_mode) { + case SET_FIELD_MODE_UNSET: + goto do_unset; + case SET_FIELD_MODE_SET: + goto do_set; + case SET_FIELD_MODE_SET_UNLESS_DEFAULT: + if (_team_attr_data_equal(attr_data, + self->d.is_port, + _team_setting_get_field(self, attr_data), + &attr_data->default_val)) + goto do_unset; + goto do_set; + } + nm_assert_not_reached(); + +do_unset: + self->_data_priv.has_fields_mask &= ~mask; + return; +do_set: + self->_data_priv.has_fields_mask |= mask; +} + +static gpointer +_team_setting_get_field(const NMTeamSetting *self, const TeamAttrData *attr_data) +{ + _team_setting_ASSERT(self); + _team_attr_data_ASSERT(attr_data); + nm_assert(_team_attr_data_is_relevant(attr_data, self->d.is_port)); + +#if NM_MORE_ASSERTS > 5 + if (attr_data->for_master && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO) + nm_assert((gpointer)(((char *) self) + attr_data->field_offset) + == &self->d.master.runner_sys_prio); +#endif + + return (((char *) self) + attr_data->field_offset); +} + +static guint32 +_team_setting_attribute_changed(NMTeamSetting * self, + const TeamAttrData *attr_data, + gboolean changed, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) +{ + guint32 changed_flags; + + _team_setting_has_field_set(self, attr_data, set_field_mode); + + if (!reset_json) { + return changed ? nm_team_attribute_to_flags(attr_data->team_attr) : 0u; + } + + if (!changed) { + /* a regular attribute was set, but the value did not change. + * + * If we previously were in non-strict mode, then + * + * - switch to strict-mode. Clearly the user set a regular attribute + * and hence now we want to validate the setting. + * + * - clear the JSON string. We need to regenerate it. + */ + if (self->_data_priv.strict_validated) + return 0; + changed_flags = nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); + } else { + changed_flags = nm_team_attribute_to_flags(attr_data->team_attr) + | nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); + } + + nm_clear_g_free((char **) &self->_data_priv._js_str); + self->_data_priv.strict_validated = TRUE; + self->_data_priv._js_str_need_synthetize = TRUE; + + return changed_flags; +} + +static guint32 +_team_setting_attribute_changed_attr(NMTeamSetting * self, + NMTeamAttribute team_attr, + gboolean changed, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) +{ + return _team_setting_attribute_changed(self, + _team_attr_data_get(self->d.is_port, team_attr), + changed, + set_field_mode, + reset_json); +} + +static gboolean +_team_setting_field_to_json(const NMTeamSetting *self, + GString * gstr, + gboolean prepend_delimiter, + const TeamAttrData * attr_data) +{ + if (!_team_setting_has_field(self, attr_data)) + return FALSE; + + if (prepend_delimiter) + nm_json_gstr_append_delimiter(gstr); + _team_attr_data_to_json(attr_data, + self->d.is_port, + gstr, + _team_setting_get_field(self, attr_data)); + return TRUE; +} + +static gboolean +_team_setting_fields_to_json_maybe(const NMTeamSetting * self, + GString * gstr, + gboolean prepend_delimiter, + const NMTeamAttribute *team_attrs_lst, + gsize team_attrs_lst_len) +{ + gsize i; + gboolean any_added = FALSE; + + for (i = 0; i < team_attrs_lst_len; i++) { + if (_team_setting_field_to_json(self, + gstr, + prepend_delimiter, + _team_attr_data_get(self->d.is_port, team_attrs_lst[i]))) { + any_added = TRUE; + prepend_delimiter = TRUE; + } + } + return any_added; +} + +static guint32 +_team_setting_set(NMTeamSetting * self, + gboolean modify, + const bool * has_lst, + const NMValueTypUnion *val_lst) +{ + guint32 changed_flags = 0; + const TeamAttrData *attr_data; + + nm_assert((!has_lst) == (!val_lst)); + + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; + attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) { + const NMValueTypUnion *p_val; + gconstpointer p_field; + gboolean has_field; + + if (!_team_attr_data_is_relevant(attr_data, self->d.is_port)) + continue; + + has_field = (has_lst && has_lst[attr_data->team_attr]); + + p_val = has_field ? &val_lst[attr_data->team_attr] : &attr_data->default_val; + + p_field = _team_setting_get_field(self, attr_data); + + if (!_team_attr_data_equal(attr_data, self->d.is_port, p_val, p_field)) { + if (modify) { + _team_attr_data_copy(attr_data, self->d.is_port, (gpointer) p_field, p_val); + } + changed_flags |= nm_team_attribute_to_flags(attr_data->team_attr); + } + + if (modify) { + _team_setting_has_field_set(self, + attr_data, + has_field ? SET_FIELD_MODE_SET : SET_FIELD_MODE_UNSET); + } + } + + return changed_flags; +} + +static guint32 +_team_setting_check_default(const NMTeamSetting *self) +{ + return _team_setting_set((NMTeamSetting *) self, FALSE, NULL, NULL); +} + +static guint32 +_team_setting_set_default(NMTeamSetting *self) +{ + return _team_setting_set(self, TRUE, NULL, NULL); +} + +/*****************************************************************************/ + +gconstpointer +_nm_team_setting_value_get(const NMTeamSetting *self, + NMTeamAttribute team_attr, + NMValueType value_type) +{ + const TeamAttrData *attr_data = _team_attr_data_get(self->d.is_port, team_attr); + + nm_assert(value_type == attr_data->value_type); + + nm_assert(_team_setting_has_field(self, attr_data) + || _team_attr_data_equal(attr_data, + self->d.is_port, + _team_setting_get_field(self, attr_data), + &attr_data->default_val)); + return _team_setting_get_field(self, attr_data); +} + +static guint32 +_team_setting_value_set(NMTeamSetting * self, + const TeamAttrData *attr_data, + gconstpointer val, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) +{ + gpointer p_field; + gboolean changed; + + nm_assert(self); + _team_attr_data_ASSERT(attr_data); + nm_assert(val); + + p_field = _team_setting_get_field(self, attr_data); + + changed = !_team_attr_data_equal(attr_data, self->d.is_port, p_field, val); + if (changed) + nm_value_type_copy(attr_data->value_type, p_field, val); + return _team_setting_attribute_changed(self, attr_data, changed, set_field_mode, reset_json); +} + +guint32 +nm_team_setting_value_reset(NMTeamSetting * self, + NMTeamAttribute team_attr, + gboolean to_default /* or else unset */) +{ + const TeamAttrData *attr_data; + + nm_assert(self); + + attr_data = _team_attr_data_get(self->d.is_port, team_attr); + + return _team_setting_value_set(self, + attr_data, + &attr_data->default_val, + to_default ? SET_FIELD_MODE_SET : SET_FIELD_MODE_UNSET, + RESET_JSON_YES); +} + +guint32 +_nm_team_setting_value_set(NMTeamSetting * self, + NMTeamAttribute team_attr, + NMValueType value_type, + gconstpointer val) +{ + const TeamAttrData *attr_data; + + nm_assert(self); + + attr_data = _team_attr_data_get(self->d.is_port, team_attr); + + nm_assert(value_type == attr_data->value_type); + + return _team_setting_value_set(self, + attr_data, + val, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); +} + +guint32 +nm_team_setting_value_link_watchers_add(NMTeamSetting *self, const NMTeamLinkWatcher *link_watcher) +{ + guint i; + gboolean changed; + + for (i = 0; i < self->d.link_watchers->len; i++) { + if (nm_team_link_watcher_equal(self->d.link_watchers->pdata[i], link_watcher)) { + changed = FALSE; + goto out; + } + } + changed = TRUE; + g_ptr_array_add((GPtrArray *) self->d.link_watchers, + _nm_team_link_watcher_ref((NMTeamLinkWatcher *) link_watcher)); +out: + return _team_setting_attribute_changed_attr(self, + NM_TEAM_ATTRIBUTE_LINK_WATCHERS, + changed, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); +} + +guint32 +nm_team_setting_value_link_watchers_remove_by_value(NMTeamSetting * self, + const NMTeamLinkWatcher *link_watcher) +{ + guint i; + + for (i = 0; i < self->d.link_watchers->len; i++) { + if (nm_team_link_watcher_equal(self->d.link_watchers->pdata[i], link_watcher)) + return nm_team_setting_value_link_watchers_remove(self, i); + } + return _team_setting_attribute_changed_attr(self, + NM_TEAM_ATTRIBUTE_LINK_WATCHERS, + FALSE, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); +} + +guint32 +nm_team_setting_value_link_watchers_remove(NMTeamSetting *self, guint idx) +{ + g_ptr_array_remove_index((GPtrArray *) self->d.link_watchers, idx); + return _team_setting_attribute_changed_attr(self, + NM_TEAM_ATTRIBUTE_LINK_WATCHERS, + TRUE, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); +} + +static guint32 +_team_setting_value_link_watchers_set_list(NMTeamSetting * self, + const NMTeamLinkWatcher *const *arr, + guint len, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) +{ + gboolean changed; + + if (self->d.link_watchers->len == len + && nm_team_link_watchers_cmp( + (const NMTeamLinkWatcher *const *) self->d.link_watchers->pdata, + arr, + len, + FALSE) + == 0) { + changed = FALSE; + goto out; + } + + changed = TRUE; + if (len == 0) + g_ptr_array_set_size((GPtrArray *) self->d.link_watchers, 0); + else { + _nm_unused gs_unref_ptrarray GPtrArray *old_val_destroy = NULL; + guint i; + + old_val_destroy = (GPtrArray *) g_steal_pointer(&self->_data_priv.link_watchers); + + self->_data_priv.link_watchers = + g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); + + for (i = 0; i < len; i++) { + if (arr[i]) { + g_ptr_array_add((GPtrArray *) self->d.link_watchers, + _nm_team_link_watcher_ref((NMTeamLinkWatcher *) arr[i])); + } + } + } + +out: + return _team_setting_attribute_changed_attr(self, + NM_TEAM_ATTRIBUTE_LINK_WATCHERS, + changed, + set_field_mode, + reset_json); +} + +guint32 +nm_team_setting_value_link_watchers_set_list(NMTeamSetting * self, + const NMTeamLinkWatcher *const *arr, + guint len) +{ + return _team_setting_value_link_watchers_set_list(self, + arr, + len, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); +} + +/*****************************************************************************/ + +guint32 +nm_team_setting_value_master_runner_tx_hash_add(NMTeamSetting *self, const char *txhash) +{ + gboolean changed; + guint i; + + if (!self->d.master.runner_tx_hash) + self->_data_priv.master.runner_tx_hash = g_ptr_array_new_with_free_func(g_free); + else { + for (i = 0; i < self->d.master.runner_tx_hash->len; i++) { + if (nm_streq(txhash, self->d.master.runner_tx_hash->pdata[i])) { + changed = FALSE; + goto out; + } + } + } + changed = TRUE; + g_ptr_array_add((GPtrArray *) self->d.master.runner_tx_hash, g_strdup(txhash)); +out: + return _team_setting_attribute_changed_attr(self, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, + changed, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); +} + +guint32 +nm_team_setting_value_master_runner_tx_hash_remove(NMTeamSetting *self, guint idx) +{ + g_ptr_array_remove_index((GPtrArray *) self->d.master.runner_tx_hash, idx); + return _team_setting_attribute_changed_attr(self, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, + TRUE, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); +} + +static guint32 +_team_setting_value_master_runner_tx_hash_set_list(NMTeamSetting * self, + const char *const *arr, + guint len, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) +{ + _nm_unused gs_unref_ptrarray GPtrArray *old_val_destroy = NULL; + gboolean changed; + guint i; + + if (nm_utils_strv_cmp_n(self->d.master.runner_tx_hash + ? (const char *const *) self->d.master.runner_tx_hash->pdata + : NULL, + self->d.master.runner_tx_hash ? self->d.master.runner_tx_hash->len : 0u, + arr, + len) + == 0) { + changed = FALSE; + goto out; + } + + changed = TRUE; + + old_val_destroy = (GPtrArray *) g_steal_pointer(&self->_data_priv.master.runner_tx_hash); + + for (i = 0; i < len; i++) { + if (!arr[i]) + continue; + if (!self->d.master.runner_tx_hash) + self->_data_priv.master.runner_tx_hash = g_ptr_array_new_with_free_func(g_free); + g_ptr_array_add((GPtrArray *) self->d.master.runner_tx_hash, g_strdup(arr[i])); + } + +out: + return _team_setting_attribute_changed_attr(self, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, + changed, + set_field_mode, + reset_json); +} + +guint32 +nm_team_setting_value_master_runner_tx_hash_set_list(NMTeamSetting * self, + const char *const *arr, + guint len) +{ + return _team_setting_value_master_runner_tx_hash_set_list(self, + arr, + len, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); +} + +/*****************************************************************************/ + +#define _LINK_WATCHER_ATTR_GET(args, link_watcher_attribute, _value_type) \ + ({ \ + const NMValueTypUnioMaybe *const _args = (args); \ + \ + nm_assert(link_watcher_attr_datas[(link_watcher_attribute)].value_type == (_value_type)); \ + \ + _args[(link_watcher_attribute)].has \ + ? &_args[(link_watcher_attribute)].val \ + : &link_watcher_attr_datas[(link_watcher_attribute)].default_val; \ + }) +#define _LINK_WATCHER_ATTR_GET_BOOL(args, link_watcher_attribute) \ + (_LINK_WATCHER_ATTR_GET(args, link_watcher_attribute, NM_VALUE_TYPE_BOOL)->v_bool) +#define _LINK_WATCHER_ATTR_GET_INT(args, link_watcher_attribute) \ + (_LINK_WATCHER_ATTR_GET(args, link_watcher_attribute, NM_VALUE_TYPE_INT)->v_int) +#define _LINK_WATCHER_ATTR_GET_STRING(args, link_watcher_attribute) \ + (_LINK_WATCHER_ATTR_GET(args, link_watcher_attribute, NM_VALUE_TYPE_STRING)->v_string) + +#define _LINK_WATCHER_ATTR_SET(args, link_watcher_attribute, _value_type, c_type, val) \ + ({ \ + nm_assert(link_watcher_attr_datas[(link_watcher_attribute)].value_type == (_value_type)); \ + \ + NM_VALUE_TYP_UNIO_MAYBE_SET(&(args)[(link_watcher_attribute)], c_type, (val)); \ + }) +#define _LINK_WATCHER_ATTR_SET_BOOL(args, link_watcher_attribute, val) \ + _LINK_WATCHER_ATTR_SET((args), (link_watcher_attribute), NM_VALUE_TYPE_BOOL, v_bool, (val)) +#define _LINK_WATCHER_ATTR_SET_INT(args, link_watcher_attribute, val) \ + _LINK_WATCHER_ATTR_SET((args), (link_watcher_attribute), NM_VALUE_TYPE_INT, v_int, (val)) +#define _LINK_WATCHER_ATTR_SET_STRING(args, link_watcher_attribute, val) \ + _LINK_WATCHER_ATTR_SET((args), (link_watcher_attribute), NM_VALUE_TYPE_STRING, v_string, (val)) + +static void +_link_watcher_unpack(const NMTeamLinkWatcher *link_watcher, + NMValueTypUnioMaybe args[static G_N_ELEMENTS(link_watcher_attr_datas)]) +{ + const char * v_name = nm_team_link_watcher_get_name(link_watcher); + NMTeamLinkWatcherArpPingFlags v_arp_ping_flags; + + memset(args, 0, sizeof(args[0]) * G_N_ELEMENTS(link_watcher_attr_datas)); + + _LINK_WATCHER_ATTR_SET_STRING(args, LINK_WATCHER_ATTRIBUTE_NAME, v_name); + + if (nm_streq(v_name, NM_TEAM_LINK_WATCHER_ETHTOOL)) { + _LINK_WATCHER_ATTR_SET_INT(args, + LINK_WATCHER_ATTRIBUTE_DELAY_UP, + nm_team_link_watcher_get_delay_up(link_watcher)); + _LINK_WATCHER_ATTR_SET_INT(args, + LINK_WATCHER_ATTRIBUTE_DELAY_DOWN, + nm_team_link_watcher_get_delay_down(link_watcher)); + } else if (NM_IN_STRSET(v_name, + NM_TEAM_LINK_WATCHER_NSNA_PING, + NM_TEAM_LINK_WATCHER_ARP_PING)) { + _LINK_WATCHER_ATTR_SET_INT(args, + LINK_WATCHER_ATTRIBUTE_INIT_WAIT, + nm_team_link_watcher_get_init_wait(link_watcher)); + _LINK_WATCHER_ATTR_SET_INT(args, + LINK_WATCHER_ATTRIBUTE_INTERVAL, + nm_team_link_watcher_get_interval(link_watcher)); + _LINK_WATCHER_ATTR_SET_INT(args, + LINK_WATCHER_ATTRIBUTE_MISSED_MAX, + nm_team_link_watcher_get_missed_max(link_watcher)); + _LINK_WATCHER_ATTR_SET_STRING(args, + LINK_WATCHER_ATTRIBUTE_TARGET_HOST, + nm_team_link_watcher_get_target_host(link_watcher)); + if (nm_streq(v_name, NM_TEAM_LINK_WATCHER_ARP_PING)) { + v_arp_ping_flags = nm_team_link_watcher_get_flags(link_watcher); + _LINK_WATCHER_ATTR_SET_INT(args, + LINK_WATCHER_ATTRIBUTE_VLANID, + nm_team_link_watcher_get_vlanid(link_watcher)); + _LINK_WATCHER_ATTR_SET_STRING(args, + LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, + nm_team_link_watcher_get_source_host(link_watcher)); + _LINK_WATCHER_ATTR_SET_BOOL( + args, + LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, + NM_FLAGS_HAS(v_arp_ping_flags, NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE)); + _LINK_WATCHER_ATTR_SET_BOOL( + args, + LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, + NM_FLAGS_HAS(v_arp_ping_flags, + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE)); + _LINK_WATCHER_ATTR_SET_BOOL( + args, + LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS, + NM_FLAGS_HAS(v_arp_ping_flags, NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS)); + } + } +} + +static void +_link_watcher_to_json(const NMTeamLinkWatcher *link_watcher, GString *gstr) +{ + NMValueTypUnioMaybe args[G_N_ELEMENTS(link_watcher_attr_datas)]; + int i; + gboolean is_first = TRUE; + + if (!link_watcher) { + g_string_append(gstr, "null"); + return; + } + + _link_watcher_unpack(link_watcher, args); + + g_string_append(gstr, "{ "); + + for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) { + const NMValueTypUnioMaybe *p_val = &args[i]; + const LinkWatcherAttrData *attr_data = &link_watcher_attr_datas[i]; + + if (!p_val->has) + continue; + if (nm_value_type_equal(attr_data->value_type, &attr_data->default_val, &p_val->val)) + continue; + + if (is_first) + is_first = FALSE; + else + nm_json_gstr_append_delimiter(gstr); + nm_json_gstr_append_obj_name(gstr, attr_data->js_key, '\0'); + nm_value_type_to_json(attr_data->value_type, gstr, &p_val->val); + } + + g_string_append(gstr, " }"); +} + +static NMTeamLinkWatcher * +_link_watcher_from_json(const NMJsonVt * vt, + const nm_json_t *root_js_obj, + gboolean * out_unrecognized_content) +{ + NMValueTypUnioMaybe args[G_N_ELEMENTS(link_watcher_attr_datas)] = {}; + const char * j_key; + nm_json_t * j_val; + const char * v_name; + NMTeamLinkWatcher * result = NULL; + + if (!nm_json_is_object(root_js_obj)) + goto fail; + + nm_json_object_foreach (vt, (nm_json_t *) root_js_obj, j_key, j_val) { + const LinkWatcherAttrData *attr_data = NULL; + NMValueTypUnioMaybe * parse_result; + + if (j_key) { + int i; + + for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) { + if (nm_streq(link_watcher_attr_datas[i].js_key, j_key)) { + attr_data = &link_watcher_attr_datas[i]; + break; + } + } + } + if (!attr_data) { + *out_unrecognized_content = TRUE; + continue; + } + + parse_result = &args[attr_data->link_watcher_attr]; + + if (parse_result->has) + *out_unrecognized_content = TRUE; + + if (!nm_value_type_from_json(vt, attr_data->value_type, j_val, &parse_result->val)) + *out_unrecognized_content = TRUE; + else + parse_result->has = TRUE; + } + +#define _PARSE_RESULT_HAS_UNEXPECTED_ATTRIBUTES(_parse_results, ...) \ + ({ \ + int _i; \ + \ + for (_i = 0; _i < (int) G_N_ELEMENTS((_parse_results)); _i++) { \ + if ((_parse_results)[_i].has && !NM_IN_SET((LinkWatcherAttribute) _i, __VA_ARGS__)) \ + break; \ + } \ + \ + (_i == (int) G_N_ELEMENTS((_parse_results))); \ + }) + + v_name = _LINK_WATCHER_ATTR_GET_STRING(args, LINK_WATCHER_ATTRIBUTE_NAME); + + if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_ETHTOOL)) { + if (_PARSE_RESULT_HAS_UNEXPECTED_ATTRIBUTES(args, + _EXPECTED_LINK_WATCHER_ATTRIBUTES_ETHTOOL)) + *out_unrecognized_content = TRUE; + result = nm_team_link_watcher_new_ethtool( + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_DELAY_UP), + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_DELAY_DOWN), + NULL); + } else if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_NSNA_PING)) { + if (_PARSE_RESULT_HAS_UNEXPECTED_ATTRIBUTES(args, + _EXPECTED_LINK_WATCHER_ATTRIBUTES_NSNA_PING)) + *out_unrecognized_content = TRUE; + result = nm_team_link_watcher_new_nsna_ping( + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_INIT_WAIT), + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_INTERVAL), + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_MISSED_MAX), + _LINK_WATCHER_ATTR_GET_STRING(args, LINK_WATCHER_ATTRIBUTE_TARGET_HOST), + NULL); + } else if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_ARP_PING)) { + NMTeamLinkWatcherArpPingFlags v_flags = NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE; + + if (_PARSE_RESULT_HAS_UNEXPECTED_ATTRIBUTES(args, + _EXPECTED_LINK_WATCHER_ATTRIBUTES_ARP_PING)) + *out_unrecognized_content = TRUE; + + if (_LINK_WATCHER_ATTR_GET_BOOL(args, LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE)) + v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE; + if (_LINK_WATCHER_ATTR_GET_BOOL(args, LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE)) + v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE; + if (_LINK_WATCHER_ATTR_GET_BOOL(args, LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS)) + v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS; + + result = nm_team_link_watcher_new_arp_ping2( + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_INIT_WAIT), + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_INTERVAL), + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_MISSED_MAX), + _LINK_WATCHER_ATTR_GET_INT(args, LINK_WATCHER_ATTRIBUTE_VLANID), + _LINK_WATCHER_ATTR_GET_STRING(args, LINK_WATCHER_ATTRIBUTE_TARGET_HOST), + _LINK_WATCHER_ATTR_GET_STRING(args, LINK_WATCHER_ATTRIBUTE_SOURCE_HOST), + v_flags, + NULL); + } + + if (result) + return result; +fail: + *out_unrecognized_content = TRUE; + return NULL; +} + +/*****************************************************************************/ + +static GVariant * +_link_watcher_to_variant(const NMTeamLinkWatcher *link_watcher) +{ + NMValueTypUnioMaybe args[G_N_ELEMENTS(link_watcher_attr_datas)]; + GVariantBuilder builder; + int i; + + if (!link_watcher) + return NULL; + + _link_watcher_unpack(link_watcher, args); + + if (!args[LINK_WATCHER_ATTRIBUTE_NAME].has) + return NULL; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + + for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) { + const NMValueTypUnioMaybe *p_val = &args[i]; + const LinkWatcherAttrData *attr_data = &link_watcher_attr_datas[i]; + GVariant * v; + + if (!p_val->has) + continue; + if (nm_value_type_equal(attr_data->value_type, &attr_data->default_val, &p_val->val)) + continue; + + if (attr_data->value_type == NM_VALUE_TYPE_INT) + v = g_variant_new_int32(p_val->val.v_int); + else { + v = nm_value_type_to_variant(attr_data->value_type, &p_val->val); + } + if (!v) + continue; + + nm_assert(g_variant_is_floating(v)); + g_variant_builder_add(&builder, "{sv}", attr_data->dbus_name, v); + } + + return g_variant_builder_end(&builder); +} + +#define _LINK_WATCHER_ATTR_VARGET(variants, link_watcher_attribute, _value_type, c_type, _cmd) \ + ({ \ + GVariant *const *_variants = (variants); \ + GVariant * _cc; \ + \ + nm_assert(link_watcher_attr_datas[(link_watcher_attribute)].value_type == (_value_type)); \ + \ + (_cc = _variants[(link_watcher_attribute)]) \ + ? (_cmd) \ + : link_watcher_attr_datas[(link_watcher_attribute)].default_val.c_type; \ + }) +#define _LINK_WATCHER_ATTR_VARGET_BOOL(variants, link_watcher_attribute) \ + (_LINK_WATCHER_ATTR_VARGET(variants, \ + link_watcher_attribute, \ + NM_VALUE_TYPE_BOOL, \ + v_bool, \ + g_variant_get_boolean(_cc))) +#define _LINK_WATCHER_ATTR_VARGET_INT(variants, link_watcher_attribute) \ + (_LINK_WATCHER_ATTR_VARGET(variants, \ + link_watcher_attribute, \ + NM_VALUE_TYPE_INT, \ + v_int, \ + g_variant_get_int32(_cc))) +#define _LINK_WATCHER_ATTR_VARGET_STRING(variants, link_watcher_attribute) \ + (_LINK_WATCHER_ATTR_VARGET(variants, \ + link_watcher_attribute, \ + NM_VALUE_TYPE_STRING, \ + v_string, \ + g_variant_get_string(_cc, NULL))) + +static void +_variants_list_link_watcher_unref_auto(GVariant *(*p_variants)[]) +{ + int i; + + for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) + nm_g_variant_unref((*p_variants)[i]); +} + +static NMTeamLinkWatcher * +_link_watcher_from_variant(GVariant *watcher_var, gboolean strict_parsing, GError **error) +{ + nm_auto(_variants_list_link_watcher_unref_auto) + GVariant *variants[G_N_ELEMENTS(link_watcher_attr_datas)] = { + NULL, + }; + const char * v_key; + GVariant * v_val; + const char * v_name; + GVariantIter iter; + + g_return_val_if_fail(g_variant_is_of_type(watcher_var, G_VARIANT_TYPE("a{sv}")), NULL); + + g_variant_iter_init(&iter, watcher_var); + while (g_variant_iter_next(&iter, "{&sv}", &v_key, &v_val)) { + _nm_unused gs_unref_variant GVariant *v_val_free = v_val; + const LinkWatcherAttrData * attr_data = NULL; + const GVariantType * variant_type; + int i; + + for (i = 0; i < (int) G_N_ELEMENTS(link_watcher_attr_datas); i++) { + if (nm_streq(link_watcher_attr_datas[i].dbus_name, v_key)) { + attr_data = &link_watcher_attr_datas[i]; + break; + } + } + if (!attr_data) { + if (strict_parsing) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid D-Bus property \"%s\""), + v_key); + return NULL; + } + continue; + } + + if (attr_data->value_type == NM_VALUE_TYPE_INT) + variant_type = G_VARIANT_TYPE_INT32; + else + variant_type = nm_value_type_get_variant_type(attr_data->value_type); + + if (!g_variant_is_of_type(v_val, variant_type)) { + if (strict_parsing) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid D-Bus property \"%s\""), + v_key); + return NULL; + } + continue; + } + + if (variants[attr_data->link_watcher_attr]) { + if (strict_parsing) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("duplicate D-Bus property \"%s\""), + v_key); + return NULL; + } + g_variant_unref(variants[attr_data->link_watcher_attr]); + } + variants[attr_data->link_watcher_attr] = g_steal_pointer(&v_val_free); + } + +#define _VARIANTS_HAVE_UNEXPECTED_ATTRIBUTES(_type, _variants, _error, ...) \ + ({ \ + int _i; \ + gboolean _has_error = FALSE; \ + \ + for (_i = 0; _i < (int) G_N_ELEMENTS((_variants)); _i++) { \ + if ((_variants)[_i] && !NM_IN_SET((LinkWatcherAttribute) _i, __VA_ARGS__)) { \ + _has_error = TRUE; \ + g_set_error(_error, \ + NM_CONNECTION_ERROR, \ + NM_CONNECTION_ERROR_INVALID_PROPERTY, \ + _("invalid D-Bus property \"%s\" for \"%s\""), \ + link_watcher_attr_datas[_i].dbus_name, \ + _type); \ + break; \ + } \ + } \ + \ + _has_error; \ + }) + + v_name = _LINK_WATCHER_ATTR_VARGET_STRING(variants, LINK_WATCHER_ATTRIBUTE_NAME); + + if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_ETHTOOL)) { + if (strict_parsing + && _VARIANTS_HAVE_UNEXPECTED_ATTRIBUTES(v_name, + variants, + error, + _EXPECTED_LINK_WATCHER_ATTRIBUTES_ETHTOOL)) + return NULL; + return nm_team_link_watcher_new_ethtool( + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_DELAY_UP), + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_DELAY_DOWN), + strict_parsing ? error : NULL); + } + + if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_NSNA_PING)) { + if (strict_parsing + && _VARIANTS_HAVE_UNEXPECTED_ATTRIBUTES(v_name, + variants, + error, + _EXPECTED_LINK_WATCHER_ATTRIBUTES_NSNA_PING)) + return NULL; + return nm_team_link_watcher_new_nsna_ping( + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_INIT_WAIT), + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_INTERVAL), + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_MISSED_MAX), + _LINK_WATCHER_ATTR_VARGET_STRING(variants, LINK_WATCHER_ATTRIBUTE_TARGET_HOST), + strict_parsing ? error : NULL); + } + + if (nm_streq0(v_name, NM_TEAM_LINK_WATCHER_ARP_PING)) { + NMTeamLinkWatcherArpPingFlags v_flags = NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE; + + if (strict_parsing + && _VARIANTS_HAVE_UNEXPECTED_ATTRIBUTES(v_name, + variants, + error, + _EXPECTED_LINK_WATCHER_ATTRIBUTES_ARP_PING)) + return NULL; + + if (_LINK_WATCHER_ATTR_VARGET_BOOL(variants, LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE)) + v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE; + if (_LINK_WATCHER_ATTR_VARGET_BOOL(variants, LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE)) + v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE; + if (_LINK_WATCHER_ATTR_VARGET_BOOL(variants, LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS)) + v_flags |= NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS; + + return nm_team_link_watcher_new_arp_ping2( + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_INIT_WAIT), + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_INTERVAL), + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_MISSED_MAX), + _LINK_WATCHER_ATTR_VARGET_INT(variants, LINK_WATCHER_ATTRIBUTE_VLANID), + _LINK_WATCHER_ATTR_VARGET_STRING(variants, LINK_WATCHER_ATTRIBUTE_TARGET_HOST), + _LINK_WATCHER_ATTR_VARGET_STRING(variants, LINK_WATCHER_ATTRIBUTE_SOURCE_HOST), + v_flags, + strict_parsing ? error : NULL); + } + + if (strict_parsing) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unknown link-watcher name \"%s\""), + v_name); + } + return NULL; +} + +/*****************************************************************************/ + +/** + * _nm_utils_team_link_watchers_to_variant: + * @link_watchers: (element-type NMTeamLinkWatcher): array of #NMTeamLinkWatcher + * + * Utility function to convert a #GPtrArray of #NMTeamLinkWatcher objects + * representing link watcher configuration for team devices into a #GVariant + * of type 'aa{sv}' representing an array of link watchers. + * + * Returns: (transfer full): a new floating #GVariant representing link watchers. + **/ +GVariant * +_nm_utils_team_link_watchers_to_variant(const GPtrArray *link_watchers) +{ + GVariantBuilder builder; + guint i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + if (link_watchers) { + for (i = 0; i < link_watchers->len; i++) { + g_variant_builder_add(&builder, + "@a{sv}", + _link_watcher_to_variant(link_watchers->pdata[i])); + } + } + return g_variant_builder_end(&builder); +} + +/** + * _nm_utils_team_link_watchers_from_variant: + * @value: a #GVariant of type 'aa{sv}' + * @strict_parsing: whether to parse strictly or ignore everything invalid. + * @error: error reason. + * + * Utility function to convert a #GVariant representing a list of team link + * watchers int a #GPtrArray of #NMTeamLinkWatcher objects. + * + * Returns: (transfer full) (element-type NMTeamLinkWatcher): a newly allocated + * #GPtrArray of #NMTeamLinkWatcher objects. + * + * Note that if you provide an @error, then the function can only fail (and return %NULL) + * or succeed (and not return %NULL). If you don't provide an @error, then the function + * never returns %NULL. + **/ +GPtrArray * +_nm_utils_team_link_watchers_from_variant(GVariant *value, gboolean strict_parsing, GError **error) +{ + gs_unref_ptrarray GPtrArray *link_watchers = NULL; + GVariantIter iter; + GVariant * watcher_var; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); + + link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); + + g_variant_iter_init(&iter, value); + while (g_variant_iter_next(&iter, "@a{sv}", &watcher_var)) { + _nm_unused gs_unref_variant GVariant *watcher_var_free = watcher_var; + NMTeamLinkWatcher * watcher; + + watcher = _link_watcher_from_variant(watcher_var, strict_parsing, error); + if (error && *error) + return NULL; + if (watcher) + g_ptr_array_add(link_watchers, watcher); + } + + return g_steal_pointer(&link_watchers); +} + +/*****************************************************************************/ + +const char * +nm_team_setting_config_get(const NMTeamSetting *self) +{ + char *js_str; + + nm_assert(self); + + if (G_LIKELY(!self->d._js_str_need_synthetize)) + return self->d._js_str; + + nm_assert(!self->d._js_str); + nm_assert(self->d.strict_validated); + + if (_team_setting_check_default(self) == 0) { + /* the default is set. We signal this as a NULL JSON string. + * Nothing to do. */ + js_str = NULL; + } else { + gboolean list_is_empty = TRUE; + GString *gstr; + + gstr = g_string_new(NULL); + + g_string_append(gstr, "{ "); + + if (self->d.is_port) { + static const NMTeamAttribute attr_lst_port[] = { + NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID, + NM_TEAM_ATTRIBUTE_PORT_PRIO, + NM_TEAM_ATTRIBUTE_PORT_STICKY, + NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, + NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, + }; + + if (_team_setting_fields_to_json_maybe(self, + gstr, + !list_is_empty, + attr_lst_port, + G_N_ELEMENTS(attr_lst_port))) + list_is_empty = FALSE; + } else { + static const NMTeamAttribute attr_lst_runner_pt1[] = { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, + }; + static const NMTeamAttribute attr_lst_runner_pt2[] = { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, + }; + static const NMTeamAttribute attr_lst_runner_pt3[] = { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, + }; + static const NMTeamAttribute attr_lst_notify_peers[] = { + NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT, + NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, + }; + static const NMTeamAttribute attr_lst_mcast_rejoin[] = { + NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, + NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, + }; + + if (_team_setting_has_fields_any_v(self, + attr_lst_runner_pt1, + G_N_ELEMENTS(attr_lst_runner_pt1)) + || _team_setting_has_fields_any_v(self, + attr_lst_runner_pt2, + G_N_ELEMENTS(attr_lst_runner_pt2)) + || _team_setting_has_fields_any_v(self, + attr_lst_runner_pt3, + G_N_ELEMENTS(attr_lst_runner_pt3))) { + gboolean list_is_empty2 = TRUE; + + nm_assert(list_is_empty); + + nm_json_gstr_append_obj_name(gstr, "runner", '{'); + + if (_team_setting_fields_to_json_maybe(self, + gstr, + !list_is_empty2, + attr_lst_runner_pt1, + G_N_ELEMENTS(attr_lst_runner_pt1))) + list_is_empty2 = FALSE; + + if (_team_setting_has_fields_any_v(self, + attr_lst_runner_pt2, + G_N_ELEMENTS(attr_lst_runner_pt2))) { + if (!list_is_empty2) + nm_json_gstr_append_delimiter(gstr); + nm_json_gstr_append_obj_name(gstr, "tx_balancer", '{'); + if (!_team_setting_fields_to_json_maybe(self, + gstr, + FALSE, + attr_lst_runner_pt2, + G_N_ELEMENTS(attr_lst_runner_pt2))) + nm_assert_not_reached(); + g_string_append(gstr, " }"); + list_is_empty2 = FALSE; + } + + if (_team_setting_fields_to_json_maybe(self, + gstr, + !list_is_empty2, + attr_lst_runner_pt3, + G_N_ELEMENTS(attr_lst_runner_pt3))) + list_is_empty2 = FALSE; + + nm_assert(!list_is_empty2); + g_string_append(gstr, " }"); + list_is_empty = FALSE; + } + + if (_team_setting_has_fields_any_v(self, + attr_lst_notify_peers, + G_N_ELEMENTS(attr_lst_notify_peers))) { + if (!list_is_empty) + nm_json_gstr_append_delimiter(gstr); + nm_json_gstr_append_obj_name(gstr, "notify_peers", '{'); + if (!_team_setting_fields_to_json_maybe(self, + gstr, + FALSE, + attr_lst_notify_peers, + G_N_ELEMENTS(attr_lst_notify_peers))) + nm_assert_not_reached(); + g_string_append(gstr, " }"); + list_is_empty = FALSE; + } + + if (_team_setting_has_fields_any_v(self, + attr_lst_mcast_rejoin, + G_N_ELEMENTS(attr_lst_mcast_rejoin))) { + if (!list_is_empty) + nm_json_gstr_append_delimiter(gstr); + nm_json_gstr_append_obj_name(gstr, "mcast_rejoin", '{'); + if (!_team_setting_fields_to_json_maybe(self, + gstr, + FALSE, + attr_lst_mcast_rejoin, + G_N_ELEMENTS(attr_lst_mcast_rejoin))) + nm_assert_not_reached(); + g_string_append(gstr, " }"); + list_is_empty = FALSE; + } + } + + if (_team_setting_field_to_json( + self, + gstr, + !list_is_empty, + _team_attr_data_get(self->d.is_port, NM_TEAM_ATTRIBUTE_LINK_WATCHERS))) + list_is_empty = FALSE; + + if (!list_is_empty) + g_string_append(gstr, " }"); + + js_str = g_string_free(gstr, list_is_empty); + } + + /* mutate the constant object. In C++ speak, these fields are "mutable". + * That is because we construct the JSON string lazily/on-demand. */ + *((char **) &self->_data_priv._js_str) = js_str; + *((bool *) &self->_data_priv._js_str_need_synthetize) = FALSE; + + return self->d._js_str; +} + +/*****************************************************************************/ + +static gboolean +_attr_data_match_keys(const TeamAttrData *attr_data, const char *const *keys, guint8 n_keys) +{ + guint8 i; + + _team_attr_data_ASSERT(attr_data); + nm_assert(keys); + nm_assert(n_keys > 0); + nm_assert(({ + gboolean all_non_null = TRUE; + + for (i = 0; i < n_keys; i++) + all_non_null = all_non_null && keys[i] && keys[i][0] != '\0'; + all_non_null; + })); + + if (attr_data->js_keys_len < n_keys) + return FALSE; + for (i = 0; i < n_keys; i++) { + if (!nm_streq(keys[i], attr_data->js_keys[i])) + return FALSE; + } + return TRUE; +} + +static const TeamAttrData * +_attr_data_find_by_json_key(gboolean is_port, const char *const *keys, guint8 n_keys) +{ + const TeamAttrData *attr_data; + + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; + attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) { + if (_team_attr_data_is_relevant(attr_data, is_port) + && _attr_data_match_keys(attr_data, keys, n_keys)) + return attr_data; + } + + return NULL; +} + +static void +_js_parse_locate_keys(const NMJsonVt *vt, + NMTeamSetting * self, + nm_json_t * root_js_obj, + nm_json_t * found_keys[static _NM_TEAM_ATTRIBUTE_NUM], + gboolean * out_unrecognized_content) +{ + const char *keys[3]; + const char *cur_key1; + const char *cur_key2; + const char *cur_key3; + nm_json_t * cur_val1; + nm_json_t * cur_val2; + nm_json_t * cur_val3; + + nm_assert(vt); + +#define _handle(_self, _cur_key, _cur_val, _keys, _level, _found_keys, _out_unrecognized_content) \ + ({ \ + const TeamAttrData *_attr_data; \ + gboolean _handled = FALSE; \ + \ + (_keys)[(_level) -1] = (_cur_key); \ + _attr_data = _attr_data_find_by_json_key((_self)->d.is_port, (_keys), (_level)); \ + if (_attr_data && _attr_data->js_keys_len == (_level)) { \ + if ((_found_keys)[_attr_data->team_attr]) \ + *(_out_unrecognized_content) = TRUE; \ + (_found_keys)[_attr_data->team_attr] = (_cur_val); \ + _handled = TRUE; \ + } else if (!_attr_data || !nm_json_is_object((_cur_val))) { \ + *(_out_unrecognized_content) = TRUE; \ + _handled = TRUE; \ + } \ + _handled; \ + }) + + nm_json_object_foreach (vt, root_js_obj, cur_key1, cur_val1) { + if (!_handle(self, cur_key1, cur_val1, keys, 1, found_keys, out_unrecognized_content)) { + nm_json_object_foreach (vt, cur_val1, cur_key2, cur_val2) { + if (!_handle(self, + cur_key2, + cur_val2, + keys, + 2, + found_keys, + out_unrecognized_content)) { + nm_json_object_foreach (vt, cur_val2, cur_key3, cur_val3) { + if (!_handle(self, + cur_key3, + cur_val3, + keys, + 3, + found_keys, + out_unrecognized_content)) + *out_unrecognized_content = TRUE; + } + } + } + } + } + +#undef _handle +} + +static void +_js_parse_unpack(const NMJsonVt *vt, + gboolean is_port, + nm_json_t * found_keys[static _NM_TEAM_ATTRIBUTE_NUM], + bool out_has_lst[static _NM_TEAM_ATTRIBUTE_NUM], + NMValueTypUnion out_val_lst[static _NM_TEAM_ATTRIBUTE_NUM], + gboolean * out_unrecognized_content, + GPtrArray ** out_ptr_array_link_watchers_free, + GPtrArray ** out_ptr_array_master_runner_tx_hash_free) +{ + const TeamAttrData *attr_data; + + nm_assert(vt); + + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; + attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) { + NMValueTypUnion *p_out_val; + gboolean valid = FALSE; + nm_json_t * arg_js_obj; + + if (!_team_attr_data_is_relevant(attr_data, is_port)) + continue; + + nm_assert(!out_has_lst[attr_data->team_attr]); + + arg_js_obj = found_keys[attr_data->team_attr]; + if (!arg_js_obj) + continue; + + p_out_val = &out_val_lst[attr_data->team_attr]; + + if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) + valid = nm_value_type_from_json(vt, attr_data->value_type, arg_js_obj, p_out_val); + else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { + GPtrArray * link_watchers = NULL; + NMTeamLinkWatcher *link_watcher; + + nm_assert(out_ptr_array_link_watchers_free && !*out_ptr_array_link_watchers_free); + if (nm_json_is_array(arg_js_obj)) { + gsize i, len; + + len = vt->nm_json_array_size(arg_js_obj); + link_watchers = + g_ptr_array_new_full(len, (GDestroyNotify) nm_team_link_watcher_unref); + for (i = 0; i < len; i++) { + link_watcher = _link_watcher_from_json(vt, + vt->nm_json_array_get(arg_js_obj, i), + out_unrecognized_content); + if (link_watcher) + g_ptr_array_add(link_watchers, link_watcher); + } + } else { + link_watcher = _link_watcher_from_json(vt, arg_js_obj, out_unrecognized_content); + if (link_watcher) { + link_watchers = + g_ptr_array_new_full(1, (GDestroyNotify) nm_team_link_watcher_unref); + g_ptr_array_add(link_watchers, link_watcher); + } + } + if (link_watchers) { + valid = TRUE; + p_out_val->v_ptrarray = link_watchers; + *out_ptr_array_link_watchers_free = link_watchers; + } + } else if (!is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + GPtrArray *strv = NULL; + + nm_assert(out_ptr_array_master_runner_tx_hash_free + && !*out_ptr_array_master_runner_tx_hash_free); + if (nm_json_is_array(arg_js_obj)) { + gsize i, len; + + len = vt->nm_json_array_size(arg_js_obj); + if (len > 0) { + strv = g_ptr_array_sized_new(len); + for (i = 0; i < len; i++) { + const char *v_string; + + if (nm_jansson_json_as_string(vt, + vt->nm_json_array_get(arg_js_obj, i), + &v_string) + <= 0 + || !v_string || v_string[0] == '\0') { + /* we remember that there was some invalid content, but parts of the + * list could still be parsed. */ + *out_unrecognized_content = TRUE; + continue; + } + g_ptr_array_add(strv, (char *) v_string); + } + } + valid = TRUE; + *out_ptr_array_master_runner_tx_hash_free = strv; + } + p_out_val->v_ptrarray = strv; + } else + nm_assert_not_reached(); + + out_has_lst[attr_data->team_attr] = valid; + if (!valid) + *out_unrecognized_content = TRUE; + } +} + +guint32 +nm_team_setting_config_set(NMTeamSetting *self, const char *js_str) +{ + const NMJsonVt *vt; + guint32 changed_flags = 0; + gboolean do_set_default = TRUE; + gboolean new_js_str_invalid = FALSE; + + _team_setting_ASSERT(self); + + if (!js_str || js_str[0] == '\0') { + changed_flags = _team_setting_set_default(self); + if (changed_flags != 0 || !nm_streq0(js_str, self->d._js_str)) + changed_flags |= nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); + nm_clear_g_free((char **) &self->_data_priv._js_str); + self->_data_priv._js_str = g_strdup(js_str); + self->_data_priv._js_str_need_synthetize = FALSE; + self->_data_priv.strict_validated = TRUE; + self->_data_priv.js_str_invalid = FALSE; + return changed_flags; + } + + if (self->d._js_str && nm_streq(js_str, self->d._js_str)) { + if (!self->d.strict_validated) { + /* setting the same JSON string twice in a row has no effect. */ + return 0; + } + } else + changed_flags |= nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); + + if ((vt = nm_json_vt())) { + nm_auto_decref_json nm_json_t *root_js_obj = NULL; + + root_js_obj = vt->nm_json_loads(js_str, 0, NULL); + if (!root_js_obj || !nm_json_is_object(root_js_obj)) + new_js_str_invalid = TRUE; + else { + gboolean unrecognized_content = FALSE; + bool has_lst[_NM_TEAM_ATTRIBUTE_NUM] = { + FALSE, + }; + NMValueTypUnion val_lst[_NM_TEAM_ATTRIBUTE_NUM]; + nm_json_t * found_keys[_NM_TEAM_ATTRIBUTE_NUM] = { + NULL, + }; + gs_unref_ptrarray GPtrArray *ptr_array_master_runner_tx_hash_free = NULL; + gs_unref_ptrarray GPtrArray *ptr_array_link_watchers_free = NULL; + + _js_parse_locate_keys(vt, self, root_js_obj, found_keys, &unrecognized_content); + + _js_parse_unpack(vt, + self->d.is_port, + found_keys, + has_lst, + val_lst, + &unrecognized_content, + &ptr_array_link_watchers_free, + &ptr_array_master_runner_tx_hash_free); + + do_set_default = FALSE; + + changed_flags |= _team_setting_set(self, TRUE, has_lst, val_lst); + } + } + + if (do_set_default) + changed_flags |= _team_setting_set_default(self); + + self->_data_priv.strict_validated = FALSE; + self->_data_priv._js_str_need_synthetize = FALSE; + self->_data_priv.js_str_invalid = new_js_str_invalid; + g_free((char *) self->_data_priv._js_str); + self->_data_priv._js_str = g_strdup(js_str); + + return changed_flags; +} + +/*****************************************************************************/ + +static void +_team_setting_prefix_error_plain(gboolean is_port, const char *property_name, GError **error) +{ + g_prefix_error(error, + "%s.%s: ", + is_port ? NM_SETTING_TEAM_PORT_SETTING_NAME : NM_SETTING_TEAM_SETTING_NAME, + property_name); +} + +static void +_team_setting_prefix_error(const NMTeamSetting *self, + const char * prop_name_master, + const char * prop_name_port, + GError ** error) +{ + _team_setting_ASSERT(self); + nm_assert(self->d.is_port ? (!!prop_name_port) : (!!prop_name_master)); + _team_setting_prefix_error_plain(self->d.is_port, + self->d.is_port ? prop_name_port : prop_name_master, + error); +} + +static gboolean +_team_setting_verify_properties(const NMTeamSetting *self, GError **error) +{ + const TeamAttrData *attr_data; + guint i; + + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; + attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) { + if (!_team_attr_data_is_relevant(attr_data, self->d.is_port)) + continue; + if (!_team_setting_has_field(self, attr_data)) + continue; + + if (attr_data->has_range) { + gconstpointer p_field; + + p_field = _team_setting_get_field(self, attr_data); + if (attr_data->value_type == NM_VALUE_TYPE_INT32) { + gint32 v = *((const gint32 *) p_field); + + if (v < attr_data->range.r_int32.min || v > attr_data->range.r_int32.max) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("value out or range")); + _team_setting_prefix_error_plain(self->d.is_port, + attr_data->property_name, + error); + return FALSE; + } + } else if (attr_data->value_type == NM_VALUE_TYPE_STRING) { + const char *v = *((const char *const *) p_field); + + if (nm_utils_strv_find_first((char **) attr_data->range.r_string.valid_names, -1, v) + < 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("invalid value")); + _team_setting_prefix_error_plain(self->d.is_port, + attr_data->property_name, + error); + return FALSE; + } + } else + nm_assert_not_reached(); + } + + if (!self->d.is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + if (self->d.master.runner_tx_hash) { + for (i = 0; i < self->d.master.runner_tx_hash->len; i++) { + const char *val = self->d.master.runner_tx_hash->pdata[i]; + + if (!val + || (nm_utils_strv_find_first((char **) _valid_names_runner_tx_hash, -1, val) + < 0)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("invalid runner-tx-hash")); + _team_setting_prefix_error_plain(self->d.is_port, + NM_SETTING_TEAM_RUNNER_TX_HASH, + error); + return FALSE; + } + } + } + } + } + + if (!self->d.is_port) { + for (i = 0; i < G_N_ELEMENTS(_runner_compat_lst); i++) { + const RunnerCompatElem *e = &_runner_compat_lst[i]; + + nm_assert(NM_PTRARRAY_LEN(e->valid_runners) > 0); + + attr_data = _team_attr_data_get(FALSE, e->team_attr); + + if (!_team_setting_has_field(self, attr_data)) + continue; + if (self->d.master.runner + && (nm_utils_strv_find_first((char **) e->valid_runners, -1, self->d.master.runner) + >= 0)) + continue; + if (e->valid_runners[1] == NULL) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("%s is only allowed for runner %s"), + attr_data->property_name, + e->valid_runners[0]); + } else { + gs_free char *s = NULL; + + s = g_strjoinv(",", (char **) e->valid_runners); + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("%s is only allowed for runners %s"), + attr_data->property_name, + s); + } + _team_setting_prefix_error_plain(self->d.is_port, NM_SETTING_TEAM_RUNNER, error); + return FALSE; + } + } else { + gboolean has_lacp_attrs; + gboolean has_activebackup_attrs; + + has_lacp_attrs = _team_setting_has_fields_any(self, + NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, + NM_TEAM_ATTRIBUTE_PORT_LACP_KEY); + has_activebackup_attrs = _team_setting_has_fields_any(self, + NM_TEAM_ATTRIBUTE_PORT_PRIO, + NM_TEAM_ATTRIBUTE_PORT_STICKY); + if (has_lacp_attrs && has_activebackup_attrs) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("cannot set parameters for lacp and activebackup runners together")); + _team_setting_prefix_error(self, + NM_SETTING_TEAM_LINK_WATCHERS, + NM_SETTING_TEAM_PORT_LINK_WATCHERS, + error); + return FALSE; + } + } + + for (i = 0; i < self->d.link_watchers->len; i++) { + if (!self->d.link_watchers->pdata[i]) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("missing link watcher")); + _team_setting_prefix_error(self, + NM_SETTING_TEAM_LINK_WATCHERS, + NM_SETTING_TEAM_PORT_LINK_WATCHERS, + error); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +_team_setting_verify_config(const NMTeamSetting *self, GError **error) +{ + const char *js_str; + + /* we always materialize the JSON string. That is because we want to validate the + * string length of the resulting JSON. */ + js_str = nm_team_setting_config_get(self); + + if (js_str) { + if (strlen(js_str) > 1 * 1024 * 1024) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("team config exceeds size limit")); + _team_setting_prefix_error(self, + NM_SETTING_TEAM_CONFIG, + NM_SETTING_TEAM_PORT_CONFIG, + error); + return FALSE; + } + if (!g_utf8_validate(js_str, -1, NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("team config is not valid UTF-8")); + _team_setting_prefix_error(self, + NM_SETTING_TEAM_CONFIG, + NM_SETTING_TEAM_PORT_CONFIG, + error); + return FALSE; + } + if (self->d.js_str_invalid) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid json")); + _team_setting_prefix_error(self, + NM_SETTING_TEAM_CONFIG, + NM_SETTING_TEAM_PORT_CONFIG, + error); + return FALSE; + } + } + + return TRUE; +} + +gboolean +nm_team_setting_verify(const NMTeamSetting *self, GError **error) +{ + if (self->d.strict_validated) { + if (!_team_setting_verify_properties(self, error)) + return FALSE; + } + return _team_setting_verify_config(self, error); +} + +/*****************************************************************************/ + +int +nm_team_setting_cmp(const NMTeamSetting *self_a, + const NMTeamSetting *self_b, + gboolean ignore_js_str) +{ + const TeamAttrData *attr_data; + + NM_CMP_SELF(self_a, self_b); + + NM_CMP_FIELD_UNSAFE(self_a, self_b, d.is_port); + + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; + attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) { + if (!_team_attr_data_is_relevant(attr_data, self_a->d.is_port)) + continue; + + NM_CMP_RETURN(_team_attr_data_cmp(attr_data, + self_a->d.is_port, + _team_setting_get_field(self_a, attr_data), + _team_setting_get_field(self_b, attr_data))); + } + + if (!ignore_js_str) { + NM_CMP_DIRECT_STRCMP0(nm_team_setting_config_get(self_a), + nm_team_setting_config_get(self_b)); + } + + return 0; +} + +guint32 +nm_team_setting_reset(NMTeamSetting *self, const NMTeamSetting *src) +{ + const TeamAttrData *attr_data; + guint32 changed_flags; + + _team_setting_ASSERT(self); + _team_setting_ASSERT(src); + nm_assert(self->d.is_port == src->d.is_port); + + if (self == src) + return 0; + + changed_flags = 0; + + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; + attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) { + if (!_team_attr_data_is_relevant(attr_data, self->d.is_port)) + continue; + if (_team_attr_data_equal(attr_data, + self->d.is_port, + _team_setting_get_field(self, attr_data), + _team_setting_get_field(src, attr_data))) + continue; + _team_attr_data_copy(attr_data, + self->d.is_port, + _team_setting_get_field(self, attr_data), + _team_setting_get_field(src, attr_data)); + changed_flags |= nm_team_attribute_to_flags(attr_data->team_attr); + } + + self->_data_priv.has_fields_mask = src->d.has_fields_mask; + + if (!nm_streq0(self->d._js_str, src->d._js_str)) { + g_free((char *) self->_data_priv._js_str); + self->_data_priv._js_str = g_strdup(src->d._js_str); + changed_flags |= nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); + } else if (changed_flags != 0) + changed_flags |= nm_team_attribute_to_flags(NM_TEAM_ATTRIBUTE_CONFIG); + + self->_data_priv._js_str_need_synthetize = src->d._js_str_need_synthetize; + self->_data_priv.strict_validated = src->d.strict_validated; + self->_data_priv.js_str_invalid = src->d.js_str_invalid; + + return changed_flags; +} + +static void +_variants_list_team_unref_auto(GVariant *(*p_variants)[]) +{ + int i; + + for (i = 0; i < _NM_TEAM_ATTRIBUTE_NUM; i++) + nm_g_variant_unref((*p_variants)[i]); +} + +gboolean +nm_team_setting_reset_from_dbus(NMTeamSetting * self, + GVariant * setting_dict, + GHashTable * keys, + guint32 * out_changed, + guint /* NMSettingParseFlags */ parse_flags, + GError ** error) +{ + nm_auto(_variants_list_team_unref_auto) GVariant *variants[_NM_TEAM_ATTRIBUTE_NUM] = { + NULL, + }; + gs_unref_ptrarray GPtrArray *v_link_watchers = NULL; + const TeamAttrData * attr_data; + GVariantIter iter; + const char * v_key; + GVariant * v_val; + const NMJsonVt * vt; + + *out_changed = 0; + + g_variant_iter_init(&iter, setting_dict); + while (g_variant_iter_next(&iter, "{&sv}", &v_key, &v_val)) { + _nm_unused gs_unref_variant GVariant *v_val_free = v_val; + const GVariantType * variant_type = NULL; + + attr_data = _team_attr_data_find_for_property_name(self->d.is_port, v_key); + if (!attr_data) { + /* _nm_setting_new_from_dbus() already checks for unknown keys. Don't + * do that here. */ + continue; + } + + if (keys) + g_hash_table_remove(keys, v_key); + + if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) + variant_type = nm_value_type_get_variant_type(attr_data->value_type); + else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_CONFIG) + variant_type = G_VARIANT_TYPE_STRING; + else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) + variant_type = G_VARIANT_TYPE("aa{sv}"); + else if (!self->d.is_port + && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) + variant_type = G_VARIANT_TYPE_STRING_ARRAY; + else + nm_assert_not_reached(); + + if (!g_variant_is_of_type(v_val, variant_type)) { + if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid D-Bus type \"%s\""), + g_variant_get_type_string(v_val)); + _team_setting_prefix_error_plain(self->d.is_port, attr_data->property_name, error); + return FALSE; + } + continue; + } + + /* _nm_setting_new_from_dbus() already checks for duplicate keys. Don't + * do that here. */ + nm_g_variant_unref(variants[attr_data->team_attr]); + variants[attr_data->team_attr] = g_steal_pointer(&v_val_free); + } + + vt = nm_json_vt(); + + if (variants[NM_TEAM_ATTRIBUTE_LINK_WATCHERS]) { + if (variants[NM_TEAM_ATTRIBUTE_CONFIG] && vt + && !NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + /* we don't require the content of the "link-watchers" and we also + * don't perform strict validation. No need to parse it. */ + } else { + gs_free_error GError *local = NULL; + + /* We might need the parsed v_link_watchers array below (because there is no JSON + * "config" present or because we don't have json support). + * + * Or we might run with NM_SETTING_PARSE_FLAGS_STRICT. In that mode, we may not necessarily + * require that the entire setting as a whole validates (if a JSON config is present and + * we are not "strict_validated") , but we require that we can at least parse the link watchers + * on their own. */ + v_link_watchers = _nm_utils_team_link_watchers_from_variant( + variants[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], + NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT), + &local); + if (local && NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid link-watchers: %s"), + local->message); + _team_setting_prefix_error(self, + NM_SETTING_TEAM_LINK_WATCHERS, + NM_SETTING_TEAM_PORT_LINK_WATCHERS, + error); + return FALSE; + } + } + } + + *out_changed |= nm_team_setting_config_set( + self, + variants[NM_TEAM_ATTRIBUTE_CONFIG] + ? g_variant_get_string(variants[NM_TEAM_ATTRIBUTE_CONFIG], NULL) + : NULL); + + if (vt && variants[NM_TEAM_ATTRIBUTE_CONFIG]) { + /* for team settings, the JSON must be able to express all possible options. That means, + * if the GVariant contains both the JSON "config" and other options, then the other options + * are silently ignored. */ + } else { + guint32 extra_changed = 0u; + + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; + attr_data < &team_attr_datas[G_N_ELEMENTS(team_attr_datas)]; + attr_data++) { + NMValueTypUnion val; + guint32 changed_flags = 0u; + + if (!_team_attr_data_is_relevant(attr_data, self->d.is_port)) + continue; + if (!variants[attr_data->team_attr]) + continue; + + if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) { + nm_value_type_get_from_variant(attr_data->value_type, + &val, + variants[attr_data->team_attr], + FALSE); + changed_flags = _team_setting_value_set(self, + attr_data, + &val, + SET_FIELD_MODE_SET, + RESET_JSON_NO); + } else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { + changed_flags = _team_setting_value_link_watchers_set_list( + self, + v_link_watchers ? (const NMTeamLinkWatcher *const *) v_link_watchers->pdata + : NULL, + v_link_watchers ? v_link_watchers->len : 0u, + SET_FIELD_MODE_SET, + RESET_JSON_NO); + } else if (!self->d.is_port + && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + gs_free const char **strv = NULL; + gsize len; + + strv = g_variant_get_strv(variants[attr_data->team_attr], &len); + changed_flags = _team_setting_value_master_runner_tx_hash_set_list( + self, + strv, + NM_MIN(len, (gsize) G_MAXUINT), + SET_FIELD_MODE_SET, + RESET_JSON_NO); + } else + nm_assert_not_reached(); + + extra_changed |= changed_flags; + } + + if (!variants[NM_TEAM_ATTRIBUTE_CONFIG]) { + /* clear the JSON string so it can be regenerated. But only if we didn't set + * it above. */ + self->_data_priv.strict_validated = TRUE; + self->_data_priv._js_str_need_synthetize = TRUE; + } + + *out_changed |= extra_changed; + } + + return TRUE; +} + +/*****************************************************************************/ + +gboolean +nm_team_setting_maybe_changed(NMSetting * source, + const GParamSpec *const *obj_properties, + guint32 changed_flags) +{ + NMTeamAttribute team_attr; + int count_flags; + guint32 ch; + + if (changed_flags == 0u) + return FALSE; + + count_flags = 0; + for (ch = changed_flags; ch != 0u; ch >>= 1) { + if (NM_FLAGS_HAS(ch, 0x1u)) + count_flags++; + } + + if (count_flags > 1) + g_object_freeze_notify(G_OBJECT(source)); + + ch = changed_flags; + for (team_attr = 0; team_attr < _NM_TEAM_ATTRIBUTE_NUM; team_attr++) { + if (!NM_FLAGS_ANY(ch, nm_team_attribute_to_flags(team_attr))) + continue; + g_object_notify_by_pspec(G_OBJECT(source), (GParamSpec *) obj_properties[team_attr]); + ch &= ~nm_team_attribute_to_flags(team_attr); + if (ch == 0) + break; + } + + if (count_flags > 1) + g_object_thaw_notify(G_OBJECT(source)); + + return TRUE; +} + +/*****************************************************************************/ + +NMTeamSetting * +_nm_setting_get_team_setting(struct _NMSetting *setting) +{ + if (NM_IS_SETTING_TEAM(setting)) + return _nm_setting_team_get_team_setting(NM_SETTING_TEAM(setting)); + return _nm_setting_team_port_get_team_setting(NM_SETTING_TEAM_PORT(setting)); +} + +static GVariant * +_nm_team_settings_property_to_dbus(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + NMTeamSetting * self = _nm_setting_get_team_setting(setting); + const TeamAttrData *attr_data = + _team_attr_data_get(self->d.is_port, + sett_info->property_infos[property_idx].param_spec->param_id); + + if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_CONFIG) { + const char *config; + + if (self->d.strict_validated && !_nm_utils_is_manager_process) { + /* if we are in strict validating mode on the client side, the JSON is generated + * artificially. In this case, don't send the config via D-Bus to the server. + * + * This also will cause NetworkManager to strictly validate the settings. + * If a JSON "config" is present, strict validation won't be performed. */ + return NULL; + } + + config = nm_team_setting_config_get(self); + return config ? g_variant_new_string(config) : NULL; + } + + if (!_team_setting_has_field(self, attr_data)) + return NULL; + + if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) { + return nm_value_type_to_variant(attr_data->value_type, + _team_setting_get_field(self, attr_data)); + } + if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) + return _nm_utils_team_link_watchers_to_variant(self->d.link_watchers); + if (!self->d.is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + return g_variant_new_strv(self->d.master.runner_tx_hash + ? (const char *const *) self->d.master.runner_tx_hash->pdata + : NULL, + self->d.master.runner_tx_hash ? self->d.master.runner_tx_hash->len + : 0u); + } + + nm_assert_not_reached(); + return NULL; +} + +static void +_nm_team_settings_property_from_dbus_link_watchers(GVariant *dbus_value, GValue *prop_value) +{ + g_value_take_boxed(prop_value, + _nm_utils_team_link_watchers_from_variant(dbus_value, FALSE, NULL)); +} + +const NMSettInfoPropertType nm_sett_info_propert_type_team_b = { + .dbus_type = G_VARIANT_TYPE_BOOLEAN, + .to_dbus_fcn = _nm_team_settings_property_to_dbus, +}; + +const NMSettInfoPropertType nm_sett_info_propert_type_team_i = { + .dbus_type = G_VARIANT_TYPE_INT32, + .to_dbus_fcn = _nm_team_settings_property_to_dbus, +}; + +const NMSettInfoPropertType nm_sett_info_propert_type_team_s = { + .dbus_type = G_VARIANT_TYPE_STRING, + .to_dbus_fcn = _nm_team_settings_property_to_dbus, +}; + +const NMSettInfoPropertType nm_sett_info_propert_type_team_as = { + .dbus_type = NM_G_VARIANT_TYPE("as"), + .to_dbus_fcn = _nm_team_settings_property_to_dbus, +}; + +const NMSettInfoPropertType nm_sett_info_propert_type_team_link_watchers = { + .dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = _nm_team_settings_property_to_dbus, + .gprop_from_dbus_fcn = _nm_team_settings_property_from_dbus_link_watchers, +}; + +/*****************************************************************************/ + +NMTeamSetting * +nm_team_setting_new(gboolean is_port, const char *js_str) +{ + NMTeamSetting *self; + gsize l; + + G_STATIC_ASSERT_EXPR(sizeof(*self) == sizeof(self->_data_priv)); + G_STATIC_ASSERT_EXPR(sizeof(*self) + == NM_CONST_MAX(nm_offsetofend(NMTeamSetting, d.master), + nm_offsetofend(NMTeamSetting, d.port))); + + l = is_port ? nm_offsetofend(NMTeamSetting, d.port) : nm_offsetofend(NMTeamSetting, d.master); + + self = g_malloc0(l); + + self->_data_priv.is_port = is_port; + self->_data_priv.strict_validated = TRUE; + self->_data_priv._js_str_need_synthetize = FALSE; + self->_data_priv.link_watchers = + g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); + + _team_setting_ASSERT(self); + + nm_team_setting_config_set(self, js_str); + + _team_setting_ASSERT(self); + + return self; +} + +void +nm_team_setting_free(NMTeamSetting *self) +{ + if (!self) + return; + + _team_setting_ASSERT(self); + + if (!self->d.is_port) { + nm_clear_pointer(((GPtrArray **) &self->_data_priv.master.runner_tx_hash), + g_ptr_array_unref); + g_free((char *) self->_data_priv.master.runner); + g_free((char *) self->_data_priv.master.runner_hwaddr_policy); + g_free((char *) self->_data_priv.master.runner_tx_balancer); + g_free((char *) self->_data_priv.master.runner_agg_select_policy); + } + g_ptr_array_unref((GPtrArray *) self->_data_priv.link_watchers); + g_free((char *) self->_data_priv._js_str); + g_free(self); +} diff --git a/src/libnm-core-impl/nm-team-utils.h b/src/libnm-core-impl/nm-team-utils.h new file mode 100644 index 0000000000..1488eb9da5 --- /dev/null +++ b/src/libnm-core-impl/nm-team-utils.h @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#ifndef __NM_TEAM_UITLS_H__ +#define __NM_TEAM_UITLS_H__ + +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) + #error Cannot use this header. +#endif + +#include "nm-glib-aux/nm-value-type.h" +#include "libnm-core-intern/nm-core-internal.h" + +struct _NMSetting; + +struct NMTeamLinkWatcher; + +typedef enum { + + _NM_TEAM_ATTRIBUTE_0 = 0, + NM_TEAM_ATTRIBUTE_CONFIG = 1, + NM_TEAM_ATTRIBUTE_LINK_WATCHERS = 2, + + _NM_TEAM_ATTRIBUTE_START = 3, + + NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT = _NM_TEAM_ATTRIBUTE_START, + NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, + NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, + NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, + _NM_TEAM_ATTRIBUTE_MASTER_NUM, + + NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID = _NM_TEAM_ATTRIBUTE_START, + NM_TEAM_ATTRIBUTE_PORT_PRIO, + NM_TEAM_ATTRIBUTE_PORT_STICKY, + NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, + NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, + _NM_TEAM_ATTRIBUTE_PORT_NUM, + + _NM_TEAM_ATTRIBUTE_NUM = MAX(_NM_TEAM_ATTRIBUTE_MASTER_NUM, _NM_TEAM_ATTRIBUTE_PORT_NUM), + +} NMTeamAttribute; + +static inline guint32 +nm_team_attribute_to_flags(NMTeamAttribute team_attr) +{ + nm_assert(_NM_INT_NOT_NEGATIVE(team_attr)); + nm_assert(team_attr < _NM_TEAM_ATTRIBUTE_NUM); + G_STATIC_ASSERT_EXPR(_NM_TEAM_ATTRIBUTE_NUM < 32); + + return ((guint32) 1) << team_attr; +} + +struct _NMTeamSettingData { + const char *_js_str; + + const GPtrArray *link_watchers; + + /* this means that @_js_str is unset and needs to be created by + * converting the properties to JSON. This flag indicates that + * we need to re-generate the JSON string on-demand (lazily). */ + bool _js_str_need_synthetize; + + bool strict_validated : 1; + + /* indicates tha the JSON is invalid. Usually, we do a very relaxed validation of + * the JSON config, in case !@strict_validated and accept all unknown fields. This + * flag indicates that the JSON value is not even parsable as JSON. nm_connection_verify() + * would reject such a setting. */ + bool js_str_invalid : 1; + + bool is_port : 1; + + guint32 has_fields_mask; + + union { + struct { + const GPtrArray *runner_tx_hash; + const char * runner; + const char * runner_hwaddr_policy; + const char * runner_tx_balancer; + const char * runner_agg_select_policy; + gint32 notify_peers_count; + gint32 notify_peers_interval; + gint32 mcast_rejoin_count; + gint32 mcast_rejoin_interval; + gint32 runner_sys_prio; + gint32 runner_min_ports; + gint32 runner_tx_balancer_interval; + bool runner_active; + bool runner_fast_rate; + } master; + struct { + gint32 queue_id; + gint32 prio; + gint32 lacp_prio; + gint32 lacp_key; + bool sticky; + } port; + }; +}; + +/*****************************************************************************/ + +typedef struct { + union { + const struct _NMTeamSettingData d; + + struct _NMTeamSettingData _data_priv; + }; +} NMTeamSetting; + +NMTeamSetting *nm_team_setting_new(gboolean is_port, const char *js_str); + +void nm_team_setting_free(NMTeamSetting *self); + +NM_AUTO_DEFINE_FCN0(NMTeamSetting *, _nm_auto_free_team_setting, nm_team_setting_free); +#define nm_auto_free_team_setting nm_auto(_nm_auto_free_team_setting) + +/*****************************************************************************/ + +const char *nm_team_setting_config_get(const NMTeamSetting *self); + +guint32 nm_team_setting_config_set(NMTeamSetting *self, const char *js_str); + +/*****************************************************************************/ + +gconstpointer _nm_team_setting_value_get(const NMTeamSetting *self, + NMTeamAttribute team_attr, + NMValueType value_type); + +static inline gboolean +nm_team_setting_value_get_bool(const NMTeamSetting *self, NMTeamAttribute team_attr) +{ + const bool *p; + + p = _nm_team_setting_value_get(self, team_attr, NM_VALUE_TYPE_BOOL); + return p ? *p : 0; +} + +static inline gint32 +nm_team_setting_value_get_int32(const NMTeamSetting *self, NMTeamAttribute team_attr) +{ + const gint32 *p; + + p = _nm_team_setting_value_get(self, team_attr, NM_VALUE_TYPE_INT32); + return p ? *p : 0; +} + +static inline const char * +nm_team_setting_value_get_string(const NMTeamSetting *self, NMTeamAttribute team_attr) +{ + const char *const *p; + + p = _nm_team_setting_value_get(self, team_attr, NM_VALUE_TYPE_STRING); + return p ? *p : NULL; +} + +/*****************************************************************************/ + +guint32 nm_team_setting_value_reset(NMTeamSetting * self, + NMTeamAttribute team_attr, + gboolean to_default /* or else unset */); + +guint32 _nm_team_setting_value_set(NMTeamSetting * self, + NMTeamAttribute team_attr, + NMValueType value_type, + gconstpointer val); + +static inline guint32 +nm_team_setting_value_set_bool(NMTeamSetting *self, NMTeamAttribute team_attr, gboolean val) +{ + const bool bool_val = val; + + return _nm_team_setting_value_set(self, team_attr, NM_VALUE_TYPE_BOOL, &bool_val); +} + +static inline guint32 +nm_team_setting_value_set_int32(NMTeamSetting *self, NMTeamAttribute team_attr, gint32 val) +{ + return _nm_team_setting_value_set(self, team_attr, NM_VALUE_TYPE_INT32, &val); +} + +static inline guint32 +nm_team_setting_value_set_string(NMTeamSetting *self, NMTeamAttribute team_attr, const char *arg) +{ + return _nm_team_setting_value_set(self, team_attr, NM_VALUE_TYPE_STRING, &arg); +} + +/*****************************************************************************/ + +guint32 nm_team_setting_value_link_watchers_add(NMTeamSetting * self, + const struct NMTeamLinkWatcher *link_watcher); + +guint32 nm_team_setting_value_link_watchers_remove(NMTeamSetting *self, guint idx); + +guint32 +nm_team_setting_value_link_watchers_remove_by_value(NMTeamSetting * self, + const struct NMTeamLinkWatcher *link_watcher); + +guint32 nm_team_setting_value_link_watchers_set_list(NMTeamSetting * self, + const struct NMTeamLinkWatcher *const *arr, + guint len); + +/*****************************************************************************/ + +guint32 nm_team_setting_value_master_runner_tx_hash_add(NMTeamSetting *self, const char *txhash); + +guint32 nm_team_setting_value_master_runner_tx_hash_remove(NMTeamSetting *self, guint idx); + +guint32 nm_team_setting_value_master_runner_tx_hash_set_list(NMTeamSetting * self, + const char *const *arr, + guint len); + +/*****************************************************************************/ + +gboolean nm_team_setting_verify(const NMTeamSetting *self, GError **error); + +/*****************************************************************************/ + +int nm_team_setting_cmp(const NMTeamSetting *self_a, + const NMTeamSetting *self_b, + gboolean ignore_js_str); + +guint32 nm_team_setting_reset(NMTeamSetting *self, const NMTeamSetting *src); + +gboolean nm_team_setting_reset_from_dbus(NMTeamSetting * self, + GVariant * setting_dict, + GHashTable * keys, + guint32 * out_changed, + guint /* NMSettingParseFlags */ parse_flags, + GError ** error); + +/*****************************************************************************/ + +GPtrArray * +_nm_utils_team_link_watchers_from_variant(GVariant *value, gboolean strict_parsing, GError **error); +GVariant *_nm_utils_team_link_watchers_to_variant(const GPtrArray *link_watchers); + +/*****************************************************************************/ + +gboolean nm_team_setting_maybe_changed(struct _NMSetting * source, + const GParamSpec *const *obj_properties, + guint32 changed); + +struct _NMSettingTeam; +struct _NMSettingTeamPort; +NMTeamSetting *_nm_setting_team_get_team_setting(struct _NMSettingTeam *setting); +NMTeamSetting *_nm_setting_team_port_get_team_setting(struct _NMSettingTeamPort *setting); +NMTeamSetting *_nm_setting_get_team_setting(struct _NMSetting *setting); + +/*****************************************************************************/ + +extern const NMSettInfoPropertType nm_sett_info_propert_type_team_b; +extern const NMSettInfoPropertType nm_sett_info_propert_type_team_i; +extern const NMSettInfoPropertType nm_sett_info_propert_type_team_s; +extern const NMSettInfoPropertType nm_sett_info_propert_type_team_as; +extern const NMSettInfoPropertType nm_sett_info_propert_type_team_link_watchers; + +#endif /* __NM_TEAM_UITLS_H__ */ diff --git a/src/libnm-core-impl/nm-utils-private.h b/src/libnm-core-impl/nm-utils-private.h new file mode 100644 index 0000000000..eb545d0fa8 --- /dev/null +++ b/src/libnm-core-impl/nm-utils-private.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2005 - 2017 Red Hat, Inc. + */ + +#ifndef __NM_UTILS_PRIVATE_H__ +#define __NM_UTILS_PRIVATE_H__ + +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) + #error Cannot use this header. +#endif + +#include "nm-setting-private.h" +#include "nm-setting-ip-config.h" + +#define NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(_name, _type, ...) \ + (&((const NMVariantAttributeSpec){.name = _name, .type = _type, __VA_ARGS__})) + +gboolean _nm_utils_string_slist_validate(GSList *list, const char **valid_values); + +gboolean _nm_utils_secret_flags_validate(NMSettingSecretFlags secret_flags, + const char * setting_name, + const char * property_name, + NMSettingSecretFlags disallowed_flags, + GError ** error); + +gboolean _nm_utils_wps_method_validate(NMSettingWirelessSecurityWpsMethod wps_method, + const char * setting_name, + const char * property_name, + gboolean wps_required, + GError ** error); + +/* D-Bus transform funcs */ + +extern const NMSettInfoPropertType nm_sett_info_propert_type_strdict; + +extern const NMSettInfoPropertType nm_sett_info_propert_type_mac_address; + +extern const NMSettInfoPropertType nm_sett_info_propert_type_cloned_mac_address; + +extern const NMSettInfoPropertType nm_sett_info_propert_type_assigned_mac_address; + +extern const NMSettInfoPropertType nm_sett_info_propert_type_bridge_vlans; + +void _nm_utils_strdict_from_dbus(GVariant *dbus_value, GValue *prop_value); + +void _nm_utils_bytes_from_dbus(GVariant *dbus_value, GValue *prop_value); + +char *_nm_utils_hwaddr_canonical_or_invalid(const char *mac, gssize length); + +gboolean _nm_utils_hwaddr_link_local_valid(const char *mac); + +gboolean _nm_sriov_vf_parse_vlans(NMSriovVF *vf, const char *str, GError **error); + +gboolean _nm_utils_bridge_vlan_verify_list(GPtrArray * vlans, + gboolean check_normalizable, + GError ** error, + const char *setting, + const char *property); + +#endif diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c new file mode 100644 index 0000000000..d4ab51df5f --- /dev/null +++ b/src/libnm-core-impl/nm-utils.c @@ -0,0 +1,6056 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2005 - 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nm-glib-aux/nm-json-aux.h" +#include "nm-glib-aux/nm-str-buf.h" +#include "nm-glib-aux/nm-enum-utils.h" +#include "nm-glib-aux/nm-time-utils.h" +#include "nm-glib-aux/nm-secret-utils.h" +#include "systemd/nm-sd-utils-shared.h" +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" +#include "nm-crypto.h" +#include "nm-setting-bond.h" +#include "nm-setting-bridge.h" +#include "nm-setting-bridge-port.h" +#include "nm-setting-infiniband.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-team.h" +#include "nm-setting-vlan.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireless.h" + +/** + * SECTION:nm-utils + * @short_description: Utility functions + * + * A collection of utility functions for working with SSIDs, IP addresses, Wi-Fi + * access points and devices, among other things. + */ + +/*****************************************************************************/ + +/** + * NMUtilsPredicateStr: + * @str: the name to check. + * + * This function takes a string argument and returns either %TRUE or %FALSE. + * It is a general purpose predicate, for example used by nm_setting_option_clear_by_name(). + * + * Returns: %TRUE if the predicate function matches. + * + * Since: 1.26 + */ + +/*****************************************************************************/ + +struct _NMSockAddrEndpoint { + const char *host; + guint16 port; + guint refcount; + char endpoint[]; +}; + +static gboolean +NM_IS_SOCK_ADDR_ENDPOINT(const NMSockAddrEndpoint *self) +{ + return self && self->refcount > 0; +} + +static const char * +_parse_endpoint(char *str, guint16 *out_port) +{ + char * s; + const char *s_port; + gint16 port; + + /* Like + * - https://git.zx2c4.com/WireGuard/tree/src/tools/config.c?id=5e99a6d43fe2351adf36c786f5ea2086a8fe7ab8#n192 + * - https://github.com/systemd/systemd/blob/911649fdd43f3a9158b847947724a772a5a45c34/src/network/netdev/wireguard.c#L614 + */ + + g_strstrip(str); + + if (!str[0]) + return NULL; + + if (str[0] == '[') { + str++; + s = strchr(str, ']'); + if (!s) + return NULL; + if (s == str) + return NULL; + if (s[1] != ':') + return NULL; + if (!s[2]) + return NULL; + *s = '\0'; + s_port = &s[2]; + } else { + s = strrchr(str, ':'); + if (!s) + return NULL; + if (s == str) + return NULL; + if (!s[1]) + return NULL; + *s = '\0'; + s_port = &s[1]; + } + + if (!NM_STRCHAR_ALL(s_port, ch, (ch >= '0' && ch <= '9'))) + return NULL; + + port = _nm_utils_ascii_str_to_int64(s_port, 10, 1, G_MAXUINT16, 0); + if (port == 0) + return NULL; + + *out_port = port; + return str; +} + +/** + * nm_sock_addr_endpoint_new: + * @endpoint: the endpoint string. + * + * This function cannot fail, even if the @endpoint is invalid. + * The reason is to allow NMSockAddrEndpoint also to be used + * for tracking invalid endpoints. Use nm_sock_addr_endpoint_get_host() + * to determine whether the endpoint is valid. + * + * Returns: (transfer full): the new #NMSockAddrEndpoint endpoint. + */ +NMSockAddrEndpoint * +nm_sock_addr_endpoint_new(const char *endpoint) +{ + NMSockAddrEndpoint *ep; + gsize l_endpoint; + gsize l_host = 0; + gsize i; + gs_free char * host_clone = NULL; + const char * host; + guint16 port; + + g_return_val_if_fail(endpoint, NULL); + + l_endpoint = strlen(endpoint) + 1; + + host = _parse_endpoint(nm_strndup_a(200, endpoint, l_endpoint - 1, &host_clone), &port); + + if (host) + l_host = strlen(host) + 1; + + ep = g_malloc(sizeof(NMSockAddrEndpoint) + l_endpoint + l_host); + ep->refcount = 1; + memcpy(ep->endpoint, endpoint, l_endpoint); + if (host) { + i = l_endpoint; + memcpy(&ep->endpoint[i], host, l_host); + ep->host = &ep->endpoint[i]; + ep->port = port; + } else { + ep->host = NULL; + ep->port = 0; + } + return ep; +} + +/** + * nm_sock_addr_endpoint_ref: + * @self: (allow-none): the #NMSockAddrEndpoint + */ +NMSockAddrEndpoint * +nm_sock_addr_endpoint_ref(NMSockAddrEndpoint *self) +{ + if (!self) + return NULL; + + g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), NULL); + + nm_assert(self->refcount < G_MAXUINT); + + self->refcount++; + return self; +} + +/** + * nm_sock_addr_endpoint_unref: + * @self: (allow-none): the #NMSockAddrEndpoint + */ +void +nm_sock_addr_endpoint_unref(NMSockAddrEndpoint *self) +{ + if (!self) + return; + + g_return_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self)); + + if (--self->refcount == 0) + g_free(self); +} + +/** + * nm_sock_addr_endpoint_get_endpoint: + * @self: the #NMSockAddrEndpoint + * + * Gives the endpoint string. Since #NMSockAddrEndpoint's only + * information is the endpoint string, this can be used for comparing + * to instances for equality and order them lexically. + * + * Returns: (transfer none): the endpoint. + */ +const char * +nm_sock_addr_endpoint_get_endpoint(NMSockAddrEndpoint *self) +{ + g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), NULL); + + return self->endpoint; +} + +/** + * nm_sock_addr_endpoint_get_host: + * @self: the #NMSockAddrEndpoint + * + * Returns: (transfer none): the parsed host part of the endpoint. + * If the endpoint is invalid, %NULL will be returned. + */ +const char * +nm_sock_addr_endpoint_get_host(NMSockAddrEndpoint *self) +{ + g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), NULL); + + return self->host; +} + +/** + * nm_sock_addr_endpoint_get_port: + * @self: the #NMSockAddrEndpoint + * + * Returns: the parsed port part of the endpoint (the service). + * If the endpoint is invalid, -1 will be returned. + */ +gint32 +nm_sock_addr_endpoint_get_port(NMSockAddrEndpoint *self) +{ + g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), -1); + + return self->host ? (int) self->port : -1; +} + +gboolean +nm_sock_addr_endpoint_get_fixed_sockaddr(NMSockAddrEndpoint *self, gpointer sockaddr) +{ + int addr_family; + NMIPAddr addrbin; + const char *s; + guint scope_id = 0; + + g_return_val_if_fail(NM_IS_SOCK_ADDR_ENDPOINT(self), FALSE); + g_return_val_if_fail(sockaddr, FALSE); + + if (!self->host) + return FALSE; + + if (nm_utils_parse_inaddr_bin(AF_UNSPEC, self->host, &addr_family, &addrbin)) + goto good; + + /* See if there is an IPv6 scope-id... + * + * Note that it does not make sense to persist connection profiles to disk, + * that refenrence a scope-id (because the interface's ifindex changes on + * reboot). However, we also support runtime only changes like `nmcli device modify` + * where nothing is persisted to disk. At least in that case, passing a scope-id + * might be reasonable. So, parse that too. */ + s = strchr(self->host, '%'); + if (!s) + return FALSE; + + if (s[1] == '\0' || !NM_STRCHAR_ALL(&s[1], ch, (ch >= '0' && ch <= '9'))) + return FALSE; + + scope_id = _nm_utils_ascii_str_to_int64(&s[1], 10, 0, G_MAXINT32, G_MAXUINT); + if (scope_id == G_MAXUINT && errno) + return FALSE; + + { + gs_free char *tmp_str = NULL; + const char * host_part; + + host_part = nm_strndup_a(200, self->host, s - self->host, &tmp_str); + if (nm_utils_parse_inaddr_bin(AF_INET6, host_part, &addr_family, &addrbin)) + goto good; + } + + return FALSE; + +good: + switch (addr_family) { + case AF_INET: + *((struct sockaddr_in *) sockaddr) = (struct sockaddr_in){ + .sin_family = AF_INET, + .sin_addr = addrbin.addr4_struct, + .sin_port = htons(self->port), + }; + return TRUE; + case AF_INET6: + *((struct sockaddr_in6 *) sockaddr) = (struct sockaddr_in6){ + .sin6_family = AF_INET6, + .sin6_addr = addrbin.addr6, + .sin6_port = htons(self->port), + .sin6_scope_id = scope_id, + .sin6_flowinfo = 0, + }; + return TRUE; + } + + return FALSE; +} + +/*****************************************************************************/ + +struct IsoLangToEncodings { + const char * lang; + const char *const *encodings; +}; + +#define LANG_ENCODINGS(l, ...) \ + { \ + .lang = l, .encodings = NM_MAKE_STRV(__VA_ARGS__), \ + } + +/* 5-letter language codes */ +static const struct IsoLangToEncodings isoLangEntries5[] = { + /* Simplified Chinese */ + LANG_ENCODINGS("zh_cn", "euc-cn", "gb2312", "gb18030"), /* PRC */ + LANG_ENCODINGS("zh_sg", "euc-cn", "gb2312", "gb18030"), /* Singapore */ + + /* Traditional Chinese */ + LANG_ENCODINGS("zh_tw", "big5", "euc-tw"), /* Taiwan */ + LANG_ENCODINGS("zh_hk", "big5", "euc-tw", "big5-hkcs"), /* Hong Kong */ + LANG_ENCODINGS("zh_mo", "big5", "euc-tw"), /* Macau */ + + LANG_ENCODINGS(NULL, NULL)}; + +/* 2-letter language codes; we don't care about the other 3 in this table */ +static const struct IsoLangToEncodings isoLangEntries2[] = { + /* Japanese */ + LANG_ENCODINGS("ja", "euc-jp", "shift_jis", "iso-2022-jp"), + + /* Korean */ + LANG_ENCODINGS("ko", "euc-kr", "iso-2022-kr", "johab"), + + /* Thai */ + LANG_ENCODINGS("th", "iso-8859-11", "windows-874"), + + /* Central European */ + LANG_ENCODINGS("hu", "iso-8859-2", "windows-1250"), /* Hungarian */ + LANG_ENCODINGS("cs", "iso-8859-2", "windows-1250"), /* Czech */ + LANG_ENCODINGS("hr", "iso-8859-2", "windows-1250"), /* Croatian */ + LANG_ENCODINGS("pl", "iso-8859-2", "windows-1250"), /* Polish */ + LANG_ENCODINGS("ro", "iso-8859-2", "windows-1250"), /* Romanian */ + LANG_ENCODINGS("sk", "iso-8859-2", "windows-1250"), /* Slovakian */ + LANG_ENCODINGS("sl", "iso-8859-2", "windows-1250"), /* Slovenian */ + LANG_ENCODINGS("sh", "iso-8859-2", "windows-1250"), /* Serbo-Croatian */ + + /* Cyrillic */ + LANG_ENCODINGS("ru", "koi8-r", "windows-1251", "iso-8859-5"), /* Russian */ + LANG_ENCODINGS("be", "koi8-r", "windows-1251", "iso-8859-5"), /* Belorussian */ + LANG_ENCODINGS("bg", "windows-1251", "koi8-r", "iso-8859-5"), /* Bulgarian */ + LANG_ENCODINGS("mk", "koi8-r", "windows-1251", "iso-8859-5"), /* Macedonian */ + LANG_ENCODINGS("sr", "koi8-r", "windows-1251", "iso-8859-5"), /* Serbian */ + LANG_ENCODINGS("uk", "koi8-u", "koi8-r", "windows-1251"), /* Ukrainian */ + + /* Arabic */ + LANG_ENCODINGS("ar", "iso-8859-6", "windows-1256"), + + /* Baltic */ + LANG_ENCODINGS("et", "iso-8859-4", "windows-1257"), /* Estonian */ + LANG_ENCODINGS("lt", "iso-8859-4", "windows-1257"), /* Lithuanian */ + LANG_ENCODINGS("lv", "iso-8859-4", "windows-1257"), /* Latvian */ + + /* Greek */ + LANG_ENCODINGS("el", "iso-8859-7", "windows-1253"), + + /* Hebrew */ + LANG_ENCODINGS("he", "iso-8859-8", "windows-1255"), + LANG_ENCODINGS("iw", "iso-8859-8", "windows-1255"), + + /* Turkish */ + LANG_ENCODINGS("tr", "iso-8859-9", "windows-1254"), + + /* Table end */ + LANG_ENCODINGS(NULL, NULL)}; + +static GHashTable *langToEncodings5 = NULL; +static GHashTable *langToEncodings2 = NULL; + +static void +init_lang_to_encodings_hash(void) +{ + struct IsoLangToEncodings *enc; + + if (G_UNLIKELY(langToEncodings5 == NULL)) { + /* Five-letter codes */ + enc = (struct IsoLangToEncodings *) &isoLangEntries5[0]; + langToEncodings5 = g_hash_table_new(nm_str_hash, g_str_equal); + while (enc->lang) { + g_hash_table_insert(langToEncodings5, (gpointer) enc->lang, (gpointer) enc->encodings); + enc++; + } + } + + if (G_UNLIKELY(langToEncodings2 == NULL)) { + /* Two-letter codes */ + enc = (struct IsoLangToEncodings *) &isoLangEntries2[0]; + langToEncodings2 = g_hash_table_new(nm_str_hash, g_str_equal); + while (enc->lang) { + g_hash_table_insert(langToEncodings2, (gpointer) enc->lang, (gpointer) enc->encodings); + enc++; + } + } +} + +static gboolean +get_encodings_for_lang(const char *lang, const char *const **encodings) +{ + gs_free char *tmp_lang = NULL; + + g_return_val_if_fail(lang, FALSE); + g_return_val_if_fail(encodings, FALSE); + + init_lang_to_encodings_hash(); + + if ((*encodings = g_hash_table_lookup(langToEncodings5, lang))) + return TRUE; + + /* Truncate tmp_lang to length of 2 */ + if (strlen(lang) > 2) { + tmp_lang = g_strdup(lang); + tmp_lang[2] = '\0'; + if ((*encodings = g_hash_table_lookup(langToEncodings2, tmp_lang))) + return TRUE; + } + + return FALSE; +} + +static const char *const * +get_system_encodings(void) +{ + static const char *const *cached_encodings; + static char * default_encodings[4]; + const char *const * encodings = NULL; + char * lang; + + if (cached_encodings) + return cached_encodings; + + /* Use environment variables as encoding hint */ + lang = getenv("LC_ALL"); + if (!lang) + lang = getenv("LC_CTYPE"); + if (!lang) + lang = getenv("LANG"); + if (lang) { + char *dot; + + lang = g_ascii_strdown(lang, -1); + if ((dot = strchr(lang, '.'))) + *dot = '\0'; + + get_encodings_for_lang(lang, &encodings); + g_free(lang); + } + if (!encodings) { + g_get_charset((const char **) &default_encodings[0]); + default_encodings[1] = "iso-8859-1"; + default_encodings[2] = "windows-1251"; + default_encodings[3] = NULL; + encodings = (const char *const *) default_encodings; + } + + cached_encodings = encodings; + return cached_encodings; +} + +/*****************************************************************************/ + +static void __attribute__((constructor)) _nm_utils_init(void) +{ + static int initialized = 0; + + if (g_atomic_int_get(&initialized) != 0) + return; + + /* we don't expect this code to run multiple times, nor on multiple threads. + * + * In practice, it would not be a problem if two threads concurrently try to + * run the initialization code below, all code below itself is thread-safe, + * Hence, a poor-man guard "initialized" above is more than sufficient, + * although it does not guarantee that the code is not run concurrently. */ + + bindtextdomain(GETTEXT_PACKAGE, NMLOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + + _nm_dbus_errors_init(); + + g_atomic_int_set(&initialized, 1); +} + +/*****************************************************************************/ + +gboolean _nm_utils_is_manager_process; + +/* ssid helpers */ + +/** + * nm_utils_ssid_to_utf8: + * @ssid: (array length=len): pointer to a buffer containing the SSID data + * @len: length of the SSID data in @ssid + * + * Wi-Fi SSIDs are byte arrays, they are _not_ strings. Thus, an SSID may + * contain embedded NULLs and other unprintable characters. Often it is + * useful to print the SSID out for debugging purposes, but that should be the + * _only_ use of this function. Do not use this function for any persistent + * storage of the SSID, since the printable SSID returned from this function + * cannot be converted back into the real SSID of the access point. + * + * This function does almost everything humanly possible to convert the input + * into a printable UTF-8 string, using roughly the following procedure: + * + * 1) if the input data is already UTF-8 safe, no conversion is performed + * 2) attempts to get the current system language from the LANG environment + * variable, and depending on the language, uses a table of alternative + * encodings to try. For example, if LANG=hu_HU, the table may first try + * the ISO-8859-2 encoding, and if that fails, try the Windows-1250 encoding. + * If all fallback encodings fail, replaces non-UTF-8 characters with '?'. + * 3) If the system language was unable to be determined, falls back to the + * ISO-8859-1 encoding, then to the Windows-1251 encoding. + * 4) If step 3 fails, replaces non-UTF-8 characters with '?'. + * + * Again, this function should be used for debugging and display purposes + * _only_. + * + * Returns: (transfer full): an allocated string containing a UTF-8 + * representation of the SSID, which must be freed by the caller using g_free(). + * Returns %NULL on errors. + **/ +char * +nm_utils_ssid_to_utf8(const guint8 *ssid, gsize len) +{ + const char *const *encodings; + const char *const *e; + char * converted = NULL; + + g_return_val_if_fail(ssid != NULL, NULL); + + if (g_utf8_validate((const char *) ssid, len, NULL)) + return g_strndup((const char *) ssid, len); + + encodings = get_system_encodings(); + + for (e = encodings; *e; e++) { + converted = g_convert((const char *) ssid, len, "UTF-8", *e, NULL, NULL, NULL); + if (converted) + break; + } + + if (!converted) { + converted = g_convert_with_fallback((const char *) ssid, + len, + "UTF-8", + encodings[0], + "?", + NULL, + NULL, + NULL); + } + + if (!converted) { + /* If there is still no converted string, the SSID probably + * contains characters not valid in the current locale. Convert + * the string to ASCII instead. + */ + + /* Use the printable range of 0x20-0x7E */ + char *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" + "abcdefghijklmnopqrstuvwxyz{|}~"; + + converted = g_strndup((const char *) ssid, len); + g_strcanon(converted, valid_chars, '?'); + } + + return converted; +} + +char * +_nm_utils_ssid_to_utf8(GBytes *ssid) +{ + const guint8 *p; + gsize l; + + g_return_val_if_fail(ssid, NULL); + + p = g_bytes_get_data(ssid, &l); + return nm_utils_ssid_to_utf8(p, l); +} + +/* Shamelessly ripped from the Linux kernel ieee80211 stack */ +/** + * nm_utils_is_empty_ssid: + * @ssid: (array length=len): pointer to a buffer containing the SSID data + * @len: length of the SSID data in @ssid + * + * Different manufacturers use different mechanisms for not broadcasting the + * AP's SSID. This function attempts to detect blank/empty SSIDs using a + * number of known SSID-cloaking methods. + * + * Returns: %TRUE if the SSID is "empty", %FALSE if it is not + **/ +gboolean +nm_utils_is_empty_ssid(const guint8 *ssid, gsize len) +{ + /* Single white space is for Linksys APs */ + if (len == 1 && ssid[0] == ' ') + return TRUE; + + /* Otherwise, if the entire ssid is 0, we assume it is hidden */ + while (len--) { + if (ssid[len] != '\0') + return FALSE; + } + return TRUE; +} + +gboolean +_nm_utils_is_empty_ssid(GBytes *ssid) +{ + const guint8 *p; + gsize l; + + g_return_val_if_fail(ssid, FALSE); + + p = g_bytes_get_data(ssid, &l); + return nm_utils_is_empty_ssid(p, l); +} + +#define ESSID_MAX_SIZE 32 + +/** + * nm_utils_escape_ssid: + * @ssid: (array length=len): pointer to a buffer containing the SSID data + * @len: length of the SSID data in @ssid + * + * This function does a quick printable character conversion of the SSID, simply + * replacing embedded NULLs and non-printable characters with the hexadecimal + * representation of that character. Intended for debugging only, should not + * be used for display of SSIDs. + * + * Returns: pointer to the escaped SSID, which uses an internal static buffer + * and will be overwritten by subsequent calls to this function + **/ +const char * +nm_utils_escape_ssid(const guint8 *ssid, gsize len) +{ + static char escaped[ESSID_MAX_SIZE * 2 + 1]; + const guint8 *s = ssid; + char * d = escaped; + + if (nm_utils_is_empty_ssid(ssid, len)) { + memcpy(escaped, "", sizeof("")); + return escaped; + } + + len = MIN(len, (guint32) ESSID_MAX_SIZE); + while (len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} + +char * +_nm_utils_ssid_to_string_arr(const guint8 *ssid, gsize len) +{ + gs_free char *s_copy = NULL; + const char * s_cnst; + + if (len == 0) + return g_strdup("(empty)"); + + s_cnst = + nm_utils_buf_utf8safe_escape(ssid, len, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, &s_copy); + nm_assert(s_cnst); + + if (nm_utils_is_empty_ssid(ssid, len)) + return g_strdup_printf("\"%s\" (hidden)", s_cnst); + + return g_strdup_printf("\"%s\"", s_cnst); +} + +char * +_nm_utils_ssid_to_string(GBytes *ssid) +{ + gconstpointer p; + gsize l; + + if (!ssid) + return g_strdup("(none)"); + + p = g_bytes_get_data(ssid, &l); + return _nm_utils_ssid_to_string_arr(p, l); +} + +/** + * nm_utils_same_ssid: + * @ssid1: (array length=len1): the first SSID to compare + * @len1: length of the SSID data in @ssid1 + * @ssid2: (array length=len2): the second SSID to compare + * @len2: length of the SSID data in @ssid2 + * @ignore_trailing_null: %TRUE to ignore one trailing NULL byte + * + * Earlier versions of the Linux kernel added a NULL byte to the end of the + * SSID to enable easy printing of the SSID on the console or in a terminal, + * but this behavior was problematic (SSIDs are simply byte arrays, not strings) + * and thus was changed. This function compensates for that behavior at the + * cost of some compatibility with odd SSIDs that may legitimately have trailing + * NULLs, even though that is functionally pointless. + * + * Returns: %TRUE if the SSIDs are the same, %FALSE if they are not + **/ +gboolean +nm_utils_same_ssid(const guint8 *ssid1, + gsize len1, + const guint8 *ssid2, + gsize len2, + gboolean ignore_trailing_null) +{ + g_return_val_if_fail(ssid1 != NULL || len1 == 0, FALSE); + g_return_val_if_fail(ssid2 != NULL || len2 == 0, FALSE); + + if (ssid1 == ssid2 && len1 == len2) + return TRUE; + if (!ssid1 || !ssid2) + return FALSE; + + if (ignore_trailing_null) { + if (len1 && ssid1[len1 - 1] == '\0') + len1--; + if (len2 && ssid2[len2 - 1] == '\0') + len2--; + } + + if (len1 != len2) + return FALSE; + + return memcmp(ssid1, ssid2, len1) == 0 ? TRUE : FALSE; +} + +gboolean +_nm_utils_string_slist_validate(GSList *list, const char **valid_values) +{ + GSList *iter; + + for (iter = list; iter; iter = iter->next) { + if (!g_strv_contains(valid_values, (char *) iter->data)) + return FALSE; + } + + return TRUE; +} + +/** + * _nm_utils_hash_values_to_slist: + * @hash: a #GHashTable + * + * Utility function to iterate over a hash table and return + * its values as a #GSList. + * + * Returns: (element-type gpointer) (transfer container): a newly allocated #GSList + * containing the values of the hash table. The caller must free the + * returned list with g_slist_free(). The hash values are not owned + * by the returned list. + **/ +GSList * +_nm_utils_hash_values_to_slist(GHashTable *hash) +{ + GSList * list = NULL; + GHashTableIter iter; + void * value; + + g_return_val_if_fail(hash, NULL); + + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, NULL, &value)) + list = g_slist_prepend(list, value); + + return list; +} + +static GVariant * +_nm_utils_strdict_to_dbus(const GValue *prop_value) +{ + return nm_utils_strdict_to_variant_ass(g_value_get_boxed(prop_value)); +} + +void +_nm_utils_strdict_from_dbus(GVariant *dbus_value, GValue *prop_value) +{ + GVariantIter iter; + const char * key, *value; + GHashTable * hash; + + hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); + g_variant_iter_init(&iter, dbus_value); + while (g_variant_iter_next(&iter, "{&s&s}", &key, &value)) + g_hash_table_insert(hash, g_strdup(key), g_strdup(value)); + + g_value_take_boxed(prop_value, hash); +} + +const NMSettInfoPropertType nm_sett_info_propert_type_strdict = { + .dbus_type = NM_G_VARIANT_TYPE("a{ss}"), + .gprop_to_dbus_fcn = _nm_utils_strdict_to_dbus, + .gprop_from_dbus_fcn = _nm_utils_strdict_from_dbus, +}; + +GHashTable * +_nm_utils_copy_strdict(GHashTable *strdict) +{ + GHashTable * copy; + GHashTableIter iter; + gpointer key, value; + + copy = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); + if (strdict) { + g_hash_table_iter_init(&iter, strdict); + while (g_hash_table_iter_next(&iter, &key, &value)) + g_hash_table_insert(copy, g_strdup(key), g_strdup(value)); + } + return copy; +} + +GPtrArray * +_nm_utils_copy_array(const GPtrArray *array, NMUtilsCopyFunc copy_func, GDestroyNotify free_func) +{ + GPtrArray *copy; + guint i; + + if (!array) + return g_ptr_array_new_with_free_func(free_func); + + copy = g_ptr_array_new_full(array->len, free_func); + for (i = 0; i < array->len; i++) + g_ptr_array_add(copy, copy_func(array->pdata[i])); + return copy; +} + +GPtrArray * +_nm_utils_copy_object_array(const GPtrArray *array) +{ + return _nm_utils_copy_array(array, g_object_ref, g_object_unref); +} + +gssize +_nm_utils_ptrarray_find_first(gconstpointer *list, gssize len, gconstpointer needle) +{ + gssize i; + + if (len == 0) + return -1; + + if (len > 0) { + g_return_val_if_fail(list, -1); + for (i = 0; i < len; i++) { + if (list[i] == needle) + return i; + } + } else { + g_return_val_if_fail(needle, -1); + for (i = 0; list && list[i]; i++) { + if (list[i] == needle) + return i; + } + } + return -1; +} + +void +_nm_utils_bytes_from_dbus(GVariant *dbus_value, GValue *prop_value) +{ + GBytes *bytes; + + if (g_variant_n_children(dbus_value)) { + gconstpointer data; + gsize length; + + data = g_variant_get_fixed_array(dbus_value, &length, 1); + bytes = g_bytes_new(data, length); + } else + bytes = NULL; + g_value_take_boxed(prop_value, bytes); +} + +/*****************************************************************************/ + +GSList * +_nm_utils_strv_to_slist(char **strv, gboolean deep_copy) +{ + GSList *list = NULL; + gsize i; + + if (!strv) + return NULL; + + if (deep_copy) { + for (i = 0; strv[i]; i++) + list = g_slist_prepend(list, g_strdup(strv[i])); + } else { + for (i = 0; strv[i]; i++) + list = g_slist_prepend(list, strv[i]); + } + return g_slist_reverse(list); +} + +char ** +_nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy) +{ + const GSList *iter; + char ** strv; + guint len, i; + + if (!slist) + return NULL; + + len = g_slist_length((GSList *) slist); + + strv = g_new(char *, len + 1); + + if (deep_copy) { + for (i = 0, iter = slist; iter; iter = iter->next, i++) { + nm_assert(iter->data); + strv[i] = g_strdup(iter->data); + } + } else { + for (i = 0, iter = slist; iter; iter = iter->next, i++) { + nm_assert(iter->data); + strv[i] = iter->data; + } + } + strv[i] = NULL; + + return strv; +} + +GPtrArray * +_nm_utils_strv_to_ptrarray(char **strv) +{ + GPtrArray *ptrarray; + gsize i, l; + + l = NM_PTRARRAY_LEN(strv); + + ptrarray = g_ptr_array_new_full(l, g_free); + + if (strv) { + for (i = 0; strv[i]; i++) + g_ptr_array_add(ptrarray, g_strdup(strv[i])); + } + + return ptrarray; +} + +char ** +_nm_utils_ptrarray_to_strv(const GPtrArray *ptrarray) +{ + char **strv; + guint i; + + if (!ptrarray) + return g_new0(char *, 1); + + strv = g_new(char *, ptrarray->len + 1); + + for (i = 0; i < ptrarray->len; i++) + strv[i] = g_strdup(ptrarray->pdata[i]); + strv[i] = NULL; + + return strv; +} + +/*****************************************************************************/ + +static gboolean +device_supports_ap_ciphers(guint32 dev_caps, guint32 ap_flags, gboolean static_wep) +{ + gboolean have_pair = FALSE; + gboolean have_group = FALSE; + /* Device needs to support at least one pairwise and one group cipher */ + + /* Pairwise */ + if (static_wep) { + /* Static WEP only uses group ciphers */ + have_pair = TRUE; + } else { + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40) + if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP40) + have_pair = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104) + if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP104) + have_pair = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) + if (ap_flags & NM_802_11_AP_SEC_PAIR_TKIP) + have_pair = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) + if (ap_flags & NM_802_11_AP_SEC_PAIR_CCMP) + have_pair = TRUE; + } + + /* Group */ + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40) + if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP40) + have_group = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104) + if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP104) + have_group = TRUE; + if (!static_wep) { + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) + if (ap_flags & NM_802_11_AP_SEC_GROUP_TKIP) + have_group = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) + if (ap_flags & NM_802_11_AP_SEC_GROUP_CCMP) + have_group = TRUE; + } + + return (have_pair && have_group); +} + +/** + * nm_utils_ap_mode_security_valid: + * @type: the security type to check device capabilities against, + * e.g. #NMU_SEC_STATIC_WEP + * @wifi_caps: bitfield of the capabilities of the specific Wi-Fi device, e.g. + * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40 + * + * Given a set of device capabilities, and a desired security type to check + * against, determines whether the combination of device capabilities and + * desired security type are valid for AP/Hotspot connections. + * + * Returns: %TRUE if the device capabilities are compatible with the desired + * @type, %FALSE if they are not. + **/ +gboolean +nm_utils_ap_mode_security_valid(NMUtilsSecurityType type, NMDeviceWifiCapabilities wifi_caps) +{ + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_AP)) + return FALSE; + + /* Return TRUE for any security that wpa_supplicant's lightweight AP + * mode can handle: which is open, WEP, and WPA/WPA2 PSK. + */ + switch (type) { + case NMU_SEC_NONE: + case NMU_SEC_STATIC_WEP: + case NMU_SEC_WPA_PSK: + case NMU_SEC_WPA2_PSK: + case NMU_SEC_SAE: + case NMU_SEC_OWE: + return TRUE; + case NMU_SEC_LEAP: + case NMU_SEC_DYNAMIC_WEP: + case NMU_SEC_WPA_ENTERPRISE: + case NMU_SEC_WPA2_ENTERPRISE: + case NMU_SEC_WPA3_SUITE_B_192: + return FALSE; + case NMU_SEC_INVALID: + break; + } + return FALSE; +} + +/** + * nm_utils_security_valid: + * @type: the security type to check AP flags and device capabilities against, + * e.g. #NMU_SEC_STATIC_WEP + * @wifi_caps: bitfield of the capabilities of the specific Wi-Fi device, e.g. + * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40 + * @have_ap: whether the @ap_flags, @ap_wpa, and @ap_rsn arguments are valid + * @adhoc: whether the capabilities being tested are from an Ad-Hoc AP (IBSS) + * @ap_flags: bitfield of AP capabilities, e.g. #NM_802_11_AP_FLAGS_PRIVACY + * @ap_wpa: bitfield of AP capabilities derived from the AP's WPA beacon, + * e.g. (#NM_802_11_AP_SEC_PAIR_TKIP | #NM_802_11_AP_SEC_KEY_MGMT_PSK) + * @ap_rsn: bitfield of AP capabilities derived from the AP's RSN/WPA2 beacon, + * e.g. (#NM_802_11_AP_SEC_PAIR_CCMP | #NM_802_11_AP_SEC_PAIR_TKIP) + * + * Given a set of device capabilities, and a desired security type to check + * against, determines whether the combination of device, desired security + * type, and AP capabilities intersect. + * + * NOTE: this function cannot handle checking security for AP/Hotspot mode; + * use nm_utils_ap_mode_security_valid() instead. + * + * Returns: %TRUE if the device capabilities and AP capabilities intersect and are + * compatible with the desired @type, %FALSE if they are not + **/ +gboolean +nm_utils_security_valid(NMUtilsSecurityType type, + NMDeviceWifiCapabilities wifi_caps, + gboolean have_ap, + gboolean adhoc, + NM80211ApFlags ap_flags, + NM80211ApSecurityFlags ap_wpa, + NM80211ApSecurityFlags ap_rsn) +{ + switch (type) { + case NMU_SEC_NONE: + if (!have_ap) + return TRUE; + if (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) + return FALSE; + if (ap_wpa || ap_rsn) + return FALSE; + return TRUE; + case NMU_SEC_LEAP: /* require PRIVACY bit for LEAP? */ + if (adhoc) + return FALSE; + /* fall-through */ + case NMU_SEC_STATIC_WEP: + if (!have_ap) { + if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) + return TRUE; + return FALSE; + } + if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + return FALSE; + if (ap_wpa || ap_rsn) { + if (!device_supports_ap_ciphers(wifi_caps, ap_wpa, TRUE)) { + if (!device_supports_ap_ciphers(wifi_caps, ap_rsn, TRUE)) + return FALSE; + } + } + return TRUE; + case NMU_SEC_DYNAMIC_WEP: + if (adhoc) + return FALSE; + if (!have_ap) { + if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) + return TRUE; + return FALSE; + } + if (ap_rsn || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + return FALSE; + /* Some APs broadcast minimal WPA-enabled beacons that must be handled */ + if (ap_wpa) { + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + if (!device_supports_ap_ciphers(wifi_caps, ap_wpa, FALSE)) + return FALSE; + } + return TRUE; + case NMU_SEC_WPA_PSK: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) + return FALSE; + if (!have_ap) + return TRUE; + if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) { + if ((ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + return TRUE; + if ((ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + } + return FALSE; + case NMU_SEC_WPA2_PSK: + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (!have_ap) + return TRUE; + if (adhoc) { + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_IBSS_RSN)) + return FALSE; + if ((ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + return FALSE; + } + if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) { + if ((ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + return TRUE; + if ((ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + } + return FALSE; + case NMU_SEC_WPA_ENTERPRISE: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) + return FALSE; + if (!have_ap) + return TRUE; + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + /* Ensure at least one WPA cipher is supported */ + if (!device_supports_ap_ciphers(wifi_caps, ap_wpa, FALSE)) + return FALSE; + return TRUE; + case NMU_SEC_WPA2_ENTERPRISE: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (!have_ap) + return TRUE; + if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + /* Ensure at least one WPA cipher is supported */ + if (!device_supports_ap_ciphers(wifi_caps, ap_rsn, FALSE)) + return FALSE; + return TRUE; + case NMU_SEC_SAE: + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (adhoc) + return FALSE; + if (!have_ap) + return TRUE; + if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE) { + if ((ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + } + return FALSE; + case NMU_SEC_OWE: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (!have_ap) + return TRUE; + if (!NM_FLAGS_ANY(ap_rsn, NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) + return FALSE; + return TRUE; + case NMU_SEC_WPA3_SUITE_B_192: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (!have_ap) + return TRUE; + if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192) + return TRUE; + return FALSE; + case NMU_SEC_INVALID: + break; + } + + return FALSE; +} + +/** + * nm_utils_wep_key_valid: + * @key: a string that might be a WEP key + * @wep_type: the #NMWepKeyType type of the WEP key + * + * Checks if @key is a valid WEP key + * + * Returns: %TRUE if @key is a WEP key, %FALSE if not + */ +gboolean +nm_utils_wep_key_valid(const char *key, NMWepKeyType wep_type) +{ + gsize keylen; + gsize i; + + if (!key) + return FALSE; + + if (wep_type == NM_WEP_KEY_TYPE_UNKNOWN) { + return nm_utils_wep_key_valid(key, NM_WEP_KEY_TYPE_KEY) + || nm_utils_wep_key_valid(key, NM_WEP_KEY_TYPE_PASSPHRASE); + } + + keylen = strlen(key); + if (wep_type == NM_WEP_KEY_TYPE_KEY) { + if (keylen == 10 || keylen == 26) { + /* Hex key */ + for (i = 0; i < keylen; i++) { + if (!g_ascii_isxdigit(key[i])) + return FALSE; + } + } else if (keylen == 5 || keylen == 13) { + /* ASCII key */ + for (i = 0; i < keylen; i++) { + if (!g_ascii_isprint(key[i])) + return FALSE; + } + } else + return FALSE; + } else if (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE) { + if (!keylen || keylen > 64) + return FALSE; + } + + return TRUE; +} + +/** + * nm_utils_wpa_psk_valid: + * @psk: a string that might be a WPA PSK + * + * Checks if @psk is a valid WPA PSK + * + * Returns: %TRUE if @psk is a WPA PSK, %FALSE if not + */ +gboolean +nm_utils_wpa_psk_valid(const char *psk) +{ + gsize psklen; + gsize i; + + if (!psk) + return FALSE; + + psklen = strlen(psk); + if (psklen < 8 || psklen > 64) + return FALSE; + + if (psklen == 64) { + /* Hex PSK */ + for (i = 0; i < psklen; i++) { + if (!g_ascii_isxdigit(psk[i])) + return FALSE; + } + } + + return TRUE; +} + +/** + * nm_utils_ip4_dns_to_variant: + * @dns: (type utf8): an array of IP address strings + * + * Utility function to convert an array of IP address strings int a #GVariant of + * type 'au' representing an array of IPv4 addresses. + * + * Returns: (transfer none): a new floating #GVariant representing @dns. + **/ +GVariant * +nm_utils_ip4_dns_to_variant(char **dns) +{ + GVariantBuilder builder; + gsize i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); + + if (dns) { + for (i = 0; dns[i]; i++) { + guint32 ip = 0; + + inet_pton(AF_INET, dns[i], &ip); + g_variant_builder_add(&builder, "u", ip); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * nm_utils_ip4_dns_from_variant: + * @value: a #GVariant of type 'au' + * + * Utility function to convert a #GVariant of type 'au' representing a list of + * IPv4 addresses into an array of IP address strings. + * + * Returns: (transfer full) (type utf8): a %NULL-terminated array of IP address strings. + **/ +char ** +nm_utils_ip4_dns_from_variant(GVariant *value) +{ + const guint32 *array; + gsize length; + char ** dns; + gsize i; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("au")), NULL); + + array = g_variant_get_fixed_array(value, &length, sizeof(guint32)); + dns = g_new(char *, length + 1u); + for (i = 0; i < length; i++) + dns[i] = nm_utils_inet4_ntop_dup(array[i]); + dns[i] = NULL; + + return dns; +} + +/** + * nm_utils_ip4_addresses_to_variant: + * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects + * @gateway: (allow-none): the gateway IP address + * + * Utility function to convert a #GPtrArray of #NMIPAddress objects representing + * IPv4 addresses into a #GVariant of type 'aau' representing an array of + * NetworkManager IPv4 addresses (which are tuples of address, prefix, and + * gateway). The "gateway" field of the first address will get the value of + * @gateway (if non-%NULL). In all of the other addresses, that field will be 0. + * + * Returns: (transfer none): a new floating #GVariant representing @addresses. + **/ +GVariant * +nm_utils_ip4_addresses_to_variant(GPtrArray *addresses, const char *gateway) +{ + GVariantBuilder builder; + guint i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("aau")); + + if (addresses) { + for (i = 0; i < addresses->len; i++) { + NMIPAddress *addr = addresses->pdata[i]; + guint32 array[3]; + in_addr_t gw; + + if (nm_ip_address_get_family(addr) != AF_INET) + continue; + + gw = 0u; + if (gateway) { + in_addr_t a; + + if (inet_pton(AF_INET, gateway, &a) == 1) + gw = a; + gateway = NULL; + } + + nm_ip_address_get_address_binary(addr, &array[0]); + array[1] = nm_ip_address_get_prefix(addr); + array[2] = gw; + + g_variant_builder_add( + &builder, + "@au", + g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 3, sizeof(guint32))); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * nm_utils_ip4_addresses_from_variant: + * @value: a #GVariant of type 'aau' + * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway + * + * Utility function to convert a #GVariant of type 'aau' representing a list of + * NetworkManager IPv4 addresses (which are tuples of address, prefix, and + * gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field of + * the first address (if set) will be returned in @out_gateway; the "gateway" fields + * of the other addresses are ignored. + * + * Returns: (transfer full) (element-type NMIPAddress): a newly allocated + * #GPtrArray of #NMIPAddress objects + **/ +GPtrArray * +nm_utils_ip4_addresses_from_variant(GVariant *value, char **out_gateway) +{ + GPtrArray * addresses; + GVariantIter iter; + GVariant * addr_var; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aau")), NULL); + + if (out_gateway) + *out_gateway = NULL; + + g_variant_iter_init(&iter, value); + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + + while (g_variant_iter_next(&iter, "@au", &addr_var)) { + const guint32 *addr_array; + gsize length; + NMIPAddress * addr; + GError * error = NULL; + + addr_array = g_variant_get_fixed_array(addr_var, &length, sizeof(guint32)); + if (length < 3) { + g_warning("Ignoring invalid IP4 address"); + g_variant_unref(addr_var); + continue; + } + + addr = nm_ip_address_new_binary(AF_INET, &addr_array[0], addr_array[1], &error); + if (addr) { + g_ptr_array_add(addresses, addr); + + if (addr_array[2] && out_gateway && !*out_gateway) + *out_gateway = nm_utils_inet4_ntop_dup(addr_array[2]); + } else { + g_warning("Ignoring invalid IP4 address: %s", error->message); + g_clear_error(&error); + } + + g_variant_unref(addr_var); + } + + return addresses; +} + +/** + * nm_utils_ip4_routes_to_variant: + * @routes: (element-type NMIPRoute): an array of #NMIP4Route objects + * + * Utility function to convert a #GPtrArray of #NMIPRoute objects representing + * IPv4 routes into a #GVariant of type 'aau' representing an array of + * NetworkManager IPv4 routes (which are tuples of route, prefix, next hop, and + * metric). + * + * Returns: (transfer none): a new floating #GVariant representing @routes. + **/ +GVariant * +nm_utils_ip4_routes_to_variant(GPtrArray *routes) +{ + GVariantBuilder builder; + guint i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("aau")); + + if (routes) { + for (i = 0; i < routes->len; i++) { + NMIPRoute *route = routes->pdata[i]; + guint32 array[4]; + + if (nm_ip_route_get_family(route) != AF_INET) + continue; + + nm_ip_route_get_dest_binary(route, &array[0]); + array[1] = nm_ip_route_get_prefix(route); + nm_ip_route_get_next_hop_binary(route, &array[2]); + /* The old routes format uses "0" for default, not "-1" */ + array[3] = MAX(0, nm_ip_route_get_metric(route)); + + g_variant_builder_add( + &builder, + "@au", + g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 4, sizeof(guint32))); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * nm_utils_ip4_routes_from_variant: + * @value: #GVariant of type 'aau' + * + * Utility function to convert a #GVariant of type 'aau' representing an array + * of NetworkManager IPv4 routes (which are tuples of route, prefix, next hop, + * and metric) into a #GPtrArray of #NMIPRoute objects. + * + * Returns: (transfer full) (element-type NMIPRoute): a newly allocated + * #GPtrArray of #NMIPRoute objects + **/ +GPtrArray * +nm_utils_ip4_routes_from_variant(GVariant *value) +{ + GVariantIter iter; + GVariant * route_var; + GPtrArray * routes; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aau")), NULL); + + g_variant_iter_init(&iter, value); + routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); + + while (g_variant_iter_next(&iter, "@au", &route_var)) { + const guint32 *route_array; + gsize length; + NMIPRoute * route; + GError * error = NULL; + + route_array = g_variant_get_fixed_array(route_var, &length, sizeof(guint32)); + if (length < 4) { + g_warning("Ignoring invalid IP4 route"); + g_variant_unref(route_var); + continue; + } + + route = nm_ip_route_new_binary(AF_INET, + &route_array[0], + route_array[1], + &route_array[2], + /* The old routes format uses "0" for default, not "-1" */ + route_array[3] ? (gint64) route_array[3] : -1, + &error); + if (route) + g_ptr_array_add(routes, route); + else { + g_warning("Ignoring invalid IP4 route: %s", error->message); + g_clear_error(&error); + } + g_variant_unref(route_var); + } + + return routes; +} + +/** + * nm_utils_ip4_netmask_to_prefix: + * @netmask: an IPv4 netmask in network byte order + * + * Returns: the CIDR prefix represented by the netmask + **/ +guint32 +nm_utils_ip4_netmask_to_prefix(guint32 netmask) +{ + G_STATIC_ASSERT_EXPR(__SIZEOF_INT__ == 4); + G_STATIC_ASSERT_EXPR(sizeof(int) == 4); + G_STATIC_ASSERT_EXPR(sizeof(netmask) == 4); + + return ((netmask != 0u) ? (guint32)(32 - __builtin_ctz(ntohl(netmask))) : 0u); +} + +/** + * nm_utils_ip4_prefix_to_netmask: + * @prefix: a CIDR prefix + * + * Returns: the netmask represented by the prefix, in network byte order + **/ +guint32 +nm_utils_ip4_prefix_to_netmask(guint32 prefix) +{ + return _nm_utils_ip4_prefix_to_netmask(prefix); +} + +/** + * nm_utils_ip4_get_default_prefix: + * @ip: an IPv4 address (in network byte order) + * + * When the Internet was originally set up, various ranges of IP addresses were + * segmented into three network classes: A, B, and C. This function will return + * a prefix that is associated with the IP address specified defining where it + * falls in the predefined classes. + * + * Returns: the default class prefix for the given IP + **/ +/* The function is originally from ipcalc.c of Red Hat's initscripts. */ +guint32 +nm_utils_ip4_get_default_prefix(guint32 ip) +{ + return _nm_utils_ip4_get_default_prefix(ip); +} + +/** + * nm_utils_ip6_dns_to_variant: + * @dns: (type utf8): an array of IP address strings + * + * Utility function to convert an array of IP address strings int a #GVariant of + * type 'aay' representing an array of IPv6 addresses. + * + * If a string cannot be parsed, it will be silently ignored. + * + * Returns: (transfer none): a new floating #GVariant representing @dns. + **/ +GVariant * +nm_utils_ip6_dns_to_variant(char **dns) +{ + GVariantBuilder builder; + gsize i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("aay")); + if (dns) { + for (i = 0; dns[i]; i++) { + struct in6_addr ip; + + if (inet_pton(AF_INET6, dns[i], &ip) != 1) + continue; + g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip)); + } + } + return g_variant_builder_end(&builder); +} + +/** + * nm_utils_ip6_dns_from_variant: + * @value: a #GVariant of type 'aay' + * + * Utility function to convert a #GVariant of type 'aay' representing a list of + * IPv6 addresses into an array of IP address strings. Each "ay" entry must be + * a IPv6 address in binary form (16 bytes long). Invalid entries are silently + * ignored. + * + * Returns: (transfer full) (type utf8): a %NULL-terminated array of IP address strings. + **/ +char ** +nm_utils_ip6_dns_from_variant(GVariant *value) +{ + GVariantIter iter; + GVariant * ip_var; + char ** dns; + gsize i; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aay")), NULL); + + dns = g_new(char *, g_variant_n_children(value) + 1); + + g_variant_iter_init(&iter, value); + i = 0; + while (g_variant_iter_next(&iter, "@ay", &ip_var)) { + gsize length; + const struct in6_addr *ip = g_variant_get_fixed_array(ip_var, &length, 1); + + if (length == sizeof(struct in6_addr)) + dns[i++] = nm_utils_inet6_ntop_dup(ip); + + g_variant_unref(ip_var); + } + dns[i] = NULL; + + return dns; +} + +/** + * nm_utils_ip6_addresses_to_variant: + * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects + * @gateway: (allow-none): the gateway IP address + * + * Utility function to convert a #GPtrArray of #NMIPAddress objects representing + * IPv6 addresses into a #GVariant of type 'a(ayuay)' representing an array of + * NetworkManager IPv6 addresses (which are tuples of address, prefix, and + * gateway). The "gateway" field of the first address will get the value of + * @gateway (if non-%NULL). In all of the other addresses, that field will be + * all 0s. + * + * Returns: (transfer none): a new floating #GVariant representing @addresses. + **/ +GVariant * +nm_utils_ip6_addresses_to_variant(GPtrArray *addresses, const char *gateway) +{ + GVariantBuilder builder; + guint i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ayuay)")); + + if (addresses) { + for (i = 0; i < addresses->len; i++) { + NMIPAddress * addr = addresses->pdata[i]; + struct in6_addr address_bin; + struct in6_addr gateway_bin_data; + const struct in6_addr *gateway_bin; + + if (nm_ip_address_get_family(addr) != AF_INET6) + continue; + + nm_ip_address_get_address_binary(addr, &address_bin); + + gateway_bin = &in6addr_any; + if (gateway) { + if (inet_pton(AF_INET6, gateway, &gateway_bin_data) == 1) + gateway_bin = &gateway_bin_data; + gateway = NULL; + } + + g_variant_builder_add(&builder, + "(@ayu@ay)", + nm_g_variant_new_ay_in6addr(&address_bin), + (guint32) nm_ip_address_get_prefix(addr), + nm_g_variant_new_ay_in6addr(gateway_bin)); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * nm_utils_ip6_addresses_from_variant: + * @value: a #GVariant of type 'a(ayuay)' + * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway + * + * Utility function to convert a #GVariant of type 'a(ayuay)' representing a + * list of NetworkManager IPv6 addresses (which are tuples of address, prefix, + * and gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field + * of the first address (if set) will be returned in @out_gateway; the "gateway" + * fields of the other addresses are ignored. + * + * Returns: (transfer full) (element-type NMIPAddress): a newly allocated + * #GPtrArray of #NMIPAddress objects + **/ +GPtrArray * +nm_utils_ip6_addresses_from_variant(GVariant *value, char **out_gateway) +{ + GVariantIter iter; + GVariant * addr_var, *gateway_var; + guint32 prefix; + GPtrArray * addresses; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("a(ayuay)")), NULL); + + if (out_gateway) + *out_gateway = NULL; + + g_variant_iter_init(&iter, value); + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + + while (g_variant_iter_next(&iter, "(@ayu@ay)", &addr_var, &prefix, &gateway_var)) { + NMIPAddress * addr; + const struct in6_addr *addr_bytes, *gateway_bytes; + gsize addr_len, gateway_len; + GError * error = NULL; + + if (!g_variant_is_of_type(addr_var, G_VARIANT_TYPE_BYTESTRING) + || !g_variant_is_of_type(gateway_var, G_VARIANT_TYPE_BYTESTRING)) { + g_warning("%s: ignoring invalid IP6 address structure", __func__); + goto next; + } + + addr_bytes = g_variant_get_fixed_array(addr_var, &addr_len, 1); + if (addr_len != 16) { + g_warning("%s: ignoring invalid IP6 address of length %d", __func__, (int) addr_len); + goto next; + } + + addr = nm_ip_address_new_binary(AF_INET6, addr_bytes, prefix, &error); + if (addr) { + g_ptr_array_add(addresses, addr); + + if (out_gateway && !*out_gateway) { + gateway_bytes = g_variant_get_fixed_array(gateway_var, &gateway_len, 1); + if (gateway_len != 16) { + g_warning("%s: ignoring invalid IP6 address of length %d", + __func__, + (int) gateway_len); + goto next; + } + if (!IN6_IS_ADDR_UNSPECIFIED(gateway_bytes)) + *out_gateway = nm_utils_inet6_ntop_dup(gateway_bytes); + } + } else { + g_warning("Ignoring invalid IP6 address: %s", error->message); + g_clear_error(&error); + } + +next: + g_variant_unref(addr_var); + g_variant_unref(gateway_var); + } + + return addresses; +} + +/** + * nm_utils_ip6_routes_to_variant: + * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects + * + * Utility function to convert a #GPtrArray of #NMIPRoute objects representing + * IPv6 routes into a #GVariant of type 'a(ayuayu)' representing an array of + * NetworkManager IPv6 routes (which are tuples of route, prefix, next hop, and + * metric). + * + * Returns: (transfer none): a new floating #GVariant representing @routes. + **/ +GVariant * +nm_utils_ip6_routes_to_variant(GPtrArray *routes) +{ + GVariantBuilder builder; + guint i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ayuayu)")); + + if (routes) { + for (i = 0; i < routes->len; i++) { + NMIPRoute * route = routes->pdata[i]; + struct in6_addr dest_bytes; + struct in6_addr next_hop_bytes; + guint32 metric; + + if (nm_ip_route_get_family(route) != AF_INET6) + continue; + + nm_ip_route_get_dest_binary(route, &dest_bytes); + nm_ip_route_get_next_hop_binary(route, &next_hop_bytes); + + /* The old routes format uses "0" for default, not "-1" */ + metric = NM_MAX(0, nm_ip_route_get_metric(route)); + + g_variant_builder_add(&builder, + "(@ayu@ayu)", + nm_g_variant_new_ay_in6addr(&dest_bytes), + (guint32) nm_ip_route_get_prefix(route), + nm_g_variant_new_ay_in6addr(&next_hop_bytes), + metric); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * nm_utils_ip6_routes_from_variant: + * @value: #GVariant of type 'a(ayuayu)' + * + * Utility function to convert a #GVariant of type 'a(ayuayu)' representing an + * array of NetworkManager IPv6 routes (which are tuples of route, prefix, next + * hop, and metric) into a #GPtrArray of #NMIPRoute objects. + * + * Returns: (transfer full) (element-type NMIPRoute): a newly allocated + * #GPtrArray of #NMIPRoute objects + **/ +GPtrArray * +nm_utils_ip6_routes_from_variant(GVariant *value) +{ + GPtrArray * routes; + GVariantIter iter; + GVariant * dest_var, *next_hop_var; + const struct in6_addr *dest, *next_hop; + gsize dest_len, next_hop_len; + guint32 prefix, metric; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("a(ayuayu)")), NULL); + + routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); + + g_variant_iter_init(&iter, value); + while (g_variant_iter_next(&iter, "(@ayu@ayu)", &dest_var, &prefix, &next_hop_var, &metric)) { + NMIPRoute *route; + GError * error = NULL; + + if (!g_variant_is_of_type(dest_var, G_VARIANT_TYPE_BYTESTRING) + || !g_variant_is_of_type(next_hop_var, G_VARIANT_TYPE_BYTESTRING)) { + g_warning("%s: ignoring invalid IP6 address structure", __func__); + goto next; + } + + dest = g_variant_get_fixed_array(dest_var, &dest_len, 1); + if (dest_len != 16) { + g_warning("%s: ignoring invalid IP6 address of length %d", __func__, (int) dest_len); + goto next; + } + + next_hop = g_variant_get_fixed_array(next_hop_var, &next_hop_len, 1); + if (next_hop_len != 16) { + g_warning("%s: ignoring invalid IP6 address of length %d", + __func__, + (int) next_hop_len); + goto next; + } + + route = nm_ip_route_new_binary(AF_INET6, + dest, + prefix, + next_hop, + metric ? (gint64) metric : -1, + &error); + if (route) + g_ptr_array_add(routes, route); + else { + g_warning("Ignoring invalid IP6 route: %s", error->message); + g_clear_error(&error); + } + +next: + g_variant_unref(dest_var); + g_variant_unref(next_hop_var); + } + + return routes; +} + +/** + * nm_utils_ip_addresses_to_variant: + * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects + * + * Utility function to convert a #GPtrArray of #NMIPAddress objects representing + * IPv4 or IPv6 addresses into a #GVariant of type 'aa{sv}' representing an + * array of new-style NetworkManager IP addresses. All addresses will include + * "address" (an IP address string), and "prefix" (a uint). Some addresses may + * include additional attributes. + * + * Returns: (transfer none): a new floating #GVariant representing @addresses. + **/ +GVariant * +nm_utils_ip_addresses_to_variant(GPtrArray *addresses) +{ + GVariantBuilder builder; + guint i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + if (addresses) { + for (i = 0; i < addresses->len; i++) { + NMIPAddress * addr = addresses->pdata[i]; + GVariantBuilder addr_builder; + gs_free const char **names = NULL; + guint j, len; + + g_variant_builder_init(&addr_builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&addr_builder, + "{sv}", + "address", + g_variant_new_string(nm_ip_address_get_address(addr))); + g_variant_builder_add(&addr_builder, + "{sv}", + "prefix", + g_variant_new_uint32(nm_ip_address_get_prefix(addr))); + + names = _nm_ip_address_get_attribute_names(addr, TRUE, &len); + for (j = 0; j < len; j++) { + g_variant_builder_add(&addr_builder, + "{sv}", + names[j], + nm_ip_address_get_attribute(addr, names[j])); + } + + g_variant_builder_add(&builder, "a{sv}", &addr_builder); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * nm_utils_ip_addresses_from_variant: + * @value: a #GVariant of type 'aa{sv}' + * @family: an IP address family + * + * Utility function to convert a #GVariant representing a list of new-style + * NetworkManager IPv4 or IPv6 addresses (as described in the documentation for + * nm_utils_ip_addresses_to_variant()) into a #GPtrArray of #NMIPAddress + * objects. + * + * Returns: (transfer full) (element-type NMIPAddress): a newly allocated + * #GPtrArray of #NMIPAddress objects + **/ +GPtrArray * +nm_utils_ip_addresses_from_variant(GVariant *value, int family) +{ + GPtrArray * addresses; + GVariantIter iter, attrs_iter; + GVariant * addr_var; + const char * ip; + guint32 prefix; + const char * attr_name; + GVariant * attr_val; + NMIPAddress *addr; + GError * error = NULL; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); + + g_variant_iter_init(&iter, value); + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + + while (g_variant_iter_next(&iter, "@a{sv}", &addr_var)) { + if (!g_variant_lookup(addr_var, "address", "&s", &ip) + || !g_variant_lookup(addr_var, "prefix", "u", &prefix)) { + g_warning("Ignoring invalid address"); + g_variant_unref(addr_var); + continue; + } + + addr = nm_ip_address_new(family, ip, prefix, &error); + if (!addr) { + g_warning("Ignoring invalid address: %s", error->message); + g_clear_error(&error); + g_variant_unref(addr_var); + continue; + } + + g_variant_iter_init(&attrs_iter, addr_var); + while (g_variant_iter_next(&attrs_iter, "{&sv}", &attr_name, &attr_val)) { + if (!NM_IN_STRSET(attr_name, "address", "prefix")) + nm_ip_address_set_attribute(addr, attr_name, attr_val); + g_variant_unref(attr_val); + } + + g_variant_unref(addr_var); + g_ptr_array_add(addresses, addr); + } + + return addresses; +} + +/** + * nm_utils_ip_routes_to_variant: + * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects + * + * Utility function to convert a #GPtrArray of #NMIPRoute objects representing + * IPv4 or IPv6 routes into a #GVariant of type 'aa{sv}' representing an array + * of new-style NetworkManager IP routes (which are tuples of destination, + * prefix, next hop, metric, and additional attributes). + * + * Returns: (transfer none): a new floating #GVariant representing @routes. + **/ +GVariant * +nm_utils_ip_routes_to_variant(GPtrArray *routes) +{ + GVariantBuilder builder; + guint i; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + if (routes) { + for (i = 0; i < routes->len; i++) { + NMIPRoute * route = routes->pdata[i]; + GVariantBuilder route_builder; + gs_free const char **names = NULL; + guint j, len; + + g_variant_builder_init(&route_builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&route_builder, + "{sv}", + "dest", + g_variant_new_string(nm_ip_route_get_dest(route))); + g_variant_builder_add(&route_builder, + "{sv}", + "prefix", + g_variant_new_uint32(nm_ip_route_get_prefix(route))); + if (nm_ip_route_get_next_hop(route)) { + g_variant_builder_add(&route_builder, + "{sv}", + "next-hop", + g_variant_new_string(nm_ip_route_get_next_hop(route))); + } + if (nm_ip_route_get_metric(route) != -1) { + g_variant_builder_add( + &route_builder, + "{sv}", + "metric", + g_variant_new_uint32((guint32) nm_ip_route_get_metric(route))); + } + + names = _nm_ip_route_get_attribute_names(route, TRUE, &len); + for (j = 0; j < len; j++) { + g_variant_builder_add(&route_builder, + "{sv}", + names[j], + nm_ip_route_get_attribute(route, names[j])); + } + + g_variant_builder_add(&builder, "a{sv}", &route_builder); + } + } + + return g_variant_builder_end(&builder); +} + +/** + * nm_utils_ip_routes_from_variant: + * @value: a #GVariant of type 'aa{sv}' + * @family: an IP address family + * + * Utility function to convert a #GVariant representing a list of new-style + * NetworkManager IPv4 or IPv6 addresses (which are tuples of destination, + * prefix, next hop, metric, and additional attributes) into a #GPtrArray of + * #NMIPRoute objects. + * + * Returns: (transfer full) (element-type NMIPRoute): a newly allocated + * #GPtrArray of #NMIPRoute objects + **/ +GPtrArray * +nm_utils_ip_routes_from_variant(GVariant *value, int family) +{ + GPtrArray * routes; + GVariantIter iter, attrs_iter; + GVariant * route_var; + const char * dest, *next_hop; + guint32 prefix, metric32; + gint64 metric; + const char * attr_name; + GVariant * attr_val; + NMIPRoute * route; + GError * error = NULL; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL); + + g_variant_iter_init(&iter, value); + routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); + + while (g_variant_iter_next(&iter, "@a{sv}", &route_var)) { + if (!g_variant_lookup(route_var, "dest", "&s", &dest) + || !g_variant_lookup(route_var, "prefix", "u", &prefix)) { + g_warning("Ignoring invalid address"); + goto next; + } + if (!g_variant_lookup(route_var, "next-hop", "&s", &next_hop)) + next_hop = NULL; + if (g_variant_lookup(route_var, "metric", "u", &metric32)) + metric = metric32; + else + metric = -1; + + route = nm_ip_route_new(family, dest, prefix, next_hop, metric, &error); + if (!route) { + g_warning("Ignoring invalid route: %s", error->message); + g_clear_error(&error); + goto next; + } + + g_variant_iter_init(&attrs_iter, route_var); + while (g_variant_iter_next(&attrs_iter, "{&sv}", &attr_name, &attr_val)) { + if (!NM_IN_STRSET(attr_name, "dest", "prefix", "next-hop", "metric")) + nm_ip_route_set_attribute(route, attr_name, attr_val); + g_variant_unref(attr_val); + } + + g_ptr_array_add(routes, route); +next: + g_variant_unref(route_var); + } + + return routes; +} + +/*****************************************************************************/ + +static void +_string_append_tc_handle(GString *string, guint32 handle) +{ + g_string_append_printf(string, "%x:", TC_H_MAJ(handle) >> 16); + if (TC_H_MIN(handle) != TC_H_UNSPEC) + g_string_append_printf(string, "%x", TC_H_MIN(handle)); +} + +/** + * _nm_utils_string_append_tc_parent: + * @string: the string to write the parent handle to + * @prefix: optional prefix for the numeric handle + * @parent: the parent handle + * + * This is used to either write out the parent handle to the tc qdisc string + * or to pretty-format (use symbolic name for root) the key in keyfile. + * The presence of prefix determines which one is the case. + * + * Private API due to general ugliness and overall uselessness for anything + * sensible. + */ +void +_nm_utils_string_append_tc_parent(GString *string, const char *prefix, guint32 parent) +{ + if (parent == TC_H_ROOT) { + g_string_append(string, "root"); + } else { + if (prefix) { + if (parent == TC_H_INGRESS) + return; + g_string_append_printf(string, "%s ", prefix); + } + _string_append_tc_handle(string, parent); + } + + if (prefix) + g_string_append_c(string, ' '); +} + +/** + * _nm_utils_parse_tc_handle: + * @str: the string representation of a qdisc handle + * @error: location of the error + * + * Parses tc style handle number into a numeric representation. + * Don't use this, use nm_utils_tc_qdisc_from_str() instead. + */ +guint32 +_nm_utils_parse_tc_handle(const char *str, GError **error) +{ + gint64 maj; + gint64 min = 0; + const char *sep; + + nm_assert(str); + + maj = nm_g_ascii_strtoll(str, (char **) &sep, 0x10); + if (sep == str) + goto fail; + + sep = nm_str_skip_leading_spaces(sep); + + if (sep[0] == ':') { + const char *str2 = &sep[1]; + + min = nm_g_ascii_strtoll(str2, (char **) &sep, 0x10); + sep = nm_str_skip_leading_spaces(sep); + if (sep[0] != '\0') + goto fail; + } else if (sep[0] != '\0') + goto fail; + + if (maj <= 0 || maj > 0xffff || min < 0 || min > 0xffff + || !NM_STRCHAR_ALL(str, ch, (g_ascii_isxdigit(ch) || ch == ':' || g_ascii_isspace(ch)))) { + goto fail; + } + + return TC_H_MAKE(((guint32) maj) << 16, (guint32) min); +fail: + nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("'%s' is not a valid handle."), str); + return TC_H_UNSPEC; +} + +static const NMVariantAttributeSpec *const tc_object_attribute_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("root", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("parent", G_VARIANT_TYPE_STRING, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("handle", G_VARIANT_TYPE_STRING, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("", + G_VARIANT_TYPE_STRING, + .no_value = TRUE, + .consumes_rest = TRUE, ), + NULL, +}; + +static const NMVariantAttributeSpec *const tc_qdisc_sfq_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("quantum", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("perturb", G_VARIANT_TYPE_INT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("limit", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("divisor", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("flows", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("depth", G_VARIANT_TYPE_UINT32, ), + NULL, +}; + +static const NMVariantAttributeSpec *const tc_qdisc_tbf_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("rate", G_VARIANT_TYPE_UINT64, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("burst", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("limit", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("latency", G_VARIANT_TYPE_UINT32, ), + NULL, +}; + +static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("limit", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("flows", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("target", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("interval", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("quantum", G_VARIANT_TYPE_UINT32, ), + + /* 0x83126E97u is not a valid value (it means "disabled"). We should reject that + * value. Or alternatively, reject all values >= MAX_INT(32). */ + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("ce_threshold", G_VARIANT_TYPE_UINT32, ), + + /* kernel clamps the value at 2^31. Possibly such values should be rejected from configuration + * as they cannot be configured. Leaving the attribute unspecified causes kernel to choose + * a default (currently 32MB). */ + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("memory_limit", G_VARIANT_TYPE_UINT32, ), + + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("ecn", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NULL, +}; + +typedef struct { + const char * kind; + const NMVariantAttributeSpec *const *attrs; +} NMQdiscAttributeSpec; + +static const NMQdiscAttributeSpec *const tc_qdisc_attribute_spec[] = { + &(const NMQdiscAttributeSpec){"fq_codel", tc_qdisc_fq_codel_spec}, + &(const NMQdiscAttributeSpec){"sfq", tc_qdisc_sfq_spec}, + &(const NMQdiscAttributeSpec){"tbf", tc_qdisc_tbf_spec}, + NULL, +}; + +/*****************************************************************************/ + +/** + * _nm_utils_string_append_tc_qdisc_rest: + * @string: the string to write the formatted qdisc to + * @qdisc: the %NMTCQdisc + * + * This formats the rest of the qdisc string but the parent. Useful to format + * the keyfile value and nowhere else. + * Use nm_utils_tc_qdisc_to_str() that also includes the parent instead. + */ +void +_nm_utils_string_append_tc_qdisc_rest(GString *string, NMTCQdisc *qdisc) +{ + guint32 handle = nm_tc_qdisc_get_handle(qdisc); + const char * kind = nm_tc_qdisc_get_kind(qdisc); + gs_free char *str = NULL; + + if (handle != TC_H_UNSPEC && !NM_IN_STRSET(kind, "ingress", "clsact")) { + g_string_append(string, "handle "); + _string_append_tc_handle(string, handle); + g_string_append_c(string, ' '); + } + + g_string_append(string, kind); + + str = nm_utils_format_variant_attributes(_nm_tc_qdisc_get_attributes(qdisc), ' ', ' '); + if (str) { + g_string_append_c(string, ' '); + g_string_append(string, str); + } +} + +/** + * nm_utils_tc_qdisc_to_str: + * @qdisc: the %NMTCQdisc + * @error: location of the error + * + * Turns the %NMTCQdisc into a tc style string representation of the queueing + * discipline. + * + * Returns: formatted string or %NULL + * + * Since: 1.12 + */ +char * +nm_utils_tc_qdisc_to_str(NMTCQdisc *qdisc, GError **error) +{ + GString *string; + + string = g_string_sized_new(60); + + _nm_utils_string_append_tc_parent(string, "parent", nm_tc_qdisc_get_parent(qdisc)); + _nm_utils_string_append_tc_qdisc_rest(string, qdisc); + + return g_string_free(string, FALSE); +} + +static gboolean +_tc_read_common_opts(const char *str, + guint32 * handle, + guint32 * parent, + char ** kind, + char ** rest, + GError ** error) +{ + gs_unref_hashtable GHashTable *ht = NULL; + GVariant * variant; + + ht = nm_utils_parse_variant_attributes(str, ' ', ' ', FALSE, tc_object_attribute_spec, error); + if (!ht) + return FALSE; + + if (g_hash_table_contains(ht, "root")) + *parent = TC_H_ROOT; + + variant = g_hash_table_lookup(ht, "parent"); + if (variant) { + if (*parent != TC_H_UNSPEC) { + g_set_error(error, + 1, + 0, + _("'%s' unexpected: parent already specified."), + g_variant_get_string(variant, NULL)); + return FALSE; + } + *parent = _nm_utils_parse_tc_handle(g_variant_get_string(variant, NULL), error); + if (*parent == TC_H_UNSPEC) + return FALSE; + } + + variant = g_hash_table_lookup(ht, "handle"); + if (variant) { + *handle = _nm_utils_parse_tc_handle(g_variant_get_string(variant, NULL), error); + if (*handle == TC_H_UNSPEC) + return FALSE; + if (TC_H_MIN(*handle)) { + g_set_error(error, + 1, + 0, + _("invalid handle: '%s'"), + g_variant_get_string(variant, NULL)); + return FALSE; + } + } + + variant = g_hash_table_lookup(ht, "kind"); + if (variant) { + *kind = g_variant_dup_string(variant, NULL); + if (NM_IN_STRSET(*kind, "ingress", "clsact")) { + if (*parent == TC_H_UNSPEC) + *parent = TC_H_INGRESS; + if (*handle == TC_H_UNSPEC) + *handle = TC_H_MAKE(TC_H_INGRESS, 0); + } + } + + if (*parent == TC_H_UNSPEC) { + if (*kind) { + g_free(*kind); + *kind = NULL; + } + g_set_error_literal(error, 1, 0, _("parent not specified.")); + return FALSE; + } + + variant = g_hash_table_lookup(ht, ""); + if (variant) + *rest = g_variant_dup_string(variant, NULL); + + return TRUE; +} + +/** + * nm_utils_tc_qdisc_from_str: + * @str: the string representation of a qdisc + * @error: location of the error + * + * Parses the tc style string qdisc representation of the queueing + * discipline to a %NMTCQdisc instance. Supports a subset of the tc language. + * + * Returns: the %NMTCQdisc or %NULL + * + * Since: 1.12 + */ +NMTCQdisc * +nm_utils_tc_qdisc_from_str(const char *str, GError **error) +{ + guint32 handle = TC_H_UNSPEC; + guint32 parent = TC_H_UNSPEC; + gs_free char * kind = NULL; + gs_free char * rest = NULL; + NMTCQdisc * qdisc = NULL; + gs_unref_hashtable GHashTable *options = NULL; + GHashTableIter iter; + gpointer key, value; + guint i; + + nm_assert(str); + nm_assert(!error || !*error); + + if (!_tc_read_common_opts(str, &handle, &parent, &kind, &rest, error)) + return NULL; + + for (i = 0; rest && tc_qdisc_attribute_spec[i]; i++) { + if (nm_streq(tc_qdisc_attribute_spec[i]->kind, kind)) { + options = nm_utils_parse_variant_attributes(rest, + ' ', + ' ', + FALSE, + tc_qdisc_attribute_spec[i]->attrs, + error); + if (!options) + return NULL; + break; + } + } + nm_clear_g_free(&rest); + + if (options) { + value = g_hash_table_lookup(options, ""); + if (value) + rest = g_variant_dup_string(value, NULL); + } + + if (rest) { + g_set_error(error, 1, 0, _("unsupported qdisc option: '%s'."), rest); + return NULL; + } + + qdisc = nm_tc_qdisc_new(kind, parent, error); + if (!qdisc) + return NULL; + + nm_tc_qdisc_set_handle(qdisc, handle); + + if (options) { + g_hash_table_iter_init(&iter, options); + while (g_hash_table_iter_next(&iter, &key, &value)) + nm_tc_qdisc_set_attribute(qdisc, key, g_variant_ref_sink(value)); + } + + return qdisc; +} + +/*****************************************************************************/ + +static const NMVariantAttributeSpec *const tc_action_simple_attribute_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("sdata", G_VARIANT_TYPE_BYTESTRING, ), + NULL, +}; + +static const NMVariantAttributeSpec *const tc_action_mirred_attribute_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("egress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("ingress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("mirror", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("redirect", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("dev", G_VARIANT_TYPE_STRING, ), + NULL, +}; + +static const NMVariantAttributeSpec *const tc_action_attribute_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("", + G_VARIANT_TYPE_STRING, + .no_value = TRUE, + .consumes_rest = TRUE, ), + NULL, +}; + +static gboolean +_string_append_tc_action(GString *string, NMTCAction *action, GError **error) +{ + const char * kind = nm_tc_action_get_kind(action); + gs_free char * str = NULL; + const NMVariantAttributeSpec *const *attrs; + + if (nm_streq(kind, "simple")) + attrs = tc_action_simple_attribute_spec; + else if (nm_streq(kind, "mirred")) + attrs = tc_action_mirred_attribute_spec; + else + attrs = NULL; + + g_string_append(string, kind); + + str = + _nm_utils_format_variant_attributes(_nm_tc_action_get_attributes(action), attrs, ' ', ' '); + if (str) { + g_string_append_c(string, ' '); + g_string_append(string, str); + } + + return TRUE; +} + +/** + * nm_utils_tc_action_to_str: + * @action: the %NMTCAction + * @error: location of the error + * + * Turns the %NMTCAction into a tc style string representation of the queueing + * discipline. + * + * Returns: formatted string or %NULL + * + * Since: 1.12 + */ +char * +nm_utils_tc_action_to_str(NMTCAction *action, GError **error) +{ + GString *string; + + string = g_string_sized_new(60); + if (!_string_append_tc_action(string, action, error)) { + g_string_free(string, TRUE); + return NULL; + } + + return g_string_free(string, FALSE); +} + +/** + * nm_utils_tc_action_from_str: + * @str: the string representation of a action + * @error: location of the error + * + * Parses the tc style string action representation of the queueing + * discipline to a %NMTCAction instance. Supports a subset of the tc language. + * + * Returns: the %NMTCAction or %NULL + * + * Since: 1.12 + */ +NMTCAction * +nm_utils_tc_action_from_str(const char *str, GError **error) +{ + const char * kind = NULL; + const char * rest = NULL; + NMTCAction * action = NULL; + gs_unref_hashtable GHashTable *ht = NULL; + gs_unref_hashtable GHashTable * options = NULL; + GVariant * variant; + const NMVariantAttributeSpec *const *attrs; + + nm_assert(str); + nm_assert(!error || !*error); + + ht = nm_utils_parse_variant_attributes(str, ' ', ' ', FALSE, tc_action_attribute_spec, error); + if (!ht) + return FALSE; + + variant = g_hash_table_lookup(ht, "kind"); + if (variant) { + kind = g_variant_get_string(variant, NULL); + } else { + g_set_error_literal(error, 1, 0, _("action name missing.")); + return NULL; + } + + kind = g_variant_get_string(variant, NULL); + if (nm_streq(kind, "simple")) + attrs = tc_action_simple_attribute_spec; + else if (nm_streq(kind, "mirred")) + attrs = tc_action_mirred_attribute_spec; + else + attrs = NULL; + + variant = g_hash_table_lookup(ht, ""); + if (variant) + rest = g_variant_get_string(variant, NULL); + + action = nm_tc_action_new(kind, error); + if (!action) + return NULL; + + if (rest) { + GHashTableIter iter; + gpointer key, value; + + if (!attrs) { + nm_tc_action_unref(action); + g_set_error(error, 1, 0, _("unsupported action option: '%s'."), rest); + return NULL; + } + + options = nm_utils_parse_variant_attributes(rest, ' ', ' ', FALSE, attrs, error); + if (!options) { + nm_tc_action_unref(action); + return NULL; + } + + g_hash_table_iter_init(&iter, options); + while (g_hash_table_iter_next(&iter, &key, &value)) + nm_tc_action_set_attribute(action, key, g_variant_ref_sink(value)); + } + + return action; +} + +/*****************************************************************************/ + +/** + * _nm_utils_string_append_tc_tfilter_rest: + * @string: the string to write the formatted tfilter to + * @tfilter: the %NMTCTfilter + * + * This formats the rest of the tfilter string but the parent. Useful to format + * the keyfile value and nowhere else. + * Use nm_utils_tc_tfilter_to_str() that also includes the parent instead. + */ +gboolean +_nm_utils_string_append_tc_tfilter_rest(GString *string, NMTCTfilter *tfilter, GError **error) +{ + guint32 handle = nm_tc_tfilter_get_handle(tfilter); + const char *kind = nm_tc_tfilter_get_kind(tfilter); + NMTCAction *action; + + if (handle != TC_H_UNSPEC) { + g_string_append(string, "handle "); + _string_append_tc_handle(string, handle); + g_string_append_c(string, ' '); + } + + g_string_append(string, kind); + + action = nm_tc_tfilter_get_action(tfilter); + if (action) { + g_string_append(string, " action "); + if (!_string_append_tc_action(string, action, error)) + return FALSE; + } + + return TRUE; +} + +/** + * nm_utils_tc_tfilter_to_str: + * @tfilter: the %NMTCTfilter + * @error: location of the error + * + * Turns the %NMTCTfilter into a tc style string representation of the queueing + * discipline. + * + * Returns: formatted string or %NULL + * + * Since: 1.12 + */ +char * +nm_utils_tc_tfilter_to_str(NMTCTfilter *tfilter, GError **error) +{ + GString *string; + + string = g_string_sized_new(60); + + _nm_utils_string_append_tc_parent(string, "parent", nm_tc_tfilter_get_parent(tfilter)); + if (!_nm_utils_string_append_tc_tfilter_rest(string, tfilter, error)) { + g_string_free(string, TRUE); + return NULL; + } + + return g_string_free(string, FALSE); +} + +static const NMVariantAttributeSpec *const tc_tfilter_attribute_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("action", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("", + G_VARIANT_TYPE_STRING, + .no_value = TRUE, + .consumes_rest = TRUE, ), + NULL, +}; + +/** + * nm_utils_tc_tfilter_from_str: + * @str: the string representation of a tfilter + * @error: location of the error + * + * Parses the tc style string tfilter representation of the queueing + * discipline to a %NMTCTfilter instance. Supports a subset of the tc language. + * + * Returns: the %NMTCTfilter or %NULL + * + * Since: 1.12 + */ +NMTCTfilter * +nm_utils_tc_tfilter_from_str(const char *str, GError **error) +{ + guint32 handle = TC_H_UNSPEC; + guint32 parent = TC_H_UNSPEC; + gs_free char * kind = NULL; + gs_free char * rest = NULL; + NMTCAction * action = NULL; + const char * extra_opts = NULL; + NMTCTfilter * tfilter = NULL; + gs_unref_hashtable GHashTable *ht = NULL; + GVariant * variant; + + nm_assert(str); + nm_assert(!error || !*error); + + if (!_tc_read_common_opts(str, &handle, &parent, &kind, &rest, error)) + return NULL; + + if (rest) { + ht = nm_utils_parse_variant_attributes(rest, + ' ', + ' ', + FALSE, + tc_tfilter_attribute_spec, + error); + if (!ht) + return NULL; + + variant = g_hash_table_lookup(ht, ""); + if (variant) + extra_opts = g_variant_get_string(variant, NULL); + + if (g_hash_table_contains(ht, "action")) { + action = nm_utils_tc_action_from_str(extra_opts, error); + if (!action) { + g_prefix_error(error, _("invalid action: ")); + return NULL; + } + } else { + g_set_error(error, 1, 0, _("unsupported tfilter option: '%s'."), rest); + return NULL; + } + } + + tfilter = nm_tc_tfilter_new(kind, parent, error); + if (!tfilter) + return NULL; + + nm_tc_tfilter_set_handle(tfilter, handle); + if (action) { + nm_tc_tfilter_set_action(tfilter, action); + nm_tc_action_unref(action); + } + + return tfilter; +} + +/*****************************************************************************/ + +extern const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[]; + +/** + * nm_utils_sriov_vf_to_str: + * @vf: the %NMSriovVF + * @omit_index: if %TRUE, the VF index will be omitted from output string + * @error: (out) (allow-none): location to store the error on failure + * + * Converts a SR-IOV virtual function object to its string representation. + * + * Returns: a newly allocated string or %NULL on error + * + * Since: 1.14 + */ +char * +nm_utils_sriov_vf_to_str(const NMSriovVF *vf, gboolean omit_index, GError **error) +{ + gs_free NMUtilsNamedValue *values = NULL; + gs_free const char ** names = NULL; + const guint * vlan_ids; + guint num_vlans, num_attrs; + guint i; + GString * str; + + str = g_string_new(""); + if (!omit_index) + g_string_append_printf(str, "%u", nm_sriov_vf_get_index(vf)); + + names = nm_sriov_vf_get_attribute_names(vf); + num_attrs = names ? g_strv_length((char **) names) : 0; + values = g_new0(NMUtilsNamedValue, num_attrs); + + for (i = 0; i < num_attrs; i++) { + values[i].name = names[i]; + values[i].value_ptr = nm_sriov_vf_get_attribute(vf, names[i]); + } + + if (num_attrs > 0) { + if (!omit_index) + g_string_append_c(str, ' '); + _nm_utils_format_variant_attributes_full(str, values, num_attrs, NULL, ' ', '='); + } + + vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num_vlans); + if (num_vlans != 0) { + g_string_append(str, " vlans"); + for (i = 0; i < num_vlans; i++) { + guint32 qos; + NMSriovVFVlanProtocol protocol; + + qos = nm_sriov_vf_get_vlan_qos(vf, vlan_ids[i]); + protocol = nm_sriov_vf_get_vlan_protocol(vf, vlan_ids[i]); + + g_string_append_c(str, i == 0 ? '=' : ';'); + + g_string_append_printf(str, "%u", vlan_ids[i]); + + if (qos != 0 || protocol != NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q) { + g_string_append_printf(str, + ".%u%s", + (unsigned) qos, + protocol == NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q ? "" : ".ad"); + } + } + } + + return g_string_free(str, FALSE); +} + +gboolean +_nm_sriov_vf_parse_vlans(NMSriovVF *vf, const char *str, GError **error) +{ + gs_free const char **vlans = NULL; + guint i; + + vlans = nm_utils_strsplit_set(str, ";"); + if (!vlans) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "empty VF VLAN"); + return FALSE; + } + + for (i = 0; vlans[i]; i++) { + gs_strfreev char **params = NULL; + guint id = G_MAXUINT; + gint64 qos = -1; + + /* we accept leading/trailing whitespace around vlans[1]. Hence + * the nm_str_skip_leading_spaces() and g_strchomp() below. + * + * However, we don't accept any whitespace inside the specifier. + * Hence the NM_STRCHAR_ALL() checks. */ + + params = g_strsplit(nm_str_skip_leading_spaces(vlans[i]), ".", 3); + if (!params || !params[0] || *params[0] == '\0') { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "empty VF VLAN"); + return FALSE; + } + + if (!params[1]) + g_strchomp(params[0]); + if (NM_STRCHAR_ALL(params[0], ch, ch == 'x' || g_ascii_isdigit(ch))) + id = _nm_utils_ascii_str_to_int64(params[0], 0, 0, 4095, G_MAXUINT); + if (id == G_MAXUINT) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN id '%s'", + params[0]); + return FALSE; + } + if (!nm_sriov_vf_add_vlan(vf, id)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "duplicate VLAN id %u", + id); + return FALSE; + } + + if (!params[1]) + continue; + + if (!params[2]) + g_strchomp(params[1]); + if (NM_STRCHAR_ALL(params[1], ch, ch == 'x' || g_ascii_isdigit(ch))) + qos = _nm_utils_ascii_str_to_int64(params[1], 0, 0, G_MAXUINT32, -1); + if (qos == -1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN QoS '%s'", + params[1]); + return FALSE; + } + nm_sriov_vf_set_vlan_qos(vf, id, qos); + + if (!params[2]) + continue; + + g_strchomp(params[2]); + + if (nm_streq(params[2], "ad")) + nm_sriov_vf_set_vlan_protocol(vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + else if (nm_streq(params[2], "q")) + nm_sriov_vf_set_vlan_protocol(vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + else { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN protocol '%s'", + params[2]); + return FALSE; + } + } + + return TRUE; +} + +/** + * nm_utils_sriov_vf_from_str: + * @str: the input string + * @error: (out) (allow-none): location to store the error on failure + * + * Converts a string to a SR-IOV virtual function object. + * + * Returns: (transfer full): the virtual function object + * + * Since: 1.14 + */ +NMSriovVF * +nm_utils_sriov_vf_from_str(const char *str, GError **error) +{ + gs_free char *index_free = NULL; + const char * detail; + + g_return_val_if_fail(str, NULL); + g_return_val_if_fail(!error || !*error, NULL); + + while (*str == ' ') + str++; + + detail = strchr(str, ' '); + if (detail) { + str = nm_strndup_a(200, str, detail - str, &index_free); + detail++; + } + + return _nm_utils_sriov_vf_from_strparts(str, detail, FALSE, error); +} + +NMSriovVF * +_nm_utils_sriov_vf_from_strparts(const char *index, + const char *detail, + gboolean ignore_unknown, + GError ** error) +{ + NMSriovVF * vf; + guint32 n_index; + GHashTableIter iter; + char * key; + GVariant * variant; + gs_unref_hashtable GHashTable *ht = NULL; + + n_index = _nm_utils_ascii_str_to_int64(index, 10, 0, G_MAXUINT32, 0); + if (errno) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid index"); + return NULL; + } + + vf = nm_sriov_vf_new(n_index); + if (detail) { + ht = nm_utils_parse_variant_attributes(detail, + ' ', + '=', + ignore_unknown, + _nm_sriov_vf_attribute_spec, + error); + if (!ht) { + nm_sriov_vf_unref(vf); + return NULL; + } + + if ((variant = g_hash_table_lookup(ht, "vlans"))) { + if (!_nm_sriov_vf_parse_vlans(vf, g_variant_get_string(variant, NULL), error)) { + nm_sriov_vf_unref(vf); + return NULL; + } + g_hash_table_remove(ht, "vlans"); + } + + g_hash_table_iter_init(&iter, ht); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &variant)) + nm_sriov_vf_set_attribute(vf, key, g_variant_ref_sink(variant)); + } + + return vf; +} + +/*****************************************************************************/ + +NMUuid * +_nm_utils_uuid_parse(const char *str, NMUuid *out_uuid) +{ + nm_assert(str); + nm_assert(out_uuid); + + if (uuid_parse(str, out_uuid->uuid) != 0) + return NULL; + return out_uuid; +} + +char * +_nm_utils_uuid_unparse(const NMUuid *uuid, char *out_str /*[37]*/) +{ + nm_assert(uuid); + + if (!out_str) { + /* for convenience, allow %NULL to indicate that a new + * string should be allocated. */ + out_str = g_malloc(37); + } + uuid_unparse_lower(uuid->uuid, out_str); + return out_str; +} + +NMUuid * +_nm_utils_uuid_generate_random(NMUuid *out_uuid) +{ + nm_assert(out_uuid); + + uuid_generate_random(out_uuid->uuid); + return out_uuid; +} + +gboolean +nm_utils_uuid_is_null(const NMUuid *uuid) +{ + int i; + + if (!uuid) + return TRUE; + + for (i = 0; i < (int) G_N_ELEMENTS(uuid->uuid); i++) { + if (uuid->uuid[i]) + return FALSE; + } + return TRUE; +} + +/** + * nm_utils_uuid_generate_buf_: + * @buf: input buffer, must contain at least 37 bytes + * + * Returns: generates a new random UUID, writes it to @buf and returns @buf. + **/ +char * +nm_utils_uuid_generate_buf_(char *buf) +{ + NMUuid uuid; + + nm_assert(buf); + + _nm_utils_uuid_generate_random(&uuid); + return _nm_utils_uuid_unparse(&uuid, buf); +} + +/** + * nm_utils_uuid_generate: + * + * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection + * object's #NMSettingConnection:id: property. Should be freed with g_free() + **/ +char * +nm_utils_uuid_generate(void) +{ + return nm_utils_uuid_generate_buf_(g_malloc(37)); +} + +/** + * nm_utils_uuid_generate_from_string_bin: + * @uuid: the UUID to update inplace. This function cannot + * fail to succeed. + * @s: a string to use as the seed for the UUID + * @slen: if negative, treat @s as zero terminated C string. + * Otherwise, assume the length as given (and allow @s to be + * non-null terminated or contain '\0'). + * @uuid_type: a type identifier which UUID format to generate. + * @type_args: additional arguments, depending on the uuid_type + * + * For a given @s, this function will always return the same UUID. + * + * Returns: the input @uuid. This function cannot fail. + **/ +NMUuid * +nm_utils_uuid_generate_from_string_bin(NMUuid * uuid, + const char *s, + gssize slen, + int uuid_type, + gpointer type_args) +{ + g_return_val_if_fail(uuid, FALSE); + g_return_val_if_fail(slen == 0 || s, FALSE); + + if (slen < 0) + slen = s ? strlen(s) : 0; + + switch (uuid_type) { + case NM_UTILS_UUID_TYPE_LEGACY: + g_return_val_if_fail(!type_args, NULL); + nm_crypto_md5_hash(NULL, 0, (guint8 *) s, slen, (guint8 *) uuid, sizeof(*uuid)); + break; + case NM_UTILS_UUID_TYPE_VERSION3: + case NM_UTILS_UUID_TYPE_VERSION5: + { + NMUuid ns_uuid = {}; + + if (type_args) { + /* type_args can be a name space UUID. Interpret it as (char *) */ + if (!_nm_utils_uuid_parse(type_args, &ns_uuid)) + g_return_val_if_reached(NULL); + } + + if (uuid_type == NM_UTILS_UUID_TYPE_VERSION3) { + nm_crypto_md5_hash((guint8 *) s, + slen, + (guint8 *) &ns_uuid, + sizeof(ns_uuid), + (guint8 *) uuid, + sizeof(*uuid)); + } else { + nm_auto_free_checksum GChecksum *sum = NULL; + union { + guint8 sha1[NM_UTILS_CHECKSUM_LENGTH_SHA1]; + NMUuid uuid; + } digest; + + sum = g_checksum_new(G_CHECKSUM_SHA1); + g_checksum_update(sum, (guchar *) &ns_uuid, sizeof(ns_uuid)); + g_checksum_update(sum, (guchar *) s, slen); + nm_utils_checksum_get_digest(sum, digest.sha1); + + G_STATIC_ASSERT_EXPR(sizeof(digest.sha1) > sizeof(digest.uuid)); + *uuid = digest.uuid; + } + + uuid->uuid[6] = (uuid->uuid[6] & 0x0F) | (uuid_type << 4); + uuid->uuid[8] = (uuid->uuid[8] & 0x3F) | 0x80; + break; + } + default: + g_return_val_if_reached(NULL); + } + + return uuid; +} + +/** + * nm_utils_uuid_generate_from_string: + * @s: a string to use as the seed for the UUID + * @slen: if negative, treat @s as zero terminated C string. + * Otherwise, assume the length as given (and allow @s to be + * non-null terminated or contain '\0'). + * @uuid_type: a type identifier which UUID format to generate. + * @type_args: additional arguments, depending on the uuid_type + * + * For a given @s, this function will always return the same UUID. + * + * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection + * object's #NMSettingConnection:id: property + **/ +char * +nm_utils_uuid_generate_from_string(const char *s, gssize slen, int uuid_type, gpointer type_args) +{ + NMUuid uuid; + + nm_utils_uuid_generate_from_string_bin(&uuid, s, slen, uuid_type, type_args); + return _nm_utils_uuid_unparse(&uuid, NULL); +} + +/** + * _nm_utils_uuid_generate_from_strings: + * @string1: a variadic list of strings. Must be NULL terminated. + * + * Returns a variant3 UUID based on the concatenated C strings. + * It does not simply concatenate them, but also includes the + * terminating '\0' character. For example "a", "b", gives + * "a\0b\0". + * + * This has the advantage, that the following invocations + * all give different UUIDs: (NULL), (""), ("",""), ("","a"), ("a",""), + * ("aa"), ("aa", ""), ("", "aa"), ... + */ +char * +_nm_utils_uuid_generate_from_strings(const char *string1, ...) +{ + if (!string1) + return nm_utils_uuid_generate_from_string(NULL, + 0, + NM_UTILS_UUID_TYPE_VERSION3, + NM_UTILS_UUID_NS); + + { + nm_auto_str_buf NMStrBuf str = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); + va_list args; + const char * s; + + nm_str_buf_append_len(&str, string1, strlen(string1) + 1u); + + va_start(args, string1); + s = va_arg(args, const char *); + while (s) { + nm_str_buf_append_len(&str, s, strlen(s) + 1u); + s = va_arg(args, const char *); + } + va_end(args); + + return nm_utils_uuid_generate_from_string(nm_str_buf_get_str_unsafe(&str), + str.len, + NM_UTILS_UUID_TYPE_VERSION3, + NM_UTILS_UUID_NS); + } +} + +/*****************************************************************************/ + +static gboolean +file_has_extension(const char *filename, const char *extensions[]) +{ + const char *ext; + gsize i; + + ext = strrchr(filename, '.'); + if (!ext) + return FALSE; + + for (i = 0; extensions[i]; i++) { + if (!g_ascii_strcasecmp(ext, extensions[i])) + return TRUE; + } + + return FALSE; +} + +/** + * nm_utils_file_is_certificate: + * @filename: name of the file to test + * + * Tests if @filename has a valid extension for an X.509 certificate file + * (".cer", ".crt", ".der", or ".pem"), and contains a certificate in a format + * recognized by NetworkManager. + * + * Returns: %TRUE if the file is a certificate, %FALSE if it is not + **/ +gboolean +nm_utils_file_is_certificate(const char *filename) +{ + const char * extensions[] = {".der", ".pem", ".crt", ".cer", NULL}; + NMCryptoFileFormat file_format; + + g_return_val_if_fail(filename != NULL, FALSE); + + if (!file_has_extension(filename, extensions)) + return FALSE; + + if (!nm_crypto_load_and_verify_certificate(filename, &file_format, NULL, NULL)) + return FALSE; + return file_format = NM_CRYPTO_FILE_FORMAT_X509; +} + +/** + * nm_utils_file_is_private_key: + * @filename: name of the file to test + * @out_encrypted: (out): on return, whether the file is encrypted + * + * Tests if @filename has a valid extension for an X.509 private key file + * (".der", ".key", ".pem", or ".p12"), and contains a private key in a format + * recognized by NetworkManager. + * + * Returns: %TRUE if the file is a private key, %FALSE if it is not + **/ +gboolean +nm_utils_file_is_private_key(const char *filename, gboolean *out_encrypted) +{ + const char *extensions[] = {".der", ".pem", ".p12", ".key", NULL}; + + g_return_val_if_fail(filename != NULL, FALSE); + + NM_SET_OUT(out_encrypted, FALSE); + if (!file_has_extension(filename, extensions)) + return FALSE; + + return nm_crypto_verify_private_key(filename, NULL, out_encrypted, NULL) + != NM_CRYPTO_FILE_FORMAT_UNKNOWN; +} + +/** + * nm_utils_file_is_pkcs12: + * @filename: name of the file to test + * + * Tests if @filename is a PKCS#12 file. + * + * Returns: %TRUE if the file is PKCS#12, %FALSE if it is not + **/ +gboolean +nm_utils_file_is_pkcs12(const char *filename) +{ + g_return_val_if_fail(filename != NULL, FALSE); + + return nm_crypto_is_pkcs12_file(filename, NULL); +} + +/*****************************************************************************/ + +gboolean +_nm_utils_check_file(const char * filename, + gint64 check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + struct stat * out_st, + GError ** error) +{ + struct stat st_backup; + + if (!out_st) + out_st = &st_backup; + + if (stat(filename, out_st) != 0) { + int errsv = errno; + + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("failed stat file %s: %s"), + filename, + nm_strerror_native(errsv)); + return FALSE; + } + + /* ignore non-files. */ + if (!S_ISREG(out_st->st_mode)) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("not a file (%s)"), + filename); + return FALSE; + } + + /* with check_owner enabled, check that the file belongs to the + * owner or root. */ + if (check_owner >= 0 && (out_st->st_uid != 0 && (gint64) out_st->st_uid != check_owner)) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("invalid file owner %d for %s"), + out_st->st_uid, + filename); + return FALSE; + } + + /* with check_owner enabled, check that the file cannot be modified + * by other users (except root). */ + if (check_owner >= 0 && NM_FLAGS_ANY(out_st->st_mode, S_IWGRP | S_IWOTH | S_ISUID)) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("file permissions for %s"), + filename); + return FALSE; + } + + if (check_file && !check_file(filename, out_st, user_data, error)) { + if (error && !*error) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("reject %s"), + filename); + } + return FALSE; + } + + return TRUE; +} + +gboolean +_nm_utils_check_module_file(const char * name, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError ** error) +{ + if (!g_path_is_absolute(name)) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("path is not absolute (%s)"), + name); + return FALSE; + } + + /* Set special error code if the file doesn't exist. + * The VPN package might be split into separate packages, + * so it could be correct that the plugin file is missing. + * + * Note that nm-applet checks for this error code to fail + * gracefully. */ + if (!g_file_test(name, G_FILE_TEST_EXISTS)) { + g_set_error(error, + G_FILE_ERROR, + G_FILE_ERROR_NOENT, + _("Plugin file does not exist (%s)"), + name); + return FALSE; + } + + if (!g_file_test(name, G_FILE_TEST_IS_REGULAR)) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("Plugin is not a valid file (%s)"), + name); + return FALSE; + } + + if (g_str_has_suffix(name, ".la")) { + /* g_module_open() treats files that end with .la special. + * We don't want to parse the libtool archive. Just error out. */ + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("libtool archives are not supported (%s)"), + name); + return FALSE; + } + + return _nm_utils_check_file(name, check_owner, check_file, user_data, NULL, error); +} + +/*****************************************************************************/ + +/** + * nm_utils_file_search_in_paths: + * @progname: the helper program name, like "iptables" + * Must be a non-empty string, without path separator (/). + * @try_first: (allow-none): a custom path to try first before searching. + * It is silently ignored if it is empty or not an absolute path. + * @paths: (allow-none): a %NULL terminated list of search paths. + * Can be empty or %NULL, in which case only @try_first is checked. + * @file_test_flags: the flags passed to g_file_test() when searching + * for @progname. Set it to 0 to skip the g_file_test(). + * @predicate: (scope call): if given, pass the file name to this function + * for additional checks. This check is performed after the check for + * @file_test_flags. You cannot omit both @file_test_flags and @predicate. + * @user_data: (closure) (allow-none): user data for @predicate function. + * @error: (allow-none): on failure, set a "not found" error %G_IO_ERROR %G_IO_ERROR_NOT_FOUND. + * + * Searches for a @progname file in a list of search @paths. + * + * Returns: (transfer none): the full path to the helper, if found, or %NULL if not found. + * The returned string is not owned by the caller, but later + * invocations of the function might overwrite it. + */ +const char * +nm_utils_file_search_in_paths(const char * progname, + const char * try_first, + const char *const * paths, + GFileTest file_test_flags, + NMUtilsFileSearchInPathsPredicate predicate, + gpointer user_data, + GError ** error) +{ + g_return_val_if_fail(!error || !*error, NULL); + g_return_val_if_fail(progname && progname[0] && !strchr(progname, '/'), NULL); + g_return_val_if_fail(file_test_flags || predicate, NULL); + + /* Only consider @try_first if it is a valid, absolute path. This makes + * it simpler to pass in a path from configure checks. */ + if (try_first && try_first[0] == '/' + && (file_test_flags == 0 || g_file_test(try_first, file_test_flags)) + && (!predicate || predicate(try_first, user_data))) + return g_intern_string(try_first); + + if (paths && paths[0]) { + nm_auto_str_buf NMStrBuf strbuf = + NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); + + for (; *paths; paths++) { + const char *path = *paths; + const char *s; + + if (!path[0]) + continue; + + nm_str_buf_reset(&strbuf); + nm_str_buf_append(&strbuf, path); + nm_str_buf_ensure_trailing_c(&strbuf, '/'); + s = nm_str_buf_append0(&strbuf, progname); + + if ((file_test_flags == 0 || g_file_test(s, file_test_flags)) + && (!predicate || predicate(s, user_data))) + return g_intern_string(s); + } + } + + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_NOT_FOUND, + _("Could not find \"%s\" binary"), + progname); + return NULL; +} + +/*****************************************************************************/ + +/* Band, channel/frequency stuff for wireless */ +struct cf_pair { + guint32 chan; + guint32 freq; +}; + +static const struct cf_pair a_table[] = { + /* A band */ + {7, 5035}, {8, 5040}, {9, 5045}, {11, 5055}, {12, 5060}, {16, 5080}, {34, 5170}, + {36, 5180}, {38, 5190}, {40, 5200}, {42, 5210}, {44, 5220}, {46, 5230}, {48, 5240}, + {50, 5250}, {52, 5260}, {56, 5280}, {58, 5290}, {60, 5300}, {64, 5320}, {100, 5500}, + {104, 5520}, {108, 5540}, {112, 5560}, {116, 5580}, {120, 5600}, {124, 5620}, {128, 5640}, + {132, 5660}, {136, 5680}, {140, 5700}, {149, 5745}, {152, 5760}, {153, 5765}, {157, 5785}, + {160, 5800}, {161, 5805}, {165, 5825}, {183, 4915}, {184, 4920}, {185, 4925}, {187, 4935}, + {188, 4945}, {192, 4960}, {196, 4980}, {0, 0}}; + +static const guint a_table_freqs[G_N_ELEMENTS(a_table)] = { + /* A band */ + 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240, 5250, 5260, + 5280, 5290, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, + 5760, 5765, 5785, 5800, 5805, 5825, 4915, 4920, 4925, 4935, 4945, 4960, 4980, 0, +}; + +static const struct cf_pair bg_table[] = { + /* B/G band */ + {1, 2412}, + {2, 2417}, + {3, 2422}, + {4, 2427}, + {5, 2432}, + {6, 2437}, + {7, 2442}, + {8, 2447}, + {9, 2452}, + {10, 2457}, + {11, 2462}, + {12, 2467}, + {13, 2472}, + {14, 2484}, + {0, 0}}; + +static const guint bg_table_freqs[G_N_ELEMENTS(bg_table)] = { + /* B/G band */ + 2412, + 2417, + 2422, + 2427, + 2432, + 2437, + 2442, + 2447, + 2452, + 2457, + 2462, + 2467, + 2472, + 2484, + 0, +}; + +/** + * nm_utils_wifi_freq_to_channel: + * @freq: frequency + * + * Utility function to translate a Wi-Fi frequency to its corresponding channel. + * + * Returns: the channel represented by the frequency or 0 + **/ +guint32 +nm_utils_wifi_freq_to_channel(guint32 freq) +{ + int i = 0; + + if (freq > 4900) { + while (a_table[i].freq && (a_table[i].freq != freq)) + i++; + return a_table[i].chan; + } + + while (bg_table[i].freq && (bg_table[i].freq != freq)) + i++; + return bg_table[i].chan; +} + +/** + * nm_utils_wifi_freq_to_band: + * @freq: frequency + * + * Utility function to translate a Wi-Fi frequency to its corresponding band. + * + * Returns: the band containing the frequency or NULL if freq is invalid + **/ +const char * +nm_utils_wifi_freq_to_band(guint32 freq) +{ + if (freq >= 4915 && freq <= 5825) + return "a"; + else if (freq >= 2412 && freq <= 2484) + return "bg"; + + return NULL; +} + +/** + * nm_utils_wifi_channel_to_freq: + * @channel: channel + * @band: frequency band for wireless ("a" or "bg") + * + * Utility function to translate a Wi-Fi channel to its corresponding frequency. + * + * Returns: the frequency represented by the channel of the band, + * or -1 when the freq is invalid, or 0 when the band + * is invalid + **/ +guint32 +nm_utils_wifi_channel_to_freq(guint32 channel, const char *band) +{ + int i; + + g_return_val_if_fail(band, 0); + + if (nm_streq(band, "a")) { + for (i = 0; a_table[i].chan; i++) { + if (a_table[i].chan == channel) + return a_table[i].freq; + } + return ((guint32) -1); + } + + if (nm_streq(band, "bg")) { + for (i = 0; bg_table[i].chan; i++) { + if (bg_table[i].chan == channel) + return bg_table[i].freq; + } + return ((guint32) -1); + } + + return 0; +} + +/** + * nm_utils_wifi_find_next_channel: + * @channel: current channel + * @direction: whether going downward (0 or less) or upward (1 or more) + * @band: frequency band for wireless ("a" or "bg") + * + * Utility function to find out next/previous Wi-Fi channel for a channel. + * + * Returns: the next channel in the specified direction or 0 + **/ +guint32 +nm_utils_wifi_find_next_channel(guint32 channel, int direction, char *band) +{ + size_t a_size = G_N_ELEMENTS(a_table); + size_t bg_size = G_N_ELEMENTS(bg_table); + const struct cf_pair *pair; + + if (nm_streq(band, "a")) { + if (channel < a_table[0].chan) + return a_table[0].chan; + if (channel > a_table[a_size - 2].chan) + return a_table[a_size - 2].chan; + pair = &a_table[0]; + } else if (nm_streq(band, "bg")) { + if (channel < bg_table[0].chan) + return bg_table[0].chan; + if (channel > bg_table[bg_size - 2].chan) + return bg_table[bg_size - 2].chan; + pair = &bg_table[0]; + } else + g_return_val_if_reached(0); + + while (pair->chan) { + if (channel == pair->chan) + return channel; + if ((channel < (pair + 1)->chan) && (channel > pair->chan)) { + if (direction > 0) + return (pair + 1)->chan; + else + return pair->chan; + } + pair++; + } + return 0; +} + +/** + * nm_utils_wifi_is_channel_valid: + * @channel: channel + * @band: frequency band for wireless ("a" or "bg") + * + * Utility function to verify Wi-Fi channel validity. + * + * Returns: %TRUE or %FALSE + **/ +gboolean +nm_utils_wifi_is_channel_valid(guint32 channel, const char *band) +{ + guint32 freq; + + freq = nm_utils_wifi_channel_to_freq(channel, band); + + return !NM_IN_SET(freq, 0u, (guint32) -1); +} + +#define _nm_assert_wifi_freqs(table, table_freqs) \ + G_STMT_START \ + { \ + if (NM_MORE_ASSERT_ONCE(5)) { \ + int i, j; \ + \ + G_STATIC_ASSERT(G_N_ELEMENTS(table) > 0); \ + G_STATIC_ASSERT(G_N_ELEMENTS(table) == G_N_ELEMENTS(table_freqs)); \ + \ + for (i = 0; i < (int) G_N_ELEMENTS(table); i++) { \ + nm_assert((i == G_N_ELEMENTS(table) - 1) == (table[i].chan == 0)); \ + nm_assert((i == G_N_ELEMENTS(table) - 1) == (table[i].freq == 0)); \ + nm_assert(table[i].freq == table_freqs[i]); \ + for (j = 0; j < i; j++) { \ + nm_assert(table[j].chan != table[i].chan); \ + nm_assert(table[j].freq != table[i].freq); \ + } \ + } \ + } \ + } \ + G_STMT_END + +/** + * nm_utils_wifi_2ghz_freqs: + * + * Utility function to return 2.4 GHz Wi-Fi frequencies (802.11bg band). + * + * Returns: zero-terminated array of frequencies numbers (in MHz) + * + * Since: 1.2 + **/ +const guint * +nm_utils_wifi_2ghz_freqs(void) +{ + _nm_assert_wifi_freqs(bg_table, bg_table_freqs); + return bg_table_freqs; +} + +/** + * nm_utils_wifi_5ghz_freqs: + * + * Utility function to return 5 GHz Wi-Fi frequencies (802.11a band). + * + * Returns: zero-terminated array of frequencies numbers (in MHz) + * + * Since: 1.2 + **/ +const guint * +nm_utils_wifi_5ghz_freqs(void) +{ + _nm_assert_wifi_freqs(a_table, a_table_freqs); + return a_table_freqs; +} + +/** + * nm_utils_wifi_strength_bars: + * @strength: the access point strength, from 0 to 100 + * + * Converts @strength into a 4-character-wide graphical representation of + * strength suitable for printing to stdout. + * + * Previous versions used to take a guess at the terminal type and possibly + * return a wide UTF-8 encoded string. Now it always returns a 7-bit + * clean strings of one to 0 to 4 asterisks. Users that actually need + * the functionality are encouraged to make their implementations instead. + * + * Returns: the graphical representation of the access point strength + */ +const char * +nm_utils_wifi_strength_bars(guint8 strength) +{ + if (strength > 80) + return "****"; + else if (strength > 55) + return "*** "; + else if (strength > 30) + return "** "; + else if (strength > 5) + return "* "; + else + return " "; +} + +/** + * nm_utils_hwaddr_len: + * @type: the type of address; either ARPHRD_ETHER or + * ARPHRD_INFINIBAND + * + * Returns the length in octets of a hardware address of type @type. + * + * Before 1.28, it was an error to call this function with any value other than + * ARPHRD_ETHER or ARPHRD_INFINIBAND. + * + * Return value: the length or zero if the type is unrecognized. + */ +gsize +nm_utils_hwaddr_len(int type) +{ + switch (type) { + case ARPHRD_ETHER: + return ETH_ALEN; + case ARPHRD_INFINIBAND: + return INFINIBAND_ALEN; + default: + return 0; + } +} + +/** + * nm_utils_hexstr2bin: + * @hex: a string of hexadecimal characters with optional ':' separators + * + * Converts a hexadecimal string @hex into an array of bytes. The optional + * separator ':' may be used between single or pairs of hexadecimal characters, + * eg "00:11" or "0:1". Any "0x" at the beginning of @hex is ignored. @hex + * may not start or end with ':'. + * + * Return value: (transfer full): the converted bytes, or %NULL on error + */ +GBytes * +nm_utils_hexstr2bin(const char *hex) +{ + guint8 *buffer; + gsize len; + + buffer = nm_utils_hexstr2bin_alloc(hex, TRUE, FALSE, ":", 0, &len); + if (!buffer) + return NULL; + buffer = g_realloc(buffer, len); + return g_bytes_new_take(buffer, len); +} + +/** + * nm_utils_hwaddr_atoba: + * @asc: the ASCII representation of a hardware address + * @length: the expected length in bytes of the result + * + * Parses @asc and converts it to binary form in a #GByteArray. See + * nm_utils_hwaddr_aton() if you don't want a #GByteArray. + * + * Return value: (transfer full): a new #GByteArray, or %NULL if @asc couldn't + * be parsed + */ +GByteArray * +nm_utils_hwaddr_atoba(const char *asc, gsize length) +{ + GByteArray *ba; + + g_return_val_if_fail(asc, NULL); + g_return_val_if_fail(length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL); + + ba = g_byte_array_sized_new(length); + g_byte_array_set_size(ba, length); + if (!_nm_utils_hwaddr_aton_exact(asc, ba->data, length)) + goto fail; + + return ba; +fail: + g_byte_array_unref(ba); + return NULL; +} + +/** + * nm_utils_hwaddr_aton: + * @asc: the ASCII representation of a hardware address + * @buffer: (type guint8) (array length=length): buffer to store the result into + * @length: the expected length in bytes of the result and + * the size of the buffer in bytes. + * + * Parses @asc and converts it to binary form in @buffer. + * Bytes in @asc can be separated by colons (:), or hyphens (-), but not mixed. + * + * Return value: @buffer, or %NULL if @asc couldn't be parsed + * or would be shorter or longer than @length. + */ +guint8 * +nm_utils_hwaddr_aton(const char *asc, gpointer buffer, gsize length) +{ + g_return_val_if_fail(asc, NULL); + g_return_val_if_fail(buffer, NULL); + g_return_val_if_fail(length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL); + + return _nm_utils_hwaddr_aton_exact(asc, buffer, length); +} + +/** + * nm_utils_bin2hexstr: + * @src: (type guint8) (array length=len): an array of bytes + * @len: the length of the @src array + * @final_len: an index where to cut off the returned string, or -1 + * + * Converts the byte array @src into a hexadecimal string. If @final_len is + * greater than -1, the returned string is terminated at that index + * (returned_string[final_len] == '\0'), + * + * Return value: (transfer full): the textual form of @bytes + */ +char * +nm_utils_bin2hexstr(gconstpointer src, gsize len, int final_len) +{ + char *result; + gsize buflen = (len * 2) + 1; + + g_return_val_if_fail(src != NULL, NULL); + g_return_val_if_fail(len > 0 && (buflen - 1) / 2 == len, NULL); + g_return_val_if_fail(final_len < 0 || (gsize) final_len < buflen, NULL); + + result = g_malloc(buflen); + + nm_utils_bin2hexstr_full(src, len, '\0', FALSE, result); + + /* Cut converted key off at the correct length for this cipher type */ + if (final_len >= 0 && (gsize) final_len < buflen) + result[final_len] = '\0'; + + return result; +} + +/** + * nm_utils_hwaddr_ntoa: + * @addr: (type guint8) (array length=length): a binary hardware address + * @length: the length of @addr + * + * Converts @addr to textual form. + * + * Return value: (transfer full): the textual form of @addr + */ +char * +nm_utils_hwaddr_ntoa(gconstpointer addr, gsize length) +{ + g_return_val_if_fail(addr, g_strdup("")); + g_return_val_if_fail(length > 0, g_strdup("")); + + return nm_utils_bin2hexstr_full(addr, length, ':', TRUE, NULL); +} + +/** + * nm_utils_hwaddr_valid: + * @asc: the ASCII representation of a hardware address + * @length: the length of address that @asc is expected to convert to + * (or -1 to accept any length up to %NM_UTILS_HWADDR_LEN_MAX) + * + * Parses @asc to see if it is a valid hardware address of the given + * length. + * + * Return value: %TRUE if @asc appears to be a valid hardware address + * of the indicated length, %FALSE if not. + */ +gboolean +nm_utils_hwaddr_valid(const char *asc, gssize length) +{ + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; + gsize l; + + g_return_val_if_fail(asc != NULL, FALSE); + g_return_val_if_fail(length >= -1 && length <= NM_UTILS_HWADDR_LEN_MAX, FALSE); + + if (length == 0) + return FALSE; + + if (!_nm_utils_hwaddr_aton(asc, buf, sizeof(buf), &l)) + return FALSE; + + return length == -1 || length == (gssize) l; +} + +/** + * nm_utils_hwaddr_canonical: + * @asc: the ASCII representation of a hardware address + * @length: the length of address that @asc is expected to convert to + * (or -1 to accept any length up to %NM_UTILS_HWADDR_LEN_MAX) + * + * Parses @asc to see if it is a valid hardware address of the given + * length, and if so, returns it in canonical form (uppercase, with + * leading 0s as needed, and with colons rather than hyphens). + * + * Return value: (transfer full): the canonicalized address if @asc appears to + * be a valid hardware address of the indicated length, %NULL if not. + */ +char * +nm_utils_hwaddr_canonical(const char *asc, gssize length) +{ + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; + gsize l; + + g_return_val_if_fail(asc, NULL); + g_return_val_if_fail(length == -1 || (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX), NULL); + + if (!_nm_utils_hwaddr_aton(asc, buf, sizeof(buf), &l)) + return NULL; + if (length != -1 && length != (gssize) l) + return NULL; + return nm_utils_hwaddr_ntoa(buf, l); +} + +/* This is used to possibly canonicalize values passed to MAC address property + * setters. Unlike nm_utils_hwaddr_canonical(), it accepts %NULL, and if you + * pass it an invalid MAC address, it just returns that string rather than + * returning %NULL (so that we can return a proper error from verify() later). + */ +char * +_nm_utils_hwaddr_canonical_or_invalid(const char *mac, gssize length) +{ + char *canonical; + + if (!mac) + return NULL; + + canonical = nm_utils_hwaddr_canonical(mac, length); + if (canonical) + return canonical; + else + return g_strdup(mac); +} + +/* + * Determine if given Ethernet address is link-local + * + * Return value: %TRUE if @mac is link local + * reserved addr (01:80:c2:00:00:0X) per IEEE 802.1Q 8.6.3 Frame filtering, %FALSE if not. + */ +gboolean +_nm_utils_hwaddr_link_local_valid(const char *mac) +{ + guint8 mac_net[ETH_ALEN]; + static const guint8 eth_reserved_addr_base[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; + + if (!mac) + return FALSE; + + if (!nm_utils_hwaddr_aton(mac, mac_net, ETH_ALEN)) + return FALSE; + + if (memcmp(mac_net, eth_reserved_addr_base, ETH_ALEN - 1) || (mac_net[5] & 0xF0)) + return FALSE; + + if (mac_net[5] == 1 /* 802.3x Pause address */ + || mac_net[5] == 2 /* 802.3ad Slow protocols */ + || mac_net[5] == 3) /* 802.1X PAE address */ + return FALSE; + + return TRUE; +} + +/** + * nm_utils_hwaddr_matches: + * @hwaddr1: (nullable): pointer to a binary or ASCII hardware address, or %NULL + * @hwaddr1_len: size of @hwaddr1, or -1 if @hwaddr1 is ASCII + * @hwaddr2: (nullable): pointer to a binary or ASCII hardware address, or %NULL + * @hwaddr2_len: size of @hwaddr2, or -1 if @hwaddr2 is ASCII + * + * Generalized hardware address comparison function. Tests if @hwaddr1 and + * @hwaddr2 "equal" (or more precisely, "equivalent"), with several advantages + * over a simple memcmp(): + * + * 1. If @hwaddr1_len or @hwaddr2_len is -1, then the corresponding address is + * assumed to be ASCII rather than binary, and will be converted to binary + * before being compared. + * + * 2. If @hwaddr1 or @hwaddr2 is %NULL, it is treated instead as though it was + * a zero-filled buffer @hwaddr1_len or @hwaddr2_len bytes long. + * + * 3. If @hwaddr1 and @hwaddr2 are InfiniBand hardware addresses (that is, if + * they are INFINIBAND_ALEN bytes long in binary form) + * then only the last 8 bytes are compared, since those are the only bytes + * that actually identify the hardware. (The other 12 bytes will change + * depending on the configuration of the InfiniBand fabric that the device + * is connected to.) + * + * If a passed-in ASCII hardware address cannot be parsed, or would parse to an + * address larger than %NM_UTILS_HWADDR_LEN_MAX, then it will silently fail to + * match. (This means that externally-provided address strings do not need to be + * sanity-checked before comparing them against known good addresses; they are + * guaranteed to not match if they are invalid.) + * + * Return value: %TRUE if @hwaddr1 and @hwaddr2 are equivalent, %FALSE if they are + * different (or either of them is invalid). + */ +gboolean +nm_utils_hwaddr_matches(gconstpointer hwaddr1, + gssize hwaddr1_len, + gconstpointer hwaddr2, + gssize hwaddr2_len) +{ + guint8 buf1[NM_UTILS_HWADDR_LEN_MAX], buf2[NM_UTILS_HWADDR_LEN_MAX]; + gsize l; + + if (hwaddr1_len == -1) { + if (hwaddr1 == NULL) { + hwaddr1_len = 0; + } else if (_nm_utils_hwaddr_aton(hwaddr1, buf1, sizeof(buf1), &l)) { + hwaddr1 = buf1; + hwaddr1_len = l; + } else { + g_return_val_if_fail(hwaddr2_len == -1 + || (hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX), + FALSE); + return FALSE; + } + } else { + g_return_val_if_fail(hwaddr1_len > 0 && hwaddr1_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE); + + if (!hwaddr1) { + memset(buf1, 0, hwaddr1_len); + hwaddr1 = buf1; + } + } + + if (hwaddr2_len == -1) { + if (hwaddr2 == NULL) + l = 0; + else if (!_nm_utils_hwaddr_aton(hwaddr2, buf2, sizeof(buf2), &l)) + return FALSE; + if (l != hwaddr1_len) + return FALSE; + hwaddr2 = buf2; + } else { + g_return_val_if_fail(hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE); + + if (hwaddr2_len != hwaddr1_len) + return FALSE; + + if (!hwaddr2) { + memset(buf2, 0, hwaddr2_len); + hwaddr2 = buf2; + } + } + + if (G_UNLIKELY(hwaddr1_len <= 0 || hwaddr1_len > NM_UTILS_HWADDR_LEN_MAX)) { + /* Only valid addresses can compare equal. In particular, + * addresses that are too long or of zero bytes, never + * compare equal. */ + return FALSE; + } + + if (hwaddr1_len == INFINIBAND_ALEN) { + hwaddr1 = &((guint8 *) hwaddr1)[INFINIBAND_ALEN - 8]; + hwaddr2 = &((guint8 *) hwaddr2)[INFINIBAND_ALEN - 8]; + hwaddr1_len = 8; + } + + return !memcmp(hwaddr1, hwaddr2, hwaddr1_len); +} + +/*****************************************************************************/ + +static GVariant * +_nm_utils_hwaddr_to_dbus_impl(const char *str) +{ + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; + gsize len; + + if (!str) + return NULL; + if (!_nm_utils_hwaddr_aton(str, buf, sizeof(buf), &len)) + return NULL; + + return g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, buf, len, 1); +} + +static GVariant * +_nm_utils_hwaddr_cloned_get(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_free char *addr = NULL; + + nm_assert(nm_streq(sett_info->property_infos[property_idx].name, "cloned-mac-address")); + + g_object_get(setting, "cloned-mac-address", &addr, NULL); + return _nm_utils_hwaddr_to_dbus_impl(addr); +} + +static gboolean +_nm_utils_hwaddr_cloned_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + gsize length; + const guint8 *array; + char * str; + + nm_assert(nm_streq0(property, "cloned-mac-address")); + + if (!_nm_setting_use_legacy_property(setting, + connection_dict, + "cloned-mac-address", + "assigned-mac-address")) + return TRUE; + + length = 0; + array = g_variant_get_fixed_array(value, &length, 1); + + if (!length) + return TRUE; + + str = nm_utils_hwaddr_ntoa(array, length); + g_object_set(setting, "cloned-mac-address", str, NULL); + g_free(str); + return TRUE; +} + +static gboolean +_nm_utils_hwaddr_cloned_not_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + NMSettingParseFlags parse_flags, + GError ** error) +{ + nm_assert(nm_streq0(property, "cloned-mac-address")); + return TRUE; +} + +const NMSettInfoPropertType nm_sett_info_propert_type_cloned_mac_address = { + .dbus_type = G_VARIANT_TYPE_BYTESTRING, + .to_dbus_fcn = _nm_utils_hwaddr_cloned_get, + .from_dbus_fcn = _nm_utils_hwaddr_cloned_set, + .missing_from_dbus_fcn = _nm_utils_hwaddr_cloned_not_set, +}; + +static GVariant * +_nm_utils_hwaddr_cloned_data_synth(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_free char *addr = NULL; + + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + return NULL; + + nm_assert(nm_streq0(sett_info->property_infos[property_idx].name, "assigned-mac-address")); + + g_object_get(setting, "cloned-mac-address", &addr, NULL); + + /* Before introducing the extended "cloned-mac-address" (and its D-Bus + * field "assigned-mac-address"), libnm's _nm_utils_hwaddr_to_dbus() + * would drop invalid values as it was unable to serialize them. + * + * Now, we would like to send invalid values as "assigned-mac-address" + * over D-Bus and let the server reject them. + * + * However, clients used to set the cloned-mac-address property + * to "" and it just worked as the value was not serialized in + * an ill form. + * + * To preserve that behavior, serialize "" as NULL. + */ + + return addr && addr[0] ? g_variant_new_take_string(g_steal_pointer(&addr)) : NULL; +} + +static gboolean +_nm_utils_hwaddr_cloned_data_set(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + nm_assert(nm_streq0(property, "assigned-mac-address")); + + if (_nm_setting_use_legacy_property(setting, + connection_dict, + "cloned-mac-address", + "assigned-mac-address")) + return TRUE; + + g_object_set(setting, + "cloned-mac-address", + nm_str_not_empty(g_variant_get_string(value, NULL)), + NULL); + return TRUE; +} + +const NMSettInfoPropertType nm_sett_info_propert_type_assigned_mac_address = { + .dbus_type = G_VARIANT_TYPE_STRING, + .to_dbus_fcn = _nm_utils_hwaddr_cloned_data_synth, + .from_dbus_fcn = _nm_utils_hwaddr_cloned_data_set, +}; + +static GVariant * +_nm_utils_hwaddr_to_dbus(const GValue *prop_value) +{ + return _nm_utils_hwaddr_to_dbus_impl(g_value_get_string(prop_value)); +} + +static void +_nm_utils_hwaddr_from_dbus(GVariant *dbus_value, GValue *prop_value) +{ + gsize length = 0; + const guint8 *array = g_variant_get_fixed_array(dbus_value, &length, 1); + char * str; + + str = length ? nm_utils_hwaddr_ntoa(array, length) : NULL; + g_value_take_string(prop_value, str); +} + +const NMSettInfoPropertType nm_sett_info_propert_type_mac_address = { + .dbus_type = G_VARIANT_TYPE_BYTESTRING, + .gprop_to_dbus_fcn = _nm_utils_hwaddr_to_dbus, + .gprop_from_dbus_fcn = _nm_utils_hwaddr_from_dbus, +}; + +/*****************************************************************************/ + +/* Validate secret-flags. Most settings don't validate them, which is a bug. + * But we possibly cannot enforce a strict validation now. + * + * For new settings, they shall validate the secret-flags strictly. */ +gboolean +_nm_utils_secret_flags_validate(NMSettingSecretFlags secret_flags, + const char * setting_name, + const char * property_name, + NMSettingSecretFlags disallowed_flags, + GError ** error) +{ + if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) + return TRUE; + + if (NM_FLAGS_ANY(secret_flags, ~NM_SETTING_SECRET_FLAG_ALL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unknown secret flags")); + if (setting_name) + g_prefix_error(error, "%s.%s: ", setting_name, property_name); + return FALSE; + } + + if (!nm_utils_is_power_of_two(secret_flags)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("conflicting secret flags")); + if (setting_name) + g_prefix_error(error, "%s.%s: ", setting_name, property_name); + return FALSE; + } + + if (NM_FLAGS_ANY(secret_flags, disallowed_flags)) { + if (NM_FLAGS_HAS(secret_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("secret flags must not be \"not-required\"")); + if (setting_name) + g_prefix_error(error, "%s.%s: ", setting_name, property_name); + return FALSE; + } + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unsupported secret flags")); + if (setting_name) + g_prefix_error(error, "%s.%s: ", setting_name, property_name); + return FALSE; + } + + return TRUE; +} + +gboolean +_nm_utils_wps_method_validate(NMSettingWirelessSecurityWpsMethod wps_method, + const char * setting_name, + const char * property_name, + gboolean wps_required, + GError ** error) +{ + if (wps_method > NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, "%s.%s: ", setting_name, property_name); + return FALSE; + } + + if (NM_FLAGS_HAS(wps_method, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED)) { + if (wps_method != NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can't be simultaneously disabled and enabled")); + g_prefix_error(error, "%s.%s: ", setting_name, property_name); + return FALSE; + } + if (wps_required) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("WPS is required")); + g_prefix_error(error, "%s.%s: ", setting_name, property_name); + return FALSE; + } + } + + return TRUE; +} + +/*****************************************************************************/ + +static char * +_split_word(char *s) +{ + /* takes @s and truncates the string on the first white-space. + * then it returns the first word afterwards (again seeking + * over leading white-space). */ + for (; s[0]; s++) { + if (g_ascii_isspace(s[0])) { + s[0] = '\0'; + s++; + while (g_ascii_isspace(s[0])) + s++; + return s; + } + } + return s; +} + +gboolean +_nm_utils_generate_mac_address_mask_parse(const char * value, + struct ether_addr * out_mask, + struct ether_addr **out_ouis, + gsize * out_ouis_len, + GError ** error) +{ + gs_free char * s_free = NULL; + char * s, *s_next; + struct ether_addr mask; + gs_unref_array GArray *ouis = NULL; + + g_return_val_if_fail(!error || !*error, FALSE); + + if (!value || !*value) { + /* NULL and "" are valid values and both mean the default + * "q */ + if (out_mask) { + memset(out_mask, 0, sizeof(*out_mask)); + out_mask->ether_addr_octet[0] |= 0x02; + } + NM_SET_OUT(out_ouis, NULL); + NM_SET_OUT(out_ouis_len, 0); + return TRUE; + } + + s_free = g_strdup(value); + s = s_free; + + /* skip over leading whitespace */ + while (g_ascii_isspace(s[0])) + s++; + + /* parse the first mask */ + s_next = _split_word(s); + if (!nm_utils_hwaddr_aton(s, &mask, ETH_ALEN)) { + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + _("not a valid ethernet MAC address for mask at position %lld"), + (long long) (s - s_free)); + return FALSE; + } + + if (s_next[0]) { + ouis = g_array_sized_new(FALSE, FALSE, sizeof(struct ether_addr), 4); + + do { + s = s_next; + s_next = _split_word(s); + + g_array_set_size(ouis, ouis->len + 1); + if (!nm_utils_hwaddr_aton(s, + &g_array_index(ouis, struct ether_addr, ouis->len - 1), + ETH_ALEN)) { + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + _("not a valid ethernet MAC address #%u at position %lld"), + ouis->len, + (long long) (s - s_free)); + return FALSE; + } + } while (s_next[0]); + } + + NM_SET_OUT(out_mask, mask); + NM_SET_OUT(out_ouis_len, ouis ? ouis->len : 0); + NM_SET_OUT(out_ouis, + ouis ? ((struct ether_addr *) g_array_free(g_steal_pointer(&ouis), FALSE)) : NULL); + return TRUE; +} + +/*****************************************************************************/ + +gboolean +nm_utils_is_valid_iface_name_utf8safe(const char *utf8safe_name) +{ + gs_free gpointer bin_to_free = NULL; + gconstpointer bin; + gsize len; + + g_return_val_if_fail(utf8safe_name, FALSE); + + bin = nm_utils_buf_utf8safe_unescape(utf8safe_name, + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, + &len, + &bin_to_free); + + if (bin_to_free) { + /* some unescaping happened... */ + + if (len != strlen(bin)) { + /* there are embedded NUL chars. Invalid. */ + return FALSE; + } + } + + return nm_utils_ifname_valid_kernel(bin, NULL); +} + +/** + * nm_utils_is_valid_iface_name: + * @name: (allow-none): Name of interface + * @error: location to store the error occurring, or %NULL to ignore + * + * Validate the network interface name. + * + * This function is a 1:1 copy of the kernel's interface validation + * function in net/core/dev.c. + * + * Returns: %TRUE if interface name is valid, otherwise %FALSE is returned. + * + * Before 1.20, this function did not accept %NULL as @name argument. If you + * want to run against older versions of libnm, don't pass %NULL. + */ +gboolean +nm_utils_is_valid_iface_name(const char *name, GError **error) +{ + g_return_val_if_fail(!error || !*error, FALSE); + + return nm_utils_ifname_valid_kernel(name, error); +} + +/** + * nm_utils_iface_valid_name: + * @name: (allow-none): Name of interface + * + * Validate the network interface name. + * + * Deprecated: 1.6: Use nm_utils_is_valid_iface_name() instead, with better error reporting. + * + * Returns: %TRUE if interface name is valid, otherwise %FALSE is returned. + * + * Before 1.20, this function did not accept %NULL as @name argument. If you + * want to run against older versions of libnm, don't pass %NULL. + */ +gboolean +nm_utils_iface_valid_name(const char *name) +{ + return nm_utils_is_valid_iface_name(name, NULL); +} + +/** + * nm_utils_is_uuid: + * @str: (allow-none): a string that might be a UUID + * + * Checks if @str is a UUID + * + * Returns: %TRUE if @str is a UUID, %FALSE if not + * + * In older versions, nm_utils_is_uuid() did not accept %NULL as @str + * argument. Don't pass %NULL if you run against older versions of libnm. + */ +gboolean +nm_utils_is_uuid(const char *str) +{ + const char *p = str; + int num_dashes = 0; + + if (!p) + return FALSE; + + while (*p) { + if (*p == '-') + num_dashes++; + else if (!g_ascii_isxdigit(*p)) + return FALSE; + p++; + } + + if ((num_dashes == 4) && (p - str == 36)) + return TRUE; + + /* Backwards compat for older configurations */ + if ((num_dashes == 0) && (p - str == 40)) + return TRUE; + + return FALSE; +} + +static _nm_thread_local char _nm_utils_inet_ntop_buffer[NM_UTILS_INET_ADDRSTRLEN]; + +/** + * nm_utils_inet4_ntop: (skip) + * @inaddr: the address that should be converted to string. + * @dst: the destination buffer, it must contain at least + * INET_ADDRSTRLEN or %NM_UTILS_INET_ADDRSTRLEN + * characters. If set to %NULL, it will return a pointer to an internal, static + * buffer (shared with nm_utils_inet6_ntop()). Beware, that the internal + * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or + * nm_utils_inet6_ntop() that does not provide its own @dst buffer. Since + * 1.28, the internal buffer is thread local and thus thread safe. Before + * it was not thread safe. When in doubt, pass your own + * @dst buffer to avoid these issues. + * + * Wrapper for inet_ntop. + * + * Returns: the input buffer @dst, or a pointer to an + * internal, static buffer. This function cannot fail. + **/ +const char * +nm_utils_inet4_ntop(in_addr_t inaddr, char *dst) +{ + /* relying on the static buffer (by leaving @dst as %NULL) is discouraged. + * Don't do that! + * + * However, still support it to be lenient against mistakes and because + * this is public API of libnm. */ + return _nm_utils_inet4_ntop(inaddr, dst ?: _nm_utils_inet_ntop_buffer); +} + +/** + * nm_utils_inet6_ntop: (skip) + * @in6addr: the address that should be converted to string. + * @dst: the destination buffer, it must contain at least + * INET6_ADDRSTRLEN or %NM_UTILS_INET_ADDRSTRLEN + * characters. If set to %NULL, it will return a pointer to an internal, static + * buffer (shared with nm_utils_inet4_ntop()). Beware, that the internal + * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or + * nm_utils_inet6_ntop() that does not provide its own @dst buffer. Since + * 1.28, the internal buffer is thread local and thus thread safe. Before + * it was not thread safe. When in doubt, pass your own + * @dst buffer to avoid these issues. + * + * Wrapper for inet_ntop. + * + * Returns: the input buffer @dst, or a pointer to an + * internal, static buffer. %NULL is not allowed as @in6addr, + * otherwise, this function cannot fail. + **/ +const char * +nm_utils_inet6_ntop(const struct in6_addr *in6addr, char *dst) +{ + /* relying on the static buffer (by leaving @dst as %NULL) is discouraged. + * Don't do that! + * + * However, still support it to be lenient against mistakes and because + * this is public API of libnm. */ + g_return_val_if_fail(in6addr, NULL); + return _nm_utils_inet6_ntop(in6addr, dst ?: _nm_utils_inet_ntop_buffer); +} + +/** + * nm_utils_ipaddr_valid: + * @family: AF_INET or AF_INET6, or + * AF_UNSPEC to accept either + * @ip: an IP address + * + * Checks if @ip contains a valid IP address of the given family. + * + * Return value: %TRUE or %FALSE + */ +gboolean +nm_utils_ipaddr_valid(int family, const char *ip) +{ + g_return_val_if_fail(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC, FALSE); + + return nm_utils_ipaddr_is_valid(family, ip); +} + +/** + * nm_utils_iinet6_is_token: + * @in6addr: the AF_INET6 address structure + * + * Checks if only the bottom 64bits of the address are set. + * + * Return value: %TRUE or %FALSE + */ +gboolean +_nm_utils_inet6_is_token(const struct in6_addr *in6addr) +{ + if (in6addr->s6_addr[0] || in6addr->s6_addr[1] || in6addr->s6_addr[2] || in6addr->s6_addr[3] + || in6addr->s6_addr[4] || in6addr->s6_addr[5] || in6addr->s6_addr[6] || in6addr->s6_addr[7]) + return FALSE; + + if (in6addr->s6_addr[8] || in6addr->s6_addr[9] || in6addr->s6_addr[10] || in6addr->s6_addr[11] + || in6addr->s6_addr[12] || in6addr->s6_addr[13] || in6addr->s6_addr[14] + || in6addr->s6_addr[15]) + return TRUE; + + return FALSE; +} + +/** + * _nm_utils_dhcp_duid_valid: + * @duid: the candidate DUID + * + * Checks if @duid string contains either a special duid value ("ll", + * "llt", "lease" or the "stable" variants) or a valid hex DUID. + * + * Return value: %TRUE or %FALSE + */ +gboolean +_nm_utils_dhcp_duid_valid(const char *duid, GBytes **out_duid_bin) +{ + guint8 duid_arr[128 + 2]; + gsize duid_len; + + NM_SET_OUT(out_duid_bin, NULL); + + if (!duid) + return FALSE; + + if (NM_IN_STRSET(duid, "lease", "llt", "ll", "stable-llt", "stable-ll", "stable-uuid")) { + return TRUE; + } + + if (nm_utils_hexstr2bin_full(duid, + FALSE, + FALSE, + FALSE, + ":", + 0, + duid_arr, + sizeof(duid_arr), + &duid_len)) { + /* MAX DUID length is 128 octects + the type code (2 octects). */ + if (duid_len > 2 && duid_len <= (128 + 2)) { + NM_SET_OUT(out_duid_bin, g_bytes_new(duid_arr, duid_len)); + return TRUE; + } + } + + return FALSE; +} + +/** + * nm_utils_check_virtual_device_compatibility: + * @virtual_type: a virtual connection type + * @other_type: a connection type to test against @virtual_type + * + * Determines if a connection of type @virtual_type can (in the + * general case) work with connections of type @other_type. + * + * If @virtual_type is %NM_TYPE_SETTING_VLAN, then this checks if + * @other_type is a valid type for the parent of a VLAN. + * + * If @virtual_type is a "master" type (eg, %NM_TYPE_SETTING_BRIDGE), + * then this checks if @other_type is a valid type for a slave of that + * master. + * + * Note that even if this returns %TRUE it is not guaranteed that + * every connection of type @other_type is + * compatible with @virtual_type; it may depend on the exact + * configuration of the two connections, or on the capabilities of an + * underlying device driver. + * + * Returns: %TRUE or %FALSE + */ +gboolean +nm_utils_check_virtual_device_compatibility(GType virtual_type, GType other_type) +{ + g_return_val_if_fail(_nm_setting_type_get_base_type_priority(virtual_type) + != NM_SETTING_PRIORITY_INVALID, + FALSE); + g_return_val_if_fail(_nm_setting_type_get_base_type_priority(other_type) + != NM_SETTING_PRIORITY_INVALID, + FALSE); + + if (virtual_type == NM_TYPE_SETTING_BOND) { + return (other_type == NM_TYPE_SETTING_INFINIBAND || other_type == NM_TYPE_SETTING_WIRED + || other_type == NM_TYPE_SETTING_BRIDGE || other_type == NM_TYPE_SETTING_BOND + || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN); + } else if (virtual_type == NM_TYPE_SETTING_BRIDGE) { + return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_BOND + || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN); + } else if (virtual_type == NM_TYPE_SETTING_TEAM) { + return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_BRIDGE + || other_type == NM_TYPE_SETTING_BOND || other_type == NM_TYPE_SETTING_TEAM + || other_type == NM_TYPE_SETTING_VLAN); + } else if (virtual_type == NM_TYPE_SETTING_VLAN) { + return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_WIRELESS + || other_type == NM_TYPE_SETTING_BRIDGE || other_type == NM_TYPE_SETTING_BOND + || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN); + } else { + g_warn_if_reached(); + return FALSE; + } +} + +/*****************************************************************************/ + +/** + * nm_utils_bond_mode_int_to_string: + * @mode: bonding mode as a numeric value + * + * Convert bonding mode from integer value to descriptive name. + * See https://www.kernel.org/doc/Documentation/networking/bonding.txt for + * available modes. + * + * Returns: bonding mode string, or NULL on error + * + * Since: 1.2 + */ +const char * +nm_utils_bond_mode_int_to_string(int mode) +{ + return _nm_setting_bond_mode_to_string(mode); +} + +/** + * nm_utils_bond_mode_string_to_int: + * @mode: bonding mode as string + * + * Convert bonding mode from string representation to numeric value. + * See https://www.kernel.org/doc/Documentation/networking/bonding.txt for + * available modes. + * The @mode string can be either a descriptive name or a number (as string). + * + * Returns: numeric bond mode, or -1 on error + * + * Since: 1.2 + */ +int +nm_utils_bond_mode_string_to_int(const char *mode) +{ + return _nm_setting_bond_mode_from_string(mode); +} + +/*****************************************************************************/ + +#define STRSTRDICTKEY_V1_SET 0x01 +#define STRSTRDICTKEY_V2_SET 0x02 +#define STRSTRDICTKEY_ALL_SET 0x03 + +struct _NMUtilsStrStrDictKey { + char type; + char data[1]; +}; + +guint +_nm_utils_strstrdictkey_hash(gconstpointer a) +{ + const NMUtilsStrStrDictKey *k = a; + const char * p; + NMHashState h; + + nm_hash_init(&h, 76642997u); + if (k) { + if (((int) k->type) & ~STRSTRDICTKEY_ALL_SET) + g_return_val_if_reached(0); + + nm_hash_update_val(&h, k->type); + if (k->type & STRSTRDICTKEY_ALL_SET) { + p = strchr(k->data, '\0'); + if (k->type == STRSTRDICTKEY_ALL_SET) { + /* the key contains two strings. Continue... */ + p = strchr(p + 1, '\0'); + } + if (p != k->data) + nm_hash_update(&h, k->data, p - k->data); + } + } + return nm_hash_complete(&h); +} + +gboolean +_nm_utils_strstrdictkey_equal(gconstpointer a, gconstpointer b) +{ + const NMUtilsStrStrDictKey *k1 = a; + const NMUtilsStrStrDictKey *k2 = b; + + if (k1 == k2) + return TRUE; + if (!k1 || !k2) + return FALSE; + + if (k1->type != k2->type) + return FALSE; + + if (k1->type & STRSTRDICTKEY_ALL_SET) { + if (!nm_streq(k1->data, k2->data)) + return FALSE; + + if (k1->type == STRSTRDICTKEY_ALL_SET) { + gsize l = strlen(k1->data) + 1; + + return nm_streq(&k1->data[l], &k2->data[l]); + } + } + + return TRUE; +} + +NMUtilsStrStrDictKey * +_nm_utils_strstrdictkey_create(const char *v1, const char *v2) +{ + char type = 0; + gsize l1 = 0, l2 = 0; + NMUtilsStrStrDictKey *k; + + if (!v1 && !v2) + return g_malloc0(1); + + /* we need to distinguish between ("",NULL) and (NULL,""). + * Thus, in @type we encode which strings we have present + * as not-NULL. */ + if (v1) { + type |= STRSTRDICTKEY_V1_SET; + l1 = strlen(v1) + 1; + } + if (v2) { + type |= STRSTRDICTKEY_V2_SET; + l2 = strlen(v2) + 1; + } + + k = g_malloc(G_STRUCT_OFFSET(NMUtilsStrStrDictKey, data) + l1 + l2); + k->type = type; + if (v1) + memcpy(&k->data[0], v1, l1); + if (v2) + memcpy(&k->data[l1], v2, l2); + + return k; +} + +static gboolean +validate_dns_option(const char * name, + gboolean numeric, + gboolean ipv6, + const NMUtilsDNSOptionDesc *option_descs) +{ + const NMUtilsDNSOptionDesc *desc; + + if (!option_descs) + return !!*name; + + for (desc = option_descs; desc->name; desc++) { + if (nm_streq(name, desc->name) && numeric == desc->numeric && (!desc->ipv6_only || ipv6)) + return TRUE; + } + + return FALSE; +} + +/** + * _nm_utils_dns_option_validate: + * @option: option string + * @out_name: (out) (allow-none): the option name + * @out_value: (out) (allow-none): the option value + * @ipv6: whether the option refers to a IPv6 configuration + * @option_descs: (allow-none): an array of NMUtilsDNSOptionDesc which describes the + * valid options + * + * Parses a DNS option in the form "name" or "name:number" and, if + * @option_descs is not NULL, checks that the option conforms to one + * of the provided descriptors. If @option_descs is NULL @ipv6 is + * not considered. + * + * Returns: %TRUE when the parsing was successful and the option is valid, + * %FALSE otherwise + */ +gboolean +_nm_utils_dns_option_validate(const char * option, + char ** out_name, + long * out_value, + gboolean ipv6, + const NMUtilsDNSOptionDesc *option_descs) +{ + gs_free char *option0_free = NULL; + const char * option0; + const char * option1; + const char * delim; + long option1_num; + + g_return_val_if_fail(option != NULL, FALSE); + + NM_SET_OUT(out_name, NULL); + NM_SET_OUT(out_value, -1); + + if (!option[0]) + return FALSE; + + delim = strchr(option, ':'); + if (!delim) { + if (!validate_dns_option(option, FALSE, ipv6, option_descs)) + return FALSE; + NM_SET_OUT(out_name, g_strdup(option)); + return TRUE; + } + + option1 = &delim[1]; + + if (!option1[0]) + return FALSE; + if (!NM_STRCHAR_ALL(option1, ch, g_ascii_isdigit(ch))) + return FALSE; + + option0 = nm_strndup_a(300, option, delim - option, &option0_free); + + if (!validate_dns_option(option0, TRUE, ipv6, option_descs)) + return FALSE; + + option1_num = _nm_utils_ascii_str_to_int64(option1, 10, 0, G_MAXINT32, -1); + if (option1_num == -1) + return FALSE; + + NM_SET_OUT(out_name, g_steal_pointer(&option0_free) ?: g_strdup(option0)); + NM_SET_OUT(out_value, option1_num); + return TRUE; +} + +/** + * _nm_utils_dns_option_find_idx: + * @array: an array of strings + * @option: a dns option string + * + * Searches for an option in an array of strings. The match is + * performed only the option name; the option value is ignored. + * + * Returns: the index of the option in the array or -1 if was not + * found. + */ +gssize +_nm_utils_dns_option_find_idx(GPtrArray *array, const char *option) +{ + gs_free char *option_name = NULL; + guint i; + + if (!_nm_utils_dns_option_validate(option, &option_name, NULL, FALSE, NULL)) + return -1; + + for (i = 0; i < array->len; i++) { + gs_free char *tmp_name = NULL; + + if (_nm_utils_dns_option_validate(array->pdata[i], &tmp_name, NULL, FALSE, NULL)) { + if (nm_streq(tmp_name, option_name)) + return i; + } + } + + return -1; +} + +/*****************************************************************************/ + +/** + * nm_utils_enum_to_str: + * @type: the %GType of the enum + * @value: the value to be translated + * + * Converts an enum value to its string representation. If the enum is a + * %G_TYPE_FLAGS the function returns a comma-separated list of matching values. + * If the value has no corresponding string representation, it is converted + * to a number. For enums it is converted to a decimal number, for flags + * to an (unsigned) hex number. + * + * Returns: a newly allocated string or %NULL + * + * Since: 1.2 + */ +char * +nm_utils_enum_to_str(GType type, int value) +{ + return _nm_utils_enum_to_str_full(type, value, ", ", NULL); +} + +/** + * nm_utils_enum_from_str: + * @type: the %GType of the enum + * @str: the input string + * @out_value: (out) (allow-none): the output value + * @err_token: (out) (allow-none) (transfer full): location to store the first unrecognized token + * + * Converts a string to the matching enum value. + * + * If the enum is a %G_TYPE_FLAGS the function returns the logical OR of values + * matching the comma-separated tokens in the string; if an unknown token is found + * the function returns %FALSE and stores a pointer to a newly allocated string + * containing the unrecognized token in @err_token. + * + * Returns: %TRUE if the conversion was successful, %FALSE otherwise + * + * Since: 1.2 + */ +gboolean +nm_utils_enum_from_str(GType type, const char *str, int *out_value, char **err_token) +{ + return _nm_utils_enum_from_str_full(type, str, out_value, err_token, NULL); +} + +/** + * nm_utils_enum_get_values: + * @type: the %GType of the enum + * @from: the first element to be returned + * @to: the last element to be returned + * + * Returns the list of possible values for a given enum. + * + * Returns: (transfer container): a NULL-terminated dynamically-allocated array of static strings + * or %NULL on error + * + * Since: 1.2 + */ +const char ** +nm_utils_enum_get_values(GType type, int from, int to) +{ + return _nm_utils_enum_get_values(type, from, to); +} + +/*****************************************************************************/ + +static gboolean +_nm_utils_is_json_object_no_validation(const char *str, GError **error) +{ + nm_assert(str); + + /* libjansson also requires only utf-8 encoding. */ + if (!g_utf8_validate(str, -1, NULL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("not valid utf-8")); + return FALSE; + } + while (g_ascii_isspace(str[0])) + str++; + + /* do some very basic validation to see if this might be a JSON object. */ + if (str[0] == '{') { + gsize l; + + l = strlen(str) - 1; + while (l > 0 && g_ascii_isspace(str[l])) + l--; + + if (str[l] == '}') + return TRUE; + } + + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a JSON object")); + return FALSE; +} + +/** + * nm_utils_is_json_object: + * @str: the JSON string to test + * @error: optional error reason + * + * Returns: whether the passed string is valid JSON. + * If libnm is not compiled with libjansson support, this check will + * also return %TRUE for possibly invalid inputs. If that is a problem + * for you, you must validate the JSON yourself. + * + * Since: 1.6 + */ +gboolean +nm_utils_is_json_object(const char *str, GError **error) +{ + nm_auto_decref_json nm_json_t *json = NULL; + const NMJsonVt * vt; + nm_json_error_t jerror; + + g_return_val_if_fail(!error || !*error, FALSE); + + if (!str || !str[0]) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + str ? _("value is NULL") : _("value is empty")); + return FALSE; + } + + if (!(vt = nm_json_vt())) + return _nm_utils_is_json_object_no_validation(str, error); + + json = vt->nm_json_loads(str, NM_JSON_REJECT_DUPLICATES, &jerror); + if (!json) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid JSON at position %d (%s)"), + jerror.position, + jerror.text); + return FALSE; + } + + /* valid JSON (depending on the definition) can also be a literal. + * Here we only allow objects. */ + if (!nm_json_is_object(json)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a JSON object")); + return FALSE; + } + + return TRUE; +} + +static char * +attribute_unescape(const char *start, const char *end) +{ + char *ret, *dest; + + nm_assert(start <= end); + dest = ret = g_malloc(end - start + 1); + + for (; start < end && *start; start++) { + if (*start == '\\') { + start++; + if (!*start) + break; + } + *dest++ = *start; + } + *dest = '\0'; + + return ret; +} + +gboolean +_nmtst_variant_attribute_spec_assert_sorted(const NMVariantAttributeSpec *const *array, gsize len) +{ + gsize i; + + g_assert(array); + g_assert(len > 0); + g_assert_cmpint(len, ==, NM_PTRARRAY_LEN(array)); + + for (i = 0; i < len; i++) { + nm_assert(array[i]->name); + nm_assert(array[i]->name[0]); + if (i > 0) + nm_assert(strcmp(array[i - 1]->name, array[i]->name) < 0); + } + nm_assert(!array[i]); + + return TRUE; +} + +const NMVariantAttributeSpec * +_nm_variant_attribute_spec_find_binary_search(const NMVariantAttributeSpec *const *array, + gsize len, + const char * name) +{ + gssize idx; + + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMVariantAttributeSpec, name) == 0); + + idx = nm_utils_ptrarray_find_binary_search((gconstpointer *) array, + len, + &name, + nm_strcmp_p_with_data, + NULL, + NULL, + NULL); + if (idx < 0) + return NULL; + return array[idx]; +} + +/** + * nm_utils_parse_variant_attributes: + * @string: the input string + * @attr_separator: the attribute separator character + * @key_value_separator: character separating key and values + * @ignore_unknown: whether unknown attributes should be ignored + * @spec: the attribute format specifiers + * @error: (out) (allow-none): location to store the error on failure + * + * Parse attributes from a string. + * + * Returns: (transfer full) (element-type utf8 GVariant): a #GHashTable mapping + * attribute names to #GVariant values. Warning: the variant are still floating + * references, owned by the hash table. If you take a reference, ensure to sink + * the one of the hash table first. + * + * Since: 1.8 + */ +GHashTable * +nm_utils_parse_variant_attributes(const char * string, + char attr_separator, + char key_value_separator, + gboolean ignore_unknown, + const NMVariantAttributeSpec *const *spec, + GError ** error) +{ + gs_unref_hashtable GHashTable * ht = NULL; + const char * ptr = string, *start = NULL, *sep; + GVariant * variant; + const NMVariantAttributeSpec *const *s; + + g_return_val_if_fail(string, NULL); + g_return_val_if_fail(attr_separator, NULL); + g_return_val_if_fail(key_value_separator, NULL); + g_return_val_if_fail(!error || !*error, NULL); + + ht = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + + while (TRUE) { + gs_free char *name = NULL, *value = NULL; + + if (!start) + start = ptr; + if (*ptr == '\\') { + ptr++; + if (!*ptr) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("unterminated escape sequence")); + return NULL; + } + goto next; + } + if (*ptr == attr_separator || *ptr == '\0') { + if (ptr == start) { + /* multiple separators */ + start = NULL; + goto next; + } + + /* Find the key-value separator */ + for (sep = start; sep != ptr; sep++) { + if (*sep == '\\') { + sep++; + if (!*sep) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("unterminated escape sequence")); + return NULL; + } + } + if (*sep == key_value_separator) + break; + } + + name = attribute_unescape(start, sep); + + for (s = spec; *s; s++) { + if (g_hash_table_contains(ht, (*s)->name)) + continue; + if (nm_streq(name, (*s)->name)) + break; + if ((*s)->no_value && g_variant_type_equal((*s)->type, G_VARIANT_TYPE_STRING)) + break; + } + + if (!*s) { + if (ignore_unknown) + goto next; + else { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("unknown attribute '%s'"), + name); + return NULL; + } + } + + if ((*s)->no_value) { + if ((*s)->consumes_rest) { + value = g_strdup(start); + ptr = strchr(start, '\0'); + } else { + value = g_steal_pointer(&name); + } + } else { + if (*sep != key_value_separator) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("missing key-value separator '%c' after '%s'"), + key_value_separator, + name); + return NULL; + } + + /* The attribute and key/value separators are the same. Look for the next one. */ + if (ptr == sep) + goto next; + + value = attribute_unescape(sep + 1, ptr); + } + + if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_UINT32)) { + gint64 num = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXUINT32, -1); + + if (num == -1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid uint32 value '%s' for attribute '%s'"), + value, + (*s)->name); + return NULL; + } + variant = g_variant_new_uint32(num); + } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_INT32)) { + gint64 num = + _nm_utils_ascii_str_to_int64(value, 10, G_MININT32, G_MAXINT32, G_MAXINT64); + + if (num == G_MAXINT64) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid int32 value '%s' for attribute '%s'"), + value, + (*s)->name); + return NULL; + } + variant = g_variant_new_int32(num); + } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_UINT64)) { + guint64 num = _nm_utils_ascii_str_to_uint64(value, 10, 0, G_MAXUINT64, G_MAXUINT64); + + if (num == G_MAXUINT64 && errno != 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid uint64 value '%s' for attribute '%s'"), + value, + (*s)->name); + return NULL; + } + variant = g_variant_new_uint64(num); + } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_BYTE)) { + gint64 num = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXUINT8, -1); + + if (num == -1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid uint8 value '%s' for attribute '%s'"), + value, + (*s)->name); + return NULL; + } + variant = g_variant_new_byte((guchar) num); + } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_BOOLEAN)) { + int b; + + b = (*s)->no_value ? TRUE : _nm_utils_ascii_str_to_bool(value, -1); + if (b == -1) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid boolean value '%s' for attribute '%s'"), + value, + (*s)->name); + return NULL; + } + variant = g_variant_new_boolean(b); + } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_STRING)) { + variant = g_variant_new_take_string(g_steal_pointer(&value)); + } else if (g_variant_type_equal((*s)->type, G_VARIANT_TYPE_BYTESTRING)) { + variant = g_variant_new_bytestring(value); + } else { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("unsupported attribute '%s' of type '%s'"), + (*s)->name, + (char *) (*s)->type); + return NULL; + } + + g_hash_table_insert(ht, g_strdup((*s)->name), variant); + start = NULL; + } +next: + if (*ptr == '\0') + break; + ptr++; + } + + return g_steal_pointer(&ht); +} + +/* + * nm_utils_format_variant_attributes: + * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values + * @attr_separator: the attribute separator character + * @key_value_separator: character separating key and values + * + * Format attributes to a string. + * + * Returns: (transfer full): the string representing attributes, or %NULL + * in case there are no attributes + * + * Since: 1.8 + */ +char * +nm_utils_format_variant_attributes(GHashTable *attributes, + char attr_separator, + char key_value_separator) +{ + return _nm_utils_format_variant_attributes(attributes, + NULL, + attr_separator, + key_value_separator); +} + +/*****************************************************************************/ + +/* + * nm_utils_get_timestamp_msec(): + * + * Gets current time in milliseconds of CLOCK_BOOTTIME. + * + * Returns: time in milliseconds + * + * Since: 1.12 + */ +gint64 +nm_utils_get_timestamp_msec(void) +{ + gint64 ts; + + ts = nm_utils_clock_gettime_msec(CLOCK_BOOTTIME); + if (ts >= 0) + return ts; + + if (ts == -EINVAL) { + /* The fallback to CLOCK_MONOTONIC is taken only if we're running on a + * criminally old kernel, prior to 2.6.39 (released on 18 May, 2011). + * That happens during buildcheck on old builders, we don't expect to + * be actually runs on kernels that old. */ + ts = nm_utils_clock_gettime_msec(CLOCK_MONOTONIC); + if (ts >= 0) + return ts; + } + + g_return_val_if_reached(-1); +} + +/*****************************************************************************/ + +/** + * nm_utils_version: + * + * Returns: the version ID of the libnm version. That is, the %NM_VERSION + * at runtime. + * + * Since: 1.6.0 + */ +guint +nm_utils_version(void) +{ + return NM_VERSION; +} + +/*****************************************************************************/ + +NM_UTILS_FLAGS2STR_DEFINE(nm_bluetooth_capability_to_string, + NMBluetoothCapabilities, + NM_UTILS_FLAGS2STR(NM_BT_CAPABILITY_NONE, "NONE"), + NM_UTILS_FLAGS2STR(NM_BT_CAPABILITY_DUN, "DUN"), + NM_UTILS_FLAGS2STR(NM_BT_CAPABILITY_NAP, "NAP"), ); + +/*****************************************************************************/ + +/** + * nm_utils_base64secret_decode: + * @base64_key: the (possibly invalid) base64 encode key. + * @required_key_len: the expected (binary) length of the key after + * decoding. If the length does not match, the validation fails. + * @out_key: (allow-none): (out): an optional output buffer for the binary + * key. If given, it will be filled with exactly @required_key_len + * bytes. + * + * Returns: %TRUE if the input key is a valid base64 encoded key + * with @required_key_len bytes. + * + * Since: 1.16 + */ +gboolean +nm_utils_base64secret_decode(const char *base64_key, gsize required_key_len, guint8 *out_key) +{ + nm_auto_free guint8 *bin_arr = NULL; + gsize base64_key_len; + gsize bin_len; + int r; + + if (!base64_key) + return FALSE; + + base64_key_len = strlen(base64_key); + + r = nm_sd_utils_unbase64mem(base64_key, base64_key_len, TRUE, &bin_arr, &bin_len); + if (r < 0) + return FALSE; + if (bin_len != required_key_len) { + nm_explicit_bzero(bin_arr, bin_len); + return FALSE; + } + + if (out_key) + memcpy(out_key, bin_arr, required_key_len); + + nm_explicit_bzero(bin_arr, bin_len); + return TRUE; +} + +gboolean +nm_utils_base64secret_normalize(const char *base64_key, + gsize required_key_len, + char ** out_base64_key_norm) +{ + gs_free guint8 *buf_free = NULL; + guint8 buf_static[200]; + guint8 * buf; + + if (required_key_len > sizeof(buf_static)) { + buf_free = g_new(guint8, required_key_len); + buf = buf_free; + } else + buf = buf_static; + + if (!nm_utils_base64secret_decode(base64_key, required_key_len, buf)) { + NM_SET_OUT(out_base64_key_norm, NULL); + return FALSE; + } + + NM_SET_OUT(out_base64_key_norm, g_base64_encode(buf, required_key_len)); + nm_explicit_bzero(buf, required_key_len); + return TRUE; +} + +static GVariant * +_nm_utils_bridge_vlans_to_dbus(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options) +{ + gs_unref_ptrarray GPtrArray *vlans = NULL; + GVariantBuilder builder; + guint i; + const char * property_name = sett_info->property_infos[property_idx].name; + + nm_assert(property_name); + + g_object_get(setting, property_name, &vlans, NULL); + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + if (vlans) { + for (i = 0; i < vlans->len; i++) { + NMBridgeVlan * vlan = vlans->pdata[i]; + GVariantBuilder vlan_builder; + guint16 vid_start, vid_end; + + nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); + + g_variant_builder_init(&vlan_builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&vlan_builder, + "{sv}", + "vid-start", + g_variant_new_uint16(vid_start)); + g_variant_builder_add(&vlan_builder, "{sv}", "vid-end", g_variant_new_uint16(vid_end)); + g_variant_builder_add(&vlan_builder, + "{sv}", + "pvid", + g_variant_new_boolean(nm_bridge_vlan_is_pvid(vlan))); + g_variant_builder_add(&vlan_builder, + "{sv}", + "untagged", + g_variant_new_boolean(nm_bridge_vlan_is_untagged(vlan))); + g_variant_builder_add(&builder, "a{sv}", &vlan_builder); + } + } + + return g_variant_builder_end(&builder); +} + +static gboolean +_nm_utils_bridge_vlans_from_dbus(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error) +{ + gs_unref_ptrarray GPtrArray *vlans = NULL; + GVariantIter vlan_iter; + GVariant * vlan_var; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), FALSE); + + vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); + g_variant_iter_init(&vlan_iter, value); + while (g_variant_iter_next(&vlan_iter, "@a{sv}", &vlan_var)) { + _nm_unused gs_unref_variant GVariant *var_unref = vlan_var; + NMBridgeVlan * vlan; + guint16 vid_start, vid_end; + gboolean pvid = FALSE, untagged = FALSE; + + if (!g_variant_lookup(vlan_var, "vid-start", "q", &vid_start)) + continue; + if (vid_start < NM_BRIDGE_VLAN_VID_MIN || vid_start > NM_BRIDGE_VLAN_VID_MAX) + continue; + + if (!g_variant_lookup(vlan_var, "vid-end", "q", &vid_end)) + continue; + if (vid_end < NM_BRIDGE_VLAN_VID_MIN || vid_end > NM_BRIDGE_VLAN_VID_MAX) + continue; + if (vid_start > vid_end) + continue; + + if (!g_variant_lookup(vlan_var, "pvid", "b", &pvid)) + pvid = FALSE; + if (pvid && vid_start != vid_end) + continue; + if (!g_variant_lookup(vlan_var, "untagged", "b", &untagged)) + untagged = FALSE; + + vlan = nm_bridge_vlan_new(vid_start, vid_end); + nm_bridge_vlan_set_untagged(vlan, untagged); + nm_bridge_vlan_set_pvid(vlan, pvid); + g_ptr_array_add(vlans, vlan); + } + + g_object_set(setting, property, vlans, NULL); + + return TRUE; +} + +const NMSettInfoPropertType nm_sett_info_propert_type_bridge_vlans = { + .dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = _nm_utils_bridge_vlans_to_dbus, + .from_dbus_fcn = _nm_utils_bridge_vlans_from_dbus, +}; + +gboolean +_nm_utils_bridge_vlan_verify_list(GPtrArray * vlans, + gboolean check_normalizable, + GError ** error, + const char *setting, + const char *property) +{ + guint i; + gs_unref_hashtable GHashTable *h = NULL; + gboolean pvid_found = FALSE; + + if (!vlans || vlans->len <= 1) + return TRUE; + + if (check_normalizable) { + guint16 vid_prev_end, vid_start, vid_end; + + nm_assert(_nm_utils_bridge_vlan_verify_list(vlans, FALSE, NULL, setting, property)); + + nm_bridge_vlan_get_vid_range(vlans->pdata[0], NULL, &vid_prev_end); + for (i = 1; i < vlans->len; i++) { + const NMBridgeVlan *vlan = vlans->pdata[i]; + + nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); + + if (vid_prev_end > vid_start) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Bridge VLANs %d and %d are not sorted by ascending vid"), + vid_prev_end, + vid_start); + g_prefix_error(error, "%s.%s: ", setting, property); + return FALSE; + } + + vid_prev_end = vid_end; + } + return TRUE; + } + + h = g_hash_table_new(nm_direct_hash, NULL); + for (i = 0; i < vlans->len; i++) { + NMBridgeVlan *vlan = vlans->pdata[i]; + guint16 v, vid_start, vid_end; + + nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); + + for (v = vid_start; v <= vid_end; v++) { + if (!nm_g_hash_table_add(h, GUINT_TO_POINTER(v))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("duplicate bridge VLAN vid %u"), + v); + g_prefix_error(error, "%s.%s: ", setting, property); + return FALSE; + } + } + + if (nm_bridge_vlan_is_pvid(vlan)) { + if (vid_start != vid_end || pvid_found) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("only one VLAN can be the PVID")); + g_prefix_error(error, "%s.%s: ", setting, property); + return FALSE; + } + pvid_found = TRUE; + } + } + + return TRUE; +} + +gboolean +_nm_utils_iaid_verify(const char *str, gint64 *out_value) +{ + gint64 iaid; + + NM_SET_OUT(out_value, -1); + + if (!str || !str[0]) + return FALSE; + + if (NM_IAID_IS_SPECIAL(str)) + return TRUE; + + if (NM_STRCHAR_ALL(str, ch, ch >= '0' && ch <= '9') && (str[0] != '0' || str[1] == '\0') + && (iaid = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT32, -1)) != -1) { + NM_SET_OUT(out_value, iaid); + return TRUE; + } + + return FALSE; +} + +gboolean +_nm_utils_validate_dhcp_hostname_flags(NMDhcpHostnameFlags flags, int addr_family, GError **error) +{ + NMDhcpHostnameFlags unknown; + + unknown = flags; + unknown &= ~(NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE + | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE | NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS); + if (unknown) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unknown flags 0x%x"), + (guint) unknown); + return FALSE; + } + + if (NM_FLAGS_ALL(flags, + NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE + | NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE)) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'fqdn-no-update' and 'fqdn-serv-update' flags cannot be set at the same time")); + return FALSE; + } + + if (NM_FLAGS_HAS(flags, NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS) + && NM_FLAGS_ANY(flags, + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE | NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED + | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'fqdn-clear-flags' flag is incompatible with other FQDN flags")); + return FALSE; + } + + if (addr_family == AF_INET6 && (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("DHCPv6 does not support the E (encoded) FQDN flag")); + return FALSE; + } + + return TRUE; +} diff --git a/src/libnm-core-impl/nm-vpn-editor-plugin.c b/src/libnm-core-impl/nm-vpn-editor-plugin.c new file mode 100644 index 0000000000..468ddcead5 --- /dev/null +++ b/src/libnm-core-impl/nm-vpn-editor-plugin.c @@ -0,0 +1,518 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2008 Novell, Inc. + * Copyright (C) 2008 - 2010 Red Hat, Inc. + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-vpn-editor-plugin.h" + +#include +#include + +#include "libnm-core-intern/nm-core-internal.h" + +/*****************************************************************************/ + +static void nm_vpn_editor_plugin_default_init(NMVpnEditorPluginInterface *iface); + +G_DEFINE_INTERFACE(NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT) + +static void +nm_vpn_editor_plugin_default_init(NMVpnEditorPluginInterface *iface) +{ + /** + * NMVpnEditorPlugin:name: + * + * Short display name of the VPN plugin. + */ + g_object_interface_install_property( + iface, + g_param_spec_string(NM_VPN_EDITOR_PLUGIN_NAME, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnEditorPlugin:description: + * + * Longer description of the VPN plugin. + */ + g_object_interface_install_property( + iface, + g_param_spec_string(NM_VPN_EDITOR_PLUGIN_DESCRIPTION, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnEditorPlugin:service: + * + * D-Bus service name of the plugin's VPN service. + */ + g_object_interface_install_property( + iface, + g_param_spec_string(NM_VPN_EDITOR_PLUGIN_SERVICE, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +} + +/*****************************************************************************/ + +typedef struct { + NMVpnPluginInfo *plugin_info; +} NMVpnEditorPluginPrivate; + +static void +_private_destroy(gpointer data) +{ + NMVpnEditorPluginPrivate *priv = data; + + if (priv->plugin_info) + g_object_remove_weak_pointer((GObject *) priv->plugin_info, + (gpointer *) &priv->plugin_info); + + g_slice_free(NMVpnEditorPluginPrivate, priv); +} + +static NMVpnEditorPluginPrivate * +_private_get(NMVpnEditorPlugin *plugin, gboolean create) +{ + static GQuark quark = 0; + NMVpnEditorPluginPrivate *priv; + + nm_assert(NM_IS_VPN_EDITOR_PLUGIN(plugin)); + + if (G_UNLIKELY(quark == 0)) + quark = g_quark_from_string("nm-vpn-editor-plugin-private"); + + priv = g_object_get_qdata((GObject *) plugin, quark); + if (G_LIKELY(priv)) + return priv; + if (!create) + return NULL; + priv = g_slice_new0(NMVpnEditorPluginPrivate); + g_object_set_qdata_full((GObject *) plugin, quark, priv, _private_destroy); + return priv; +} + +#define NM_VPN_EDITOR_PLUGIN_GET_PRIVATE(plugin) _private_get(plugin, TRUE) +#define NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE(plugin) _private_get(plugin, FALSE) + +/*****************************************************************************/ + +/** + * nm_vpn_editor_plugin_get_plugin_info: + * @plugin: the #NMVpnEditorPlugin instance + * + * Returns: (transfer none): if set, return the #NMVpnPluginInfo instance. + * + * Since: 1.4 + */ +NMVpnPluginInfo * +nm_vpn_editor_plugin_get_plugin_info(NMVpnEditorPlugin *plugin) +{ + NMVpnEditorPluginPrivate *priv; + + g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); + + priv = NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE(plugin); + return priv ? priv->plugin_info : NULL; +} + +/** + * nm_vpn_editor_plugin_set_plugin_info: + * @plugin: the #NMVpnEditorPlugin instance + * @plugin_info: (allow-none): a #NMVpnPluginInfo instance or %NULL + * + * Set or clear the plugin-info instance. + * This takes a weak reference on @plugin_info, to avoid circular + * reference as the plugin-info might also reference the editor-plugin. + * + * Since: 1.4 + */ +void +nm_vpn_editor_plugin_set_plugin_info(NMVpnEditorPlugin *plugin, NMVpnPluginInfo *plugin_info) +{ + NMVpnEditorPluginInterface *interface; + NMVpnEditorPluginPrivate * priv; + + g_return_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin)); + + if (!plugin_info) { + priv = NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE(plugin); + if (!priv) + return; + } else { + g_return_if_fail(NM_IS_VPN_PLUGIN_INFO(plugin_info)); + priv = NM_VPN_EDITOR_PLUGIN_GET_PRIVATE(plugin); + } + + if (priv->plugin_info == plugin_info) + return; + if (priv->plugin_info) + g_object_remove_weak_pointer((GObject *) priv->plugin_info, + (gpointer *) &priv->plugin_info); + priv->plugin_info = plugin_info; + if (priv->plugin_info) + g_object_add_weak_pointer((GObject *) priv->plugin_info, (gpointer *) &priv->plugin_info); + + if (plugin_info) { + interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin); + if (interface->notify_plugin_info_set) + interface->notify_plugin_info_set(plugin, plugin_info); + } +} + +/*****************************************************************************/ + +/** + * nm_vpn_editor_plugin_get_vt: + * @plugin: the #NMVpnEditorPlugin + * @vt: (out): buffer to be filled with the VT table of the plugin + * @vt_size: the size of the buffer. Can be 0 to only query the + * size of plugin's VT. + * + * Returns an opaque VT function table for the plugin to extend + * functionality. The actual meaning of NMVpnEditorPluginVT is not + * defined in public API of libnm, instead it must be agreed by + * both the plugin and the caller. See the header-only file + * 'nm-vpn-editor-plugin-call.h' which defines the meaning. + * + * Returns: the actual size of the @plugin's virtual function table. + * + * Since: 1.4 + **/ +gsize +nm_vpn_editor_plugin_get_vt(NMVpnEditorPlugin *plugin, NMVpnEditorPluginVT *vt, gsize vt_size) +{ + const NMVpnEditorPluginVT * p_vt = NULL; + gsize p_vt_size = 0; + NMVpnEditorPluginInterface *interface; + + g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), 0); + + if (vt_size) { + g_return_val_if_fail(vt, 0); + memset(vt, 0, vt_size); + } + + interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin); + if (interface->get_vt) { + p_vt = interface->get_vt(plugin, &p_vt_size); + if (!p_vt) + p_vt_size = 0; + g_return_val_if_fail(p_vt_size, 0); + memcpy(vt, p_vt, MIN(vt_size, p_vt_size)); + } + + return p_vt_size; +} + +/*****************************************************************************/ + +static NMVpnEditorPlugin * +_nm_vpn_editor_plugin_load(const char * plugin_name, + gboolean do_file_checks, + const char * check_service, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError ** error) +{ + void * dl_module = NULL; + gboolean loaded_before; + NMVpnEditorPluginFactory factory = NULL; + gs_unref_object NMVpnEditorPlugin *editor_plugin = NULL; + gs_free char * plugin_filename_free = NULL; + const char * plugin_filename; + gs_free_error GError *factory_error = NULL; + gs_free char * plug_name = NULL; + gs_free char * plug_service = NULL; + + g_return_val_if_fail(plugin_name && *plugin_name, NULL); + + /* if @do_file_checks is FALSE, we pass plugin_name directly to + * g_module_open(). + * + * Otherwise, we allow for library names without path component. + * In which case, we prepend the plugin directory and form an + * absolute path. In that case, we perform checks on the file. + * + * One exception is that we don't allow for the "la" suffix. The + * reason is that g_module_open() interprets files with this extension + * special and we don't want that. */ + plugin_filename = plugin_name; + if (do_file_checks) { + if (!strchr(plugin_name, '/') && !g_str_has_suffix(plugin_name, ".la")) { + plugin_filename_free = g_module_build_path(NMVPNDIR, plugin_name); + plugin_filename = plugin_filename_free; + } + } + + dl_module = dlopen(plugin_filename, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); + if (!dl_module && do_file_checks) { + /* If the module is already loaded, we skip the file checks. + * + * _nm_utils_check_module_file() fails with ENOENT if the plugin file + * does not exist. That is relevant, because nm-applet checks for that. */ + if (!_nm_utils_check_module_file(plugin_filename, + check_owner, + check_file, + user_data, + error)) + return NULL; + } + + if (dl_module) { + loaded_before = TRUE; + } else { + loaded_before = FALSE; + dl_module = dlopen(plugin_filename, RTLD_LAZY | RTLD_LOCAL); + } + + if (!dl_module) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load plugin \"%s\": %s"), + plugin_name, + dlerror() ?: "unknown reason"); + return NULL; + } + + factory = dlsym(dl_module, "nm_vpn_editor_plugin_factory"); + if (!factory) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("failed to load nm_vpn_editor_plugin_factory() from %s (%s)"), + plugin_name, + dlerror()); + dlclose(dl_module); + return NULL; + } + + editor_plugin = factory(&factory_error); + + if (loaded_before) { + /* we want to leak the library, because the factory will register glib + * types, which cannot be unregistered. + * + * However, if the library was already loaded before, we want to return + * our part of the reference count. */ + dlclose(dl_module); + } + + if (!editor_plugin) { + if (factory_error) { + g_propagate_error(error, factory_error); + factory_error = NULL; + } else { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("unknown error initializing plugin %s"), + plugin_name); + } + return NULL; + } + + g_return_val_if_fail(G_IS_OBJECT(editor_plugin), NULL); + + /* Validate plugin properties */ + g_object_get(G_OBJECT(editor_plugin), + NM_VPN_EDITOR_PLUGIN_NAME, + &plug_name, + NM_VPN_EDITOR_PLUGIN_SERVICE, + &plug_service, + NULL); + + if (!plug_name || !*plug_name) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load VPN plugin in '%s': missing plugin name"), + plugin_name); + return NULL; + } + if (check_service && g_strcmp0(plug_service, check_service) != 0) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load VPN plugin in '%s': invalid service name"), + plugin_name); + return NULL; + } + + return g_steal_pointer(&editor_plugin); +} + +/** + * nm_vpn_editor_plugin_load_from_file: + * @plugin_name: The path or name of the shared library to load. + * The path must either be an absolute filename to an existing file. + * Alternatively, it can be the name (without path) of a library in the + * plugin directory of NetworkManager. + * @check_service: if not-null, check that the loaded plugin advertises + * the given service. + * @check_owner: if non-negative, check whether the file is owned + * by UID @check_owner or by root. In this case also check that + * the file is not writable by anybody else. + * @check_file: (scope call): optional callback to validate the file prior to + * loading the shared library. + * @user_data: user data for @check_file + * @error: on failure the error reason. + * + * Load the shared library @plugin_name and create a new + * #NMVpnEditorPlugin instance via the #NMVpnEditorPluginFactory + * function. + * + * If @plugin_name is not an absolute path name, it assumes the file + * is in the plugin directory of NetworkManager. In any case, the call + * will do certain checks on the file before passing it to dlopen. + * A consequence for that is, that you cannot omit the ".so" suffix + * as you could for nm_vpn_editor_plugin_load(). + * + * Returns: (transfer full): a new plugin instance or %NULL on error. + * + * Since: 1.2 + */ +NMVpnEditorPlugin * +nm_vpn_editor_plugin_load_from_file(const char * plugin_name, + const char * check_service, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError ** error) +{ + return _nm_vpn_editor_plugin_load(plugin_name, + TRUE, + check_service, + check_owner, + check_file, + user_data, + error); +} + +/** + * nm_vpn_editor_plugin_load: + * @plugin_name: The name of the shared library to load. + * This path will be directly passed to dlopen() without + * further checks. + * @check_service: if not-null, check that the loaded plugin advertises + * the given service. + * @error: on failure the error reason. + * + * Load the shared library @plugin_name and create a new + * #NMVpnEditorPlugin instance via the #NMVpnEditorPluginFactory + * function. + * + * This is similar to nm_vpn_editor_plugin_load_from_file(), but + * it does no validation of the plugin name, instead passes it directly + * to dlopen(). If you have the full path to a plugin file, + * nm_vpn_editor_plugin_load_from_file() is preferred. + * + * Returns: (transfer full): a new plugin instance or %NULL on error. + * + * Since: 1.4 + */ +NMVpnEditorPlugin * +nm_vpn_editor_plugin_load(const char *plugin_name, const char *check_service, GError **error) +{ + return _nm_vpn_editor_plugin_load(plugin_name, FALSE, check_service, -1, NULL, NULL, error); +} + +/*****************************************************************************/ + +/** + * nm_vpn_editor_plugin_get_editor: + * @plugin: the #NMVpnEditorPlugin + * @connection: the #NMConnection to be edited + * @error: on return, an error or %NULL + * + * Returns: (transfer full): a new #NMVpnEditor or %NULL on error + */ +NMVpnEditor * +nm_vpn_editor_plugin_get_editor(NMVpnEditorPlugin *plugin, NMConnection *connection, GError **error) +{ + g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); + + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->get_editor(plugin, connection, error); +} + +NMVpnEditorPluginCapability +nm_vpn_editor_plugin_get_capabilities(NMVpnEditorPlugin *plugin) +{ + g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), 0); + + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->get_capabilities(plugin); +} + +/** + * nm_vpn_editor_plugin_import: + * @plugin: the #NMVpnEditorPlugin + * @path: full path to the file to attempt to read into a new #NMConnection + * @error: on return, an error or %NULL + * + * Returns: (transfer full): a new #NMConnection imported from @path, or %NULL + * on error or if the file at @path was not recognized by this plugin + */ +NMConnection * +nm_vpn_editor_plugin_import(NMVpnEditorPlugin *plugin, const char *path, GError **error) +{ + g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); + + if (nm_vpn_editor_plugin_get_capabilities(plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) { + g_return_val_if_fail(NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->import_from_file != NULL, + NULL); + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->import_from_file(plugin, path, error); + } + + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("the plugin does not support import capability")); + return NULL; +} + +gboolean +nm_vpn_editor_plugin_export(NMVpnEditorPlugin *plugin, + const char * path, + NMConnection * connection, + GError ** error) +{ + g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), FALSE); + + if (nm_vpn_editor_plugin_get_capabilities(plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) { + g_return_val_if_fail(NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->export_to_file != NULL, + FALSE); + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->export_to_file(plugin, + path, + connection, + error); + } + + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("the plugin does not support export capability")); + return FALSE; +} + +char * +nm_vpn_editor_plugin_get_suggested_filename(NMVpnEditorPlugin *plugin, NMConnection *connection) +{ + g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); + + if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->get_suggested_filename) + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->get_suggested_filename(plugin, + connection); + return NULL; +} diff --git a/src/libnm-core-impl/nm-vpn-plugin-info.c b/src/libnm-core-impl/nm-vpn-plugin-info.c new file mode 100644 index 0000000000..dc77dfd025 --- /dev/null +++ b/src/libnm-core-impl/nm-vpn-plugin-info.c @@ -0,0 +1,1354 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-vpn-plugin-info.h" + +#include + +#include "nm-errors.h" +#include "libnm-core-intern/nm-core-internal.h" + +#define DEFAULT_DIR_ETC NMCONFDIR "/VPN" +#define DEFAULT_DIR_LIB NMLIBDIR "/VPN" + +enum { + PROP_0, + PROP_NAME, + PROP_FILENAME, + PROP_KEYFILE, + + LAST_PROP, +}; + +typedef struct { + char * filename; + char * name; + char * service; + char * auth_dialog; + char ** aliases; + GKeyFile *keyfile; + + /* It is convenient for nm_vpn_plugin_info_lookup_property() to return a const char *, + * contrary to what g_key_file_get_string() does. Hence we must cache the returned + * value somewhere... let's put it in an internal hash table. + * This contains a clone of all the strings in keyfile. */ + GHashTable *keys; + + gboolean editor_plugin_loaded; + NMVpnEditorPlugin *editor_plugin; +} NMVpnPluginInfoPrivate; + +/** + * NMVpnPluginInfo: + */ +struct _NMVpnPluginInfo { + GObject parent; + NMVpnPluginInfoPrivate _priv; +}; + +struct _NMVpnPluginInfoClass { + GObjectClass parent; +}; + +#define NM_VPN_PLUGIN_INFO_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMVpnPluginInfo, NM_IS_VPN_PLUGIN_INFO) + +static void nm_vpn_plugin_info_initable_iface_init(GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE(NMVpnPluginInfo, + nm_vpn_plugin_info, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, + nm_vpn_plugin_info_initable_iface_init);) + +/*****************************************************************************/ + +static NMVpnPluginInfo *_list_find_by_service(GSList *list, const char *name, const char *service); + +/*****************************************************************************/ + +/** + * nm_vpn_plugin_info_validate_filename: + * @filename: the filename to check + * + * Regular name files have a certain pattern. That basically means + * they have the file extension "name". Check if @filename + * is valid according to that pattern. + * + * Since: 1.2 + */ +gboolean +nm_vpn_plugin_info_validate_filename(const char *filename) +{ + if (!filename || !g_str_has_suffix(filename, ".name")) + return FALSE; + + /* originally, we didn't do further checks... but here we go. */ + if (filename[0] == '.') { + /* this also rejects name ".name" alone. */ + return FALSE; + } + return TRUE; +} + +static gboolean +nm_vpn_plugin_info_check_file_full(const char * filename, + gboolean check_absolute, + gboolean do_validate_filename, + gint64 check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + struct stat * out_st, + GError ** error) +{ + if (!filename || !*filename) { + g_set_error(error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_FAILED, _("missing filename")); + return FALSE; + } + + if (check_absolute && !g_path_is_absolute(filename)) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("filename must be an absolute path (%s)"), + filename); + return FALSE; + } + + if (do_validate_filename && !nm_vpn_plugin_info_validate_filename(filename)) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("filename has invalid format (%s)"), + filename); + return FALSE; + } + + return _nm_utils_check_file(filename, check_owner, check_file, user_data, out_st, error); +} + +/** + * _nm_vpn_plugin_info_check_file: + * @filename: the file to check + * @check_absolute: if %TRUE, only allow absolute path names. + * @do_validate_filename: if %TRUE, only accept the filename if + * nm_vpn_plugin_info_validate_filename() succeeds. + * @check_owner: if non-negative, only accept the file if the + * owner UID is equal to @check_owner or if the owner is 0. + * In this case, also check that the file is not writable by + * other users. + * @check_file: pass a callback to do your own validation. + * @user_data: user data for @check_file. + * @error: (allow-none) (out): the error reason if the check fails. + * + * Check whether the file exists and is a valid name file (in keyfile format). + * Additionally, also check for file permissions. + * + * Returns: %TRUE if a file @filename exists and has valid permissions. + * + * Since: 1.2 + */ +gboolean +_nm_vpn_plugin_info_check_file(const char * filename, + gboolean check_absolute, + gboolean do_validate_filename, + gint64 check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError ** error) +{ + return nm_vpn_plugin_info_check_file_full(filename, + check_absolute, + do_validate_filename, + check_owner, + check_file, + user_data, + NULL, + error); +} + +typedef struct { + NMVpnPluginInfo *plugin_info; + struct stat stat; +} LoadDirInfo; + +static int +_sort_files(LoadDirInfo *a, LoadDirInfo *b) +{ + time_t ta, tb; + + ta = MAX(a->stat.st_mtime, a->stat.st_ctime); + tb = MAX(b->stat.st_mtime, b->stat.st_ctime); + if (ta < tb) + return 1; + if (ta > tb) + return -1; + return g_strcmp0(nm_vpn_plugin_info_get_filename(a->plugin_info), + nm_vpn_plugin_info_get_filename(b->plugin_info)); +} + +/** + * _nm_vpn_plugin_info_get_default_dir_etc: + * + * Returns: (transfer none): compile time constant of the default + * VPN plugin directory. + */ +const char * +_nm_vpn_plugin_info_get_default_dir_etc() +{ + return DEFAULT_DIR_ETC; +} + +/** + * _nm_vpn_plugin_info_get_default_dir_lib: + * + * Returns: (transfer none): compile time constant of the default + * VPN plugin directory. + */ +const char * +_nm_vpn_plugin_info_get_default_dir_lib() +{ + return DEFAULT_DIR_LIB; +} + +/** + * _nm_vpn_plugin_info_get_default_dir_user: + * + * Returns: The user can specify a different directory for VPN plugins + * by setting NM_VPN_PLUGIN_DIR environment variable. Return + * that directory. + */ +const char * +_nm_vpn_plugin_info_get_default_dir_user() +{ + return nm_str_not_empty(g_getenv("NM_VPN_PLUGIN_DIR")); +} + +/** + * _nm_vpn_plugin_info_list_load_dir: + * @dirname: the name of the directory to load. + * @do_validate_filename: only consider filenames that have a certain + * pattern (i.e. end with ".name"). + * @check_owner: if set to a non-negative number, check that the file + * owner is either the same uid or 0. In that case, also check + * that the file is not writable by group or other. + * @check_file: (allow-none): callback to check whether the file is valid. + * @user_data: data for @check_file + * + * Iterate over the content of @dirname and load name files. + * + * Returns: (transfer full) (element-type NMVpnPluginInfo): list of loaded plugin infos. + */ +GSList * +_nm_vpn_plugin_info_list_load_dir(const char * dirname, + gboolean do_validate_filename, + gint64 check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data) +{ + GDir * dir; + const char *fn; + GArray * array; + GSList * res = NULL; + guint i; + + g_return_val_if_fail(dirname, NULL); + + if (!dirname[0]) + return NULL; + + dir = g_dir_open(dirname, 0, NULL); + if (!dir) + return NULL; + + array = g_array_new(FALSE, FALSE, sizeof(LoadDirInfo)); + + while ((fn = g_dir_read_name(dir))) { + gs_free char *filename = NULL; + LoadDirInfo info = {0}; + + filename = g_build_filename(dirname, fn, NULL); + if (nm_vpn_plugin_info_check_file_full(filename, + FALSE, + do_validate_filename, + check_owner, + check_file, + user_data, + &info.stat, + NULL)) { + info.plugin_info = nm_vpn_plugin_info_new_from_file(filename, NULL); + if (info.plugin_info) { + g_array_append_val(array, info); + continue; + } + } + } + g_dir_close(dir); + + /* sort the files so that we have a stable behavior. The directory might contain + * duplicate VPNs, so while nm_vpn_plugin_info_list_load() would load them all, the + * caller probably wants to reject duplicates. Having a stable order means we always + * reject the same files in face of duplicates. */ + g_array_sort(array, (GCompareFunc) _sort_files); + + for (i = 0; i < array->len; i++) + res = g_slist_prepend(res, g_array_index(array, LoadDirInfo, i).plugin_info); + + g_array_unref(array); + + return g_slist_reverse(res); +} + +/** + * nm_vpn_plugin_info_list_load: + * + * Returns: (element-type NMVpnPluginInfo) (transfer full): list of plugins + * loaded from the default directories rejecting duplicates. + * + * Since: 1.2 + */ +GSList * +nm_vpn_plugin_info_list_load() +{ + int i; + gint64 uid; + GSList * list = NULL; + GSList * infos, *info; + const char *const dir[] = { + /* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with + * preference to the former. + * + * load user directory with highest priority. */ + _nm_vpn_plugin_info_get_default_dir_user(), + + /* lib directory has higher priority then etc. The reason is that + * etc is deprecated and used by old plugins. We expect newer plugins + * to install their file in lib, where they have higher priority. + * + * Optimally, there are no duplicates anyway, so it doesn't really matter. */ + _nm_vpn_plugin_info_get_default_dir_lib(), + _nm_vpn_plugin_info_get_default_dir_etc(), + }; + + uid = getuid(); + + for (i = 0; i < G_N_ELEMENTS(dir); i++) { + if (!dir[i] || nm_utils_strv_find_first((char **) dir, i, dir[i]) >= 0) + continue; + + infos = _nm_vpn_plugin_info_list_load_dir(dir[i], TRUE, uid, NULL, NULL); + + for (info = infos; info; info = info->next) + nm_vpn_plugin_info_list_add(&list, info->data, NULL); + + g_slist_free_full(infos, g_object_unref); + } + return list; +} + +/** + * nm_vpn_plugin_info_new_search_file: + * @name: (allow-none): the name to search for. Either @name or @service + * must be present. + * @service: (allow-none): the service to search for. Either @name or + * @service must be present. + * + * This has the same effect as doing a full nm_vpn_plugin_info_list_load() + * followed by a search for the first matching VPN plugin info that has the + * given @name and/or @service. + * + * Returns: (transfer full): a newly created instance of plugin info + * or %NULL if no matching value was found. + * + * Since: 1.4 + */ +NMVpnPluginInfo * +nm_vpn_plugin_info_new_search_file(const char *name, const char *service) +{ + NMVpnPluginInfo *info; + GSList * infos; + + if (!name && !service) + g_return_val_if_reached(NULL); + + infos = nm_vpn_plugin_info_list_load(); + info = nm_g_object_ref(_list_find_by_service(infos, name, service)); + g_slist_free_full(infos, g_object_unref); + return info; +} + +/*****************************************************************************/ + +static gboolean +_check_no_conflict(NMVpnPluginInfo *i1, NMVpnPluginInfo *i2, GError **error) +{ + NMVpnPluginInfoPrivate *priv1, *priv2; + uint i; + struct { + const char *group; + const char *key; + } check_list[] = { + {NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "service"}, + {NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM, "plugin"}, + {NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "properties"}, + }; + + priv1 = NM_VPN_PLUGIN_INFO_GET_PRIVATE(i1); + priv2 = NM_VPN_PLUGIN_INFO_GET_PRIVATE(i2); + + for (i = 0; i < G_N_ELEMENTS(check_list); i++) { + gs_free NMUtilsStrStrDictKey *k = NULL; + const char * s1, *s2; + + k = _nm_utils_strstrdictkey_create(check_list[i].group, check_list[i].key); + s1 = g_hash_table_lookup(priv1->keys, k); + if (!s1) + continue; + s2 = g_hash_table_lookup(priv2->keys, k); + if (!s2) + continue; + + if (strcmp(s1, s2) == 0) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("there exists a conflicting plugin (%s) that has the same %s.%s value"), + priv2->name, + check_list[i].group, + check_list[i].key); + return FALSE; + } + } + return TRUE; +} + +/** + * nm_vpn_plugin_info_list_add: + * @list: (element-type NMVpnPluginInfo): list of plugins + * @plugin_info: instance to add + * @error: failure reason + * + * Returns: %TRUE if the plugin was added to @list. This will fail + * to add duplicate plugins. + * + * Since: 1.2 + */ +gboolean +nm_vpn_plugin_info_list_add(GSList **list, NMVpnPluginInfo *plugin_info, GError **error) +{ + GSList * iter; + const char *name; + + g_return_val_if_fail(list, FALSE); + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(plugin_info), FALSE); + + name = nm_vpn_plugin_info_get_name(plugin_info); + for (iter = *list; iter; iter = iter->next) { + if (iter->data == plugin_info) + return TRUE; + + if (strcmp(nm_vpn_plugin_info_get_name(iter->data), name) == 0) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("there exists a conflicting plugin with the same name (%s)"), + name); + return FALSE; + } + + /* the plugin must have unique values for certain properties. E.g. two different + * plugins cannot share the same service type. */ + if (!_check_no_conflict(plugin_info, iter->data, error)) + return FALSE; + } + + *list = g_slist_append(*list, g_object_ref(plugin_info)); + return TRUE; +} + +/** + * nm_vpn_plugin_info_list_remove: + * @list: (element-type NMVpnPluginInfo): list of plugins + * @plugin_info: instance + * + * Remove @plugin_info from @list. + * + * Returns: %TRUE if @plugin_info was in @list and successfully removed. + * + * Since: 1.2 + */ +gboolean +nm_vpn_plugin_info_list_remove(GSList **list, NMVpnPluginInfo *plugin_info) +{ + g_return_val_if_fail(list, FALSE); + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(plugin_info), FALSE); + + if (!g_slist_find(*list, plugin_info)) + return FALSE; + + *list = g_slist_remove(*list, plugin_info); + g_object_unref(plugin_info); + return TRUE; +} + +/** + * nm_vpn_plugin_info_list_find_by_name: + * @list: (element-type NMVpnPluginInfo): list of plugins + * @name: name to search + * + * Returns: (transfer none): the first plugin with a matching @name (or %NULL). + * + * Since: 1.2 + */ +NMVpnPluginInfo * +nm_vpn_plugin_info_list_find_by_name(GSList *list, const char *name) +{ + GSList *iter; + + if (!name) + g_return_val_if_reached(NULL); + + for (iter = list; iter; iter = iter->next) { + if (strcmp(nm_vpn_plugin_info_get_name(iter->data), name) == 0) + return iter->data; + } + return NULL; +} + +/** + * nm_vpn_plugin_info_list_find_by_filename: + * @list: (element-type NMVpnPluginInfo): list of plugins + * @filename: filename to search + * + * Returns: (transfer none): the first plugin with a matching @filename (or %NULL). + * + * Since: 1.2 + */ +NMVpnPluginInfo * +nm_vpn_plugin_info_list_find_by_filename(GSList *list, const char *filename) +{ + GSList *iter; + + if (!filename) + g_return_val_if_reached(NULL); + + for (iter = list; iter; iter = iter->next) { + if (g_strcmp0(nm_vpn_plugin_info_get_filename(iter->data), filename) == 0) + return iter->data; + } + return NULL; +} + +static NMVpnPluginInfo * +_list_find_by_service(GSList *list, const char *name, const char *service) +{ + for (; list; list = list->next) { + NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(list->data); + + if (name && !nm_streq(name, priv->name)) + continue; + if (service && !nm_streq(priv->service, service) + && (nm_utils_strv_find_first(priv->aliases, -1, service) < 0)) + continue; + + return list->data; + } + return NULL; +} + +/** + * nm_vpn_plugin_info_list_find_by_service: + * @list: (element-type NMVpnPluginInfo): list of plugins + * @service: service to search. This can be the main service-type + * or one of the provided aliases. + * + * Returns: (transfer none): the first plugin with a matching @service (or %NULL). + * + * Since: 1.2 + */ +NMVpnPluginInfo * +nm_vpn_plugin_info_list_find_by_service(GSList *list, const char *service) +{ + if (!service) + g_return_val_if_reached(NULL); + return _list_find_by_service(list, NULL, service); +} + +/* known_names are well known short names for the service-type. They all implicitly + * have a prefix "org.freedesktop.NetworkManager." + known_name. */ +static const char *known_names[] = { + "openvpn", + "vpnc", + "pptp", + "openconnect", + "openswan", + "libreswan", + "strongswan", + "ssh", + "l2tp", + "iodine", + "fortisslvpn", +}; + +/** + * nm_vpn_plugin_info_list_find_service_type: + * @list: (element-type NMVpnPluginInfo): a possibly empty #GSList of #NMVpnPluginInfo instances + * @name: a name to lookup the service-type. + * + * A VPN plugin provides one or several service-types, like org.freedesktop.NetworkManager.libreswan + * Certain plugins provide more then one service type, via aliases (org.freedesktop.NetworkManager.openswan). + * This function looks up a service-type (or an alias) based on a name. + * + * Preferably, the name can be a full service-type/alias of an installed + * plugin. Otherwise, it can be the name of a VPN plugin (in which case, the + * primary, non-aliased service-type is returned). Otherwise, it can be + * one of several well known short-names (which is a hard-coded list of + * types in libnm). On success, this returns a full qualified service-type + * (or an alias). It doesn't say, that such an plugin is actually available, + * but it could be retrieved via nm_vpn_plugin_info_list_find_by_service(). + * + * Returns: (transfer full): the resolved service-type or %NULL on failure. + * + * Since: 1.4 + */ +char * +nm_vpn_plugin_info_list_find_service_type(GSList *list, const char *name) +{ + NMVpnPluginInfo *info; + char * n; + + if (!name) + g_return_val_if_reached(NULL); + if (!*name) + return NULL; + + /* First, try to interpret @name as a full service-type (or alias). */ + info = _list_find_by_service(list, NULL, name); + if (info) + return g_strdup(name); + + /* try to interpret @name as plugin name, in which case we return + * the main service-type (not an alias). */ + info = _list_find_by_service(list, name, NULL); + if (info) + return g_strdup(NM_VPN_PLUGIN_INFO_GET_PRIVATE(info)->service); + + /* check the hard-coded list of short-names. They all have the same + * well-known prefix org.freedesktop.NetworkManager and the name. */ + if (nm_utils_strv_find_first((char **) known_names, G_N_ELEMENTS(known_names), name) >= 0) + return g_strdup_printf("%s.%s", NM_DBUS_INTERFACE, name); + + /* try, if there exists a plugin with @name under org.freedesktop.NetworkManager. + * Allow this to be a valid abbreviation. */ + n = g_strdup_printf("%s.%s", NM_DBUS_INTERFACE, name); + if (_list_find_by_service(list, NULL, n)) + return n; + g_free(n); + + /* currently, VPN plugins have no way to define a short-name for their + * alias name, unless the alias name is prefixed by org.freedesktop.NetworkManager. */ + + return NULL; +} + +static const char * +_service_type_get_default_abbreviation(const char *service_type) +{ + if (!g_str_has_prefix(service_type, NM_DBUS_INTERFACE)) + return NULL; + service_type += NM_STRLEN(NM_DBUS_INTERFACE); + if (service_type[0] != '.') + return NULL; + service_type++; + if (!service_type[0]) + return NULL; + return service_type; +} + +/** + * nm_vpn_plugin_info_list_get_service_types: + * @list: (element-type NMVpnPluginInfo): a possibly empty #GSList of #NMVpnPluginInfo + * @only_existing: only include results that are actually in @list. + * Otherwise, the result is extended with a hard-code list or + * well-known plugins + * @with_abbreviations: if %FALSE, only full service types are returned. + * Otherwise, this also includes abbreviated names that can be used + * with nm_vpn_plugin_info_list_find_service_type(). + * + * Returns: (transfer full): a %NULL terminated strv list of strings. + * The list itself and the values must be freed with g_strfreev(). + * + * Since: 1.4 + */ +char ** +nm_vpn_plugin_info_list_get_service_types(GSList * list, + gboolean only_existing, + gboolean with_abbreviations) +{ + GSList * iter; + GPtrArray * l; + guint i, j; + const char *n; + + l = g_ptr_array_sized_new(20); + + for (iter = list; iter; iter = iter->next) { + NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(iter->data); + + g_ptr_array_add(l, g_strdup(priv->service)); + if (priv->aliases) { + for (i = 0; priv->aliases[i]; i++) + g_ptr_array_add(l, g_strdup(priv->aliases[i])); + } + + if (with_abbreviations) { + g_ptr_array_add(l, g_strdup(priv->name)); + n = _service_type_get_default_abbreviation(priv->service); + if (n) + g_ptr_array_add(l, g_strdup(n)); + for (i = 0; priv->aliases && priv->aliases[i]; i++) { + n = _service_type_get_default_abbreviation(priv->aliases[i]); + if (n) + g_ptr_array_add(l, g_strdup(n)); + } + } + } + + if (!only_existing) { + for (i = 0; i < G_N_ELEMENTS(known_names); i++) { + g_ptr_array_add(l, g_strdup_printf("%s.%s", NM_DBUS_INTERFACE, known_names[i])); + if (with_abbreviations) + g_ptr_array_add(l, g_strdup(known_names[i])); + } + } + + if (l->len <= 0) { + g_ptr_array_free(l, TRUE); + return g_new0(char *, 1); + } + + /* sort the result and remove duplicates. */ + g_ptr_array_sort(l, nm_strcmp_p); + for (i = 1, j = 1; i < l->len; i++) { + if (nm_streq(l->pdata[j - 1], l->pdata[i])) + g_free(l->pdata[i]); + else + l->pdata[j++] = l->pdata[i]; + } + + if (j == l->len) + g_ptr_array_add(l, NULL); + else + l->pdata[j] = NULL; + return (char **) g_ptr_array_free(l, FALSE); +} + +/*****************************************************************************/ + +/** + * nm_vpn_plugin_info_get_filename: + * @self: plugin info instance + * + * Returns: (transfer none): the filename. Can be %NULL. + * + * Since: 1.2 + */ +const char * +nm_vpn_plugin_info_get_filename(NMVpnPluginInfo *self) +{ + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + return NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->filename; +} + +/** + * nm_vpn_plugin_info_get_name: + * @self: plugin info instance + * + * Returns: (transfer none): the name. Cannot be %NULL. + * + * Since: 1.2 + */ +const char * +nm_vpn_plugin_info_get_name(NMVpnPluginInfo *self) +{ + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + return NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->name; +} + +/** + * nm_vpn_plugin_info_get_service: + * @self: plugin info instance + * + * Returns: (transfer none): the service. Cannot be %NULL. + * + * Since: 1.4 + */ +const char * +nm_vpn_plugin_info_get_service(NMVpnPluginInfo *self) +{ + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + return NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->service; +} + +/** + * nm_vpn_plugin_info_get_auth_dialog: + * @self: plugin info instance + * + * Returns: the absolute path to the auth-dialog helper or %NULL. + * + * Since: 1.4 + **/ +const char * +nm_vpn_plugin_info_get_auth_dialog(NMVpnPluginInfo *self) +{ + NMVpnPluginInfoPrivate *priv; + + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); + + if (G_UNLIKELY(priv->auth_dialog == NULL)) { + const char *s; + + s = g_hash_table_lookup( + priv->keys, + _nm_utils_strstrdictkey_static(NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "auth-dialog")); + if (!s || !s[0]) + priv->auth_dialog = g_strdup(""); + else if (g_path_is_absolute(s)) + priv->auth_dialog = g_strdup(s); + else { + /* for relative paths, we take the basename and assume it's in LIBEXECDIR. */ + gs_free char *prog_basename = g_path_get_basename(s); + + priv->auth_dialog = g_build_filename(LIBEXECDIR, prog_basename, NULL); + } + } + + return priv->auth_dialog[0] ? priv->auth_dialog : NULL; +} + +/** + * nm_vpn_plugin_info_supports_hints: + * @self: plugin info instance + * + * Returns: %TRUE if the supports hints for secret requests, otherwise %FALSE + * + * Since: 1.4 + */ +gboolean +nm_vpn_plugin_info_supports_hints(NMVpnPluginInfo *self) +{ + const char *s; + + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), FALSE); + + s = nm_vpn_plugin_info_lookup_property(self, + NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, + "supports-hints"); + return _nm_utils_ascii_str_to_bool(s, FALSE); +} + +/** + * nm_vpn_plugin_info_get_plugin: + * @self: plugin info instance + * + * Returns: (transfer none): the plugin. Can be %NULL. + * + * Since: 1.2 + */ +const char * +nm_vpn_plugin_info_get_plugin(NMVpnPluginInfo *self) +{ + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + return g_hash_table_lookup( + NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->keys, + _nm_utils_strstrdictkey_static(NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM, "plugin")); +} + +/** + * nm_vpn_plugin_info_get_program: + * @self: plugin info instance + * + * Returns: (transfer none): the program. Can be %NULL. + * + * Since: 1.2 + */ +const char * +nm_vpn_plugin_info_get_program(NMVpnPluginInfo *self) +{ + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + return g_hash_table_lookup( + NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->keys, + _nm_utils_strstrdictkey_static(NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "program")); +} + +/** + * nm_vpn_plugin_info_supports_multiple: + * @self: plugin info instance + * + * Returns: %TRUE if the service supports multiple instances with different bus names, otherwise %FALSE + * + * Since: 1.2 + */ +gboolean +nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self) +{ + const char *s; + + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), FALSE); + + s = nm_vpn_plugin_info_lookup_property(self, + NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, + "supports-multiple-connections"); + return _nm_utils_ascii_str_to_bool(s, FALSE); +} + +/** + * nm_vpn_plugin_info_get_aliases: + * @self: plugin info instance + * + * Returns: (array zero-terminated=1) (element-type utf8) (transfer none): + * the aliases from the name-file. + * + * Since: 1.4 + */ +const char *const * +nm_vpn_plugin_info_get_aliases(NMVpnPluginInfo *self) +{ + NMVpnPluginInfoPrivate *priv; + + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); + if (priv->aliases) + return (const char *const *) priv->aliases; + + /* For convenience, we always want to return non-NULL, even for empty + * aliases. Hack around that, by making a NULL terminated array using + * the NULL of priv->aliases. */ + return (const char *const *) &priv->aliases; +} + +/** + * nm_vpn_plugin_info_lookup_property: + * @self: plugin info instance + * @group: group name + * @key: name of the property + * + * Returns: (transfer none): #NMVpnPluginInfo is internally a #GKeyFile. Returns the matching + * property. + * + * Since: 1.2 + */ +const char * +nm_vpn_plugin_info_lookup_property(NMVpnPluginInfo *self, const char *group, const char *key) +{ + NMVpnPluginInfoPrivate *priv; + gs_free NMUtilsStrStrDictKey *k = NULL; + + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + g_return_val_if_fail(group, NULL); + g_return_val_if_fail(key, NULL); + + priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); + + k = _nm_utils_strstrdictkey_create(group, key); + return g_hash_table_lookup(priv->keys, k); +} + +/*****************************************************************************/ + +/** + * nm_vpn_plugin_info_get_editor_plugin: + * @self: plugin info instance + * + * Returns: (transfer none): the cached #NMVpnEditorPlugin instance. + * + * Since: 1.2 + */ +NMVpnEditorPlugin * +nm_vpn_plugin_info_get_editor_plugin(NMVpnPluginInfo *self) +{ + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + return NM_VPN_PLUGIN_INFO_GET_PRIVATE(self)->editor_plugin; +} + +/** + * nm_vpn_plugin_info_set_editor_plugin: + * @self: plugin info instance + * @plugin: (allow-none): plugin instance + * + * Set the internal plugin instance. If %NULL, only clear the previous instance. + * + * Since: 1.2 + */ +void +nm_vpn_plugin_info_set_editor_plugin(NMVpnPluginInfo *self, NMVpnEditorPlugin *plugin) +{ + NMVpnPluginInfoPrivate *priv; + NMVpnEditorPlugin * old; + + g_return_if_fail(NM_IS_VPN_PLUGIN_INFO(self)); + g_return_if_fail(!plugin || G_IS_OBJECT(plugin)); + + priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); + + if (!plugin) { + priv->editor_plugin_loaded = FALSE; + g_clear_object(&priv->editor_plugin); + } else { + old = priv->editor_plugin; + priv->editor_plugin = g_object_ref(plugin); + priv->editor_plugin_loaded = TRUE; + if (old) + g_object_unref(old); + } +} + +/** + * nm_vpn_plugin_info_load_editor_plugin: + * @self: plugin info instance + * @error: error reason on failure + * + * Returns: (transfer none): loads the plugin and returns the newly created + * instance. The plugin is owned by @self and can be later retrieved again + * via nm_vpn_plugin_info_get_editor_plugin(). You can load the + * plugin only once, unless you reset the state via + * nm_vpn_plugin_info_set_editor_plugin(). + * + * Since: 1.2 + */ +NMVpnEditorPlugin * +nm_vpn_plugin_info_load_editor_plugin(NMVpnPluginInfo *self, GError **error) +{ + NMVpnPluginInfoPrivate *priv; + const char * plugin_filename; + + g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), NULL); + + priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); + + if (priv->editor_plugin) + return priv->editor_plugin; + + plugin_filename = nm_vpn_plugin_info_get_plugin(self); + if (!plugin_filename || !*plugin_filename) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("missing \"plugin\" setting")); + return NULL; + } + + /* We only try once to load the plugin. If we previously tried and it was + * unsuccessful, error out immediately. */ + if (priv->editor_plugin_loaded) { + g_set_error(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("%s: don't retry loading plugin which already failed previously"), + priv->name); + return NULL; + } + + priv->editor_plugin_loaded = TRUE; + priv->editor_plugin = nm_vpn_editor_plugin_load_from_file(plugin_filename, + nm_vpn_plugin_info_get_service(self), + getuid(), + NULL, + NULL, + error); + if (priv->editor_plugin) + nm_vpn_editor_plugin_set_plugin_info(priv->editor_plugin, self); + return priv->editor_plugin; +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string(value, priv->name); + break; + case PROP_FILENAME: + g_value_set_string(value, priv->filename); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_FILENAME: + priv->filename = g_value_dup_string(value); + break; + case PROP_KEYFILE: + priv->keyfile = g_value_dup_boxed(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_vpn_plugin_info_init(NMVpnPluginInfo *plugin) +{} + +static gboolean +init_sync(GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMVpnPluginInfo * self = NM_VPN_PLUGIN_INFO(initable); + NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); + gs_strfreev char ** groups = NULL; + guint i, j; + + if (!priv->keyfile) { + if (!priv->filename) { + g_set_error_literal(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + _("missing filename to load VPN plugin info")); + return FALSE; + } + priv->keyfile = g_key_file_new(); + if (!g_key_file_load_from_file(priv->keyfile, priv->filename, G_KEY_FILE_NONE, error)) + return FALSE; + } + + /* we reqire at least a "name" */ + priv->name = + g_key_file_get_string(priv->keyfile, NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "name", NULL); + if (!priv->name || !priv->name[0]) { + g_set_error_literal(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + _("missing name for VPN plugin info")); + return FALSE; + } + + /* we also require "service", because that how we associate NMSettingVpn:service-type with the + * NMVpnPluginInfo. */ + priv->service = g_key_file_get_string(priv->keyfile, + NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, + "service", + NULL); + if (!priv->service || !*priv->service) { + g_set_error_literal(error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + _("missing service for VPN plugin info")); + return FALSE; + } + + priv->aliases = g_key_file_get_string_list(priv->keyfile, + NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, + "aliases", + NULL, + NULL); + if (priv->aliases && !priv->aliases[0]) + nm_clear_g_free(&priv->aliases); + + priv->keys = g_hash_table_new_full(_nm_utils_strstrdictkey_hash, + _nm_utils_strstrdictkey_equal, + g_free, + g_free); + groups = g_key_file_get_groups(priv->keyfile, NULL); + for (i = 0; groups && groups[i]; i++) { + gs_strfreev char **keys = NULL; + + keys = g_key_file_get_keys(priv->keyfile, groups[i], NULL, NULL); + for (j = 0; keys && keys[j]; j++) { + char *s; + + /* Lookup the value via get_string(). We want that behavior for all our + * values. */ + s = g_key_file_get_string(priv->keyfile, groups[i], keys[j], NULL); + if (s) + g_hash_table_insert(priv->keys, + _nm_utils_strstrdictkey_create(groups[i], keys[j]), + s); + } + } + + nm_clear_pointer(&priv->keyfile, g_key_file_unref); + + return TRUE; +} + +/** + * nm_vpn_plugin_info_new_from_file: + * @filename: filename to read. + * @error: on failure, the error reason. + * + * Read the plugin info from file @filename. Does not do + * any further verification on the file. You might want to check + * file permissions and ownership of the file. + * + * Returns: %NULL if there is any error or a newly created + * #NMVpnPluginInfo instance. + * + * Since: 1.2 + */ +NMVpnPluginInfo * +nm_vpn_plugin_info_new_from_file(const char *filename, GError **error) +{ + g_return_val_if_fail(filename, NULL); + + return NM_VPN_PLUGIN_INFO(g_initable_new(NM_TYPE_VPN_PLUGIN_INFO, + NULL, + error, + NM_VPN_PLUGIN_INFO_FILENAME, + filename, + NULL)); +} + +/** + * nm_vpn_plugin_info_new_with_data: + * @filename: optional filename. + * @keyfile: inject data for the plugin info instance. + * @error: construction may fail if the keyfile lacks mandatory fields. + * In this case, return the error reason. + * + * This constructor does not read any data from file but + * takes instead a @keyfile argument. + * + * Returns: new plugin info instance. + * + * Since: 1.2 + */ +NMVpnPluginInfo * +nm_vpn_plugin_info_new_with_data(const char *filename, GKeyFile *keyfile, GError **error) +{ + g_return_val_if_fail(keyfile, NULL); + + return NM_VPN_PLUGIN_INFO(g_initable_new(NM_TYPE_VPN_PLUGIN_INFO, + NULL, + error, + NM_VPN_PLUGIN_INFO_FILENAME, + filename, + NM_VPN_PLUGIN_INFO_KEYFILE, + keyfile, + NULL)); +} + +static void +dispose(GObject *object) +{ + NMVpnPluginInfo * self = NM_VPN_PLUGIN_INFO(object); + NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); + + g_clear_object(&priv->editor_plugin); + + G_OBJECT_CLASS(nm_vpn_plugin_info_parent_class)->dispose(object); +} + +static void +finalize(GObject *object) +{ + NMVpnPluginInfo * self = NM_VPN_PLUGIN_INFO(object); + NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE(self); + + g_free(priv->name); + g_free(priv->service); + g_free(priv->auth_dialog); + g_strfreev(priv->aliases); + g_free(priv->filename); + g_hash_table_unref(priv->keys); + + nm_clear_pointer(&priv->keyfile, g_key_file_unref); + + G_OBJECT_CLASS(nm_vpn_plugin_info_parent_class)->finalize(object); +} + +static void +nm_vpn_plugin_info_class_init(NMVpnPluginInfoClass *plugin_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(plugin_class); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + /** + * NMVpnPluginInfo:name: + * + * The name of the VPN plugin. + * + * Since: 1.2 + */ + g_object_class_install_property(object_class, + PROP_NAME, + g_param_spec_string(NM_VPN_PLUGIN_INFO_NAME, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnPluginInfo:filename: + * + * The filename from which the info was loaded. + * Can be %NULL if the instance was not loaded from + * a file (i.e. the keyfile instance was passed to the + * constructor). + * + * Since: 1.2 + */ + g_object_class_install_property( + object_class, + PROP_FILENAME, + g_param_spec_string(NM_VPN_PLUGIN_INFO_FILENAME, + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnPluginInfo:keyfile: + * + * Initialize the instance with a different keyfile instance. + * When passing a keyfile instance, the constructor will not + * try to read from filename. + * + * Since: 1.2 + */ + g_object_class_install_property( + object_class, + PROP_KEYFILE, + g_param_spec_boxed(NM_VPN_PLUGIN_INFO_KEYFILE, + "", + "", + G_TYPE_KEY_FILE, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); +} + +static void +nm_vpn_plugin_info_initable_iface_init(GInitableIface *iface) +{ + iface->init = init_sync; +} diff --git a/src/libnm-core-impl/tests/certs/ca-no-ending-newline.pem b/src/libnm-core-impl/tests/certs/ca-no-ending-newline.pem new file mode 100644 index 0000000000..664e299aa7 --- /dev/null +++ b/src/libnm-core-impl/tests/certs/ca-no-ending-newline.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- \ No newline at end of file diff --git a/src/libnm-core-impl/tests/certs/pkcs8-decrypted.der b/src/libnm-core-impl/tests/certs/pkcs8-decrypted.der new file mode 100644 index 0000000000..2cbdeb5e30 Binary files /dev/null and b/src/libnm-core-impl/tests/certs/pkcs8-decrypted.der differ diff --git a/src/libnm-core-impl/tests/certs/pkcs8-enc-key.pem b/src/libnm-core-impl/tests/certs/pkcs8-enc-key.pem new file mode 100644 index 0000000000..0d08f2d299 --- /dev/null +++ b/src/libnm-core-impl/tests/certs/pkcs8-enc-key.pem @@ -0,0 +1,29 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIE6TAbBgkqhkiG9w0BBQMwDgQIwiGFT4Jz6RsCAggABIIEyJNMddDYofbhydUp +J3VyrYIjv3LziJ7dkTXE3+mEYRCQrGLgljWBbib2JOLVCFt8melL6Yv1RcoVR7X7 +vrRqyycu0DumI4f5+Bf4wc234JNVhSaLYsw244fFtcnK2Gyn4IaVmWmrNvrwfX/w +SKcVmO30D5C5PCKzv2bou5FmnJLKdDQV1t816cr9T8pTx7MHvBzSZXbh86334BhF +T3zNwo8j2/+Gq2NBWUn+2GTTV8/r26aIwPcFi4QH6I2ghBwFmFHqU3/PoRm6nkmg +CqJj2Dggy+8zE5qg0iId7lrio0OjCH+Qed6NGwIa2lgv/bhuJVP3FOk4gqamJWHi +WMaq9McmS+03q2iokYeSQGbx85x+I90RTFZKhFx4dkerf6oTC/YoL4F++ff0e91v +sOrQsBkgRhrRtFwa9OFCzbsknlixONdd+ITkyX490xz1wcZTDkKtMDRLIPWa2O0b +MEq75jPYThZ5pF1vc5r+rqPafN7SfI+DDmhzJYEQNRoCWA4pH9Gwv0ayKnOgoj4K +TuFhXvcyWzTnVXmcqEFyf3CRrB0Ti+Z61enupC+FCuYV5lGsx9kJaTumTk2UPD02 +9Ap3asDLozdEPSXBG3+oCM2s01/IJlxtR84C97r9rpmWTc9K6DCBScETe9KnIghW +PU7XFogueG5Gwpe+x+IlTDq+qiyUNVX1uMGDcIaCC3VsoWqZrpnGGBhsovwBaXKt +T9fT2nE27Fd6DRWso4fgos6PPx7RVveu17BTMVQeUq9L8GrV4JNrE3a9aoXdbUhc +6gMiyAqxh/HEyciYoXsR9oVNi+VM0y8q3hL5nIcgDrCZr/c9aQ8+fuQBDXRrmrQd +bR2iwNLCBnbmQmM/vM333VhJ4MSOKd3SGw/j41K+Nr3uP5KRZUwV+5yy3ef/hGxU +i9JjCmSUt2bfWRUFlNaf1hCTYaKD0xnVr1SLFU4snIgh2qKawyqVc9EE2f+FcOM5 +0RtwQ3ku6FOk3cy6/xeKpResCHbWDS6nQaIKYyLukV+gm5MJIhOMkj2z4T1eXGUr +Nu/L7Gz+ps7ct0lM8W82n5lzSEa5/l1eNGM0wtQoAwutFEZp7Nx/IBKK87jVttr6 +82UVJeRk7rO2Mpobfw2LbKwga4rsuLrx3UwVDBWdLx7dNIc1rGoAxhsc72+skFgF +Uztwy4Yv1Uiji4T6v+mObPZD/HiIDL0vF02Pz08rNlgB0DgaTKrpql2FutIuQAdf +AciffQIoh9VGERlJoWuunG/UTxg2XRl2m1vCDrgBMInax+PXCv7/5Vh21AQc3fWP +uf4k6JSy46hYni7VTVKn6C/Di9z7oIrGl/jDkDsaenAbToyX9VWr3s7EBwnhTQ/I +OQ9bkWCagHIQlwJbu4M4/VAbiR26NrcR0C3JXBlPlT0qvFFB8gKbJAQEXtwIFS2h +m2fe0k6mQASMwdbJYXZ/wfsg5PPAWsKtny1aMvi0mTPSD5uRhIfEGEuR+AT4UbEW +BkEIE0lgGly4P1SpunKDQQE6m/e7h8Nl4pi8SMSme3YoX5MJwCP/CNkLBDVenAZI +oBrdoVox86SjwnUozVG192lcEAULlk+3ZGt6T9JXLBQl9hpNtyTC6SFh84R+5RoN +AevNl1bDfO+Vci0uJw== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/src/libnm-core-impl/tests/certs/pkcs8-noenc-key.pem b/src/libnm-core-impl/tests/certs/pkcs8-noenc-key.pem new file mode 100644 index 0000000000..f73fb55ab2 --- /dev/null +++ b/src/libnm-core-impl/tests/certs/pkcs8-noenc-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQC80HGgFdlFIL2F +W5rHQ99xOkMrWcZ7an9YurDebAE3M0UwqxM24+5mWbxc8FJ8yYugdMzuI5Nq77IA +DwJpv9ZjMfnKC1VDMj3bmmMdPurfx8pLdLw/jhk3wBaYk6vMvh4z66Yvmb7valGq +Pxh6CRTnekNGI9XA7me4JNBlisl0Qasn9g4pl9PiGJAruEamS4Pk6dSWbfw58bs7 +/Yo5ejyt/Mn1n0Q/r3Gv/lAS0qRvmrW6GE1rMtANMfuGRNlAln21TzNcJzykm+sp +RWptxXEI0NY7u9+RP4M3C1mJxWir7AZDbtinpOZH6vF+92yMzgEYOLK/WZVdSPdW +tROv9xtPAgMBAAECggEBAJAfp+vjYZJjuGaYEuAxjdhW+biYcWn5U7V9484TsSXa +i+DnZOZMO8iCjMaAZuZ7zYmwPlE0dK12w29KBbSEy3eySRIRboa5TgBXq3pCcXRZ +g6/vLlZw+AzXIiha6BODt3g4UwUYnWcQx79lJCDa18sNR1a9ucbn8+Har/wiYT3M +JjTbUT6wR6rKEXchB58ZugYGhOTfugSDQg4U/dwEHPIaJ/wme++JUV5B/tjeGCG3 +F43o2Oos5vjfrDSpUKIYZn+2BdhP434jkwj22wQ2sy0ruU/kQx8nogMTRfP1v4GU +9QmNXj/DB24K388ZxcDmcxBJxrGAJ0MohYFo28DqRBECgYEA6hyKEqe2UbJx/+B6 +8mYgHb+pS2j0M4jPl11q9MMLVxLnDY9xZ85IEyWHQEC0GavPSAois0oiDeGAm32c +j6TFyV3/oPTmZSyV93/agWgnH9Xtc481pbNAb0GMfyotvRRE/+6ti9+Cl7oH9Qmm +ldMk7Hn6sK9t2mUOW8idPjKqlqcCgYEAzne25BryLJoIinbRMZg9KTfxfgUE6EKc +Tk5+9CFQn0/AItQJuKbIUyggYH4psWW5hWq6hFlmMYMR48FKv9ry7pZTB0djaoYD +lN+wSuhzUYWXedkAjvPmekITmf6rbnPfwOZvsr8CGMEUekqJPnPLzsQy+Ea2y/fb +QY4SHe7gExkCgYEAr+1scOJpZvFjK7ckjT3jipd6ADpJsORxo7zG4FImFnQU/6K4 +xRpGHWVJQyaccOIkrW04cGUYPDgmrjJx0ZwwKceijvEaphMgS1JgAHklVY4sl3ea +CAAxPqoSi4lFv94Yj/9rmT4IZD6fNivfbJ20FKUBl37tXX4tkRmr2I64lOcCgYEA +x3eqzrclrmdlxvfBZOuScwbkHP6WXhk0TwbQ6eRhsnfmxP8bITSoJoaGuRJKD2Oa +l0WkSobgDwd0uhecsrvBpTS/pDGY32n3fdWZyNTHzEOHMyWtv23tBcJek5ERaBU0 +X3WBBiw4x1eKBBeMfjR6+xhbsbcHlQiw36V05UxJWMkCgYEAhtcYvrfU4K48IJTU +qp03nvd+dMY3IUTdZNOCh8bswLKyn3aq3MfWF9Vp7kDAI3cfyMpSrAQnmg4nVcn6 +Gf3wakG8bpiSRbJnGN+iLm8JsD+3Vw9KzvKOOQVmpT7xt5Kupx1hWvLHQWvfYgOG +qEtTM8/+LD7W3I7midJNt50CD8A= +-----END PRIVATE KEY----- diff --git a/src/libnm-core-impl/tests/certs/test-aes-128-key.pem b/src/libnm-core-impl/tests/certs/test-aes-128-key.pem new file mode 100644 index 0000000000..aab8f463ca --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test-aes-128-key.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,800391B7DD72364B4C2562E0B6AEA000 + +E9dgNCIATOr4CN5c8o6B+8wdqq/I1BLmPmW2qT7YZepoF7E+RUb8ZLjo1VO2XsJw +Ir4EzuH7837zBD9dP5CjlY8cWfR63gZpEWRY5Jub8kzvqiL4UZ0Qr8IHOZxAkKEz +EL1Pn7e+tYt4kA372LPZHWO3vRCgmL1iSJj2/k3avPWAx7NUie4bzGI+00WNv699 +ClKzsJbWB1eiQvYgOr4aVV26oWfa896JkBoGhgZQ6ckqFpsdAos8m46iOSVZrwgq +Y2/d1CvfQod+87c8LRatwAjf+d6YAJJaeMyxjCGuAY6/JyDsorUkM2OlvbTt6WOA +gSPWO8I+Ov6THb4IuPhpIJ30Sl88tc6MlIByW49EWu2G1jPw3L8iqRzZ50Z85dyz +N9yFP91wEwi5F0Zed4iEpg3NVfklEe/VYqCldc5f9fZ84G5V98ZlAdNSqwd/UNBU +iPTflGqVpp1u+J2isOk+Agpj1MCxh2q0RNuvY9KHzOYBScirfbG4DKNbQgS/5Zw7 +3g9YL5Wbo7BczHLiXf/2adu6T8wI1LKRjkeLV9dK1Vw3ZaGy3mB9oFhCgjh9BNHw +wC78CVcUErjtOXdQagiCQn5k5EGeAB97QFROoAFjAmGvq3xCi4EHd9Sk6fcMm7Oi +1fuVR5EXUubF4Llq06lFzQp01s2F73noH49bs3qwdf0n8nrL2XhKB0XCOV/I3K5c +Y3W+YSl361QGjZ/NUcFLIIy+Uro90MmUBNk6af+wGHRJeflpVnK0ATX1PtpNHziz +jiMiIZicjgfVLxl1a5zTl6KUmGWKlZb533adQ0s6q9Qmi5Vk5L5W/GdMjcFtZbM6 +GU7EOkwihMLb3DVsNbm7vb8tUXqe/e5RmXtij8Yb+2a6/M9yaOHa0VjHzdiKHecr +eEYaKQDj7NCWLslNnRRh9GmgXcu2pqBhqRM3HAt3cEaHKKWHTcoWcz11pFwMHNtn +bU9GjGRVc3lCGhVNRiloO0zrKHmcBpDVLw2+ycXXpj/RaBW2fy0xRLKolyla+jEr +zdLzVI61O50ZMycOtPmE7DVZpkokn32hGer1eCOFnsN1lywi4cWLvU0jbQC+CJyw +T9vS8zB3WgOl8rC1AHsfQ4KYajlKleQm89deurQymnt/Qx49SiQA+TpwG9Xvx2TP +3Vc1NwZfM9ZZ1+6xit/rTuS3LhnmhEnGnV5ZyvAdmkCcV2iHjOnLnQWWQn24MHU3 +8Y9D4AdpI5V7Igwr3vH2NZMiw1W2Yc5EJuPAT8nIs5sgOYhXB/QLPJvulvOQhuNC +NPwJ6A505JrVNfHuEaoGUyA+mPeWuLwQo8y8cM6ZdFMG3RrwFNzuYTrc1Z/9GsmA +C0UfHf5dL0r7oWZ1SbpSvsmHYqc8sIypq0ohuLEbpegS/hWP8b2/XDRTjfTiJOrM +4LsUH9PMOJSxDlwS+7e3FdcGfgXfsMgB3aOjQvNpKEolOuv4A5LVFeMrrwtw4Xo1 +EuhstZwyarUTJenDUXzkakhA+8Yw/g2a7RsnANVTkeBuv2PbqFL4zdlsWvcpkz41 +ESxx1siSeU1E9beOII0zSi8vUD0IAevRHaWSlfU2po600IzX1FN97pa4DJV2ycgn +-----END RSA PRIVATE KEY----- diff --git a/src/libnm-core-impl/tests/certs/test-aes-256-key.pem b/src/libnm-core-impl/tests/certs/test-aes-256-key.pem new file mode 100644 index 0000000000..e51bafd3d6 --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test-aes-256-key.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,5FF6BD2D4E57E8933D4A6814DEF5305A + +9Br+xw6XOg7qUqfeE5PJ4g/PAm7eTcPMb4FzSKkaEosLo6oj4f37TwXuojJZeAmi +1EytpqM1vdYHCLdjg+qYaTIq6mzMZIyoaREokcOhcNrq5S0J39gJLVV9LjiXhCAH +GQgDBnbRT6HGz70AyTRLcW9aj6uBzTv/m92sLUw2txFeBXK8n2AA1oHJTgsFNYjf +/ZvTCE1VMQHDPx31Vn5WXSUHNc0hx4MTIwpHqWI17ohr8IiWCs5HXVfVaqrNeNEw +haD7fg8oNxjLs46/4dDWmfWXhDsMFSweZv03gZdyVjwn1IOqeVGmTdLpllfgOW7E ++XE8Y/d55s5nkOxu6eXNMtWgjclKBGr2iMxxnODmEsUt2WcV98cPS+25o3hOfy3s +NIcfxtWVRFUtjqf3ragyGLuXFqATkj1slj4LVMeewRJ1g+Z6ti0mwBN+ZrYtKdec +FRNb4zr5FW+3SqkIIJVfxJEYJDB4zODhMg8tySEHLKuT0uz42YQ4aoOHTzO5WDBY +2BI7TjRppXcExPnkAk5jqbKA6BjT9KcAVyypfxDKvCeXKdjDcL6ISOBSm6cQBh8D +HxsFzMy9PF6kKNeiNiEsVPnKYvhvs1hTBtp+IAgJ6KZnCDKplZFxo/mBAlV2KyCT +x+Mhmme3fXdLJkvxlVJAoAhwgXvomVCVTGI3JhcQIqVgxPIKYpqlHVFC7JjG+yQX +tvzCPtr9G9+Ofrm6zXjlDD7zNyl/KfFtEWhO2ePHkQlCEuKJnsnRIf/wQ0viG0yY +MH31Z/84o2pKLBKY5fq8+eYuYoP9Rk4W2LpjGMvdkKhEHL26kZofeFyqD+JcaxHc +kQh7/SbWAsREGb9Jp7I2q1mo749mse1oSFIQa5gN3jB0mgHZd6edRYeW2Up+rqEK +k6Xd6uqs7bZd5W9sP7Cf6yJOFEjqFVLQEVEXWSchgeta/JNrjGr3UzLFN2S+vhvX +XgDa41y2UdXHRqj2s864u0ZDPyGXYZnVbvQn/8xHQ7rvxHowpTn+XXUEf0AQnk3j +9h++3McwP8GuVxkwc6o9TfOL+ell5jup7F3SekwEiE3hqY8x87g6X2zD5VSnfCy3 +0t0LmPGI1b3LABeYjA1WEdhoTlHrNLkwOR4gsudrJ5nxIzfGy+IHaloXLJy4YKfX +pJ+qyGRUR42YD9IhiEmmmO1VoJgVEYfBiz50Jg8emddku6eKdmv9IKjiSb2pTbDS +4oUYKg109OOn+krk67dNXofAXrBa8v7QusC0yz9N25H05Xyou1iqpGk+uBrTqEO6 +lW9lWQo57BQU9og40xMKH/xQgIxfQRktUKsPizj8mKil4izo5KgjPSqBeEbj+Q3c +0FKlrpTXQlXfX5Z5esqMuCSiwQEzoJR+V+SUaSVcg1av0k/CJMin4Cr8roai+OjK +lhaQIvx35Bzd02yERYsfpDjmQCXmIeiDm8JtB6znbQPUJ4d8kzWR+5ACOZW/dUss +YhWJRkZpkIwTY+/sDU4mnP2R37MNo+OH4CwZyUDHjlkRPGW+6JBEpnnlI9a/1Vb1 +pjAGpi/8u/luvZGTzCzxQG2dZc5YQR869U+wFsFbLRiD0aP2SpdOH0QxxPOcdR8+ +HWyL01BJBKyK/wZWJhe+63zlk1L5CA0XYpoNkYpMlPNZkcqR7QzUOATfuBgI2aPM +AXaweaAWhpPCDsc2RypIs9DhTiCCkt8tq8Au15hVUKAoshLeewPtv0t75MEC0hVB +z6FVnNlqq0cqqcSVqvUG6JUGtFOGgG3ifEMXggq5k12+wGzY63DLR8dFPNpOL6/1 +nocOayHJIU9M8PP817PzhAUAePRRUKRg8kkbKKeZnCJxoF7O15AFVEJnl9Vyokkz +bULYhzYVx3xh8THMi+5jsnKWPJyMeYHbHH3C658SIw6Ff9fgEWscv5ZkGYdKMg+l +8hBn+++SoqIO+F3lOGco+s8qlYox106lUwJEtORXcBxmkaHSo/X2AVO8Owt4vYli +mjWnY6V9vooBgOuCMcY780pcoj2lSf9JPHDYK0j8t5VumDUSLyLt+tCj0yv/vl5L +9L++vbu2akZRC9ChijYpfhTvXoG36ePhoT7AGGnhpFjjw1VqG80GY4XSODKzH86w +kUcZoErb8swUPYOtsybtuPb+6c/YofQ8GfpVosPZgSRD4+U7v+zA3/z8xF2B0xt6 +uV8hXbropuni8KmbFuKrPZK3p2v2aZ8F0+GITwS75/hbT6D7ruUSr5q4V0VKeE8G +k3QSI0s6+74stPv3S/ByCxu8q51ffYqVw00wzPpEc4SmHEa0R7IczJKXupmDdZZM +1rASSBNzS5TZDBXP6S7npYQ8nHhgXTdCFO7eM3bp24B/i2o0s7+gkKrz0DkEbv9I +UrCJjTL8OIIP4qSLMILzZ8pB28c+zyM482ZqFY/2b7j6WlTiqa9P1adrD1gLxTQ0 +Sw9xY+sY3PAJqcnPA5NjDZL/h5plgHhCqDa9pEtdBVG2Mxcl9bXbphwD1MIzj4gr +xtlW1HUJ/iOhFcXldOJ1MCt++Bm5av4mL5adQ/oUnL5Q0oZZFwqT09k7xe7lZ98N +uj2Lfl8NN7N3ama9KatgbX5g6IALuk/rJN/4KEiiu24m+lR7c5L0pg/cG6LIFjmk +HlTsc0ANCgeZBhDJ8kvjcXDhFOqoYE/+D2VO6ZEHRsDibQ+kjpaH+DiD01/gh0N0 +HM6GGtm3GbOyZUhw5OFz04xzcyFYo2xaqzgaZieAOcrt2s6XyPVf1gww08/HtTMR +gLg14MUQvRXV6kPJfdu4OLZ//b6J0KnzVyLDRdOrWIj2raLWmKwQN9qv05/yskcD +Y6x7wq3v6iZpFjDc53sslhwp2XRsoWT9X5alVspz8WvP/kqgkTdzpPFdp1vIovOQ +kRXdzzKICDGDJUIcTL8cJ3Dv4XqNR/sVyuB4dfndzQQApbdYTDNpwX0VJDBjMkQy +Up6aiUknxa6Cbp7b1ZfUQY8yNBAIZL+R8dmobT3nAHW61DaASHSxn+elCD2Ja/6b +EiWikskyN6crMAv35ILr5ySsZK97ttNNmRoGFbt8bTjRd83Ie+UfH445kCKsY83x +aDCvWm+bbV6M9rSgjhJ3bWOudiw+EBMGvSamSnS7CYnRmwq4t+4bM2sh2nYKY0qw +-----END RSA PRIVATE KEY----- diff --git a/src/libnm-core-impl/tests/certs/test-ca-cert.pem b/src/libnm-core-impl/tests/certs/test-ca-cert.pem new file mode 100644 index 0000000000..ef1be20d2b --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test-ca-cert.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEjzCCA3egAwIBAgIJAOvnZPt59yIZMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYD +VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw +FQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UE +AxMEdGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAzMTAx +NTEyMTRaFw0xOTAzMDgxNTEyMTRaMIGLMQswCQYDVQQGEwJVUzESMBAGA1UECBMJ +QmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55 +IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3 +DQEJARYNdGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKot9j+/+CX1/gZLgJHIXCRgCItKLGnf7qGbgqB9T2ACBqR0jllKWwDKrcWU +xjXNIc+GF9Wnv+lX6G0Okn4Zt3/uRNobL+2b/yOF7M3Td3/9W873zdkQQX930YZc +Rr8uxdRPP5bxiCgtcw632y21sSEbG9mjccAUnV/0jdvfmMNj0i8gN6E0fMBiJ9S3 +FkxX/KFvt9JWE9CtoyL7ki7UIDq+6vj7Gd5N0B3dOa1y+rRHZzKlJPcSXQSEYUS4 +HmKDwiKSVahft8c4tDn7KPi0vex91hlgZVd3usL2E/Vq7o5D9FAZ5kZY0AdFXwdm +J4lO4Mj7ac7GE4vNERNcXVIX59sCAwEAAaOB8zCB8DAdBgNVHQ4EFgQUuDU3Mr7P +T3n1e3Sy8hBauoDFahAwgcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDF +ahChgZGkgY4wgYsxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO +BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQL +EwdUZXN0aW5nMQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRl +c3QuY29tggkA6+dk+3n3IhkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC +AQEAVRG4aALIvCXCiKfe7K+iJxjBVRDFPEf7JWA9LGgbFOn6pNvbxonrR+0BETdc +JV1ET4ct2xsE7QNFIkp9GKRC+6J32zCo8qtLCD5+v436r8TUG2/t2JRMkb9I2XVT +p7RJoot6M0Ltf8KNQUPYh756xmKZ4USfQUwc58MOSDGY8VWEXJOYij9Pf0e0c52t +qiCEjXH7uXiS8Pgq9TYm7AkWSOrglYhSa83x0f8mtT8Q15nBESIHZ6o8FAS2bBgn +B0BkrKRjtBUkuJG3vTox+bYINh2Gxi1JZHWSV1tN5z3hd4VFcKqanW5OgQwToBqp +3nniskIjbH0xjgZf/nVMyLnjxg== +-----END CERTIFICATE----- diff --git a/src/libnm-core-impl/tests/certs/test-cert.p12 b/src/libnm-core-impl/tests/certs/test-cert.p12 new file mode 100644 index 0000000000..ae4a683049 Binary files /dev/null and b/src/libnm-core-impl/tests/certs/test-cert.p12 differ diff --git a/src/libnm-core-impl/tests/certs/test-key-and-cert.pem b/src/libnm-core-impl/tests/certs/test-key-and-cert.pem new file mode 100644 index 0000000000..dec9aa1b8f --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test-key-and-cert.pem @@ -0,0 +1,118 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4DE0615F23D82107 + +QPNCO5Dobvz9dDhN32KkZRoEifW+HDm2PCbRQhKDiscGwB6LgypvVjHNsZiFKwzz +L4R51UqgQeJx7GSGJqE626e9z9J+UNBhop02aOO2X0eSPdvBzr/uJ6Umiyr1xqD7 +zWf7u9l5kXElDJRhK+87GMBewp4Ie9NeXDjhF8hzC5Kiulen4AH3AYnfH3S7DimU +h8GFMg8inrudrTbcjBhCdPeHG2jCygOxw3InRFz7uaN6LIhOaPQvmvpP4Cc1WRnW +ZPq9o+eU3fPWPD5t+Op/VzYLvKwgBy/yK1rQXUm6ZMO7MhhRJ94ZCsJv+nVWpJlv +QyBlxDKxwfkfYbDELdnnDQdHdMbKatLqa0KhSkgpp8LywBtanPz731tyT0r7b3na +eLdra59lRU7ZQLPEdS3lPZd2O/KQvWf8wbg7MjXS9LxQ7R5HOPu6DNJlwXVZBmmo +cAfu2q8ubU2IePvWLD1GOrBi6hE9TiGvFJkw+wBK+t72sz3njv9Xm/zlxruaEk5m +RW/kybU3FP4PtjriBbskz3/VZaaxuRN7OoOYTkmyHmG1ADgcRUV6fea19qqsBlN8 +xb+SRtoH28oT/JVWU5neE2dbNzk5LeVO+w70NNdR5s5xqkBhbGGaJxvXwNP4ltFr +T06SMh8znOLKwWB00aRtwfU7jOwR3mOleQO4ugIHmau3zp1TqzAHW8XtpuV7qVeI +ESZOZuf0vW43BtNzgLXt1+r+bmsMsRwhnyomL9M0TUyyBdVYY9GkzTG9pOESheRo +RSvAZ8qKGUliTpgBcbt2v1+NqkszcHa6FxuvS8YU4uo5/GqsgTxHTNIB232hIrrZ +EIm6QL9TC5oFXMjy6UNqoCm5Nb8DBJ6aErt7pt7aoktqUW3O3QIzQT3IbZ4nAcTt +lVF4d7j29I9t7bcC8GOVU1neilguZUss4ghJg9x4zI5UZdR7hZ8fbFT47TyxB+j5 +r0YdmjbjVTaSyaN2JGh1wvb4TzawGNVx/U2EJE16HigOtPfsfQRJ3x+FROKBdVa4 +aIFYXkRBeIPxX6n9pcw0lBCsnXo6/5iTjQSk2VqO3rHO/wyWiEjNczhL33dY2A8W +GG5ECMO5SqXZHQQzpABqK94dxe3UC8aEESO5NhEqDuV7qQGol0qPKrUA3wb0jb2e +DrejJ9HS2m1SUDmjpvvmEGy6GN7CRibbKt5rNZdJNNvWArOF5d0F6wkixQLl73oE +lq5gLQQk9n7ClleKLhlQpBCorxilBbzmSUekkJLi0eaZiBBFWBX9udqnUZloXTgO +8qwuO8K/GPR9Jy1/UH2Vh1H+wivaqKTVgEb0NotzgzECgTEFKJafl7rUNs1OZRZ3 +VBjevi6+iDpxVFgF71kXfdUC4ph0E1XDl0ja2rrKQGivMkUhWJ57+4EV5+hBkAnt +G0RV45NwHXLrK2bd8F9PlRk2XHW6mIcFRXsW1DjeBhk/sQjvlO9R01GRSgcXtekJ +tmX17FWrMrzXHpvy1IC3fk4RVnSjpzQ8O+17YE8/la9wVaeZZzHyYFmMT7VXjIhW +QozJQ0vJ2jxJRh5GYn3tpJzdaeRfvTBik0pChNdUTnWP+BJ35xoCTs8iwJbmgVZ1 +-----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=Testing, CN=test/emailAddress=test@test.com + Validity + Not Before: Mar 10 15:13:16 2009 GMT + Not After : Mar 8 15:13:16 2019 GMT + Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=Testing, CN=test1/emailAddress=test@test.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:cd:34:b1:2e:b0:04:c6:f4:2b:a2:c0:a0:39:7a: + 82:ed:96:c4:f7:19:83:91:5c:b4:e7:9c:de:ec:48: + ec:2d:e4:51:08:26:42:ac:d3:98:26:7a:72:f7:49: + c2:9e:66:05:c6:47:29:fe:3b:ac:6b:af:6f:5e:a8: + 03:5a:73:33:ba:19:03:00:35:f5:00:bc:a8:be:14: + ce:46:69:e3:6d:ed:34:37:85:55:87:62:b3:b7:c9: + c0:cc:9a:aa:61:05:5b:cd:a2:17:42:d3:e5:6f:1c: + 60:8d:c2:15:41:46:f8:12:54:d0:38:57:e1:fd:8d: + 44:c8:fb:56:b3:b9:6c:e9:f8:9e:21:11:57:1b:8b: + f9:cf:e3:17:e7:d8:fd:ac:d1:01:c6:92:30:f3:2d: + c9:d6:c1:f0:3d:fd:ca:30:dd:75:74:e7:d1:6b:75: + d8:c5:4d:43:61:fe:f6:ad:7e:4c:63:7c:03:17:a2: + 06:8f:d0:8b:69:d3:7a:07:0f:0b:a2:cf:0c:70:38: + ba:cc:55:35:60:84:58:d8:d2:be:1f:ef:76:a9:ba: + ae:6a:dc:08:97:80:de:42:00:b7:d4:ce:9a:b0:36: + 2a:c7:6f:45:04:7c:ea:41:19:d8:b9:19:04:1f:11: + a9:22:80:bd:69:08:15:0d:3c:de:cd:7e:88:6c:0f: + a3:43 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + CE:03:7E:EF:E7:DE:C9:87:BF:DE:56:F4:C8:A3:40:F6:C8:6F:05:8C + X509v3 Authority Key Identifier: + keyid:B8:35:37:32:BE:CF:4F:79:F5:7B:74:B2:F2:10:5A:BA:80:C5:6A:10 + DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=Testing/CN=test/emailAddress=test@test.com + serial:EB:E7:64:FB:79:F7:22:19 + + Signature Algorithm: md5WithRSAEncryption + 7a:20:93:63:40:73:7d:33:01:2e:c0:13:52:a4:a7:e1:4d:82: + f4:fb:b2:7b:d0:2b:5a:3f:0e:3c:28:61:71:ab:01:4d:fe:89: + b5:cd:2f:97:59:93:53:9d:51:86:48:dd:b9:e4:73:5e:22:0b: + 12:0d:25:39:76:16:44:06:0c:40:45:21:6b:a6:b1:e0:bf:76: + 1b:36:f3:1e:41:82:57:d9:59:b7:60:40:43:1c:1d:79:f6:48: + 32:5c:4e:e2:06:89:96:41:d2:54:1f:4a:6f:f6:78:a5:3c:02: + 85:21:e2:65:e1:8a:6d:24:19:95:f8:c0:35:ab:bd:ff:3d:f1: + fb:50:2d:30:1e:67:a6:7c:50:f9:d5:77:66:77:5a:14:0f:5c: + cd:21:09:9b:a3:92:57:19:dd:01:a4:18:c5:f9:70:e4:17:43: + 8d:b1:e6:61:e9:50:89:83:4f:ce:a4:57:68:58:40:70:ae:71: + 1c:47:66:d2:30:54:50:ea:3a:87:32:64:3b:18:42:fe:5a:19: + 07:64:f7:f1:b1:10:07:fd:a7:d2:a7:a8:05:79:5b:25:ba:69: + 7b:1a:3e:b1:3e:e4:17:17:01:ba:eb:54:ae:83:00:ed:66:62: + 8d:c0:3e:8a:b4:27:5f:e9:01:ce:20:c3:34:a9:28:c0:6f:c7: + 3b:65:fe:f9 +-----BEGIN CERTIFICATE----- +MIIEojCCA4qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCVVMx +EjAQBgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMO +TXkgQ29tcGFueSBMdGQxEDAOBgNVBAsTB1Rlc3RpbmcxDTALBgNVBAMTBHRlc3Qx +HDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMDkwMzEwMTUxMzE2WhcN +MTkwMzA4MTUxMzE2WjB6MQswCQYDVQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJl +MRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzEOMAwG +A1UEAxMFdGVzdDExHDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNNLEusATG9CuiwKA5eoLtlsT3GYOR +XLTnnN7sSOwt5FEIJkKs05gmenL3ScKeZgXGRyn+O6xrr29eqANaczO6GQMANfUA +vKi+FM5GaeNt7TQ3hVWHYrO3ycDMmqphBVvNohdC0+VvHGCNwhVBRvgSVNA4V+H9 +jUTI+1azuWzp+J4hEVcbi/nP4xfn2P2s0QHGkjDzLcnWwfA9/cow3XV059FrddjF +TUNh/vatfkxjfAMXogaP0Itp03oHDwuizwxwOLrMVTVghFjY0r4f73apuq5q3AiX +gN5CALfUzpqwNirHb0UEfOpBGdi5GQQfEakigL1pCBUNPN7NfohsD6NDAgMBAAGj +ggEfMIIBGzAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy +YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUzgN+7+feyYe/3lb0yKNA9shvBYww +gcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDFahChgZGkgY4wgYsxCzAJ +BgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkx +FzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQLEwdUZXN0aW5nMQ0wCwYD +VQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tggkA6+dk+3n3 +IhkwDQYJKoZIhvcNAQEEBQADggEBAHogk2NAc30zAS7AE1Kkp+FNgvT7snvQK1o/ +DjwoYXGrAU3+ibXNL5dZk1OdUYZI3bnkc14iCxINJTl2FkQGDEBFIWumseC/dhs2 +8x5BglfZWbdgQEMcHXn2SDJcTuIGiZZB0lQfSm/2eKU8AoUh4mXhim0kGZX4wDWr +vf898ftQLTAeZ6Z8UPnVd2Z3WhQPXM0hCZujklcZ3QGkGMX5cOQXQ42x5mHpUImD +T86kV2hYQHCucRxHZtIwVFDqOocyZDsYQv5aGQdk9/GxEAf9p9KnqAV5WyW6aXsa +PrE+5BcXAbrrVK6DAO1mYo3APoq0J1/pAc4gwzSpKMBvxztl/vk= +-----END CERTIFICATE----- diff --git a/src/libnm-core-impl/tests/certs/test-key-only-decrypted.der b/src/libnm-core-impl/tests/certs/test-key-only-decrypted.der new file mode 100644 index 0000000000..c8652537a6 Binary files /dev/null and b/src/libnm-core-impl/tests/certs/test-key-only-decrypted.der differ diff --git a/src/libnm-core-impl/tests/certs/test-key-only-decrypted.pem b/src/libnm-core-impl/tests/certs/test-key-only-decrypted.pem new file mode 100644 index 0000000000..1a25da5e7d --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test-key-only-decrypted.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAztLp+/SkzmaHzIst0sO4+r7qUwiVnidKBHgxoTbS5UL1dvck +cbjTEP23V4ZoKQIb6ZMrr8B+PVgWNBAlhX4oLUL8NH/WTwrntrlAUcjliWDNc1Fj +Z+FZNjFe0IdLXZeKQiLTQvKDYnmERVvYIJfi0TQjXuy/ikF8rYBQ85scUV3kKRzB +xnyhAHAP9nl3AyL1S6t2yiCr4U5TbIZo6dYPbpVLtbXP02zUc9vAPR0gIHKrPiW7 +P81fLXf91wuo6wxzwD90JxdWzzGaqe3BOSfHqul3SPRtVok1XHlb9i+Mn5O8ExzQ +dF8wGxVDcY7/Gt9lZWnCilqrBEqA3iApjUgcgwIDAQABAoIBAQC77HCmepf04ryp +Yhz00NoXG7mWUMqBtXlPrlaKAWKG5dxbiBwZKLK/UYlxgbLK8BuklBCx1Nnfq1Yh +YDp3nTWsSp0WpsF3eJUqNhD3Pu8xcD+9dEo6bUu+LgXUu9oC5Fq/1RzYS7qNk5RX +4Sf0FY4GQLWS3tL7MJ20mE71yg5k7qRbDydOyhTh1m1CpRYONWxSsWVLM8KGRDJp +iF0cdPfD5yoPFpgDk8gwzrnXJH2Wqzv8GvyYykRK5AW7tE50y0rTAM42WZ7YS6aZ +FNMmtYxeyzXLY3LgPP0uko5anz3OXRcqCfHfFANG0y7B9MehbrjMgI6S1BbzFl07 +V1zVQVqhAoGBAPIfrWMlh1fHlRh4iRGXK2Hvxyv2oNz9KvQ4qRaLV9ejRDzdt7Pi +/utbi5LGBuDw9016nXM3I77b6PukHzsHFnWGRnyRSbkMMt6mE17nggmNqcpFWfE8 +E7HcKMhk4gbuo5AHD3Ee1Gac2AUDnzYiE+sS6WI3O9d77cc5ych5jZ+nAoGBANqt +VZCttjY0E+hEyTP37eaE8u0jfdK8AflTJlNUHWKXglES525iu8I/Bso8KaQYsYF3 +SezGRd3KQepQhtMjFKfSpF+tbnboP57Y3XGo8xhbxqV4kRX+XGsVoW3Vg2nPKBrR ++dIY5nMwua+gkHWp9RDcemD2reiIZBVx95fK8dfFAoGAdCSH2pBs/MlrFqLzNTHr +iH4pb0hN39O9YAsx6POMfo79s6izbyHLIID4Ub6WHB7ashrIHjVr+yin+NXAeWMr +/dIcS7Kxx4c3e5/0mMi6kvSWZsWfoF0uIVo3YfEqjyK36OXKHXwpbNN9t+IF5ESy +g0e+FfPiy7nR1Ig+5+CO8+8CgYEAp/75+Ug677FaidouaMpT7gC9UAkwJLFjItQK +YYIBgTi8WOSY/2jCrhwVb1CA/RwrYjbuiARasGUt9oEe0x3kRHnC5e4rKxaJqdMZ +bLRK7a+0EHNrouXiwjG/7s1VQ/ht6wzdS9btVBlezdogoQSMzQNU0SExwa7mlMMV +X3v+B7ECgYAK+Yt4jnLH1LNWoDTU0Ug5hyXsQXV8lVBSnrkvS7GtP6ZA/4OqG7lJ +/bTYFZGoiAGzOnC+YlAqSIu45CEnpr2xBsThQiWUVxspmQD1lEWWFcd77DPUwn3C +59pLgx0AqJE3n6lBOwehiXbFKBdVzX8PfPZpuCK6qc/RiTILktwURA== +-----END RSA PRIVATE KEY----- diff --git a/src/libnm-core-impl/tests/certs/test-key-only.pem b/src/libnm-core-impl/tests/certs/test-key-only.pem new file mode 100644 index 0000000000..5ef530e9ab --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test-key-only.pem @@ -0,0 +1,92 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48 + +KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k +r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+ +PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj +5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/ +amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj +yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR +PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV +xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg +T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab +HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu +Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev +0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB +m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf +rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f +FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S +uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN +vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt +1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh +ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw +l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v +tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm +aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco +0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD +u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj +DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg +-----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com + Validity + Not Before: Feb 2 02:22:25 2009 GMT + Not After : Jan 31 02:22:25 2019 GMT + Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3: + b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36: + d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86: + 68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10: + 25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9: + 40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31: + 5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79: + 84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41: + 7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c: + a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20: + ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5: + cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25: + bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f: + 74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9: + 77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93: + bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df: + 65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48: + 1c:83 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B + X509v3 Authority Key Identifier: + keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E + DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com + serial:E6:4C:5C:96:26:5E:D6:D0 + + Signature Algorithm: md5WithRSAEncryption + 88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c: + a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b: + e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5: + b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4: + 39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2: + ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6: + 76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32: + 4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48: + e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12: + 9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e: + 6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df: + 88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f: + d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16: + a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03: + 6b:80:38:6e + diff --git a/src/libnm-core-impl/tests/certs/test-tpm2wrapped-key.pem b/src/libnm-core-impl/tests/certs/test-tpm2wrapped-key.pem new file mode 100644 index 0000000000..f3fd271c32 --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test-tpm2wrapped-key.pem @@ -0,0 +1,14 @@ +-----BEGIN TSS2 PRIVATE KEY----- +MIICEwYGZ4EFCgEDoAMBAQECBQCBAAABBIIBGAEWAAEACwACBEAAAAAQABAIAAAA +AAABAOJdEXw1LO6JWskHBSYQc1NfJAe9DOAyLA4XbXI5asQ8aNbmL51DP9mQQpqq +a1CSRZAIuuorMxyRBBAFpF4OZqjNd/Nskp3iMmifr5yqAYZ3M31MqlBFiiyctqKp +VwIChwsIbKelrsXbty1icP2CH+k4w/nPymPjnfYtgpMe8QW8n6U156ujIdJcISds +QFcl3nrDnD1IumX0/LfanQrRDVSI+m6szvTrdsPMtGeaNMnlz0gx74auo7/CgEjX +69xjPvQpNLHO/nV4EHSdfXH3LamcpWO8aEAVne3MFFA9V0bpv7uKoGhRjssD9kSr +PQzNXfjHpkcOLeH4pzxDMFXDIGUEgeAA3gAgrCL3RRcBryFXToo9ZN3/f4EeeEjK +58ejYomsxqvckhgAEMxbT26fo2h27b4KPlnUpoiL2JPLB0Xz6PJAF8n0YdJUO381 +xhzPTIQop81BxljTLV2C9WGns5bWDPW9ItEbv4UalEwFfxsW4Ma5smLWn3A1UwVN +Z1cW/oUx+3nOCF1TZgbMPszToqCPlpIHd9vO709qpSyULIUkZLHS6PUM7ESY5U81 +f4BITxJR+aYaqErni/FDLsDVP0MQ3CuFHeUDHI0uEzzbfurYFjpp9+caaoWuZzpg +VYV5pjPdgg== +-----END TSS2 PRIVATE KEY----- diff --git a/src/libnm-core-impl/tests/certs/test2-cert.p12 b/src/libnm-core-impl/tests/certs/test2-cert.p12 new file mode 100644 index 0000000000..9d5732b0a9 Binary files /dev/null and b/src/libnm-core-impl/tests/certs/test2-cert.p12 differ diff --git a/src/libnm-core-impl/tests/certs/test2_ca_cert.pem b/src/libnm-core-impl/tests/certs/test2_ca_cert.pem new file mode 100644 index 0000000000..9a487ca4b4 --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test2_ca_cert.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEpDCCA4ygAwIBAgIJANDnVhixAO1GMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD +VQQGEwJVUzEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czERMA8GA1UEBxMIV2VzdGZv +cmQxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xFDASBgNVBAsTC0VuZ2luZWVyaW5n +MRAwDgYDVQQDEwdlYXB0ZXN0MRgwFgYJKoZIhvcNAQkBFglpdEBpdC5jb20wHhcN +MDcxMTA5MTU0ODI1WhcNMTcxMTA2MTU0ODI1WjCBkjELMAkGA1UEBhMCVVMxFjAU +BgNVBAgTDU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQK +Ew1SZWQgSGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMH +ZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAz9zRLSiQyQangDgEliEP8xSpnPJS7GjXzrkZS3sk +gZLuVuwoFeZRq3Hsrq/wGd/vM0KUFNmEaMc+47jnuv0UHQcQ45ZACO7s4/Aflhzj +lkmud/z06hVknIzjXmvS6q2ttCviHsXnfokl+wAxuUhsd+le0xjP9H1jXny4YBuS +jP+yGUz7PL4w1sFFghKIPrlB7m4GkFbQRqvH7FSJg86GWopPwJvNvIzhOZiO1a1D +CAAL4Ru3jxtNFxqWT87C/qUEe/2Qb7jtNyqFcKfwZyZh4u1bo0c8bjErlUZERbWz +zM3hTFypuw+i2v+0h3A8/Xb0hTjcHkUoJgfSdbsOLC5TOwIDAQABo4H6MIH3MB0G +A1UdDgQWBBR+UOaH4e8nrEuMcEXJl7UN5r/wDTCBxwYDVR0jBIG/MIG8gBR+UOaH +4e8nrEuMcEXJl7UN5r/wDaGBmKSBlTCBkjELMAkGA1UEBhMCVVMxFjAUBgNVBAgT +DU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQKEw1SZWQg +SGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHZWFwdGVz +dDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tggkA0OdWGLEA7UYwDAYDVR0TBAUw +AwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAmE2jqUymfxN2Vv7bPafoK/EpZwGPxu+z +phRFsgUgWVzidc/GtOxN81LduJ+ow8MEbQIabo4JV/MdKzuPuhAHToAQdeb0LIWa +p59vTIZiVhUt0cMAbQwKcTnfmDnXw9wytvtKgeAXJq0Jd6F+uNXTiR1btlYLZqmF +oSu54cHQlXpUT9z0BnQ8eXd7m0TwfzGQkTHQI7xBa87lZDAkJaTlhv7fR5vPmJYY +0LiXii71ce+4hxdlp7hQfwQ2sb8FPY3RlVboTRD0CvGaWypWhdSZnS790dBXgZOs +NCge6NGuHzW5LtiZE9ppuv8qJysVcIFdAqt8dkx58ksOqFcARCerXw== +-----END CERTIFICATE----- diff --git a/src/libnm-core-impl/tests/certs/test2_key_and_cert.pem b/src/libnm-core-impl/tests/certs/test2_key_and_cert.pem new file mode 100644 index 0000000000..a668596eef --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test2_key_and_cert.pem @@ -0,0 +1,119 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5FA2D6D6242C26D0 + +dyNdbh115sczbUEhiaGYJ6fazyvJss5thPFEmkP6aftYlvXY6vPtc++xFCCktiSd +qFVEyi6oDyV4iGPmX7pCJ0e+pSI6uFNXKFtxh5/+/wXZcOEMCvfu7w2IrvYF2LHY +qJDljcISSRxeINuYO7TETD5fLLRKj2X9vwwkwVN02b2N5jsrm6Bt//WbatqSB3ln +FHyQhVKkvdl9Hr1XNmEfgGfZSxxDoPu1DjhtZ5ja2LZj64C2CXdI0oq2wcAVvQNn +rZeeg9sinQJkz9rwsNaWqlYw4X+YD2JRSwZuvwkWRydYMwgb1XS/jCxtuFF8NXWP +RBAOAZZUy7onzohsJHVVa05wCKQ4klo+PEfI3vn7BeuHyciCc0eFqGRvz8eFDybH +ZdPbU/3vGp+mOB7gd27TptttTCQQy9uM5CIyovNSYsAIw1Z583Ea4q8eXgzkgD6D +isCqkGXMfPbNXU3myQGDnQwWRi2CqX+rXM8PJUhdewLAlmHRz/aYSuql2BRixJKx +eASzmFBYdAjrvafda5D+xTyJwXEwdq/HlqMK9cY28ZbNrzA2Kor2X23EKC1+VG8k +B67OsfUhW27j4u6aV5JdLf87OtF3mHFRR+Lzs7i7LYvJ8ACE+jiIi7PboZjK5Oiv +JqTK0BwDaeNYjkd6jiJh8It/ReMbLk65J3eldOklN0VMPYiqcQnHvSPC2DD1YAy+ +Rv/JVj6TvzvgEAj+hgH6MAAF6u3ARj6+10DlvhUubkOC5RztLKReu8B+427TuuDb +T03gFpHD6X9IqSiq/QfYFyHFojCVSrv6wDZOcHc1s71kpJ8R14YIVe+DrrZN/0D4 +M631jdNg3JARMZXcXTHrghGIdPmOtrsRyTTRZuGoVup/DW9MRzOzCTMSNCX8T+eq +13HMSNQEO9lMwy0sYeO5c7sjHY4K1ubZuVE1mvXq4JLz3YxXJIvgp8TUvqDnAsK+ +Fv63bDoTg5Tq63XvnaKc7Lawneyg5ZAMzPN3nM0/1EZcn/2ICI5c4Yepc5t63EI5 +KytuXx86Mcx234enj3uMeuM22POQ1SnKOef6dFzK/CE8J8eUEY/aDhX4eBl/s3nd +U4+aaFKYz3HTazePayt2SC6rP/KKMmS14q59bOQA1DiWxCvmA2ypRyP87fV5DstH +I53RD5xp1P38iaO8U/divD0W2dkv748s9DQqYrHPtWALT9esxNU07CgB8Zt070si +7pzjQ8FDCZ8ygDmwWGNSBz1nA90Cpd6gAFDrep7HAtDE4qgNfokycpaJZkXBei/U +tC4tWYRbqDEsEbeBHvQRJzzqWzk9e/P4fQoelM3aryKzKLG5z7KvywVifKMLECQ+ +tIpzoRp06nuTA/O+iLFdkCy3JEWszfvvOwTwtIIV6+3s8TU0k9MmzEe3rGL+QqT/ +Tf+9/dN5LK+LWyc99BfmCOrBuFtQmHyEXkfe6EuFYEwj0B2ZfnLCon6cdRujjK7H +IJslC1B/cBVqG3KCrbBzjeygKfJ5Ijo72oXZJOCFTLeJefZKGGWJCp9nG9h9Wrcf +fEN/mj3wBvTa90/PYFj9NuaBtrvMF8Rn9XDeYPq2JGL8YkNdPuO8A+2Yko8wcvST +-----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Massachusetts, L=Westford, O=Red Hat, Inc., OU=Engineering, CN=eaptest/emailAddress=it@it.com + Validity + Not Before: Nov 9 15:50:14 2007 GMT + Not After : Nov 6 15:50:14 2017 GMT + Subject: C=US, ST=Massachusetts, O=Red Hat, Inc., OU=Engineering, CN=client/emailAddress=it@it.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b0:8f:4f:1c:93:d4:43:e7:87:b7:22:33:55:a8: + 35:a1:c4:01:b0:f1:ed:26:23:96:ab:65:c2:c2:54: + db:79:22:03:ad:3f:6f:22:e3:63:3f:f4:21:6d:fa: + 88:c8:8f:1a:ce:55:49:7c:98:33:6a:67:8a:8d:d9: + 34:b0:c3:42:f4:72:a4:45:43:05:72:5d:0c:d3:42: + f8:9c:66:3b:b8:f8:77:ea:f6:b6:94:d7:cc:5d:62: + 34:2a:14:48:0a:bc:65:94:f5:7a:63:98:6c:88:4c: + 25:d8:95:f1:40:3d:00:d2:fb:43:28:fa:02:fb:2c: + 80:b3:e1:33:e7:8c:ce:8a:a0:1b:3d:04:4d:bc:a1: + b6:a2:42:8b:8e:f3:5b:4a:72:34:7d:8d:ba:d8:46: + 22:35:da:5c:f8:dd:fc:6d:9e:59:22:b7:6b:e7:78: + 56:54:9f:4c:d1:e2:4a:23:a3:bc:04:ea:46:6b:70: + 8a:fb:fe:8a:73:ca:36:d5:f3:e9:17:e3:22:d5:b3: + 70:05:e7:f7:37:b7:21:b5:90:53:27:27:ea:36:9b: + 00:ff:35:b0:66:3d:dc:a9:2f:95:d2:21:18:98:4f: + 28:07:09:70:20:a8:b1:82:aa:a5:df:ae:0f:e3:36: + be:68:8c:9e:80:d3:33:d0:f5:84:17:d9:0f:eb:9d: + af:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 71:AB:BB:91:B7:04:DE:43:35:36:07:8A:35:CA:BE:5C:3E:EB:B1:09 + X509v3 Authority Key Identifier: + keyid:7E:50:E6:87:E1:EF:27:AC:4B:8C:70:45:C9:97:B5:0D:E6:BF:F0:0D + DirName:/C=US/ST=Massachusetts/L=Westford/O=Red Hat, Inc./OU=Engineering/CN=eaptest/emailAddress=it@it.com + serial:D0:E7:56:18:B1:00:ED:46 + + Signature Algorithm: md5WithRSAEncryption + ce:43:6d:f7:f8:4a:66:fd:8a:2c:41:a6:e0:03:0e:60:30:d4: + 41:01:ba:46:ba:81:97:64:68:83:25:9c:e1:2c:03:8b:2d:ca: + 85:cf:bc:fa:ca:22:c4:59:28:23:8f:ff:50:94:60:1c:90:dd: + 75:f4:d4:ea:8c:fa:61:61:08:35:4a:8f:aa:a7:e9:3d:76:e9: + 08:28:55:01:c4:03:42:c7:ad:58:bb:ee:94:f7:09:b3:9a:9b: + 8b:d0:25:95:18:a6:22:d5:2c:fc:b7:bb:91:0c:7c:03:7f:9b: + 85:de:b0:e4:95:a8:73:94:27:0a:11:4e:e3:67:ae:2b:cc:e7: + 51:29:10:23:57:5c:3e:e7:ea:47:e0:f0:8f:5b:a2:9f:26:cf: + 7f:b5:7c:44:b1:7b:83:67:3c:41:ae:c6:66:64:e0:d2:ef:57: + a4:5c:1b:94:11:ce:28:e5:91:51:ef:e1:98:b7:3b:9a:cc:f7: + b9:85:76:eb:a8:2b:15:4a:cc:1a:a3:42:fa:be:1c:ce:b8:eb: + ee:12:d7:2f:e4:a8:cf:eb:2a:8f:78:e8:91:88:fa:c2:98:75: + 6a:4c:92:3f:2e:0d:e1:20:39:36:c6:2c:be:67:30:c3:f3:c3: + 65:81:ac:e3:3c:19:6a:21:ee:ea:f5:22:66:74:b2:07:53:7c: + 9a:0c:24:a6 +-----BEGIN CERTIFICATE----- +MIIEtDCCA5ygAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBkjELMAkGA1UEBhMCVVMx +FjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYD +VQQKEw1SZWQgSGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UE +AxMHZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tMB4XDTA3MTEwOTE1 +NTAxNFoXDTE3MTEwNjE1NTAxNFowfjELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1h +c3NhY2h1c2V0dHMxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xFDASBgNVBAsTC0Vu +Z2luZWVyaW5nMQ8wDQYDVQQDEwZjbGllbnQxGDAWBgkqhkiG9w0BCQEWCWl0QGl0 +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALCPTxyT1EPnh7ci +M1WoNaHEAbDx7SYjlqtlwsJU23kiA60/byLjYz/0IW36iMiPGs5VSXyYM2pnio3Z +NLDDQvRypEVDBXJdDNNC+JxmO7j4d+r2tpTXzF1iNCoUSAq8ZZT1emOYbIhMJdiV +8UA9ANL7Qyj6AvssgLPhM+eMzoqgGz0ETbyhtqJCi47zW0pyNH2NuthGIjXaXPjd +/G2eWSK3a+d4VlSfTNHiSiOjvATqRmtwivv+inPKNtXz6RfjItWzcAXn9ze3IbWQ +Uycn6jabAP81sGY93KkvldIhGJhPKAcJcCCosYKqpd+uD+M2vmiMnoDTM9D1hBfZ +D+udrwsCAwEAAaOCASYwggEiMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w +ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRxq7uRtwTeQzU2 +B4o1yr5cPuuxCTCBxwYDVR0jBIG/MIG8gBR+UOaH4e8nrEuMcEXJl7UN5r/wDaGB +mKSBlTCBkjELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxETAP +BgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMRQwEgYDVQQL +EwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJ +aXRAaXQuY29tggkA0OdWGLEA7UYwDQYJKoZIhvcNAQEEBQADggEBAM5Dbff4Smb9 +iixBpuADDmAw1EEBuka6gZdkaIMlnOEsA4styoXPvPrKIsRZKCOP/1CUYByQ3XX0 +1OqM+mFhCDVKj6qn6T126QgoVQHEA0LHrVi77pT3CbOam4vQJZUYpiLVLPy3u5EM +fAN/m4XesOSVqHOUJwoRTuNnrivM51EpECNXXD7n6kfg8I9bop8mz3+1fESxe4Nn +PEGuxmZk4NLvV6RcG5QRzijlkVHv4Zi3O5rM97mFduuoKxVKzBqjQvq+HM646+4S +1y/kqM/rKo946JGI+sKYdWpMkj8uDeEgOTbGLL5nMMPzw2WBrOM8GWoh7ur1ImZ0 +sgdTfJoMJKY= +-----END CERTIFICATE----- diff --git a/src/libnm-core-impl/tests/certs/test_ca_cert.der b/src/libnm-core-impl/tests/certs/test_ca_cert.der new file mode 100644 index 0000000000..e844f65b2c Binary files /dev/null and b/src/libnm-core-impl/tests/certs/test_ca_cert.der differ diff --git a/src/libnm-core-impl/tests/certs/test_ca_cert.pem b/src/libnm-core-impl/tests/certs/test_ca_cert.pem new file mode 100644 index 0000000000..faa3fc2905 --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test_ca_cert.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEhjCCA26gAwIBAgIJAOZMXJYmXtbQMA0GCSqGSIb3DQEBBQUAMIGIMQswCQYD +VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw +FQYDVQQKEw5NeSBDb21wYW55IEx0ZDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxME +dGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAyMDIwMjIx +NTJaFw0xOTAxMzEwMjIxNTJaMIGIMQswCQYDVQQGEwJVUzESMBAGA1UECBMJQmVy +a3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55IEx0 +ZDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3DQEJARYN +dGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANZz +iHfFR6Gqdz5Gq1elSaf7J2tznfialPyMkRoqngSItrM3JWlkfBu3ZIpGSYG8+Z8H +JjaKh/zkCCH73HcjADCocm/XtgxlOlccDtBvfDqifb2dBikcmcfh0tX0o4JU9L+z +WP7sVcUkJG7C5811lA5pAsLVooJxrZnrta6XstGvFgTSxI2Y4Jowf0syM5b/AHIQ ++htsVhSyj1DWM9day3QsEMZl55SCxCLTB6ZIJLF6NmTYwdnzWWTQf4k7kcptZJU8 +Fqv60b/ATvvUf7S+ZMGLopFIIlmc1Kkn7VTseIKy4ycYuDpyimQy3Yw4flC00vhl +hTijH+5dlVOUFrRh0bsCAwEAAaOB8DCB7TAdBgNVHQ4EFgQUUjMuImZ5guVBLo07 +suXM+r6ZM44wgb0GA1UdIwSBtTCBsoAUUjMuImZ5guVBLo07suXM+r6ZM46hgY6k +gYswgYgxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcT +B05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMQ0wCwYDVQQLEwR0ZXN0 +MQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tggkA +5kxcliZe1tAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAZsWzGp9D +10NWf8ts3A9mhcEb8oDgKNpCOZF9gqr2usZygJjY9MX2n0n81T8XaWDk1wZLlcDW +hzIalCY8rpE57Dj3MEmdCmYr3BrAy6GVlc/MO7ffTHxogl9ouScSYo8ETTtNMKCg +zwkDnXjGzmb1e59DIXMVHBBbTmJXJbM8XP9A2azJkVUyE2fSdWksXMP0XklGbW2p +DksJ+8G1IWkyRhnINV5GZLLNAT5gBA6sUv/iqQKwk8r2dsweMPtLoLWZPAaZErYh +sthGy00Q0GJkmkJpQl8QIlPq5vylNcMUhvc8tmzwk+rDVUj3jTJWqFwMtnHAaNyC +FXl9ynWpe5J28w== +-----END CERTIFICATE----- diff --git a/src/libnm-core-impl/tests/certs/test_key_and_cert.pem b/src/libnm-core-impl/tests/certs/test_key_and_cert.pem new file mode 100644 index 0000000000..c00495d0b0 --- /dev/null +++ b/src/libnm-core-impl/tests/certs/test_key_and_cert.pem @@ -0,0 +1,119 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48 + +KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k +r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+ +PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj +5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/ +amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj +yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR +PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV +xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg +T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab +HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu +Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev +0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB +m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf +rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f +FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S +uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN +vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt +1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh +ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw +l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v +tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm +aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco +0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD +u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj +DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg +-----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com + Validity + Not Before: Feb 2 02:22:25 2009 GMT + Not After : Jan 31 02:22:25 2019 GMT + Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3: + b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36: + d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86: + 68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10: + 25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9: + 40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31: + 5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79: + 84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41: + 7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c: + a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20: + ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5: + cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25: + bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f: + 74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9: + 77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93: + bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df: + 65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48: + 1c:83 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B + X509v3 Authority Key Identifier: + keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E + DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com + serial:E6:4C:5C:96:26:5E:D6:D0 + + Signature Algorithm: md5WithRSAEncryption + 88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c: + a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b: + e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5: + b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4: + 39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2: + ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6: + 76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32: + 4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48: + e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12: + 9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e: + 6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df: + 88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f: + d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16: + a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03: + 6b:80:38:6e +-----BEGIN CERTIFICATE----- +MIIErjCCA5agAwIBAgIBATANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCVVMx +EjAQBgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMO +TXkgQ29tcGFueSBMdGQxDTALBgNVBAsTBHRlc3QxDTALBgNVBAMTBHRlc3QxHDAa +BgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMDkwMjAyMDIyMjI1WhcNMTkw +MTMxMDIyMjI1WjCBizELMAkGA1UEBhMCVVMxEjAQBgNVBAgTCUJlcmtzaGlyZTEX +MBUGA1UEChMOTXkgQ29tcGFueSBMdGQxFDASBgNVBAsTC3Rlc3QtY2xpZW50MRQw +EgYDVQQDEwt0ZXN0LWNsaWVudDEjMCEGCSqGSIb3DQEJARYUdGVzdC1jbGllbnRA +dGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO0un79KTO +ZofMiy3Sw7j6vupTCJWeJ0oEeDGhNtLlQvV29yRxuNMQ/bdXhmgpAhvpkyuvwH49 +WBY0ECWFfigtQvw0f9ZPCue2uUBRyOWJYM1zUWNn4Vk2MV7Qh0tdl4pCItNC8oNi +eYRFW9ggl+LRNCNe7L+KQXytgFDzmxxRXeQpHMHGfKEAcA/2eXcDIvVLq3bKIKvh +TlNshmjp1g9ulUu1tc/TbNRz28A9HSAgcqs+Jbs/zV8td/3XC6jrDHPAP3QnF1bP +MZqp7cE5J8eq6XdI9G1WiTVceVv2L4yfk7wTHNB0XzAbFUNxjv8a32VlacKKWqsE +SoDeICmNSByDAgMBAAGjggEcMIIBGDAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf +Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNOlc2PzH +r/dd9BPTghrNUg9Kuwswgb0GA1UdIwSBtTCBsoAUUjMuImZ5guVBLo07suXM+r6Z +M46hgY6kgYswgYgxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO +BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMQ0wCwYDVQQL +EwR0ZXN0MQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3Qu +Y29tggkA5kxcliZe1tAwDQYJKoZIhvcNAQEEBQADggEBAIjE3cVKpo4fNmKAMWsr +hTQNbKfc4Vo83XRX21m+i/J5QC29m+GrDgN1IHUv6pf51H4VdcKC9bE35Isk1O8C +OxlqVrufw6W0xDmgZJZbw6gZdOwLzzPf8xLz4qsdfd4hZM2xoG96d4TUYopQ5nZd +rzrvGocOGjjE+Q0vFOAgMkwucNJxgtXlyRMsTrTIY2UdSOjDVm2IhFdlEx5CSLQD +JXFOEp0aiGXVcSE7Dr43HPCIa0UMDmzlYMuGv79AMMTPlPgcYNQb34gCekV+0cbz +B7mxjypVL753n9FGZAW3Z8WyrIxCj2pRpA0rFqTWOaX4Je1oJRO1Gaxs6ezuA2uA +OG4= +-----END CERTIFICATE----- diff --git a/src/libnm-core-impl/tests/meson.build b/src/libnm-core-impl/tests/meson.build new file mode 100644 index 0000000000..80f8ea32e5 --- /dev/null +++ b/src/libnm-core-impl/tests/meson.build @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +enum_sources = gnome.mkenums_simple( + 'nm-core-tests-enum-types', + sources: 'test-general-enums.h', + identifier_prefix: nm_id_prefix, + body_prefix: '#include "libnm-core-impl/nm-default-libnm-core.h"', +) + +test_units = [ + 'test-compare', + 'test-crypto', + 'test-general', + 'test-keyfile', + 'test-secrets', + 'test-setting', + 'test-settings-defaults', +] + +foreach test_unit: test_units + exe = executable( + 'libnm-core-' + test_unit, + [test_unit + '.c'] + enum_sources, + include_directories: [ + libnm_core_impl_inc, + ], + dependencies: [ + libnm_core_public_dep, + libnm_core_intern_dep, + libnm_core_impl_dep_link, + libnm_base_dep_link, + ], + c_args: [ + '-DG_LOG_DOMAIN="test"', + ], + link_with: libnm_systemd_logging_stub, + ) + + test( + 'libnm-core/' + test_unit, + test_script, + args: test_args + [exe.full_path()], + timeout: default_test_timeout, + ) +endforeach diff --git a/src/libnm-core-impl/tests/nm-core-tests-enum-types.c.template b/src/libnm-core-impl/tests/nm-core-tests-enum-types.c.template new file mode 100644 index 0000000000..1160be86dc --- /dev/null +++ b/src/libnm-core-impl/tests/nm-core-tests-enum-types.c.template @@ -0,0 +1,35 @@ +/*** BEGIN file-header ***/ +#include "config.h" + +#include "nm-core-tests-enum-types.h" + +#include "test-general-enums.h" +/*** END file-header ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + +/*** END value-tail ***/ diff --git a/src/libnm-core-impl/tests/nm-core-tests-enum-types.h.template b/src/libnm-core-impl/tests/nm-core-tests-enum-types.h.template new file mode 100644 index 0000000000..62e82b77ae --- /dev/null +++ b/src/libnm-core-impl/tests/nm-core-tests-enum-types.h.template @@ -0,0 +1,21 @@ +/*** BEGIN file-header ***/ +#ifndef __NM_CORE_TESTS_ENUM_TYPES_H__ +#define __NM_CORE_TESTS_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN enumeration-production ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) + +/*** END enumeration-production ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __NM_CORE_TESTS_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/src/libnm-core-impl/tests/test-compare.c b/src/libnm-core-impl/tests/test-compare.c new file mode 100644 index 0000000000..fb82c55910 --- /dev/null +++ b/src/libnm-core-impl/tests/test-compare.c @@ -0,0 +1,231 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include +#include + +#include "nm-property-compare.h" + +#include "nm-utils/nm-test-utils.h" + +static void +compare_ints(void) +{ + GVariant *value1, *value2; + + value1 = g_variant_new_int32(5); + value2 = g_variant_new_int32(5); + g_assert(nm_property_compare(value1, value2) == 0); + + g_variant_unref(value2); + value2 = g_variant_new_int32(10); + g_assert(nm_property_compare(value1, value2) < 0); + + g_variant_unref(value2); + value2 = g_variant_new_int32(-1); + g_assert(nm_property_compare(value1, value2) > 0); + + g_variant_unref(value1); + g_variant_unref(value2); +} + +static void +compare_strings(void) +{ + GVariant * value1, *value2; + const char *str1 = "hello"; + const char *str2 = "world"; + + value1 = g_variant_new_string(str1); + value2 = g_variant_new_string(str1); + g_assert(nm_property_compare(value1, value2) == 0); + + g_variant_unref(value2); + value2 = g_variant_new_string(str2); + g_assert(nm_property_compare(value1, value2) < 0); + + g_assert(nm_property_compare(value2, value1) > 0); + + g_variant_unref(value1); + g_variant_unref(value2); +} + +static void +compare_strv(void) +{ + GVariant * value1, *value2; + const char *const strv1[] = {"foo", "bar", "baz", NULL}; + const char *const strv2[] = {"foo", "bar", "bar", NULL}; + const char *const strv3[] = {"foo", "bar", NULL}; + const char *const strv4[] = {"foo", "bar", "baz", "bam", NULL}; + + value1 = g_variant_new_strv(strv1, -1); + value2 = g_variant_new_strv(strv1, -1); + g_assert(nm_property_compare(value1, value2) == 0); + + g_variant_unref(value2); + value2 = g_variant_new_strv(strv2, -1); + g_assert(nm_property_compare(value1, value2) != 0); + + g_variant_unref(value2); + value2 = g_variant_new_strv(strv3, -1); + g_assert(nm_property_compare(value1, value2) != 0); + + g_variant_unref(value2); + value2 = g_variant_new_strv(strv4, -1); + g_assert(nm_property_compare(value1, value2) != 0); + + g_variant_unref(value1); + g_variant_unref(value2); +} + +static void +compare_arrays(void) +{ + GVariant *value1, *value2; + guint32 array[] = {0, 1, 2, 3, 4}; + + value1 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + array, + G_N_ELEMENTS(array), + sizeof(guint32)); + value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + array, + G_N_ELEMENTS(array), + sizeof(guint32)); + + g_assert(nm_property_compare(value1, value2) == 0); + + g_variant_unref(value2); + value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + array + 1, + G_N_ELEMENTS(array) - 1, + sizeof(guint32)); + g_assert(nm_property_compare(value1, value2) != 0); + + array[0] = 7; + g_variant_unref(value2); + value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + array, + G_N_ELEMENTS(array), + sizeof(guint32)); + g_assert(nm_property_compare(value1, value2) != 0); + + g_variant_unref(value1); + g_variant_unref(value2); +} + +static void +compare_str_hash(void) +{ + GVariant * value1, *value2; + GVariantBuilder builder; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); + g_variant_builder_add(&builder, "{ss}", "key1", "hello"); + g_variant_builder_add(&builder, "{ss}", "key2", "world"); + g_variant_builder_add(&builder, "{ss}", "key3", "!"); + value1 = g_variant_builder_end(&builder); + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); + g_variant_builder_add(&builder, "{ss}", "key3", "!"); + g_variant_builder_add(&builder, "{ss}", "key2", "world"); + g_variant_builder_add(&builder, "{ss}", "key1", "hello"); + value2 = g_variant_builder_end(&builder); + + g_assert(nm_property_compare(value1, value2) == 0); + + g_variant_unref(value2); + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); + g_variant_builder_add(&builder, "{ss}", "key1", "hello"); + g_variant_builder_add(&builder, "{ss}", "key3", "!"); + value2 = g_variant_builder_end(&builder); + + g_assert(nm_property_compare(value1, value2) != 0); + g_assert(nm_property_compare(value2, value1) != 0); + + g_variant_unref(value2); + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); + g_variant_builder_add(&builder, "{ss}", "key1", "hello"); + g_variant_builder_add(&builder, "{ss}", "key2", "moon"); + g_variant_builder_add(&builder, "{ss}", "key3", "!"); + value2 = g_variant_builder_end(&builder); + + g_assert(nm_property_compare(value1, value2) != 0); + + g_variant_unref(value1); + g_variant_unref(value2); +} + +static void +compare_ip6_addresses(void) +{ + GVariant * value1, *value2; + struct in6_addr addr1; + struct in6_addr addr2; + struct in6_addr addr3; + guint32 prefix1 = 64; + guint32 prefix2 = 64; + guint32 prefix3 = 0; + + inet_pton(AF_INET6, "1:2:3:4:5:6:7:8", &addr1); + inet_pton(AF_INET6, "ffff:2:3:4:5:6:7:8", &addr2); + inet_pton(AF_INET6, "::", &addr3); + + value1 = g_variant_new( + "(@ayu@ay)", + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr1.s6_addr, 16, 1), + prefix1, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1)); + + value2 = g_variant_new( + "(@ayu@ay)", + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr1.s6_addr, 16, 1), + prefix1, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1)); + + g_assert(nm_property_compare(value1, value2) == 0); + + g_variant_unref(value2); + value2 = g_variant_new( + "(@ayu@ay)", + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr2.s6_addr, 16, 1), + prefix2, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1)); + + g_assert(nm_property_compare(value1, value2) != 0); + + g_variant_unref(value2); + value2 = g_variant_new( + "(@ayu@ay)", + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1), + prefix3, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1)); + + g_assert(nm_property_compare(value1, value2) != 0); + + g_variant_unref(value1); + g_variant_unref(value2); +} + +NMTST_DEFINE(); + +int +main(int argc, char *argv[]) +{ + nmtst_init(&argc, &argv, TRUE); + + g_test_add_func("/libnm/compare/ints", compare_ints); + g_test_add_func("/libnm/compare/strings", compare_strings); + g_test_add_func("/libnm/compare/strv", compare_strv); + g_test_add_func("/libnm/compare/arrays", compare_arrays); + g_test_add_func("/libnm/compare/str_hash", compare_str_hash); + g_test_add_func("/libnm/compare/ip6_addresses", compare_ip6_addresses); + + return g_test_run(); +} diff --git a/src/libnm-core-impl/tests/test-crypto.c b/src/libnm-core-impl/tests/test-crypto.c new file mode 100644 index 0000000000..16082795cb --- /dev/null +++ b/src/libnm-core-impl/tests/test-crypto.c @@ -0,0 +1,455 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Dan Williams + * Copyright (C) 2007 - 2011 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include +#include +#include + +#include "nm-crypto-impl.h" +#include "nm-utils.h" +#include "nm-errors.h" +#include "libnm-core-intern/nm-core-internal.h" + +#include "nm-utils/nm-test-utils.h" + +#define TEST_CERT_DIR NM_BUILD_SRCDIR "/src/libnm-core-impl/tests/certs" + +#if 0 +static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; +static const char *pem_rsa_key_end = "-----END RSA PRIVATE KEY-----"; + +static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----"; +static const char *pem_dsa_key_end = "-----END DSA PRIVATE KEY-----"; + +static void +dump_key_to_pem (const char *key, gsize key_len, int key_type) +{ + char *b64 = NULL; + GString *str = NULL; + const char *start_tag; + const char *end_tag; + char *p; + + switch (key_type) { + case NM_CRYPTO_KEY_TYPE_RSA: + start_tag = pem_rsa_key_begin; + end_tag = pem_rsa_key_end; + break; + case NM_CRYPTO_KEY_TYPE_DSA: + start_tag = pem_dsa_key_begin; + end_tag = pem_dsa_key_end; + break; + default: + g_warning ("Unknown key type %d", key_type); + return; + } + + b64 = g_base64_encode ((const unsigned char *) key, key_len); + if (!b64) { + g_warning ("Couldn't base64 encode the key."); + goto out; + } + + str = g_string_new (NULL); + + g_string_append (str, start_tag); + g_string_append_c (str, '\n'); + + for (p = b64; p < (b64 + strlen (b64)); p += 64) { + g_string_append_len (str, p, strnlen (p, 64)); + g_string_append_c (str, '\n'); + } + + g_string_append (str, end_tag); + g_string_append_c (str, '\n'); + + g_message ("Decrypted private key:\n\n%s", str->str); + +out: + g_free (b64); + if (str) + g_string_free (str, TRUE); +} +#endif + +static void +test_cert(gconstpointer test_data) +{ + gs_free char * path = NULL; + gs_unref_bytes GBytes *cert = NULL; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GError * error = NULL; + gboolean success; + + path = g_build_filename(TEST_CERT_DIR, (const char *) test_data, NULL); + + success = nm_crypto_load_and_verify_certificate(path, &format, &cert, &error); + nmtst_assert_success(success, error); + g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_X509); + + g_assert(nm_utils_file_is_certificate(path)); +} + +static void +test_load_private_key(const char *path, + const char *password, + const char *decrypted_path, + int expected_error) +{ + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + gboolean is_encrypted = FALSE; + gs_unref_bytes GBytes *array = NULL; + GError * error = NULL; + + g_assert(nm_utils_file_is_private_key(path, &is_encrypted)); + g_assert(is_encrypted); + + array = nmtst_crypto_decrypt_openssl_private_key(path, password, &key_type, &error); + /* Even if the password is wrong, we should determine the key type */ + g_assert_cmpint(key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); + + if (expected_error != -1) { + g_assert(array == NULL); + g_assert_error(error, NM_CRYPTO_ERROR, expected_error); + g_clear_error(&error); + return; + } + + if (password == NULL) { + g_assert(array == NULL); + g_assert_no_error(error); + return; + } + + g_assert(array != NULL); + + if (decrypted_path) { + gs_free char *contents = NULL; + gsize length; + + /* Compare the crypto decrypted key against a known-good decryption */ + if (!g_file_get_contents(decrypted_path, &contents, &length, NULL)) + g_assert_not_reached(); + g_assert(nm_utils_gbytes_equal_mem(array, contents, length)); + } +} + +static void +test_load_pkcs12(const char *path, const char *password, int expected_error) +{ + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gboolean is_encrypted = FALSE; + GError * error = NULL; + + g_assert(nm_utils_file_is_private_key(path, NULL)); + + format = nm_crypto_verify_private_key(path, password, &is_encrypted, &error); + if (expected_error != -1) { + g_assert_error(error, NM_CRYPTO_ERROR, expected_error); + g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + g_clear_error(&error); + } else { + g_assert_no_error(error); + g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); + g_assert(is_encrypted); + } +} + +static void +test_load_pkcs12_no_password(const char *path) +{ + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gboolean is_encrypted = FALSE; + GError * error = NULL; + + g_assert(nm_utils_file_is_private_key(path, NULL)); + + /* We should still get a valid returned crypto file format */ + format = nm_crypto_verify_private_key(path, NULL, &is_encrypted, &error); + g_assert_no_error(error); + g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); + g_assert(is_encrypted); +} + +static void +test_is_pkcs12(const char *path, gboolean expect_fail) +{ + gboolean is_pkcs12; + GError * error = NULL; + + is_pkcs12 = nm_crypto_is_pkcs12_file(path, &error); + + if (expect_fail) { + g_assert_error(error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA); + g_assert(!is_pkcs12); + g_clear_error(&error); + } else { + g_assert_no_error(error); + g_assert(is_pkcs12); + } +} + +static void +test_load_pkcs8(const char *path, const char *password, int expected_error) +{ + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gboolean is_encrypted = FALSE; + GError * error = NULL; + + g_assert(nm_utils_file_is_private_key(path, NULL)); + + format = nm_crypto_verify_private_key(path, password, &is_encrypted, &error); + if (expected_error != -1) { + g_assert_error(error, NM_CRYPTO_ERROR, expected_error); + g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + g_clear_error(&error); + } else { + g_assert_no_error(error); + g_assert_cmpint(format, ==, NM_CRYPTO_FILE_FORMAT_RAW_KEY); + g_assert(is_encrypted); + } +} + +static void +test_encrypt_private_key(const char *path, const char *password) +{ + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + gs_unref_bytes GBytes *array = NULL; + gs_unref_bytes GBytes *encrypted = NULL; + gs_unref_bytes GBytes *re_decrypted = NULL; + GError * error = NULL; + + array = nmtst_crypto_decrypt_openssl_private_key(path, password, &key_type, &error); + nmtst_assert_success(array, error); + g_assert_cmpint(key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); + + /* Now re-encrypt the private key */ + encrypted = nmtst_crypto_rsa_key_encrypt(g_bytes_get_data(array, NULL), + g_bytes_get_size(array), + password, + NULL, + &error); + nmtst_assert_success(encrypted, error); + + /* Then re-decrypt the private key */ + key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + re_decrypted = nmtst_crypto_decrypt_openssl_private_key_data(g_bytes_get_data(encrypted, NULL), + g_bytes_get_size(encrypted), + password, + &key_type, + &error); + nmtst_assert_success(re_decrypted, error); + g_assert_cmpint(key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); + + /* Compare the original decrypted key with the re-decrypted key */ + g_assert(g_bytes_equal(array, re_decrypted)); +} + +static void +test_key(gconstpointer test_data) +{ + char **parts, *path, *password, *decrypted_path; + int len; + + parts = g_strsplit((const char *) test_data, ", ", -1); + len = g_strv_length(parts); + if (len != 2 && len != 3) + g_error("wrong number of arguments (, , [])"); + + path = g_build_filename(TEST_CERT_DIR, parts[0], NULL); + password = parts[1]; + decrypted_path = parts[2] ? g_build_filename(TEST_CERT_DIR, parts[2], NULL) : NULL; + + test_is_pkcs12(path, TRUE); + test_load_private_key(path, password, decrypted_path, -1); + test_load_private_key(path, "blahblahblah", NULL, NM_CRYPTO_ERROR_DECRYPTION_FAILED); + test_load_private_key(path, NULL, NULL, -1); + test_encrypt_private_key(path, password); + + g_free(path); + g_free(decrypted_path); + g_strfreev(parts); +} + +static void +test_key_decrypted(gconstpointer test_data) +{ + const char *file = (const char *) test_data; + gboolean is_encrypted = FALSE; + char * path; + + path = g_build_filename(TEST_CERT_DIR, file, NULL); + + g_assert(nm_utils_file_is_private_key(path, &is_encrypted)); + g_assert(!is_encrypted); + + g_free(path); +} + +static void +test_pkcs12(gconstpointer test_data) +{ + char **parts, *path, *password; + + parts = g_strsplit((const char *) test_data, ", ", -1); + if (g_strv_length(parts) != 2) + g_error("wrong number of arguments (, )"); + + path = g_build_filename(TEST_CERT_DIR, parts[0], NULL); + password = parts[1]; + + test_is_pkcs12(path, FALSE); + test_load_pkcs12(path, password, -1); + test_load_pkcs12(path, "blahblahblah", NM_CRYPTO_ERROR_DECRYPTION_FAILED); + test_load_pkcs12_no_password(path); + + g_free(path); + g_strfreev(parts); +} + +static void +test_pkcs8(gconstpointer test_data) +{ + char **parts, *path, *password; + + parts = g_strsplit((const char *) test_data, ", ", -1); + if (g_strv_length(parts) != 2) + g_error("wrong number of arguments (, )"); + + path = g_build_filename(TEST_CERT_DIR, parts[0], NULL); + password = parts[1]; + + test_is_pkcs12(path, TRUE); + /* Note: NSS and gnutls < 3.5.4 don't support all the ciphers that openssl + * can use with PKCS#8 and thus the password can't be actually verified with + * such libraries. + */ + test_load_pkcs8(path, password, -1); + + g_free(path); + g_strfreev(parts); +} + +#define SALT "sodium chloride" +#define SHORT_PASSWORD "short" +#define LONG_PASSWORD "this is a longer password than the short one" +#define SHORT_DIGEST 16 +#define LONG_DIGEST 57 + +struct { + const char *salt, *password; + gsize digest_size; + const char *result; +} md5_tests[] = { + {NULL, SHORT_PASSWORD, SHORT_DIGEST, "4f09daa9d95bcb166a302407a0e0babe"}, + {NULL, + SHORT_PASSWORD, + LONG_DIGEST, + "4f09daa9d95bcb166a302407a0e0babeb7d62e5baf706830d007c253f0fe7584ad7e92dc00a599ec277293c298ae7" + "0ee3904c348e23be61c91"}, + {SALT, SHORT_PASSWORD, SHORT_DIGEST, "774771f7292210233b5724991d1f9894"}, + {SALT, + SHORT_PASSWORD, + LONG_DIGEST, + "774771f7292210233b5724991d1f98941a6ffdb45e4dc7fa04b1fa6aceed379c1ade0577bc8f261d109942ed57369" + "21c052664d72e0d5bade9"}, + {NULL, LONG_PASSWORD, SHORT_DIGEST, "e9c03517f81ff29bb777dac21fb1699c"}, + {NULL, + LONG_PASSWORD, + LONG_DIGEST, + "e9c03517f81ff29bb777dac21fb1699c50968c7ccd8db4f0a59d00ffd87b05876d45f25a927d51a8400c35af60fbd" + "64584349a8b7435d62fd9"}, + {SALT, LONG_PASSWORD, SHORT_DIGEST, "4e5c076e2f85f5e03994acbf3a9e10d6"}, + {SALT, + LONG_PASSWORD, + LONG_DIGEST, + "4e5c076e2f85f5e03994acbf3a9e10d61a6969c9fdf47ae8b1f7e2725b3767b05cc974bfcb5344b630c91761e015e" + "09d7794b5065662533bc9"}, + {NULL, "", SHORT_DIGEST, "d41d8cd98f00b204e9800998ecf8427e"}, + {SALT, "", SHORT_DIGEST, "7df1e0494c977195005d82a1809685e4"}, +}; + +static void +test_md5(void) +{ + char digest[LONG_DIGEST], *hex; + int i; + + for (i = 0; i < G_N_ELEMENTS(md5_tests); i++) { + memset(digest, 0, sizeof(digest)); + nm_crypto_md5_hash((const guint8 *) md5_tests[i].salt, + /* nm_crypto_md5_hash() used to clamp salt_len to 8. It + * doesn't any more, so we need to do it here now to + * get output that matches md5_tests[i].result. + */ + md5_tests[i].salt ? 8 : 0, + (const guint8 *) md5_tests[i].password, + strlen(md5_tests[i].password), + (guint8 *) digest, + md5_tests[i].digest_size); + + hex = nm_utils_bin2hexstr(digest, md5_tests[i].digest_size, -1); + g_assert_cmpstr(hex, ==, md5_tests[i].result); + g_free(hex); + } +} + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + GError * error = NULL; + gboolean success; + int ret; + + nmtst_init(&argc, &argv, TRUE); + + success = _nm_crypto_init(&error); + g_assert_no_error(error); + g_assert(success); + + g_test_add_data_func("/libnm/crypto/cert/pem", "test_ca_cert.pem", test_cert); + g_test_add_data_func("/libnm/crypto/cert/pem-2", "test2_ca_cert.pem", test_cert); + g_test_add_data_func("/libnm/crypto/cert/der", "test_ca_cert.der", test_cert); + g_test_add_data_func("/libnm/crypto/cert/pem-no-ending-newline", + "ca-no-ending-newline.pem", + test_cert); + g_test_add_data_func("/libnm/crypto/cert/pem-combined", "test_key_and_cert.pem", test_cert); + g_test_add_data_func("/libnm/crypto/cert/pem-combined-2", "test2_key_and_cert.pem", test_cert); + + g_test_add_data_func("/libnm/crypto/key/padding-6", + "test_key_and_cert.pem, test, test-key-only-decrypted.der", + test_key); + g_test_add_data_func("/libnm/crypto/key/key-only", + "test-key-only.pem, test, test-key-only-decrypted.der", + test_key); + g_test_add_data_func("/libnm/crypto/key/padding-8", + "test2_key_and_cert.pem, 12345testing", + test_key); + g_test_add_data_func("/libnm/crypto/key/aes-128", + "test-aes-128-key.pem, test-aes-password", + test_key); + g_test_add_data_func("/libnm/crypto/key/aes-256", + "test-aes-256-key.pem, test-aes-password", + test_key); + g_test_add_data_func("/libnm/crypto/key/decrypted", + "test-key-only-decrypted.pem", + test_key_decrypted); + + g_test_add_data_func("/libnm/crypto/PKCS#12/1", "test-cert.p12, test", test_pkcs12); + g_test_add_data_func("/libnm/crypto/PKCS#12/2", "test2-cert.p12, 12345testing", test_pkcs12); + + g_test_add_data_func("/libnm/crypto/PKCS#8", "pkcs8-enc-key.pem, 1234567890", test_pkcs8); + + g_test_add_func("/libnm/crypto/md5", test_md5); + + ret = g_test_run(); + + return ret; +} diff --git a/src/libnm-core-impl/tests/test-general-enums.h b/src/libnm-core-impl/tests/test-general-enums.h new file mode 100644 index 0000000000..b3163e2330 --- /dev/null +++ b/src/libnm-core-impl/tests/test-general-enums.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef _NM_TEST_GENERAL_ENUMS_H_ +#define _NM_TEST_GENERAL_ENUMS_H_ + +typedef enum { + NM_TEST_GENERAL_BOOL_ENUM_NO = 0, + NM_TEST_GENERAL_BOOL_ENUM_YES = 1, + NM_TEST_GENERAL_BOOL_ENUM_MAYBE = 2, + NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN = 3, + NM_TEST_GENERAL_BOOL_ENUM_INVALID = 4, /*< skip >*/ + NM_TEST_GENERAL_BOOL_ENUM_67 = 67, + NM_TEST_GENERAL_BOOL_ENUM_46 = 64, +} NMTestGeneralBoolEnum; + +typedef enum { + NM_TEST_GENERAL_META_FLAGS_NONE = 0, + NM_TEST_GENERAL_META_FLAGS_FOO = (1 << 0), + NM_TEST_GENERAL_META_FLAGS_BAR = (1 << 1), + NM_TEST_GENERAL_META_FLAGS_BAZ = (1 << 2), + NM_TEST_GENERAL_META_FLAGS_0x8 = (1 << 3), + NM_TEST_GENERAL_META_FLAGS_0x4 = (1 << 4), +} NMTestGeneralMetaFlags; + +typedef enum { /*< flags >*/ + NM_TEST_GENERAL_COLOR_FLAGS_WHITE = 1, /*< skip >*/ + NM_TEST_GENERAL_COLOR_FLAGS_BLUE = 2, + NM_TEST_GENERAL_COLOR_FLAGS_RED = 4, + NM_TEST_GENERAL_COLOR_FLAGS_GREEN = 8, +} NMTestGeneralColorFlags; + +#endif /* _NM_TEST_GENERAL_ENUMS_H_ */ diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c new file mode 100644 index 0000000000..80ec0e0c77 --- /dev/null +++ b/src/libnm-core-impl/tests/test-general.c @@ -0,0 +1,10654 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2008 - 2018 Red Hat, Inc. + */ + +#define NM_GLIB_COMPAT_H_TEST + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include +#include +#include +#include +#include + +#include "nm-std-aux/c-list-util.h" +#include "nm-glib-aux/nm-enum-utils.h" +#include "nm-glib-aux/nm-str-buf.h" +#include "nm-glib-aux/nm-json-aux.h" +#include "nm-base/nm-base.h" +#include "systemd/nm-sd-utils-shared.h" + +#include "nm-utils.h" +#include "nm-setting-private.h" +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "nm-core-tests-enum-types.h" +#include "nm-team-utils.h" + +#include "nm-setting-8021x.h" +#include "nm-setting-adsl.h" +#include "nm-setting-bluetooth.h" +#include "nm-setting-bond.h" +#include "nm-setting-bridge.h" +#include "nm-setting-bridge-port.h" +#include "nm-setting-cdma.h" +#include "nm-setting-connection.h" +#include "nm-setting-ethtool.h" +#include "nm-setting-generic.h" +#include "nm-setting-gsm.h" +#include "nm-setting-infiniband.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-olpc-mesh.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-serial.h" +#include "nm-setting-team.h" +#include "nm-setting-team-port.h" +#include "nm-setting-user.h" +#include "nm-setting-vlan.h" +#include "nm-setting-vpn.h" +#include "nm-setting-wimax.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-wpan.h" +#include "nm-simple-connection.h" +#include "libnm-core-intern/nm-keyfile-internal.h" +#include "nm-glib-aux/nm-dedup-multi.h" +#include "nm-base/nm-ethtool-base.h" +#include "nm-base/nm-ethtool-utils-base.h" + +#include "test-general-enums.h" + +#include "nm-utils/nm-test-utils.h" + +/* When passing a "bool" typed argument to a variadic function that + * expects a gboolean, the compiler will promote the integer type + * to have at least size (int). That way: + * g_object_set (obj, PROP_BOOL, bool_val, NULL); + * will just work correctly. */ +G_STATIC_ASSERT(sizeof(gboolean) == sizeof(int)); +G_STATIC_ASSERT(sizeof(bool) <= sizeof(int)); + +/*****************************************************************************/ + +/* NM_UTILS_HWADDR_LEN_MAX is public API of libnm(-core) and _NM_UTILS_HWADDR_LEN_MAX + * is internal API. They are the same, but the latter can be used without including libnm-core. */ +G_STATIC_ASSERT(NM_UTILS_HWADDR_LEN_MAX == _NM_UTILS_HWADDR_LEN_MAX); + +/*****************************************************************************/ + +static void +test_nm_ascii_spaces(void) +{ + int i; + const char *const S = NM_ASCII_SPACES; + + for (i = 0; S[i]; i++) + g_assert(!strchr(&S[i + 1], S[i])); + + for (i = 0; S[i] != '\0'; i++) + g_assert(g_ascii_isspace(S[i])); + + g_assert(!g_ascii_isspace((char) 0)); + for (i = 1; i < 0x100; i++) { + if (g_ascii_isspace((char) i)) + g_assert(strchr(S, (char) i)); + else + g_assert(!strchr(S, (char) i)); + } +} + +/*****************************************************************************/ + +static void +test_wired_wake_on_lan_enum(void) +{ + nm_auto_unref_gtypeclass GFlagsClass *flags_class = NULL; + gs_unref_hashtable GHashTable *vals = g_hash_table_new(nm_direct_hash, NULL); + guint i; + + G_STATIC_ASSERT_EXPR(sizeof(NMSettingWiredWakeOnLan) == sizeof(_NMSettingWiredWakeOnLan)); + G_STATIC_ASSERT_EXPR(sizeof(NMSettingWiredWakeOnLan) < sizeof(gint64)); + + G_STATIC_ASSERT_EXPR(sizeof(NMSettingWiredWakeOnLan) < sizeof(gint64)); + g_assert((((gint64)((NMSettingWiredWakeOnLan) -1)) < 0) + == (((gint64)((_NMSettingWiredWakeOnLan) -1)) < 0)); + +#define _E(n) \ + G_STMT_START \ + { \ + G_STATIC_ASSERT_EXPR(n == (gint64) _##n); \ + G_STATIC_ASSERT_EXPR(_##n == (gint64) n); \ + g_assert(_##n == _NM_SETTING_WIRED_WAKE_ON_LAN_CAST(n)); \ + if (!g_hash_table_add(vals, GUINT_TO_POINTER(n))) \ + g_assert_not_reached(); \ + } \ + G_STMT_END + _E(NM_SETTING_WIRED_WAKE_ON_LAN_NONE); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_PHY); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_ARP); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_ALL); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE); + _E(NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS); +#undef _E + + flags_class = G_FLAGS_CLASS(g_type_class_ref(NM_TYPE_SETTING_WIRED_WAKE_ON_LAN)); + for (i = 0; i < flags_class->n_values; i++) { + const GFlagsValue *value = &flags_class->values[i]; + + if (!g_hash_table_contains(vals, GUINT_TO_POINTER(value->value))) { + g_error("The enum value %s from NMSettingWiredWakeOnLan is not checked for " + "_NMSettingWiredWakeOnLan", + value->value_name); + } + } +} + +/*****************************************************************************/ + +typedef struct _nm_packed { + int v0; + char v1; + double v2; + guint8 v3; +} TestHashStruct; + +static void +_test_hash_struct(int v0, char v1, double v2, guint8 v3) +{ + const TestHashStruct s = { + .v0 = v0, + .v1 = v1, + .v2 = v2, + .v3 = v3, + }; + NMHashState h; + guint hh; + + nm_hash_init(&h, 100); + nm_hash_update(&h, &s, sizeof(s)); + hh = nm_hash_complete(&h); + + nm_hash_init(&h, 100); + nm_hash_update_val(&h, v0); + nm_hash_update_val(&h, v1); + nm_hash_update_val(&h, v2); + nm_hash_update_val(&h, v3); + g_assert_cmpint(hh, ==, nm_hash_complete(&h)); + + nm_hash_init(&h, 100); + nm_hash_update_vals(&h, v0, v1, v2, v3); + g_assert_cmpint(hh, ==, nm_hash_complete(&h)); +} + +static guint +_test_hash_str(const char *str) +{ + NMHashState h; + guint v, v2; + const guint SEED = 10; + + nm_hash_init(&h, SEED); + nm_hash_update_str0(&h, str); + v = nm_hash_complete(&h); + + /* assert that hashing a string and a buffer yields the + * same result. + * + * I think that is a desirable property. */ + nm_hash_init(&h, SEED); + nm_hash_update_mem(&h, str, strlen(str)); + v2 = nm_hash_complete(&h); + + g_assert(v == v2); + return v; +} + +#define _test_hash_vals(type, ...) \ + G_STMT_START \ + { \ + NMHashState h0, h1, h2, h3; \ + const type v[] = {__VA_ARGS__}; \ + guint h; \ + guint i; \ + \ + nm_hash_init(&h0, 10); \ + nm_hash_init(&h1, 10); \ + nm_hash_init(&h2, 10); \ + nm_hash_init(&h3, 10); \ + \ + /* assert that it doesn't matter, whether we hash the values individually, + * or all at once, or via the convenience macros nm_hash_update_val() + * and nm_hash_update_vals(). */ \ + for (i = 0; i < G_N_ELEMENTS(v); i++) { \ + nm_hash_update(&h0, &v[i], sizeof(type)); \ + nm_hash_update_val(&h1, v[i]); \ + } \ + nm_hash_update_vals(&h2, __VA_ARGS__); \ + nm_hash_update(&h3, v, sizeof(v)); \ + \ + h = nm_hash_complete(&h0); \ + g_assert_cmpint(h, ==, nm_hash_complete(&h1)); \ + g_assert_cmpint(h, ==, nm_hash_complete(&h2)); \ + g_assert_cmpint(h, ==, nm_hash_complete(&h3)); \ + } \ + G_STMT_END + +static void +test_nm_hash(void) +{ + g_assert(nm_hash_static(0)); + g_assert(nm_hash_static(777)); + + g_assert(nm_hash_str(NULL)); + g_assert(nm_hash_str("")); + g_assert(nm_hash_str("a")); + + g_assert(nm_hash_ptr(NULL)); + g_assert(nm_hash_ptr("")); + g_assert(nm_hash_ptr("a")); + + _test_hash_str(""); + _test_hash_str("a"); + _test_hash_str("aa"); + _test_hash_str("diceros bicornis longipes"); + + /* assert that nm_hash_update_vals() is the same as calling nm_hash_update_val() multiple times. */ + _test_hash_vals(int, 1); + _test_hash_vals(int, 1, 2); + _test_hash_vals(int, 1, 2, 3); + _test_hash_vals(int, 1, 2, 3, 4); + _test_hash_vals(long, 1l); + _test_hash_vals(long, 1l, 2l, 3l, 4l, 5l); + + _test_hash_struct(10, 'a', 5.4, 7); + _test_hash_struct(-10, '\0', -5.4e49, 255); + + g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 1, 0), ==, 0x002); + g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 1, 1), ==, 0x003); + g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 1, 1, 0, 0, 0, 0), ==, 0x030); + g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 1, 1, 0, 0, 0, 1), ==, 0x031); + g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint8, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); + g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); + g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 0, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); + g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 1, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x131); +} + +/*****************************************************************************/ + +static void +test_nm_g_slice_free_fcn(void) +{ + gpointer p; + struct { + char a1; + char a2; + } xx; + + p = g_slice_new(gint64); + (nm_g_slice_free_fcn(gint64))(p); + + p = g_slice_new(gint32); + (nm_g_slice_free_fcn(gint32))(p); + + p = g_slice_new(int); + (nm_g_slice_free_fcn(int))(p); + + p = g_slice_new(gint64); + nm_g_slice_free_fcn_gint64(p); + + p = g_slice_alloc(sizeof(xx)); + (nm_g_slice_free_fcn(xx))(p); +} + +/*****************************************************************************/ + +static void +_do_test_nm_utils_strsplit_set_f_one(NMUtilsStrsplitSetFlags flags, + const char * str, + gsize words_len, + const char *const * exp_words) +{ +#define DELIMITERS " \n" +#define DELIMITERS_C ' ', '\n' + + gs_free const char **words = NULL; + gsize i, j, k; + const gboolean f_allow_escaping = + NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING); + const gboolean f_preserve_empty = + NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY); + const char * s1; + gsize initial_offset; + gs_strfreev char **words_g = NULL; + + g_assert(!NM_FLAGS_ANY(flags, + ~(NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING + | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY))); + + /* assert that the expected words are valid (and don't contain unescaped delimiters). */ + for (i = 0; i < words_len; i++) { + const char *w = exp_words[i]; + + g_assert(w); + if (!f_preserve_empty) + g_assert(w[0]); + for (k = 0; w[k];) { + if (f_allow_escaping && w[k] == '\\') { + k++; + if (w[k] == '\0') + break; + k++; + continue; + } + g_assert(!NM_IN_SET(w[k], DELIMITERS_C)); + k++; + } + if (!f_allow_escaping) + g_assert(!NM_STRCHAR_ANY(w, ch, NM_IN_SET(ch, DELIMITERS_C))); + } + + initial_offset = (f_preserve_empty || !str) ? 0u : strspn(str, DELIMITERS); + + /* first compare our expected values with what g_strsplit_set() would + * do. */ + words_g = str ? g_strsplit_set(str, DELIMITERS, -1) : NULL; + if (str == NULL) { + g_assert_cmpint(words_len, ==, 0); + g_assert(!words_g); + } else if (nm_streq0(str, "")) { + g_assert_cmpint(words_len, ==, 0); + g_assert(words_g); + g_assert(!words_g[0]); + } else { + g_assert(words_g); + g_assert(words_g[0]); + if (!f_allow_escaping) { + if (!f_preserve_empty) { + for (i = 0, j = 0; words_g[i]; i++) { + if (words_g[i][0] == '\0') + g_free(words_g[i]); + else + words_g[j++] = words_g[i]; + } + words_g[j] = NULL; + } + if (f_preserve_empty) + g_assert_cmpint(words_len, >, 0); + for (i = 0; i < words_len; i++) { + g_assert(exp_words[i]); + g_assert_cmpstr(exp_words[i], ==, words_g[i]); + } + g_assert(words_g[words_len] == NULL); + g_assert_cmpint(NM_PTRARRAY_LEN(words_g), ==, words_len); + g_assert(nm_utils_strv_cmp_n(exp_words, words_len, words_g, -1) == 0); + } + } + + if (flags == NM_UTILS_STRSPLIT_SET_FLAGS_NONE && nmtst_get_rand_bool()) + words = nm_utils_strsplit_set(str, DELIMITERS); + else if (flags == NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY && nmtst_get_rand_bool()) + words = nm_utils_strsplit_set_with_empty(str, DELIMITERS); + else + words = nm_utils_strsplit_set_full(str, DELIMITERS, flags); + + g_assert_cmpint(NM_PTRARRAY_LEN(words), ==, words_len); + + if (words_len == 0) { + g_assert(!words); + g_assert(!str || NM_STRCHAR_ALL(str, ch, NM_IN_SET(ch, DELIMITERS_C))); + return; + } + + g_assert(words); + for (i = 0; i < words_len; i++) + g_assert_cmpstr(exp_words[i], ==, words[i]); + g_assert(words[words_len] == NULL); + + g_assert(nm_utils_strv_cmp_n(exp_words, words_len, words, -1) == 0); + + s1 = words[0]; + g_assert(s1 >= (char *) &words[words_len + 1]); + s1 = &s1[strlen(str)]; + for (i = 1; i < words_len; i++) { + g_assert(&(words[i - 1])[strlen(words[i - 1])] < words[i]); + g_assert(words[i] <= s1); + } + + /* while strsplit removes all delimiters, we can relatively easily find them + * in the original string. Assert that the original string and the pointer offsets + * of words correspond. In particular, find idx_delim_after and idx_delim_before + * to determine which delimiter was after/before a word. */ + { + gsize idx_word_start; + gsize idx_delim_after_old = G_MAXSIZE; + + idx_word_start = initial_offset; + for (i = 0; i < words_len; i++) { + const gsize l_i = strlen(words[i]); + gsize idx_delim_after; + gsize idx_delim_before; + + /* find the delimiter *after* words[i]. We can do that by looking at the next + * word and calculating the pointer difference. + * + * The delimiter after the very last word is '\0' and requires strlen() to find. */ + idx_delim_after = initial_offset + ((words[i] - words[0]) + l_i); + if (idx_delim_after != idx_word_start + l_i) { + g_assert(!f_preserve_empty); + g_assert_cmpint(idx_word_start + l_i, <, idx_delim_after); + idx_word_start = idx_delim_after - l_i; + } + if (i + 1 < words_len) { + gsize x = initial_offset + ((words[i + 1] - words[0]) - 1); + + if (idx_delim_after != x) { + g_assert(!f_preserve_empty); + g_assert_cmpint(idx_delim_after, <, x); + for (k = idx_delim_after; k <= x; k++) + g_assert(NM_IN_SET(str[k], DELIMITERS_C)); + } + g_assert(NM_IN_SET(str[idx_delim_after], DELIMITERS_C)); + } else { + if (f_preserve_empty) + g_assert(NM_IN_SET(str[idx_delim_after], '\0')); + else + g_assert(NM_IN_SET(str[idx_delim_after], '\0', DELIMITERS_C)); + } + + /* find the delimiter *before* words[i]. */ + if (i == 0) { + /* there is only a delimiter *before*, with !f_preserve_empty and leading + * delimiters. */ + idx_delim_before = G_MAXSIZE; + if (initial_offset > 0) { + g_assert(!f_preserve_empty); + idx_delim_before = initial_offset - 1; + } + } else + idx_delim_before = initial_offset + (words[i] - words[0]) - 1; + if (idx_delim_before != G_MAXSIZE) + g_assert(NM_IN_SET(str[idx_delim_before], DELIMITERS_C)); + if (idx_delim_after_old != idx_delim_before) { + g_assert(!f_preserve_empty); + if (i == 0) { + g_assert_cmpint(initial_offset, >, 0); + g_assert_cmpint(idx_delim_before, !=, G_MAXSIZE); + g_assert_cmpint(idx_delim_before, ==, initial_offset - 1); + } else { + g_assert_cmpint(idx_delim_after_old, !=, G_MAXSIZE); + g_assert_cmpint(idx_delim_before, !=, G_MAXSIZE); + g_assert_cmpint(idx_delim_after_old, <, idx_delim_before); + for (k = idx_delim_after_old; k <= idx_delim_before; k++) + g_assert(NM_IN_SET(str[k], DELIMITERS_C)); + } + } + + for (k = 0; k < l_i;) { + if (f_allow_escaping && str[idx_word_start + k] == '\\') { + k++; + if (k >= l_i) + break; + k++; + continue; + } + g_assert(!NM_IN_SET(str[idx_word_start + k], DELIMITERS_C)); + k++; + } + g_assert(strncmp(words[i], &str[idx_word_start], l_i) == 0); + + if (i > 0) { + const char *s = &(words[i - 1])[strlen(words[i - 1]) + 1]; + + if (s != words[i]) { + g_assert(!f_preserve_empty); + g_assert(s < words[i]); + } + } + + idx_word_start += l_i + 1; + idx_delim_after_old = idx_delim_after; + } + } +} + +static void +_do_test_nm_utils_strsplit_set_f(NMUtilsStrsplitSetFlags flags, + const char * str, + gsize words_len, + const char *const * exp_words) +{ + _do_test_nm_utils_strsplit_set_f_one(flags, str, words_len, exp_words); + + if (NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY)) { + gs_unref_ptrarray GPtrArray *exp_words2 = NULL; + gsize k; + + exp_words2 = g_ptr_array_new(); + for (k = 0; k < words_len; k++) { + if (exp_words[k][0] != '\0') + g_ptr_array_add(exp_words2, (gpointer) exp_words[k]); + } + + _do_test_nm_utils_strsplit_set_f_one(flags & (~NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY), + str, + exp_words2->len, + (const char *const *) exp_words2->pdata); + } +} + +#define do_test_nm_utils_strsplit_set_f(flags, str, ...) \ + _do_test_nm_utils_strsplit_set_f(flags, str, NM_NARG(__VA_ARGS__), NM_MAKE_STRV(__VA_ARGS__)) + +#define do_test_nm_utils_strsplit_set(allow_escaping, str, ...) \ + do_test_nm_utils_strsplit_set_f((allow_escaping) ? NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING \ + : NM_UTILS_STRSPLIT_SET_FLAGS_NONE, \ + str, \ + ##__VA_ARGS__) + +static void +_do_test_nm_utils_strsplit_set_simple(NMUtilsStrsplitSetFlags flags, + const char * str, + gsize words_len, + const char *const * exp_words) +{ + gs_free const char **tokens = NULL; + gsize n_tokens; + + tokens = nm_utils_strsplit_set_full(str, DELIMITERS, flags); + + if (!tokens) { + g_assert_cmpint(words_len, ==, 0); + return; + } + + g_assert(str && str[0]); + g_assert_cmpint(words_len, >, 0); + n_tokens = NM_PTRARRAY_LEN(tokens); + + if (nm_utils_strv_cmp_n(exp_words, words_len, tokens, -1) != 0) { + gsize i; + + g_print(">>> split \"%s\" (flags %x) got %zu tokens (%zu expected)\n", + str, + (guint) flags, + n_tokens, + words_len); + for (i = 0; i < NM_MAX(n_tokens, words_len); i++) { + const char *s1 = i < n_tokens ? tokens[i] : NULL; + const char *s2 = i < words_len ? exp_words[i] : NULL; + + g_print(">>> [%zu]: %s - %s%s%s vs. %s%s%s\n", + i, + nm_streq0(s1, s2) ? "same" : "diff", + NM_PRINT_FMT_QUOTE_STRING(s1), + NM_PRINT_FMT_QUOTE_STRING(s2)); + } + g_assert_not_reached(); + } + g_assert_cmpint(words_len, ==, NM_PTRARRAY_LEN(tokens)); +} +#define do_test_nm_utils_strsplit_set_simple(flags, str, ...) \ + _do_test_nm_utils_strsplit_set_simple((flags), \ + (str), \ + NM_NARG(__VA_ARGS__), \ + NM_MAKE_STRV(__VA_ARGS__)) + +static void +test_nm_utils_strsplit_set(void) +{ + gs_unref_ptrarray GPtrArray *words_exp = NULL; + guint test_run; + + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_NONE, NULL); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_NONE, ""); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_NONE, " "); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_NONE, "a b", "a", "b"); + + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, NULL); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, ""); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, " ", "", ""); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, " ", "", "", ""); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "a ", "a", "", ""); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + "a b", + "a", + "", + "b"); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + " ab b", + "", + "ab", + "", + "b"); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + "ab b", + "ab", + "", + "b"); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "abb", "abb"); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + "abb bb ", + "abb", + "", + "bb", + ""); + do_test_nm_utils_strsplit_set_f(NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + "abb bcb ", + "abb", + "bcb", + ""); + + do_test_nm_utils_strsplit_set(FALSE, NULL); + do_test_nm_utils_strsplit_set(FALSE, ""); + do_test_nm_utils_strsplit_set(FALSE, "\n"); + do_test_nm_utils_strsplit_set(TRUE, " \t\n", "\t"); + do_test_nm_utils_strsplit_set(FALSE, "a", "a"); + do_test_nm_utils_strsplit_set(FALSE, "a b", "a", "b"); + do_test_nm_utils_strsplit_set(FALSE, "a\rb", "a\rb"); + do_test_nm_utils_strsplit_set(FALSE, " a\rb ", "a\rb"); + do_test_nm_utils_strsplit_set(FALSE, " a bbbd afds ere", "a", "bbbd", "afds", "ere"); + do_test_nm_utils_strsplit_set(FALSE, + "1 2 3 4 5 6 7 8 9 0 " + "1 2 3 4 5 6 7 8 9 0 " + "1 2 3 4 5 6 7 8 9 0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "0"); + do_test_nm_utils_strsplit_set(TRUE, "\\", "\\"); + do_test_nm_utils_strsplit_set(TRUE, "\\ ", "\\ "); + do_test_nm_utils_strsplit_set(TRUE, "\\\\", "\\\\"); + do_test_nm_utils_strsplit_set(TRUE, "\\\t", "\\\t"); + do_test_nm_utils_strsplit_set(TRUE, "foo\\", "foo\\"); + do_test_nm_utils_strsplit_set(TRUE, "bar foo\\", "bar", "foo\\"); + do_test_nm_utils_strsplit_set(TRUE, "\\ a b\\ \\ c", "\\ a", "b\\ \\ ", "c"); + + words_exp = g_ptr_array_new_with_free_func(g_free); + for (test_run = 0; test_run < 100; test_run++) { + gboolean f_allow_escaping = nmtst_get_rand_bool(); + guint words_len = nmtst_get_rand_uint32() % 100; + gs_free char *str = NULL; + guint i; + + g_ptr_array_set_size(words_exp, 0); + for (i = 0; i < words_len; i++) { + guint word_len; + char *word; + guint j; + + word_len = nmtst_get_rand_uint32(); + if ((word_len % 100) < 30) + word_len = 0; + else + word_len = (word_len >> 10) % 100; + word = g_new(char, word_len + 3); + for (j = 0; j < word_len;) { + guint32 p = nmtst_get_rand_uint32(); + static const char delimiters_arr[] = {DELIMITERS_C}; + static const char regular_chars[] = "abcdefghijklmnopqrstuvwxyz"; + + if (!f_allow_escaping || (p % 1000) < 700) { + if (((p >> 20) % 100) < 20) + word[j++] = '\\'; + word[j++] = regular_chars[(p >> 11) % (G_N_ELEMENTS(regular_chars) - 1)]; + continue; + } + word[j++] = '\\'; + word[j++] = delimiters_arr[(p >> 11) % G_N_ELEMENTS(delimiters_arr)]; + } + word[j] = '\0'; + g_ptr_array_add(words_exp, word); + } + g_ptr_array_add(words_exp, NULL); + + str = g_strjoinv(" ", (char **) words_exp->pdata); + + if (str[0] == '\0' && words_len > 0) { + g_assert(words_len == 1); + g_assert_cmpstr(words_exp->pdata[0], ==, ""); + words_len = 0; + } + + _do_test_nm_utils_strsplit_set_f((f_allow_escaping + ? NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING + : NM_UTILS_STRSPLIT_SET_FLAGS_NONE) + | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + str, + words_len, + (const char *const *) words_exp->pdata); + } + + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "\t", "\t"); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED + | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, + "\t"); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED + | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP + | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + "\t", + ""); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED + | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP + | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + "\t\\\t\t\t\\\t", + "\t\t\t\t"); + + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "\ta", "\ta"); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED + | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, + "\ta", + "a"); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, + "\ta\\ b\t\\ ", + "\ta b\t "); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED + | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, + "\ta\\ b\t\\ \t", + "a b\t "); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "a\\ b", "a ", "b"); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, + "\ta\\ b", + "\ta ", + "b"); + do_test_nm_utils_strsplit_set_simple(NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED + | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, + "\ta\\ b", + "a ", + "b"); +} + +/*****************************************************************************/ + +static char * +_escaped_tokens_create_random_word_full(const char *const *tokens, gsize n_tokens, gsize len) +{ + GString *gstr = g_string_new(NULL); + gsize i; + char random_token[2] = {0}; + + for (i = 0; i < len; i++) { + const char *token = tokens[nmtst_get_rand_uint32() % n_tokens]; + + if (!token[0]) { + do { + random_token[0] = nmtst_get_rand_uint32(); + } while (random_token[0] == '\0'); + token = random_token; + } + g_string_append(gstr, token); + } + + /* reallocate the string, so that we don't have any excess memory from + * the GString buffer. This is so that valgrind may better detect an out + * or range access. */ + return nm_str_realloc(g_string_free(gstr, FALSE)); +} + +/* set to 1 to exclude characters that are annoying to see in the debugger + * and printf() output. */ +#define ESCAPED_TOKENS_ONLY_NICE_CHARS 0 + +static char * +_escaped_tokens_create_random_whitespace(void) +{ + static const char *tokens[] = { + " ", +#if !ESCAPED_TOKENS_ONLY_NICE_CHARS + "\n", + "\t", + "\r", + "\f", +#endif + }; + + return _escaped_tokens_create_random_word_full(tokens, + G_N_ELEMENTS(tokens), + nmtst_get_rand_word_length(NULL) / 4u); +} + +static char * +_escaped_tokens_create_random_word(void) +{ + static const char *tokens[] = { + "a", + "b", + "c", + " ", + ",", + "=", + "\\", +#if !ESCAPED_TOKENS_ONLY_NICE_CHARS + "\n", + "\f", + ":", + "", +#endif + }; + + return _escaped_tokens_create_random_word_full(tokens, + G_N_ELEMENTS(tokens), + nmtst_get_rand_word_length(NULL)); +} + +static void +_escaped_tokens_str_append_delimiter(GString *str, gboolean strict, gboolean needs_delimiter) +{ + guint len = nmtst_get_rand_word_length(NULL) / 10u; + char *s; + +again: + if (!strict) { + g_string_append(str, (s = _escaped_tokens_create_random_whitespace())); + nm_clear_g_free(&s); + } + + if (needs_delimiter) + g_string_append_c(str, ','); + + if (!strict) { + g_string_append(str, (s = _escaped_tokens_create_random_whitespace())); + nm_clear_g_free(&s); + if (len-- > 0) { + needs_delimiter = TRUE; + goto again; + } + } +} + +static void +_escaped_tokens_split(char *str, const char **out_key, const char **out_val) +{ + const char *key; + const char *val; + gsize len = strlen(str); + + g_assert(str); + + nm_utils_escaped_tokens_options_split(str, &key, &val); + g_assert(key); + g_assert(key == str); + if (val) { + g_assert(val > str); + g_assert(val > key); + g_assert(val <= &str[len]); + } + NM_SET_OUT(out_key, key); + NM_SET_OUT(out_val, val); +} + +static void +_escaped_tokens_combine(GString * combined, + const char *key, + const char *val, + gboolean strict, + gboolean allow_append_delimiter_before, + gboolean needs_delimiter_after) +{ + gs_free char *escaped_key = NULL; + gs_free char *escaped_val = NULL; + + if (allow_append_delimiter_before) + _escaped_tokens_str_append_delimiter(combined, strict, FALSE); + g_string_append(combined, nm_utils_escaped_tokens_options_escape_key(key, &escaped_key)); + if (val) { + char *s; + + if (!strict) { + g_string_append(combined, (s = _escaped_tokens_create_random_whitespace())); + nm_clear_g_free(&s); + } + g_string_append_c(combined, '='); + if (!strict) { + g_string_append(combined, (s = _escaped_tokens_create_random_whitespace())); + nm_clear_g_free(&s); + } + g_string_append(combined, nm_utils_escaped_tokens_options_escape_val(val, &escaped_val)); + } + _escaped_tokens_str_append_delimiter(combined, strict, needs_delimiter_after); +} + +static void +_escaped_tokens_check_one_impl(const char * expected_key, + const char * expected_val, + const char * expected_combination, + const char *const *other, + gsize n_other) +{ + nm_auto_free_gstring GString *combined = g_string_new(NULL); + gsize i; + + g_assert(expected_key); + g_assert(expected_combination); + g_assert(other); + + _escaped_tokens_combine(combined, expected_key, expected_val, TRUE, TRUE, FALSE); + + g_assert_cmpstr(combined->str, ==, expected_combination); + + for (i = 0; i < n_other + 2u; i++) { + nm_auto_free_gstring GString *str0 = NULL; + gs_free const char ** strv_split = NULL; + gs_free char * strv_split0 = NULL; + const char * comb; + const char * key; + const char * val; + + if (i == 0) + comb = expected_combination; + else if (i == 1) { + _escaped_tokens_combine(nm_gstring_prepare(&str0), + expected_key, + expected_val, + FALSE, + TRUE, + FALSE); + comb = str0->str; + } else + comb = other[i - 2]; + + strv_split = nm_utils_escaped_tokens_options_split_list(comb); + if (!strv_split) { + g_assert_cmpstr(expected_key, ==, ""); + g_assert_cmpstr(expected_val, ==, NULL); + continue; + } + g_assert(expected_val || expected_key[0]); + + g_assert_cmpuint(NM_PTRARRAY_LEN(strv_split), ==, 1u); + + strv_split0 = g_strdup(strv_split[0]); + + _escaped_tokens_split(strv_split0, &key, &val); + g_assert_cmpstr(key, ==, expected_key); + g_assert_cmpstr(val, ==, expected_val); + } +} + +#define _escaped_tokens_check_one(expected_key, expected_val, expected_combination, ...) \ + _escaped_tokens_check_one_impl(expected_key, \ + expected_val, \ + expected_combination, \ + NM_MAKE_STRV(__VA_ARGS__), \ + NM_NARG(__VA_ARGS__)) + +static void +test_nm_utils_escaped_tokens(void) +{ + int i_run; + + for (i_run = 0; i_run < 1000; i_run++) { + const guint num_options = nmtst_get_rand_word_length(NULL); + gs_unref_ptrarray GPtrArray *options = g_ptr_array_new_with_free_func(g_free); + nm_auto_free_gstring GString *combined = g_string_new(NULL); + gs_free const char ** strv_split = NULL; + guint i_option; + guint i; + + /* Generate a list of random words for option key-value pairs. */ + for (i_option = 0; i_option < 2u * num_options; i_option++) { + char *word = NULL; + + if (i_option % 2u == 1 && nmtst_get_rand_uint32() % 5 == 0 + && strlen(options->pdata[options->len - 1]) > 0u) { + /* For some options, leave the value unset and only generate a key. + * + * If key is "", then we cannot do that, because the test below would try + * to append "" to the combined list, which the parser then would drop. + * Only test omitting the value, if strlen() of the key is positive. */ + } else + word = _escaped_tokens_create_random_word(); + g_ptr_array_add(options, word); + } + + /* Combine the options in one comma separated list, with proper escaping. */ + for (i_option = 0; i_option < num_options; i_option++) { + _escaped_tokens_combine(combined, + options->pdata[2u * i_option + 0u], + options->pdata[2u * i_option + 1u], + FALSE, + i_option == 0, + i_option != num_options - 1); + } + + /* ensure that we can split and parse the options without difference. */ + strv_split = nm_utils_escaped_tokens_options_split_list(combined->str); + for (i_option = 0; i_option < num_options; i_option++) { + const char * expected_key = options->pdata[2u * i_option + 0u]; + const char * expected_val = options->pdata[2u * i_option + 1u]; + gs_free char *s_split = + i_option < NM_PTRARRAY_LEN(strv_split) ? g_strdup(strv_split[i_option]) : NULL; + const char *key = NULL; + const char *val = NULL; + + if (s_split) + _escaped_tokens_split(s_split, &key, &val); + + if (!nm_streq0(key, expected_key) || !nm_streq0(val, expected_val)) { + g_print(">>> ASSERTION IS ABOUT TO FAIL for item %5d of %5d\n", + i_option, + num_options); + g_print(">>> combined = \"%s\"\n", combined->str); + g_print(">>> %c parsed[%5d].key = \"%s\"\n", + nm_streq(key, expected_key) ? ' ' : 'X', + i_option, + key); + g_print(">>> %c parsed[%5d].val = %s%s%s\n", + nm_streq0(val, expected_val) ? ' ' : 'X', + i_option, + NM_PRINT_FMT_QUOTE_STRING(val)); + for (i = 0; i < num_options; i++) { + g_print(">>> %c original[%5d].key = \"%s\"\n", + i == i_option ? '*' : ' ', + i, + (char *) options->pdata[2u * i + 0u]); + g_print(">>> %c original[%5d].val = %s%s%s\n", + i == i_option ? '*' : ' ', + i, + NM_PRINT_FMT_QUOTE_STRING((char *) options->pdata[2u * i + 1u])); + } + for (i = 0; i < NM_PTRARRAY_LEN(strv_split); i++) + g_print(">>> split[%5d] = \"%s\"\n", i, strv_split[i]); + } + + g_assert_cmpstr(key, ==, expected_key); + g_assert_cmpstr(val, ==, expected_val); + } + g_assert_cmpint(NM_PTRARRAY_LEN(strv_split), ==, num_options); + + /* Above we show a full round-trip of random option key-value pairs, that they can + * without loss escape, concatenate, split-list, and split. This proofed that every + * option key-value pair can be represented as a combined string and parsed back. + * + * Now, just check that we can also parse arbitrary random words in nm_utils_escaped_tokens_options_split(). + * split() is a non-injective surjective function. As we check the round-trip above for random words, where + * options-split() is the last step, we show that every random word can be the output of the function + * (which shows, the surjective part). + * + * But multiple random input arguments, may map to the same output argument (non-injective). + * Just test whether we can handle random input words without crashing. For that, just use the + * above generate list of random words. + */ + for (i = 0; i < 1u + 2u * i_option; i++) { + gs_free char *str = NULL; + const char * cstr; + + if (i == 0) + cstr = combined->str; + else + cstr = options->pdata[i - 1u]; + if (!cstr) + continue; + + str = g_strdup(cstr); + _escaped_tokens_split(str, NULL, NULL); + } + } + + _escaped_tokens_check_one("", NULL, ""); + _escaped_tokens_check_one("", "", "=", " ="); + _escaped_tokens_check_one("a", "b", "a=b", "a = b"); + _escaped_tokens_check_one("a\\=", "b\\=", "a\\\\\\==b\\\\=", "a\\\\\\==b\\\\\\="); + _escaped_tokens_check_one("\\=", "\\=", "\\\\\\==\\\\=", "\\\\\\==\\\\\\="); + _escaped_tokens_check_one(" ", "bb=", "\\ =bb=", "\\ =bb\\="); + _escaped_tokens_check_one(" ", "bb\\=", "\\ =bb\\\\=", "\\ =bb\\\\\\="); + _escaped_tokens_check_one("a b", "a b", "a b=a b"); + _escaped_tokens_check_one("a b", "a b", "a b=a b"); + _escaped_tokens_check_one("a = b", "a = b", "a \\= b=a = b", "a \\= b=a \\= b"); +} + +/*****************************************************************************/ + +typedef struct { + int val; + CList lst; +} CListSort; + +static int +_c_list_sort_cmp(const CList *lst_a, const CList *lst_b, const void *user_data) +{ + const CListSort *a, *b; + + g_assert(lst_a); + g_assert(lst_b); + g_assert(lst_a != lst_b); + + a = c_list_entry(lst_a, CListSort, lst); + b = c_list_entry(lst_b, CListSort, lst); + + if (a->val < b->val) + return -1; + if (a->val > b->val) + return 1; + return 0; +} + +static void +_do_test_c_list_sort(CListSort *elements, guint n_list, gboolean headless) +{ + CList head, *iter, *iter_prev, *lst; + guint i; + const CListSort *el_prev; + CListSort * el; + + c_list_init(&head); + for (i = 0; i < n_list; i++) { + el = &elements[i]; + el->val = nmtst_get_rand_uint32() % (2 * n_list); + c_list_link_tail(&head, &el->lst); + } + + if (headless) { + lst = head.next; + c_list_unlink_stale(&head); + lst = c_list_sort_headless(lst, _c_list_sort_cmp, NULL); + g_assert(lst); + g_assert(lst->next); + g_assert(lst->prev); + g_assert(c_list_length(lst) == n_list - 1); + iter_prev = lst->prev; + for (iter = lst; iter != lst; iter = iter->next) { + g_assert(iter); + g_assert(iter->next); + g_assert(iter->prev == iter_prev); + } + c_list_link_before(lst, &head); + } else + c_list_sort(&head, _c_list_sort_cmp, NULL); + + g_assert(!c_list_is_empty(&head)); + g_assert(c_list_length(&head) == n_list); + + el_prev = NULL; + c_list_for_each (iter, &head) { + el = c_list_entry(iter, CListSort, lst); + g_assert(el >= elements && el < &elements[n_list]); + if (el_prev) { + if (el_prev->val == el->val) + g_assert(el_prev < el); + else + g_assert(el_prev->val < el->val); + g_assert(iter->prev == &el_prev->lst); + g_assert(el_prev->lst.next == iter); + } + el_prev = el; + } + g_assert(head.prev == &el_prev->lst); +} + +static void +test_c_list_sort(void) +{ + const guint N_ELEMENTS = 10000; + guint n_list, repeat; + gs_free CListSort *elements = NULL; + + { + CList head; + + c_list_init(&head); + c_list_sort(&head, _c_list_sort_cmp, NULL); + g_assert(c_list_length(&head) == 0); + g_assert(c_list_is_empty(&head)); + } + + elements = g_new0(CListSort, N_ELEMENTS); + for (n_list = 1; n_list < N_ELEMENTS; n_list++) { + if (n_list > 150) { + n_list += nmtst_get_rand_uint32() % n_list; + if (n_list >= N_ELEMENTS) + break; + } + { + const guint N_REPEAT = n_list > 50 ? 1 : 5; + + for (repeat = 0; repeat < N_REPEAT; repeat++) + _do_test_c_list_sort(elements, n_list, nmtst_get_rand_uint32() % 2); + } + } +} + +/*****************************************************************************/ + +typedef struct { + NMDedupMultiObj parent; + guint val; + guint other; +} DedupObj; + +static const NMDedupMultiObjClass dedup_obj_class; + +static DedupObj * +_dedup_obj_assert(const NMDedupMultiObj *obj) +{ + DedupObj *o; + + g_assert(obj); + o = (DedupObj *) obj; + g_assert(o->parent.klass == &dedup_obj_class); + g_assert(o->parent._ref_count > 0); + g_assert(o->val > 0); + return o; +} + +static const NMDedupMultiObj * +_dedup_obj_clone(const NMDedupMultiObj *obj) +{ + DedupObj *o, *o2; + + o = _dedup_obj_assert(obj); + o2 = g_slice_new0(DedupObj); + o2->parent.klass = &dedup_obj_class; + o2->parent._ref_count = 1; + o2->val = o->val; + o2->other = o->other; + return (NMDedupMultiObj *) o2; +} + +static void +_dedup_obj_destroy(NMDedupMultiObj *obj) +{ + DedupObj *o = (DedupObj *) obj; + + g_assert(o->parent._ref_count == 0); + o->parent._ref_count = 1; + o = _dedup_obj_assert(obj); + g_slice_free(DedupObj, o); +} + +static void +_dedup_obj_full_hash_update(const NMDedupMultiObj *obj, NMHashState *h) +{ + const DedupObj *o; + + o = _dedup_obj_assert(obj); + nm_hash_update_vals(h, o->val, o->other); +} + +static gboolean +_dedup_obj_full_equal(const NMDedupMultiObj *obj_a, const NMDedupMultiObj *obj_b) +{ + const DedupObj *o_a = _dedup_obj_assert(obj_a); + const DedupObj *o_b = _dedup_obj_assert(obj_b); + + return o_a->val == o_b->val && o_a->other == o_b->other; +} + +static const NMDedupMultiObjClass dedup_obj_class = { + .obj_clone = _dedup_obj_clone, + .obj_destroy = _dedup_obj_destroy, + .obj_full_hash_update = _dedup_obj_full_hash_update, + .obj_full_equal = _dedup_obj_full_equal, +}; + +#define DEDUP_OBJ_INIT(val_val, other_other) \ + (&((DedupObj){ \ + .parent = \ + { \ + .klass = &dedup_obj_class, \ + ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, \ + }, \ + .val = (val_val), \ + .other = (other_other), \ + })) + +typedef struct { + NMDedupMultiIdxType parent; + guint partition_size; + guint val_mod; +} DedupIdxType; + +static const NMDedupMultiIdxTypeClass dedup_idx_type_class; + +static const DedupIdxType * +_dedup_idx_assert(const NMDedupMultiIdxType *idx_type) +{ + DedupIdxType *t; + + g_assert(idx_type); + t = (DedupIdxType *) idx_type; + g_assert(t->parent.klass == &dedup_idx_type_class); + g_assert(t->partition_size > 0); + g_assert(t->val_mod > 0); + return t; +} + +static void +_dedup_idx_obj_id_hash_update(const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj * obj, + NMHashState * h) +{ + const DedupIdxType *t; + const DedupObj * o; + + t = _dedup_idx_assert(idx_type); + o = _dedup_obj_assert(obj); + + nm_hash_update_val(h, o->val / t->partition_size); + nm_hash_update_val(h, o->val % t->val_mod); +} + +static gboolean +_dedup_idx_obj_id_equal(const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj * obj_a, + const NMDedupMultiObj * obj_b) +{ + const DedupIdxType *t; + const DedupObj * o_a; + const DedupObj * o_b; + + t = _dedup_idx_assert(idx_type); + o_a = _dedup_obj_assert(obj_a); + o_b = _dedup_obj_assert(obj_b); + + return (o_a->val / t->partition_size) == (o_b->val / t->partition_size) + && (o_a->val % t->val_mod) == (o_b->val % t->val_mod); +} + +static void +_dedup_idx_obj_partition_hash_update(const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj * obj, + NMHashState * h) +{ + const DedupIdxType *t; + const DedupObj * o; + + t = _dedup_idx_assert(idx_type); + o = _dedup_obj_assert(obj); + + nm_hash_update_val(h, o->val / t->partition_size); +} + +static gboolean +_dedup_idx_obj_partition_equal(const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj * obj_a, + const NMDedupMultiObj * obj_b) +{ + const DedupIdxType *t; + const DedupObj * o_a; + const DedupObj * o_b; + + t = _dedup_idx_assert(idx_type); + o_a = _dedup_obj_assert(obj_a); + o_b = _dedup_obj_assert(obj_b); + + return (o_a->val / t->partition_size) == (o_b->val / t->partition_size); +} + +static const NMDedupMultiIdxTypeClass dedup_idx_type_class = { + .idx_obj_id_hash_update = _dedup_idx_obj_id_hash_update, + .idx_obj_id_equal = _dedup_idx_obj_id_equal, + .idx_obj_partition_hash_update = _dedup_idx_obj_partition_hash_update, + .idx_obj_partition_equal = _dedup_idx_obj_partition_equal, +}; + +static const DedupIdxType * +DEDUP_IDX_TYPE_INIT(DedupIdxType *idx_type, guint partition_size, guint val_mod) +{ + nm_dedup_multi_idx_type_init((NMDedupMultiIdxType *) idx_type, &dedup_idx_type_class); + idx_type->val_mod = val_mod; + idx_type->partition_size = partition_size; + return idx_type; +} + +static gboolean +_dedup_idx_add(NMDedupMultiIndex * idx, + const DedupIdxType * idx_type, + const DedupObj * obj, + NMDedupMultiIdxMode mode, + const NMDedupMultiEntry **out_entry) +{ + g_assert(idx); + _dedup_idx_assert((NMDedupMultiIdxType *) idx_type); + if (obj) + _dedup_obj_assert((NMDedupMultiObj *) obj); + return nm_dedup_multi_index_add(idx, + (NMDedupMultiIdxType *) idx_type, + obj, + mode, + out_entry, + NULL); +} + +static void +_dedup_head_entry_assert(const NMDedupMultiHeadEntry *entry) +{ + g_assert(entry); + g_assert(entry->len > 0); + g_assert(entry->len == c_list_length(&entry->lst_entries_head)); + g_assert(entry->idx_type); + g_assert(entry->is_head); +} + +static const DedupObj * +_dedup_entry_assert(const NMDedupMultiEntry *entry) +{ + g_assert(entry); + g_assert(!c_list_is_empty(&entry->lst_entries)); + g_assert(entry->head); + g_assert(!entry->is_head); + g_assert(entry->head != (gpointer) entry); + _dedup_head_entry_assert(entry->head); + return _dedup_obj_assert(entry->obj); +} + +static const DedupIdxType * +_dedup_entry_get_idx_type(const NMDedupMultiEntry *entry) +{ + _dedup_entry_assert(entry); + + g_assert(entry->head); + g_assert(entry->head->idx_type); + return _dedup_idx_assert(entry->head->idx_type); +} + +static void +_dedup_entry_assert_all(const NMDedupMultiEntry *entry, + gssize expected_idx, + const DedupObj *const * expected_obj) +{ + gsize n, i; + CList *iter; + + g_assert(entry); + _dedup_entry_assert(entry); + + g_assert(expected_obj); + n = NM_PTRARRAY_LEN(expected_obj); + + g_assert(n == c_list_length(&entry->lst_entries)); + + g_assert(expected_idx >= -1 && expected_idx < n); + g_assert(entry->head); + if (expected_idx == -1) + g_assert(entry->head == (gpointer) entry); + else + g_assert(entry->head != (gpointer) entry); + + i = 0; + c_list_for_each (iter, &entry->head->lst_entries_head) { + const NMDedupMultiEntry *entry_current = c_list_entry(iter, NMDedupMultiEntry, lst_entries); + const DedupObj * obj_current; + const DedupIdxType * idx_type = _dedup_entry_get_idx_type(entry_current); + + obj_current = _dedup_entry_assert(entry_current); + g_assert(obj_current); + g_assert(i < n); + if (expected_idx == i) + g_assert(entry_current == entry); + g_assert(idx_type->parent.klass->idx_obj_partition_equal( + &idx_type->parent, + entry_current->obj, + c_list_entry(entry->head->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj)); + i++; + } +} +#define _dedup_entry_assert_all(entry, expected_idx, ...) \ + _dedup_entry_assert_all(entry, expected_idx, (const DedupObj *const[]){__VA_ARGS__, NULL}) + +static void +test_dedup_multi(void) +{ + NMDedupMultiIndex * idx; + DedupIdxType IDX_20_3_a_stack; + const DedupIdxType *const IDX_20_3_a = DEDUP_IDX_TYPE_INIT(&IDX_20_3_a_stack, 20, 3); + const NMDedupMultiEntry * entry1; + + idx = nm_dedup_multi_index_new(); + + g_assert(_dedup_idx_add(idx, + IDX_20_3_a, + DEDUP_OBJ_INIT(1, 1), + NM_DEDUP_MULTI_IDX_MODE_APPEND, + &entry1)); + _dedup_entry_assert_all(entry1, 0, DEDUP_OBJ_INIT(1, 1)); + + g_assert(nm_dedup_multi_index_obj_find(idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT(1, 1))); + g_assert(!nm_dedup_multi_index_obj_find(idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT(1, 2))); + + g_assert(_dedup_idx_add(idx, + IDX_20_3_a, + DEDUP_OBJ_INIT(1, 2), + NM_DEDUP_MULTI_IDX_MODE_APPEND, + &entry1)); + _dedup_entry_assert_all(entry1, 0, DEDUP_OBJ_INIT(1, 2)); + + g_assert(!nm_dedup_multi_index_obj_find(idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT(1, 1))); + g_assert(nm_dedup_multi_index_obj_find(idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT(1, 2))); + + g_assert(_dedup_idx_add(idx, + IDX_20_3_a, + DEDUP_OBJ_INIT(2, 2), + NM_DEDUP_MULTI_IDX_MODE_APPEND, + &entry1)); + _dedup_entry_assert_all(entry1, 1, DEDUP_OBJ_INIT(1, 2), DEDUP_OBJ_INIT(2, 2)); + + nm_dedup_multi_index_unref(idx); +} + +/*****************************************************************************/ + +static NMConnection * +_connection_new_from_dbus(GVariant *dict, GError **error) +{ + return _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, error); +} + +static void +vpn_check_func(const char *key, const char *value, gpointer user_data) +{ + if (!strcmp(key, "foobar1")) { + g_assert_cmpstr(value, ==, "blahblah1"); + return; + } + + if (!strcmp(key, "foobar2")) { + g_assert_cmpstr(value, ==, "blahblah2"); + return; + } + + if (!strcmp(key, "foobar3")) { + g_assert_cmpstr(value, ==, "blahblah3"); + return; + } + + if (!strcmp(key, "foobar4")) { + g_assert_cmpstr(value, ==, "blahblah4"); + return; + } + + g_assert_not_reached(); +} + +static void +vpn_check_empty_func(const char *key, const char *value, gpointer user_data) +{ + g_assert_not_reached(); +} + +static void +test_setting_vpn_items(void) +{ + gs_unref_object NMConnection *connection = NULL; + NMSettingVpn * s_vpn; + + connection = + nmtst_create_minimal_connection("vpn-items", NULL, NM_SETTING_VPN_SETTING_NAME, NULL); + + s_vpn = nm_connection_get_setting_vpn(connection); + + nm_setting_vpn_add_data_item(s_vpn, "foobar1", "blahblah1"); + nm_setting_vpn_add_data_item(s_vpn, "foobar2", "blahblah2"); + nm_setting_vpn_add_data_item(s_vpn, "foobar3", "blahblah3"); + nm_setting_vpn_add_data_item(s_vpn, "foobar4", "blahblah4"); + + /* Ensure that added values are all present */ + nm_setting_vpn_foreach_data_item(s_vpn, vpn_check_func, NULL); + nm_setting_vpn_remove_data_item(s_vpn, "foobar1"); + nm_setting_vpn_remove_data_item(s_vpn, "foobar2"); + nm_setting_vpn_remove_data_item(s_vpn, "foobar3"); + nm_setting_vpn_remove_data_item(s_vpn, "foobar4"); + + g_assert(!_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert(!_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + nm_setting_vpn_add_secret(s_vpn, "foobar1", "blahblah1"); + + g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert(_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + nm_setting_vpn_add_secret(s_vpn, "foobar2", "blahblah2"); + nm_setting_vpn_add_secret(s_vpn, "foobar3", "blahblah3"); + nm_setting_vpn_add_secret(s_vpn, "foobar4", "blahblah4"); + + /* Ensure that added values are all present */ + nm_setting_vpn_foreach_secret(s_vpn, vpn_check_func, NULL); + nm_setting_vpn_remove_secret(s_vpn, "foobar1"); + nm_setting_vpn_remove_secret(s_vpn, "foobar2"); + nm_setting_vpn_remove_secret(s_vpn, "foobar3"); + + g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert(_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + nm_setting_vpn_add_data_item(s_vpn, "foobar4-flags", "blahblah4"); + + g_assert(_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + nm_setting_vpn_add_data_item(s_vpn, "foobar4-flags", "2"); + + g_assert(!_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + nm_setting_vpn_remove_secret(s_vpn, "foobar4"); + + g_assert(!_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert(!_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + nm_setting_vpn_remove_data_item(s_vpn, "foobar4-flags"); + + /* Try to add some blank values and make sure they are rejected */ + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); + nm_setting_vpn_add_data_item(s_vpn, NULL, NULL); + g_test_assert_expected_messages(); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); + nm_setting_vpn_add_data_item(s_vpn, "", ""); + g_test_assert_expected_messages(); + + nm_setting_vpn_add_data_item(s_vpn, "foobar1", ""); + g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, "foobar1"), ==, ""); + + nm_setting_vpn_add_data_item(s_vpn, "foobar1", NULL); + g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, "foobar1"), ==, NULL); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); + nm_setting_vpn_add_data_item(s_vpn, NULL, "blahblah1"); + g_test_assert_expected_messages(); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); + nm_setting_vpn_add_data_item(s_vpn, "", "blahblah1"); + g_test_assert_expected_messages(); + + nm_setting_vpn_foreach_data_item(s_vpn, vpn_check_empty_func, NULL); + + /* Try to add some blank secrets and make sure they are rejected */ + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); + nm_setting_vpn_add_secret(s_vpn, NULL, NULL); + g_test_assert_expected_messages(); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); + nm_setting_vpn_add_secret(s_vpn, "", ""); + g_test_assert_expected_messages(); + + nm_setting_vpn_add_secret(s_vpn, "foobar1", ""); + + nm_setting_vpn_add_secret(s_vpn, "foobar1", NULL); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); + nm_setting_vpn_add_secret(s_vpn, NULL, "blahblah1"); + g_test_assert_expected_messages(); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(key && key[0])); + nm_setting_vpn_add_secret(s_vpn, "", "blahblah1"); + g_test_assert_expected_messages(); + + nm_setting_vpn_foreach_secret(s_vpn, vpn_check_empty_func, NULL); +} + +static void +test_setting_vpn_update_secrets(void) +{ + NMConnection * connection; + NMSettingVpn * s_vpn; + GVariantBuilder settings_builder, vpn_builder, secrets_builder; + GVariant * settings; + gboolean success; + GError * error = NULL; + const char * tmp; + const char * key1 = "foobar"; + const char * key2 = "blahblah"; + const char * val1 = "value1"; + const char * val2 = "value2"; + + connection = nm_simple_connection_new(); + s_vpn = (NMSettingVpn *) nm_setting_vpn_new(); + nm_connection_add_setting(connection, NM_SETTING(s_vpn)); + + g_variant_builder_init(&settings_builder, NM_VARIANT_TYPE_CONNECTION); + g_variant_builder_init(&vpn_builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_init(&secrets_builder, G_VARIANT_TYPE("a{ss}")); + + g_variant_builder_add(&secrets_builder, "{ss}", key1, val1); + g_variant_builder_add(&secrets_builder, "{ss}", key2, val2); + + g_variant_builder_add(&vpn_builder, + "{sv}", + NM_SETTING_VPN_SECRETS, + g_variant_builder_end(&secrets_builder)); + g_variant_builder_add(&settings_builder, "{sa{sv}}", NM_SETTING_VPN_SETTING_NAME, &vpn_builder); + settings = g_variant_builder_end(&settings_builder); + + success = + nm_connection_update_secrets(connection, NM_SETTING_VPN_SETTING_NAME, settings, &error); + g_assert_no_error(error); + g_assert(success); + + /* Read the secrets back out */ + tmp = nm_setting_vpn_get_secret(s_vpn, key1); + g_assert(tmp); + g_assert_cmpstr(tmp, ==, val1); + + tmp = nm_setting_vpn_get_secret(s_vpn, key2); + g_assert(tmp); + g_assert_cmpstr(tmp, ==, val2); + + g_variant_unref(settings); + g_object_unref(connection); +} + +#define TO_DEL_NUM 50 +typedef struct { + NMSettingVpn *s_vpn; + char * to_del[TO_DEL_NUM]; + guint called; +} IterInfo; + +static void +del_iter_func(const char *key, const char *value, gpointer user_data) +{ + IterInfo *info = user_data; + int i; + + /* Record how many times this function gets called; it should get called + * exactly as many times as there are keys in the hash table, regardless + * of what keys we delete from the table. + */ + info->called++; + + /* During the iteration, remove a bunch of stuff from the table */ + if (info->called == 1) { + for (i = 0; i < TO_DEL_NUM; i++) + nm_setting_vpn_remove_data_item(info->s_vpn, info->to_del[i]); + } +} + +static void +test_setting_vpn_modify_during_foreach(void) +{ + NMSettingVpn *s_vpn; + IterInfo info; + char * key, *val; + int i, u = 0; + + s_vpn = (NMSettingVpn *) nm_setting_vpn_new(); + g_assert(s_vpn); + + for (i = 0; i < TO_DEL_NUM * 2; i++) { + key = g_strdup_printf("adsfasdfadf%d", i); + val = g_strdup_printf("42263236236awt%d", i); + nm_setting_vpn_add_data_item(s_vpn, key, val); + + /* Cache some keys to delete */ + if (i % 2) + info.to_del[u++] = g_strdup(key); + + g_free(key); + g_free(val); + } + + /* Iterate over current table keys */ + info.s_vpn = s_vpn; + info.called = 0; + nm_setting_vpn_foreach_data_item(s_vpn, del_iter_func, &info); + + /* Make sure all the things we removed during iteration are really gone */ + for (i = 0; i < TO_DEL_NUM; i++) { + g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, info.to_del[i]), ==, NULL); + g_free(info.to_del[i]); + } + + /* And make sure the foreach callback was called the same number of times + * as there were keys in the table at the beginning of the foreach. + */ + g_assert_cmpint(info.called, ==, TO_DEL_NUM * 2); + + g_object_unref(s_vpn); +} + +static void +test_setting_ip4_config_labels(void) +{ + NMSettingIPConfig *s_ip4; + NMIPAddress * addr; + GVariant * label; + GPtrArray * addrs; + char ** labels; + NMConnection * conn; + GVariant * dict, *dict2, *setting_dict, *value; + GError * error = NULL; + + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(s_ip4), + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + + /* addr 1 */ + addr = nm_ip_address_new(AF_INET, "1.2.3.4", 24, &error); + g_assert_no_error(error); + + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); + + addr = nm_setting_ip_config_get_address(s_ip4, 0); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label == NULL); + + /* The 'address-labels' property should be omitted from the serialization if + * there are no non-NULL labels. + */ + conn = nmtst_create_minimal_connection("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nm_connection_add_setting(conn, nm_setting_duplicate(NM_SETTING(s_ip4))); + dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); + g_object_unref(conn); + + setting_dict = + g_variant_lookup_value(dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + g_assert(setting_dict != NULL); + + value = g_variant_lookup_value(setting_dict, "address-labels", NULL); + g_assert(value == NULL); + + g_variant_unref(setting_dict); + g_variant_unref(dict); + + /* Now back to constructing the original s_ip4... */ + + /* addr 2 */ + addr = nm_ip_address_new(AF_INET, "2.3.4.5", 24, &error); + g_assert_no_error(error); + nm_ip_address_set_attribute(addr, + NM_IP_ADDRESS_ATTRIBUTE_LABEL, + g_variant_new_string("eth0:1")); + + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); + + addr = nm_setting_ip_config_get_address(s_ip4, 1); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label != NULL); + g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); + + /* addr 3 */ + addr = nm_ip_address_new(AF_INET, "3.4.5.6", 24, &error); + g_assert_no_error(error); + nm_ip_address_set_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL, NULL); + + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); + + addr = nm_setting_ip_config_get_address(s_ip4, 2); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label == NULL); + + /* Remove addr 1 and re-verify remaining addresses */ + nm_setting_ip_config_remove_address(s_ip4, 0); + nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); + + addr = nm_setting_ip_config_get_address(s_ip4, 0); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "2.3.4.5"); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label != NULL); + g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); + + addr = nm_setting_ip_config_get_address(s_ip4, 1); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "3.4.5.6"); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label == NULL); + + /* If we serialize as the daemon, the labels should appear in the D-Bus + * serialization under both 'address-labels' and 'address-data'. + */ + conn = nmtst_create_minimal_connection("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nm_connection_add_setting(conn, NM_SETTING(s_ip4)); + _nm_utils_is_manager_process = TRUE; + dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); + _nm_utils_is_manager_process = FALSE; + g_object_unref(conn); + + setting_dict = + g_variant_lookup_value(dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + g_assert(setting_dict != NULL); + + value = g_variant_lookup_value(setting_dict, "address-labels", G_VARIANT_TYPE_STRING_ARRAY); + g_assert(value != NULL); + g_variant_get(value, "^as", &labels); + g_assert_cmpint(g_strv_length(labels), ==, 2); + g_assert_cmpstr(labels[0], ==, "eth0:1"); + g_assert_cmpstr(labels[1], ==, ""); + g_variant_unref(value); + g_strfreev(labels); + + value = g_variant_lookup_value(setting_dict, "address-data", G_VARIANT_TYPE("aa{sv}")); + addrs = nm_utils_ip_addresses_from_variant(value, AF_INET); + g_variant_unref(value); + g_assert(addrs != NULL); + g_assert_cmpint(addrs->len, ==, 2); + addr = addrs->pdata[0]; + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label != NULL); + g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); + addr = addrs->pdata[1]; + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label == NULL); + g_ptr_array_unref(addrs); + + g_variant_unref(setting_dict); + + /* We should be able to deserialize the labels from either 'address-labels' + * or 'address-data'. + */ + dict2 = g_variant_ref(dict); + + NMTST_VARIANT_EDITOR( + dict, NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-data");); + conn = _connection_new_from_dbus(dict, &error); + g_assert_no_error(error); + g_variant_unref(dict); + + s_ip4 = nm_connection_get_setting_ip4_config(conn); + + addr = nm_setting_ip_config_get_address(s_ip4, 0); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "2.3.4.5"); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label != NULL); + g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); + + addr = nm_setting_ip_config_get_address(s_ip4, 1); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "3.4.5.6"); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label == NULL); + + g_object_unref(conn); + + NMTST_VARIANT_EDITOR( + dict2, NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-labels");); + conn = _connection_new_from_dbus(dict2, &error); + g_assert_no_error(error); + g_variant_unref(dict2); + + s_ip4 = nm_connection_get_setting_ip4_config(conn); + + addr = nm_setting_ip_config_get_address(s_ip4, 0); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "2.3.4.5"); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); + + addr = nm_setting_ip_config_get_address(s_ip4, 1); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "3.4.5.6"); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label == NULL); + + /* Test explicit property assignment */ + g_object_get(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL); + + nm_setting_ip_config_clear_addresses(s_ip4); + g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 0); + + g_object_set(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); + g_ptr_array_unref(addrs); + nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); + g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 2); + + addr = nm_setting_ip_config_get_address(s_ip4, 0); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "2.3.4.5"); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label != NULL); + g_assert_cmpstr(g_variant_get_string(label, NULL), ==, "eth0:1"); + + addr = nm_setting_ip_config_get_address(s_ip4, 1); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "3.4.5.6"); + label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); + g_assert(label == NULL); + + g_object_unref(conn); +} + +static void +test_setting_ip4_config_address_data(void) +{ + NMSettingIPConfig *s_ip4; + NMIPAddress * addr; + GPtrArray * addrs; + NMConnection * conn; + GVariant * dict, *setting_dict, *value; + GError * error = NULL; + + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(s_ip4), + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + + /* addr 1 */ + addr = nm_ip_address_new(AF_INET, "1.2.3.4", 24, &error); + g_assert_no_error(error); + nm_ip_address_set_attribute(addr, "one", g_variant_new_string("foo")); + nm_ip_address_set_attribute(addr, "two", g_variant_new_int32(42)); + + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); + + /* addr 2 */ + addr = nm_ip_address_new(AF_INET, "2.3.4.5", 24, &error); + g_assert_no_error(error); + + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + nmtst_assert_setting_verifies(NM_SETTING(s_ip4)); + + /* The client-side D-Bus serialization should include the attributes in + * "address-data", and should not have an "addresses" property. + */ + conn = nmtst_create_minimal_connection("address-data test", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + nm_connection_add_setting(conn, NM_SETTING(s_ip4)); + dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); + + setting_dict = + g_variant_lookup_value(dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + g_assert(setting_dict != NULL); + + value = g_variant_lookup_value(setting_dict, "addresses", NULL); + g_assert(value == NULL); + + value = g_variant_lookup_value(setting_dict, "address-data", G_VARIANT_TYPE("aa{sv}")); + addrs = nm_utils_ip_addresses_from_variant(value, AF_INET); + g_variant_unref(value); + g_assert(addrs != NULL); + g_assert_cmpint(addrs->len, ==, 2); + + addr = addrs->pdata[0]; + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "1.2.3.4"); + value = nm_ip_address_get_attribute(addr, "one"); + g_assert(value != NULL); + g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "foo"); + value = nm_ip_address_get_attribute(addr, "two"); + g_assert(value != NULL); + g_assert_cmpint(g_variant_get_int32(value), ==, 42); + + g_ptr_array_unref(addrs); + g_variant_unref(setting_dict); + g_variant_unref(dict); + + /* The daemon-side serialization should include both 'addresses' and 'address-data' */ + _nm_utils_is_manager_process = TRUE; + dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); + _nm_utils_is_manager_process = FALSE; + + setting_dict = + g_variant_lookup_value(dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + g_assert(setting_dict != NULL); + + value = g_variant_lookup_value(setting_dict, "addresses", G_VARIANT_TYPE("aau")); + g_assert(value != NULL); + g_variant_unref(value); + + value = g_variant_lookup_value(setting_dict, "address-data", G_VARIANT_TYPE("aa{sv}")); + g_assert(value != NULL); + g_variant_unref(value); + + g_variant_unref(setting_dict); + g_object_unref(conn); + + /* When we reserialize that dictionary as a client, 'address-data' will be preferred. */ + conn = _connection_new_from_dbus(dict, &error); + g_assert_no_error(error); + + s_ip4 = nm_connection_get_setting_ip4_config(conn); + + addr = nm_setting_ip_config_get_address(s_ip4, 0); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "1.2.3.4"); + value = nm_ip_address_get_attribute(addr, "one"); + g_assert(value != NULL); + g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "foo"); + value = nm_ip_address_get_attribute(addr, "two"); + g_assert(value != NULL); + g_assert_cmpint(g_variant_get_int32(value), ==, 42); + + /* But on the server side, 'addresses' will have precedence. */ + _nm_utils_is_manager_process = TRUE; + conn = _connection_new_from_dbus(dict, &error); + _nm_utils_is_manager_process = FALSE; + g_assert_no_error(error); + g_variant_unref(dict); + + s_ip4 = nm_connection_get_setting_ip4_config(conn); + + addr = nm_setting_ip_config_get_address(s_ip4, 0); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "1.2.3.4"); + value = nm_ip_address_get_attribute(addr, "one"); + g_assert(value == NULL); + value = nm_ip_address_get_attribute(addr, "two"); + g_assert(value == NULL); + + g_object_unref(conn); +} + +static void +test_setting_ip_route_attributes(void) +{ + GVariant *variant; + gboolean res, known; + +#define TEST_ATTR(name, type, value, family, exp_res, exp_known) \ + variant = g_variant_new_##type(value); \ + res = nm_ip_route_attribute_validate(name, variant, family, &known, NULL); \ + g_assert(res == exp_res); \ + g_assert(known == exp_known); \ + g_variant_unref(variant); + + TEST_ATTR("foo", uint32, 12, AF_INET, FALSE, FALSE); + + TEST_ATTR("tos", byte, 127, AF_INET, TRUE, TRUE); + TEST_ATTR("tos", string, "0x28", AF_INET, FALSE, TRUE); + + TEST_ATTR("cwnd", uint32, 10, AF_INET, TRUE, TRUE); + TEST_ATTR("cwnd", string, "11", AF_INET, FALSE, TRUE); + + TEST_ATTR("lock-mtu", boolean, TRUE, AF_INET, TRUE, TRUE); + TEST_ATTR("lock-mtu", uint32, 1, AF_INET, FALSE, TRUE); + + TEST_ATTR("from", string, "fd01::1", AF_INET6, TRUE, TRUE); + TEST_ATTR("from", string, "fd01::1/64", AF_INET6, TRUE, TRUE); + TEST_ATTR("from", string, "fd01::1/128", AF_INET6, TRUE, TRUE); + TEST_ATTR("from", string, "fd01::1/129", AF_INET6, FALSE, TRUE); + TEST_ATTR("from", string, "fd01::1/a", AF_INET6, FALSE, TRUE); + TEST_ATTR("from", string, "abc/64", AF_INET6, FALSE, TRUE); + TEST_ATTR("from", string, "1.2.3.4", AF_INET, FALSE, TRUE); + TEST_ATTR("from", string, "1.2.3.4", AF_INET6, FALSE, TRUE); + + TEST_ATTR("src", string, "1.2.3.4", AF_INET, TRUE, TRUE); + TEST_ATTR("src", string, "1.2.3.4", AF_INET6, FALSE, TRUE); + TEST_ATTR("src", string, "1.2.3.0/24", AF_INET, FALSE, TRUE); + TEST_ATTR("src", string, "fd01::12", AF_INET6, TRUE, TRUE); + + TEST_ATTR("type", string, "local", AF_INET, TRUE, TRUE); + TEST_ATTR("type", string, "local", AF_INET6, TRUE, TRUE); + TEST_ATTR("type", string, "unicast", AF_INET, TRUE, TRUE); + TEST_ATTR("type", string, "unicast", AF_INET6, TRUE, TRUE); + +#undef TEST_ATTR +} + +static void +test_setting_gsm_apn_spaces(void) +{ + gs_unref_object NMSettingGsm *s_gsm = NULL; + const char * tmp; + + s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); + g_assert(s_gsm); + + /* Trailing space */ + g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar ", NULL); + tmp = nm_setting_gsm_get_apn(s_gsm); + g_assert_cmpstr(tmp, ==, "foobar"); + + /* Leading space */ + g_object_set(s_gsm, NM_SETTING_GSM_APN, " foobar", NULL); + tmp = nm_setting_gsm_get_apn(s_gsm); + g_assert_cmpstr(tmp, ==, "foobar"); +} + +static void +test_setting_gsm_apn_bad_chars(void) +{ + gs_unref_object NMSettingGsm *s_gsm = NULL; + + s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); + g_assert(s_gsm); + + /* Make sure a valid APN works */ + g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar123.-baz", NULL); + g_assert(nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); + + /* Random invalid chars */ + g_object_set(s_gsm, NM_SETTING_GSM_APN, "@#%$@#%@#%", NULL); + g_assert(!nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); + + /* Spaces */ + g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar baz", NULL); + g_assert(!nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); + + /* 0 characters long */ + g_object_set(s_gsm, NM_SETTING_GSM_APN, "", NULL); + g_assert(nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); + + /* 65-character long */ + g_object_set(s_gsm, + NM_SETTING_GSM_APN, + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl1", + NULL); + g_assert(!nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL)); +} + +static void +test_setting_gsm_apn_underscore(void) +{ + gs_unref_object NMSettingGsm *s_gsm = NULL; + + s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); + g_assert(s_gsm); + + /* 65-character long */ + g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar_baz", NULL); + nmtst_assert_setting_verifies(NM_SETTING(s_gsm)); +} + +static void +test_setting_gsm_without_number(void) +{ + gs_unref_object NMSettingGsm *s_gsm = NULL; + + s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); + g_assert(s_gsm); + + g_object_set(s_gsm, NM_SETTING_GSM_NUMBER, NULL, NULL); + nmtst_assert_setting_verifies(NM_SETTING(s_gsm)); + + g_object_set(s_gsm, NM_SETTING_GSM_NUMBER, "", NULL); + nmtst_assert_setting_verify_fails(NM_SETTING(s_gsm), + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +test_setting_gsm_sim_operator_id(void) +{ + gs_unref_object NMSettingGsm *s_gsm = NULL; + + s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); + g_assert(s_gsm); + + /* Valid */ + g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "12345", NULL); + nmtst_assert_setting_verifies(NM_SETTING(s_gsm)); + + g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "123456", NULL); + nmtst_assert_setting_verifies(NM_SETTING(s_gsm)); + + /* Invalid */ + g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "", NULL); + nmtst_assert_setting_verify_fails(NM_SETTING(s_gsm), + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, " ", NULL); + nmtst_assert_setting_verify_fails(NM_SETTING(s_gsm), + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + g_object_set(s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "abcdef", NULL); + nmtst_assert_setting_verify_fails(NM_SETTING(s_gsm), + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static NMSettingWirelessSecurity * +make_test_wsec_setting(const char *detail) +{ + NMSettingWirelessSecurity *s_wsec; + + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); + g_assert(s_wsec); + + g_object_set(s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, + "foobarbaz", + NM_SETTING_WIRELESS_SECURITY_PSK, + "random psk", + NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + "aaaaaaaaaa", + NULL); + return s_wsec; +} + +static gboolean +_variant_contains(GVariant *vardict, const char *key) +{ + gs_unref_variant GVariant *value = NULL; + + value = g_variant_lookup_value(vardict, key, NULL); + return !!value; +} + +static void +test_setting_to_dbus_all(void) +{ + NMSettingWirelessSecurity *s_wsec; + GVariant * dict; + + s_wsec = make_test_wsec_setting("setting-to-dbus-all"); + + dict = _nm_setting_to_dbus(NM_SETTING(s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); + + /* Make sure all keys are there */ + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)); + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME)); + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_PSK)); + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0)); + + g_variant_unref(dict); + g_object_unref(s_wsec); +} + +static void +test_setting_to_dbus_no_secrets(void) +{ + NMSettingWirelessSecurity *s_wsec; + GVariant * dict; + + s_wsec = make_test_wsec_setting("setting-to-dbus-no-secrets"); + + dict = _nm_setting_to_dbus(NM_SETTING(s_wsec), NULL, NM_CONNECTION_SERIALIZE_NO_SECRETS, NULL); + + /* Make sure non-secret keys are there */ + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)); + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME)); + + /* Make sure secrets are not there */ + g_assert(!_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_PSK)); + g_assert(!_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0)); + + g_variant_unref(dict); + g_object_unref(s_wsec); +} + +static void +test_setting_to_dbus_only_secrets(void) +{ + NMSettingWirelessSecurity *s_wsec; + GVariant * dict; + + s_wsec = make_test_wsec_setting("setting-to-dbus-only-secrets"); + + dict = + _nm_setting_to_dbus(NM_SETTING(s_wsec), NULL, NM_CONNECTION_SERIALIZE_ONLY_SECRETS, NULL); + + /* Make sure non-secret keys are not there */ + g_assert(!_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)); + g_assert(!_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME)); + + /* Make sure secrets are there */ + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_PSK)); + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0)); + + g_variant_unref(dict); + g_object_unref(s_wsec); +} + +static void +test_setting_to_dbus_transform(void) +{ + NMSetting * s_wired; + GVariant * dict, *val; + const char * test_mac_address = "11:22:33:44:55:66"; + const guint8 *dbus_mac_address; + guint8 cmp_mac_address[ETH_ALEN]; + gsize len; + + s_wired = nm_setting_wired_new(); + g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, test_mac_address, NULL); + + g_assert_cmpstr(nm_setting_wired_get_mac_address(NM_SETTING_WIRED(s_wired)), + ==, + test_mac_address); + + dict = _nm_setting_to_dbus(s_wired, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); + g_assert(dict != NULL); + + val = g_variant_lookup_value(dict, NM_SETTING_WIRED_MAC_ADDRESS, G_VARIANT_TYPE_BYTESTRING); + g_assert(val != NULL); + + dbus_mac_address = g_variant_get_fixed_array(val, &len, 1); + g_assert_cmpint(len, ==, ETH_ALEN); + + nm_utils_hwaddr_aton(test_mac_address, cmp_mac_address, ETH_ALEN); + g_assert(memcmp(dbus_mac_address, cmp_mac_address, ETH_ALEN) == 0); + + g_variant_unref(val); + g_variant_unref(dict); + g_object_unref(s_wired); +} + +static void +test_setting_to_dbus_enum(void) +{ + NMSetting *s_ip6, *s_wsec, *s_serial; + GVariant * dict, *val; + + /* enum */ + s_ip6 = nm_setting_ip6_config_new(); + g_object_set(s_ip6, + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, + NULL); + + dict = _nm_setting_to_dbus(s_ip6, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); + g_assert(dict != NULL); + + val = g_variant_lookup_value(dict, NM_SETTING_IP6_CONFIG_IP6_PRIVACY, G_VARIANT_TYPE_INT32); + g_assert(val != NULL); + g_assert_cmpint(g_variant_get_int32(val), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); + g_variant_unref(val); + + g_variant_unref(dict); + g_object_unref(s_ip6); + + /* flags (and a transformed enum) */ + s_wsec = nm_setting_wireless_security_new(); + g_object_set(s_wsec, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + NM_WEP_KEY_TYPE_KEY, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, + (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED), + NULL); + + dict = _nm_setting_to_dbus(s_wsec, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); + g_assert(dict != NULL); + + val = g_variant_lookup_value(dict, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + G_VARIANT_TYPE_UINT32); + g_assert(val != NULL); + g_assert_cmpint(g_variant_get_uint32(val), ==, NM_WEP_KEY_TYPE_KEY); + g_variant_unref(val); + + val = g_variant_lookup_value(dict, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, + G_VARIANT_TYPE_UINT32); + g_assert(val != NULL); + g_assert_cmpint(g_variant_get_uint32(val), + ==, + (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED)); + g_variant_unref(val); + + g_variant_unref(dict); + g_object_unref(s_wsec); + + /* another transformed enum */ + s_serial = nm_setting_serial_new(); + g_object_set(s_serial, NM_SETTING_SERIAL_PARITY, NM_SETTING_SERIAL_PARITY_ODD, NULL); + + dict = _nm_setting_to_dbus(s_serial, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); + g_assert(dict != NULL); + + val = g_variant_lookup_value(dict, NM_SETTING_SERIAL_PARITY, G_VARIANT_TYPE_BYTE); + g_assert(val != NULL); + g_assert_cmpint(g_variant_get_byte(val), ==, 'o'); + g_variant_unref(val); + + g_variant_unref(dict); + g_object_unref(s_serial); +} + +static void +test_connection_to_dbus_setting_name(void) +{ + NMConnection * connection; + NMSettingWirelessSecurity *s_wsec; + GVariant * dict; + + connection = nm_simple_connection_new(); + s_wsec = make_test_wsec_setting("connection-to-dbus-setting-name"); + nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + + g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert(_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + g_object_set(s_wsec, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NULL); + + g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert(!_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + g_object_set(s_wsec, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + NULL); + + g_assert(_nm_connection_aggregate(connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert(_nm_connection_aggregate(connection, + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, + NULL)); + + dict = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); + + /* Make sure the keys of the first level dict are setting names, not + * the GType name of the setting objects. + */ + g_assert(_variant_contains(dict, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME)); + + g_variant_unref(dict); + g_object_unref(connection); +} + +static void +test_connection_to_dbus_deprecated_props(void) +{ + NMConnection * connection; + NMSetting * s_wireless; + GBytes * ssid; + NMSettingWirelessSecurity *s_wsec; + GVariant * dict, *wireless_dict, *sec_val; + + connection = nmtst_create_minimal_connection("test-connection-to-dbus-deprecated-props", + NULL, + NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + + s_wireless = nm_setting_wireless_new(); + ssid = g_bytes_new("1234567", 7); + g_object_set(s_wireless, NM_SETTING_WIRELESS_SSID, ssid, NULL); + g_bytes_unref(ssid); + nm_connection_add_setting(connection, s_wireless); + + /* Serialization should not have an 802-11-wireless.security property */ + dict = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); + g_assert(dict != NULL); + + wireless_dict = + g_variant_lookup_value(dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + g_assert(wireless_dict != NULL); + + sec_val = g_variant_lookup_value(wireless_dict, "security", NULL); + g_assert(sec_val == NULL); + + g_variant_unref(wireless_dict); + g_variant_unref(dict); + + /* Now add an NMSettingWirelessSecurity and try again */ + s_wsec = make_test_wsec_setting("test-connection-to-dbus-deprecated-props"); + nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + + dict = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); + g_assert(dict != NULL); + + wireless_dict = + g_variant_lookup_value(dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + g_assert(wireless_dict != NULL); + + sec_val = g_variant_lookup_value(wireless_dict, "security", NULL); + g_assert(g_variant_is_of_type(sec_val, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr(g_variant_get_string(sec_val, NULL), + ==, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + + g_variant_unref(sec_val); + g_variant_unref(wireless_dict); + g_variant_unref(dict); + g_object_unref(connection); +} + +static void +test_setting_new_from_dbus(void) +{ + NMSettingWirelessSecurity *s_wsec; + GVariant * dict; + + s_wsec = make_test_wsec_setting("setting-new-from-dbus"); + dict = _nm_setting_to_dbus(NM_SETTING(s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); + g_object_unref(s_wsec); + + s_wsec = + (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus(NM_TYPE_SETTING_WIRELESS_SECURITY, + dict, + NULL, + NM_SETTING_PARSE_FLAGS_NONE, + NULL); + g_variant_unref(dict); + + g_assert(s_wsec); + g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "wpa-psk"); + g_assert_cmpstr(nm_setting_wireless_security_get_leap_username(s_wsec), ==, "foobarbaz"); + g_assert_cmpstr(nm_setting_wireless_security_get_psk(s_wsec), ==, "random psk"); + g_object_unref(s_wsec); +} + +static void +test_setting_new_from_dbus_transform(void) +{ + NMSetting * s_wired; + GVariant * dict; + GVariantBuilder builder; + const char * test_mac_address = "11:22:33:44:55:66"; + guint8 dbus_mac_address[ETH_ALEN]; + GError * error = NULL; + + nm_utils_hwaddr_aton(test_mac_address, dbus_mac_address, ETH_ALEN); + + g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add( + &builder, + "{sv}", + NM_SETTING_WIRED_MAC_ADDRESS, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, dbus_mac_address, ETH_ALEN, 1)); + dict = g_variant_builder_end(&builder); + + s_wired = _nm_setting_new_from_dbus(NM_TYPE_SETTING_WIRED, + dict, + NULL, + NM_SETTING_PARSE_FLAGS_NONE, + &error); + g_assert_no_error(error); + + g_assert_cmpstr(nm_setting_wired_get_mac_address(NM_SETTING_WIRED(s_wired)), + ==, + test_mac_address); + + g_variant_unref(dict); + g_object_unref(s_wired); +} + +static void +test_setting_new_from_dbus_enum(void) +{ + NMSettingIP6Config * s_ip6; + NMSettingWirelessSecurity *s_wsec; + NMSettingSerial * s_serial; + GVariant * dict; + GVariantBuilder builder; + GError * error = NULL; + + /* enum */ + g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add(&builder, + "{sv}", + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + g_variant_new_int32(NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR)); + dict = g_variant_builder_end(&builder); + + s_ip6 = (NMSettingIP6Config *) _nm_setting_new_from_dbus(NM_TYPE_SETTING_IP6_CONFIG, + dict, + NULL, + NM_SETTING_PARSE_FLAGS_NONE, + &error); + g_assert_no_error(error); + + g_assert_cmpint(nm_setting_ip6_config_get_ip6_privacy(s_ip6), + ==, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); + + g_variant_unref(dict); + g_object_unref(s_ip6); + + /* flags (and a transformed enum) */ + g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add(&builder, + "{sv}", + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + g_variant_new_uint32(NM_WEP_KEY_TYPE_KEY)); + g_variant_builder_add(&builder, + "{sv}", + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, + g_variant_new_uint32(NM_SETTING_SECRET_FLAG_AGENT_OWNED + | NM_SETTING_SECRET_FLAG_NOT_SAVED)); + dict = g_variant_builder_end(&builder); + + s_wsec = + (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus(NM_TYPE_SETTING_WIRELESS_SECURITY, + dict, + NULL, + NM_SETTING_PARSE_FLAGS_NONE, + &error); + g_assert_no_error(error); + + g_assert_cmpint(nm_setting_wireless_security_get_wep_key_type(s_wsec), ==, NM_WEP_KEY_TYPE_KEY); + g_assert_cmpint(nm_setting_wireless_security_get_wep_key_flags(s_wsec), + ==, + (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED)); + + g_variant_unref(dict); + g_object_unref(s_wsec); + + /* another transformed enum */ + g_variant_builder_init(&builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add(&builder, "{sv}", NM_SETTING_SERIAL_PARITY, g_variant_new_byte('E')); + dict = g_variant_builder_end(&builder); + + s_serial = (NMSettingSerial *) _nm_setting_new_from_dbus(NM_TYPE_SETTING_SERIAL, + dict, + NULL, + NM_SETTING_PARSE_FLAGS_NONE, + &error); + g_assert_no_error(error); + + g_assert_cmpint(nm_setting_serial_get_parity(s_serial), ==, NM_SETTING_SERIAL_PARITY_EVEN); + + g_variant_unref(dict); + g_object_unref(s_serial); +} + +static void +test_setting_new_from_dbus_bad(void) +{ + NMSetting * setting; + NMConnection *conn; + GBytes * ssid; + GPtrArray * addrs; + GVariant * orig_dict, *dict; + GError * error = NULL; + + /* We want to test: + * - ordinary scalar properties + * - string properties + * - GBytes-valued properties (which are handled specially by set_property_from_dbus()) + * - enum/flags-valued properties + * - overridden properties + * - transformed properties + * + * No single setting class has examples of all of these, so we need two settings. + */ + + conn = nm_simple_connection_new(); + + setting = nm_setting_connection_new(); + g_object_set(setting, + NM_SETTING_CONNECTION_ID, + "test", + NM_SETTING_CONNECTION_UUID, + "83c5a841-1759-4cdb-bfce-8d4087956497", + NULL); + nm_connection_add_setting(conn, setting); + + setting = nm_setting_wireless_new(); + ssid = g_bytes_new("my-ssid", 7); + g_object_set(setting, + /* scalar */ + NM_SETTING_WIRELESS_RATE, + 100, + /* string */ + NM_SETTING_WIRELESS_MODE, + NM_SETTING_WIRELESS_MODE_INFRA, + /* GBytes */ + NM_SETTING_WIRELESS_SSID, + ssid, + /* transformed */ + NM_SETTING_WIRELESS_BSSID, + "00:11:22:33:44:55", + NULL); + g_bytes_unref(ssid); + nm_connection_add_setting(conn, setting); + + setting = nm_setting_ip6_config_new(); + addrs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addrs, nm_ip_address_new(AF_INET6, "1234::5678", 64, NULL)); + g_object_set(setting, + /* enum */ + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR, + /* overridden */ + NM_SETTING_IP_CONFIG_ADDRESSES, + addrs, + /* (needed in order to verify()) */ + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NULL); + g_ptr_array_unref(addrs); + nm_connection_add_setting(conn, setting); + + orig_dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); + g_object_unref(conn); + + /* sanity-check */ + conn = _connection_new_from_dbus(orig_dict, &error); + g_assert_no_error(error); + g_assert(conn); + g_object_unref(conn); + + /* Compatible mismatches */ + + dict = g_variant_ref(orig_dict); + NMTST_VARIANT_EDITOR(dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_RATE, + "i", + 10);); + conn = _connection_new_from_dbus(dict, &error); + g_assert(conn); + g_assert_no_error(error); + setting = nm_connection_get_setting(conn, NM_TYPE_SETTING_WIRELESS); + g_assert(setting); + g_assert_cmpint(nm_setting_wireless_get_rate(NM_SETTING_WIRELESS(setting)), ==, 10); + g_object_unref(conn); + g_variant_unref(dict); + + dict = g_variant_ref(orig_dict); + NMTST_VARIANT_EDITOR( + dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + "i", + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);); + conn = _connection_new_from_dbus(dict, &error); + g_assert(conn); + g_assert_no_error(error); + setting = nm_connection_get_setting(conn, NM_TYPE_SETTING_IP6_CONFIG); + g_assert(setting); + g_assert_cmpint(nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(setting)), + ==, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); + g_object_unref(conn); + g_variant_unref(dict); + + /* Incompatible mismatches */ + + dict = g_variant_ref(orig_dict); + NMTST_VARIANT_EDITOR(dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_RATE, + "s", + "ten");); + conn = _connection_new_from_dbus(dict, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "802-11-wireless.rate:")); + g_clear_error(&error); + g_variant_unref(dict); + + dict = g_variant_ref(orig_dict); + NMTST_VARIANT_EDITOR(dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MODE, + "b", + FALSE);); + conn = _connection_new_from_dbus(dict, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "802-11-wireless.mode:")); + g_clear_error(&error); + g_variant_unref(dict); + + dict = g_variant_ref(orig_dict); + NMTST_VARIANT_EDITOR(dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID, + "s", + "fred");); + conn = _connection_new_from_dbus(dict, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "802-11-wireless.ssid:")); + g_clear_error(&error); + g_variant_unref(dict); + + dict = g_variant_ref(orig_dict); + NMTST_VARIANT_EDITOR(dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_BSSID, + "i", + 42);); + conn = _connection_new_from_dbus(dict, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "802-11-wireless.bssid:")); + g_clear_error(&error); + g_variant_unref(dict); + + dict = g_variant_ref(orig_dict); + NMTST_VARIANT_EDITOR(dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + "s", + "private");); + conn = _connection_new_from_dbus(dict, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "ipv6.ip6-privacy:")); + g_clear_error(&error); + g_variant_unref(dict); + + dict = g_variant_ref(orig_dict); + NMTST_VARIANT_EDITOR(dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_ADDRESSES, + "s", + "1234::5678");); + conn = _connection_new_from_dbus(dict, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "ipv6.addresses:")); + g_clear_error(&error); + g_variant_unref(dict); + + g_variant_unref(orig_dict); +} + +static NMConnection * +new_test_connection(void) +{ + NMConnection *connection; + NMSetting * setting; + char * uuid; + guint64 timestamp = time(NULL); + + connection = nm_simple_connection_new(); + + setting = nm_setting_connection_new(); + uuid = nm_utils_uuid_generate(); + g_object_set(G_OBJECT(setting), + NM_SETTING_CONNECTION_ID, + "foobar", + NM_SETTING_CONNECTION_UUID, + uuid, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_CONNECTION_TIMESTAMP, + timestamp, + NULL); + g_free(uuid); + nm_connection_add_setting(connection, setting); + + setting = nm_setting_wired_new(); + g_object_set(G_OBJECT(setting), NM_SETTING_WIRED_MTU, 1592, NULL); + nm_connection_add_setting(connection, setting); + + setting = nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(setting), + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, + "eyeofthetiger", + NULL); + nm_connection_add_setting(connection, setting); + + return connection; +} + +static GVariant * +new_connection_dict(char ** out_uuid, + const char **out_expected_id, + const char **out_expected_ip6_method) +{ + GVariantBuilder conn_builder, setting_builder; + + g_variant_builder_init(&conn_builder, NM_VARIANT_TYPE_CONNECTION); + + *out_uuid = nm_utils_uuid_generate(); + *out_expected_id = "My happy connection"; + *out_expected_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL; + + /* Connection setting */ + g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add(&setting_builder, + "{sv}", + NM_SETTING_NAME, + g_variant_new_string(NM_SETTING_CONNECTION_SETTING_NAME)); + g_variant_builder_add(&setting_builder, + "{sv}", + NM_SETTING_CONNECTION_ID, + g_variant_new_string(*out_expected_id)); + g_variant_builder_add(&setting_builder, + "{sv}", + NM_SETTING_CONNECTION_UUID, + g_variant_new_string(*out_uuid)); + g_variant_builder_add(&setting_builder, + "{sv}", + NM_SETTING_CONNECTION_TYPE, + g_variant_new_string(NM_SETTING_WIRED_SETTING_NAME)); + + g_variant_builder_add(&conn_builder, + "{sa{sv}}", + NM_SETTING_CONNECTION_SETTING_NAME, + &setting_builder); + + /* Wired setting */ + g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add(&conn_builder, + "{sa{sv}}", + NM_SETTING_WIRED_SETTING_NAME, + &setting_builder); + + /* IP6 */ + g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add(&setting_builder, + "{sv}", + NM_SETTING_IP_CONFIG_METHOD, + g_variant_new_string(*out_expected_ip6_method)); + g_variant_builder_add(&conn_builder, + "{sa{sv}}", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + &setting_builder); + + return g_variant_builder_end(&conn_builder); +} + +static void +test_connection_replace_settings(void) +{ + NMConnection * connection; + GVariant * new_settings; + GError * error = NULL; + gboolean success; + NMSettingConnection *s_con; + NMSettingIPConfig * s_ip6; + char * uuid = NULL; + const char * expected_id = NULL, *expected_method = NULL; + + connection = new_test_connection(); + + new_settings = new_connection_dict(&uuid, &expected_id, &expected_method); + g_assert(new_settings); + + /* Replace settings and test */ + success = nm_connection_replace_settings(connection, new_settings, &error); + g_assert_no_error(error); + g_assert(success); + + s_con = nm_connection_get_setting_connection(connection); + g_assert(s_con); + g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); + g_assert_cmpstr(nm_setting_connection_get_uuid(s_con), ==, uuid); + + g_assert(nm_connection_get_setting_wired(connection)); + g_assert(!nm_connection_get_setting_ip4_config(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), ==, expected_method); + + g_free(uuid); + g_variant_unref(new_settings); + g_object_unref(connection); +} + +static void +test_connection_replace_settings_from_connection(void) +{ + NMConnection * connection, *replacement; + NMSettingConnection *s_con; + NMSetting * setting; + GBytes * ssid; + char * uuid = NULL; + const char * expected_id = "Awesome connection"; + + connection = new_test_connection(); + g_assert(connection); + + replacement = nm_simple_connection_new(); + g_assert(replacement); + + /* New connection setting */ + setting = nm_setting_connection_new(); + g_assert(setting); + + uuid = nm_utils_uuid_generate(); + g_object_set(setting, + NM_SETTING_CONNECTION_ID, + expected_id, + NM_SETTING_CONNECTION_UUID, + uuid, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + nm_connection_add_setting(replacement, setting); + + /* New wifi setting */ + setting = nm_setting_wireless_new(); + g_assert(setting); + + ssid = g_bytes_new("1234567", 7); + g_object_set(setting, + NM_SETTING_WIRELESS_SSID, + ssid, + NM_SETTING_WIRELESS_MODE, + "infrastructure", + NULL); + g_bytes_unref(ssid); + nm_connection_add_setting(replacement, setting); + + /* Replace settings and test */ + nm_connection_replace_settings_from_connection(connection, replacement); + + s_con = nm_connection_get_setting_connection(connection); + g_assert(s_con); + g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); + g_assert_cmpstr(nm_setting_connection_get_uuid(s_con), ==, uuid); + + g_assert(!nm_connection_get_setting_wired(connection)); + g_assert(!nm_connection_get_setting_ip6_config(connection)); + g_assert(nm_connection_get_setting_wireless(connection)); + + g_free(uuid); + g_object_unref(replacement); + g_object_unref(connection); +} + +static void +test_connection_replace_settings_bad(void) +{ + NMConnection * connection, *new_connection; + GVariant * new_settings; + GVariantBuilder builder, setting_builder; + GError * error = NULL; + gboolean success; + NMSettingConnection *s_con; + + new_connection = new_test_connection(); + g_assert(nm_connection_verify(new_connection, NULL)); + s_con = nm_connection_get_setting_connection(new_connection); + g_object_set(s_con, + NM_SETTING_CONNECTION_UUID, + NULL, + NM_SETTING_CONNECTION_ID, + "bad-connection", + NULL); + g_assert(!nm_connection_verify(new_connection, NULL)); + + /* nm_connection_replace_settings_from_connection() should succeed */ + connection = new_test_connection(); + nm_connection_replace_settings_from_connection(connection, new_connection); + g_assert_cmpstr(nm_connection_get_id(connection), ==, "bad-connection"); + g_assert(!nm_connection_verify(connection, NULL)); + g_object_unref(connection); + + /* nm_connection_replace_settings() should succeed */ + new_settings = nm_connection_to_dbus(new_connection, NM_CONNECTION_SERIALIZE_ALL); + g_assert(new_settings != NULL); + + connection = new_test_connection(); + success = nm_connection_replace_settings(connection, new_settings, &error); + g_assert_no_error(error); + g_assert(success); + + g_assert_cmpstr(nm_connection_get_id(connection), ==, "bad-connection"); + g_assert(!nm_connection_verify(connection, NULL)); + g_object_unref(connection); + g_variant_unref(new_settings); + + /* But given an invalid dict, it should fail */ + g_variant_builder_init(&builder, NM_VARIANT_TYPE_CONNECTION); + g_variant_builder_init(&setting_builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add(&builder, "{sa{sv}}", "ip-over-avian-carrier", &setting_builder); + new_settings = g_variant_builder_end(&builder); + + connection = new_test_connection(); + success = nm_connection_replace_settings(connection, new_settings, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING); + g_clear_error(&error); + g_assert(!success); + + g_assert(nm_connection_verify(connection, NULL)); + g_object_unref(connection); + + g_variant_unref(new_settings); + g_object_unref(new_connection); +} + +static void +test_connection_new_from_dbus(void) +{ + NMConnection * connection; + GVariant * new_settings; + GError * error = NULL; + NMSettingConnection *s_con; + NMSettingIPConfig * s_ip6; + char * uuid = NULL; + const char * expected_id = NULL, *expected_method = NULL; + + new_settings = new_connection_dict(&uuid, &expected_id, &expected_method); + g_assert(new_settings); + + /* Replace settings and test */ + connection = _connection_new_from_dbus(new_settings, &error); + g_assert_no_error(error); + g_assert(connection); + + s_con = nm_connection_get_setting_connection(connection); + g_assert(s_con); + g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); + g_assert_cmpstr(nm_setting_connection_get_uuid(s_con), ==, uuid); + + g_assert(nm_connection_get_setting_wired(connection)); + g_assert(nm_connection_get_setting_ip4_config(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), ==, expected_method); + + g_free(uuid); + g_variant_unref(new_settings); + g_object_unref(connection); +} + +static void +check_permission(NMSettingConnection *s_con, guint32 idx, const char *expected_uname) +{ + gboolean success; + const char *ptype = NULL, *pitem = NULL, *detail = NULL; + + success = nm_setting_connection_get_permission(s_con, idx, &ptype, &pitem, &detail); + g_assert(success); + + g_assert_cmpstr(ptype, ==, "user"); + + g_assert(pitem); + g_assert_cmpstr(pitem, ==, expected_uname); + + g_assert(!detail); +} + +#define TEST_UNAME "asdfasfasdf" + +static void +test_setting_connection_permissions_helpers(void) +{ + NMSettingConnection *s_con; + gboolean success; + char buf[9] = {0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00}; + char ** perms; + const char * expected_perm = "user:" TEST_UNAME ":"; + + s_con = NM_SETTING_CONNECTION(nm_setting_connection_new()); + + /* Ensure a bad [type] is rejected */ + success = nm_setting_connection_add_permission(s_con, "foobar", "blah", NULL); + g_assert(!success); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); + + /* Ensure a bad [type] is rejected */ + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(ptype)); + success = nm_setting_connection_add_permission(s_con, NULL, "blah", NULL); + g_test_assert_expected_messages(); + g_assert(!success); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); + + /* Ensure a bad [item] is rejected */ + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(pitem)); + success = nm_setting_connection_add_permission(s_con, "user", NULL, NULL); + g_test_assert_expected_messages(); + g_assert(!success); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); + + /* Ensure a bad [item] is rejected */ + success = nm_setting_connection_add_permission(s_con, "user", "", NULL); + g_assert(!success); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); + + /* Ensure an [item] with ':' is rejected */ + success = nm_setting_connection_add_permission(s_con, "user", "ad:asdf", NULL); + g_assert(!success); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); + + /* Ensure a non-UTF-8 [item] is rejected */ + success = nm_setting_connection_add_permission(s_con, "user", buf, NULL); + g_assert(!success); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); + + /* Ensure a non-NULL [detail] is rejected */ + success = nm_setting_connection_add_permission(s_con, "user", "dafasdf", "asdf"); + g_assert(!success); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); + + /* Ensure a valid call results in success */ + success = nm_setting_connection_add_permission(s_con, "user", TEST_UNAME, NULL); + g_assert(success); + + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + + check_permission(s_con, 0, TEST_UNAME); + + /* Check the actual GObject property just to be paranoid */ + g_object_get(G_OBJECT(s_con), NM_SETTING_CONNECTION_PERMISSIONS, &perms, NULL); + g_assert(perms); + g_assert_cmpint(g_strv_length(perms), ==, 1); + g_assert_cmpstr(perms[0], ==, expected_perm); + g_strfreev(perms); + + /* Now remove that permission and ensure we have 0 permissions */ + nm_setting_connection_remove_permission(s_con, 0); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 0); + + g_object_unref(s_con); +} + +static void +add_permission_property(NMSettingConnection *s_con, + const char * ptype, + const char * pitem, + int pitem_len, + const char * detail) +{ + GString *str; + char * perms[2]; + + str = g_string_sized_new(50); + if (ptype) + g_string_append(str, ptype); + g_string_append_c(str, ':'); + + if (pitem) { + if (pitem_len >= 0) + g_string_append_len(str, pitem, pitem_len); + else + g_string_append(str, pitem); + } + + g_string_append_c(str, ':'); + + if (detail) + g_string_append(str, detail); + + perms[0] = str->str; + perms[1] = NULL; + g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_PERMISSIONS, perms, NULL); + + g_string_free(str, TRUE); +} + +static void +test_setting_connection_permissions_property(void) +{ + gs_unref_object NMSettingConnection *s_con = NULL; + gboolean success; + char buf[9] = {0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00}; + + s_con = NM_SETTING_CONNECTION(nm_setting_connection_new()); + +#define _assert_permission_invalid_at_idx(s_con, idx, expected_item) \ + G_STMT_START \ + { \ + NMSettingConnection *_s_con = (s_con); \ + guint _idx = (idx); \ + const char * _ptype; \ + const char * _pitem; \ + const char * _detail; \ + const char ** _p_ptype = nmtst_get_rand_bool() ? &_ptype : NULL; \ + const char ** _p_pitem = nmtst_get_rand_bool() ? &_pitem : NULL; \ + const char ** _p_detail = nmtst_get_rand_bool() ? &_detail : NULL; \ + \ + g_assert_cmpint(_idx, <, nm_setting_connection_get_num_permissions(_s_con)); \ + g_assert( \ + nm_setting_connection_get_permission(_s_con, _idx, _p_ptype, _p_pitem, _p_detail)); \ + if (_p_ptype) \ + g_assert_cmpstr(_ptype, ==, "invalid"); \ + if (_p_pitem) { \ + const char *_expected_item = (expected_item); \ + \ + if (!_expected_item) \ + g_assert_cmpstr(_pitem, !=, NULL); \ + else \ + g_assert_cmpstr(_pitem, ==, _expected_item); \ + } \ + if (_p_detail) \ + g_assert_cmpstr(_detail, ==, NULL); \ + } \ + G_STMT_END + + /* Ensure a bad [type] is rejected */ + add_permission_property(s_con, "foobar", "blah", -1, NULL); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + _assert_permission_invalid_at_idx(s_con, 0, "foobar:blah:"); + + /* Ensure a bad [type] is rejected */ + add_permission_property(s_con, NULL, "blah", -1, NULL); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + _assert_permission_invalid_at_idx(s_con, 0, ":blah:"); + + /* Ensure a bad [item] is rejected */ + add_permission_property(s_con, "user", NULL, -1, NULL); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + _assert_permission_invalid_at_idx(s_con, 0, "user::"); + + /* Ensure a bad [item] is rejected */ + add_permission_property(s_con, "user", "", -1, NULL); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + _assert_permission_invalid_at_idx(s_con, 0, "user::"); + + /* Ensure an [item] with ':' in the middle is rejected */ + add_permission_property(s_con, "user", "ad:asdf", -1, NULL); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + _assert_permission_invalid_at_idx(s_con, 0, "user:ad:asdf:"); + + /* Ensure an [item] with ':' at the end is rejected */ + add_permission_property(s_con, "user", "adasdfaf:", -1, NULL); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + _assert_permission_invalid_at_idx(s_con, 0, "user:adasdfaf::"); + + /* Ensure a non-UTF-8 [item] is rejected */ + add_permission_property(s_con, "user", buf, (int) sizeof(buf), NULL); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + _assert_permission_invalid_at_idx(s_con, 0, NULL); + + /* Ensure a non-NULL [detail] is rejected */ + add_permission_property(s_con, "user", "dafasdf", -1, "asdf"); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); + _assert_permission_invalid_at_idx(s_con, 0, "user:dafasdf:asdf"); + + /* Ensure a valid call results in success */ + success = nm_setting_connection_add_permission(s_con, "user", TEST_UNAME, NULL); + g_assert(success); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 2); + _assert_permission_invalid_at_idx(s_con, 0, "user:dafasdf:asdf"); + check_permission(s_con, 1, TEST_UNAME); + + /* Now remove that permission and ensure we have 0 permissions */ + nm_setting_connection_remove_permission(s_con, 0); + g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); +} + +static void +test_connection_compare_same(void) +{ + NMConnection *a, *b; + + a = new_test_connection(); + b = nm_simple_connection_new_clone(a); + g_assert(nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); + g_object_unref(a); + g_object_unref(b); +} + +static void +test_connection_compare_key_only_in_a(void) +{ + NMConnection * a, *b; + NMSettingConnection *s_con; + + a = new_test_connection(); + b = nm_simple_connection_new_clone(a); + s_con = (NMSettingConnection *) nm_connection_get_setting(b, NM_TYPE_SETTING_CONNECTION); + g_assert(s_con); + g_object_set(s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL); + + g_assert(!nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); + g_object_unref(a); + g_object_unref(b); +} + +static void +test_connection_compare_setting_only_in_a(void) +{ + NMConnection *a, *b; + + a = new_test_connection(); + b = nm_simple_connection_new_clone(a); + nm_connection_remove_setting(b, NM_TYPE_SETTING_IP4_CONFIG); + g_assert(!nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); + g_object_unref(a); + g_object_unref(b); +} + +static void +test_connection_compare_key_only_in_b(void) +{ + NMConnection * a, *b; + NMSettingConnection *s_con; + + a = new_test_connection(); + b = nm_simple_connection_new_clone(a); + s_con = (NMSettingConnection *) nm_connection_get_setting(b, NM_TYPE_SETTING_CONNECTION); + g_assert(s_con); + g_object_set(s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL); + + g_assert(!nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); + g_object_unref(a); + g_object_unref(b); +} + +static void +test_connection_compare_setting_only_in_b(void) +{ + NMConnection *a, *b; + + a = new_test_connection(); + b = nm_simple_connection_new_clone(a); + nm_connection_remove_setting(a, NM_TYPE_SETTING_IP4_CONFIG); + g_assert(!nm_connection_compare(a, b, NM_SETTING_COMPARE_FLAG_EXACT)); + g_object_unref(a); + g_object_unref(b); +} + +typedef struct { + const char *key_name; + guint32 result; +} DiffKey; + +typedef struct { + const char *name; + DiffKey keys[30]; +} DiffSetting; + +#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) + +static void +ensure_diffs(GHashTable *diffs, const DiffSetting *check, gsize n_check) +{ + guint i; + + g_assert(g_hash_table_size(diffs) == n_check); + + /* Loop through the settings */ + for (i = 0; i < n_check; i++) { + GHashTable *setting_hash; + guint z = 0; + + setting_hash = g_hash_table_lookup(diffs, check[i].name); + g_assert(setting_hash); + + /* Get the number of keys to check */ + while (check[i].keys[z].key_name) + z++; + g_assert(g_hash_table_size(setting_hash) == z); + + /* Now compare the actual keys */ + for (z = 0; check[i].keys[z].key_name; z++) { + NMSettingDiffResult result; + + result = GPOINTER_TO_UINT(g_hash_table_lookup(setting_hash, check[i].keys[z].key_name)); + g_assert(result == check[i].keys[z].result); + } + } +} + +static void +test_connection_diff_a_only(void) +{ + NMConnection * connection; + GHashTable * out_diffs = NULL; + gboolean same; + const DiffSetting settings[] = { + {NM_SETTING_CONNECTION_SETTING_NAME, + {{NM_SETTING_CONNECTION_ID, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_UUID, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_STABLE_ID, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_TYPE, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_TIMESTAMP, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_AUTOCONNECT, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_MULTI_CONNECT, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_READ_ONLY, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_PERMISSIONS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_ZONE, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_MASTER, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_SECONDARIES, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_METERED, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_LLDP, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_AUTH_RETRIES, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_MDNS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_LLMNR, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_MUD_URL, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A}, + {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}}}, + {NM_SETTING_WIRED_SETTING_NAME, + { + {NM_SETTING_WIRED_PORT, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_SPEED, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_DUPLEX, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_AUTO_NEGOTIATE, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_CLONED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_MTU, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_S390_SUBCHANNELS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_S390_NETTYPE, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_S390_OPTIONS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_WAKE_ON_LAN, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, NM_SETTING_DIFF_RESULT_IN_A}, + {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, + }}, + {NM_SETTING_IP4_CONFIG_SETTING_NAME, + { + {NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DNS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DNS_SEARCH, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DNS_OPTIONS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_ADDRESSES, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_GATEWAY, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_ROUTE_METRIC, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_ROUTE_TABLE, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_ROUTING_RULES, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP4_CONFIG_DHCP_FQDN, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_NEVER_DEFAULT, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_MAY_FAIL, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DAD_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DNS_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DHCP_IAID, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS, NM_SETTING_DIFF_RESULT_IN_A}, + {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, + }}, + }; + + connection = new_test_connection(); + + same = nm_connection_diff(connection, NULL, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs); + g_assert(same == FALSE); + g_assert(out_diffs != NULL); + g_assert(g_hash_table_size(out_diffs) > 0); + + ensure_diffs(out_diffs, settings, ARRAY_LEN(settings)); + + g_hash_table_destroy(out_diffs); + g_object_unref(connection); +} + +static void +test_connection_diff_same(void) +{ + NMConnection *a, *b; + GHashTable * out_diffs = NULL; + gboolean same; + + a = new_test_connection(); + b = nm_simple_connection_new_clone(a); + + same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs); + g_assert(same == TRUE); + g_assert(out_diffs == NULL); + g_object_unref(a); + g_object_unref(b); +} + +static void +test_connection_diff_different(void) +{ + NMConnection * a, *b; + GHashTable * out_diffs = NULL; + NMSettingIPConfig *s_ip4; + gboolean same; + const DiffSetting settings[] = { + {NM_SETTING_IP4_CONFIG_SETTING_NAME, + { + {NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B}, + {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, + }}, + }; + + a = new_test_connection(); + b = nm_simple_connection_new_clone(a); + s_ip4 = nm_connection_get_setting_ip4_config(a); + g_assert(s_ip4); + g_object_set(G_OBJECT(s_ip4), + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + + same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs); + g_assert(same == FALSE); + g_assert(out_diffs != NULL); + g_assert(g_hash_table_size(out_diffs) > 0); + + ensure_diffs(out_diffs, settings, ARRAY_LEN(settings)); + + g_hash_table_destroy(out_diffs); + g_object_unref(a); + g_object_unref(b); +} + +static void +test_connection_diff_no_secrets(void) +{ + NMConnection * a, *b; + GHashTable * out_diffs = NULL; + NMSetting * s_pppoe; + gboolean same; + const DiffSetting settings[] = { + {NM_SETTING_PPPOE_SETTING_NAME, + { + {NM_SETTING_PPPOE_PASSWORD, NM_SETTING_DIFF_RESULT_IN_B}, + {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, + }}, + }; + + a = new_test_connection(); + s_pppoe = nm_setting_pppoe_new(); + g_object_set(G_OBJECT(s_pppoe), NM_SETTING_PPPOE_USERNAME, "thomas", NULL); + nm_connection_add_setting(a, s_pppoe); + + b = nm_simple_connection_new_clone(a); + + /* Add a secret to B */ + s_pppoe = NM_SETTING(nm_connection_get_setting_pppoe(b)); + g_assert(s_pppoe); + g_object_set(G_OBJECT(s_pppoe), NM_SETTING_PPPOE_PASSWORD, "secretpassword", NULL); + + /* Make sure the diff returns no results as secrets are ignored */ + same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &out_diffs); + g_assert(same == TRUE); + g_assert(out_diffs == NULL); + + /* Now make sure the diff returns results if secrets are not ignored */ + same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs); + g_assert(same == FALSE); + g_assert(out_diffs != NULL); + g_assert(g_hash_table_size(out_diffs) > 0); + + ensure_diffs(out_diffs, settings, ARRAY_LEN(settings)); + + g_hash_table_destroy(out_diffs); + g_object_unref(a); + g_object_unref(b); +} + +static void +test_connection_diff_inferrable(void) +{ + NMConnection * a, *b; + GHashTable * out_diffs = NULL; + gboolean same; + NMSettingConnection *s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + char * uuid; + const DiffSetting settings[] = { + {NM_SETTING_CONNECTION_SETTING_NAME, + { + {NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A}, + {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, + }}, + }; + + a = new_test_connection(); + b = nm_simple_connection_new_clone(a); + + /* Change the UUID, wired MTU, and set ignore-auto-dns */ + s_con = nm_connection_get_setting_connection(a); + g_assert(s_con); + uuid = nm_utils_uuid_generate(); + g_object_set(G_OBJECT(s_con), + NM_SETTING_CONNECTION_UUID, + uuid, + NM_SETTING_CONNECTION_ID, + "really neat connection", + NULL); + g_free(uuid); + + s_wired = nm_connection_get_setting_wired(a); + g_assert(s_wired); + g_object_set(G_OBJECT(s_wired), NM_SETTING_WIRED_MTU, 300, NULL); + + s_ip4 = nm_connection_get_setting_ip4_config(a); + g_assert(s_ip4); + g_object_set(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE, NULL); + + /* Make sure the diff returns no results as secrets are ignored */ + same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs); + g_assert(same == TRUE); + g_assert(out_diffs == NULL); + + /* And change a INFERRABLE property to ensure that it shows up in the diff results */ + g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, "usb0", NULL); + + /* Make sure the diff returns no results as secrets are ignored */ + same = nm_connection_diff(a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs); + g_assert(same == FALSE); + g_assert(out_diffs != NULL); + g_assert(g_hash_table_size(out_diffs) > 0); + + ensure_diffs(out_diffs, settings, ARRAY_LEN(settings)); + + g_hash_table_destroy(out_diffs); + g_object_unref(a); + g_object_unref(b); +} + +static void +add_generic_settings(NMConnection *connection, const char *ctype) +{ + NMSetting *setting; + char * uuid; + + uuid = nm_utils_uuid_generate(); + + setting = nm_setting_connection_new(); + g_object_set(setting, + NM_SETTING_CONNECTION_ID, + "asdfasdfadf", + NM_SETTING_CONNECTION_TYPE, + ctype, + NM_SETTING_CONNECTION_UUID, + uuid, + NULL); + nm_connection_add_setting(connection, setting); + + g_free(uuid); + + setting = nm_setting_ip4_config_new(); + g_object_set(setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + nm_connection_add_setting(connection, setting); + + setting = nm_setting_ip6_config_new(); + g_object_set(setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); + nm_connection_add_setting(connection, setting); +} + +static void +test_connection_good_base_types(void) +{ + NMConnection *connection; + NMSetting * setting; + gboolean success; + GError * error = NULL; + GBytes * ssid; + const char * bdaddr = "11:22:33:44:55:66"; + + /* Try a basic wired connection */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_WIRED_SETTING_NAME); + setting = nm_setting_wired_new(); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_no_error(error); + g_assert(success); + g_object_unref(connection); + + /* Try a wired PPPoE connection */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_PPPOE_SETTING_NAME); + setting = nm_setting_pppoe_new(); + g_object_set(setting, NM_SETTING_PPPOE_USERNAME, "bob smith", NULL); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_no_error(error); + g_assert(success); + g_object_unref(connection); + + /* Wifi connection */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_WIRELESS_SETTING_NAME); + + setting = nm_setting_wireless_new(); + ssid = g_bytes_new("1234567", 7); + g_object_set(setting, + NM_SETTING_WIRELESS_SSID, + ssid, + NM_SETTING_WIRELESS_MODE, + "infrastructure", + NULL); + g_bytes_unref(ssid); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_no_error(error); + g_assert(success); + g_object_unref(connection); + + /* Bluetooth connection */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_BLUETOOTH_SETTING_NAME); + + setting = nm_setting_bluetooth_new(); + g_object_set(setting, + NM_SETTING_BLUETOOTH_BDADDR, + bdaddr, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_BLUETOOTH_TYPE_PANU, + NULL); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_no_error(error); + g_assert(success); + g_object_unref(connection); + + /* WiMAX connection */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_WIMAX_SETTING_NAME); + setting = nm_setting_wimax_new(); + g_object_set(setting, NM_SETTING_WIMAX_NETWORK_NAME, "CLEAR", NULL); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_no_error(error); + g_assert(success); + g_object_unref(connection); + + /* GSM connection */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_GSM_SETTING_NAME); + + setting = nm_setting_gsm_new(); + g_object_set(setting, NM_SETTING_GSM_APN, "metered.billing.sucks", NULL); + nm_connection_add_setting(connection, setting); + + /* CDMA connection */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_CDMA_SETTING_NAME); + + setting = nm_setting_cdma_new(); + g_object_set(setting, + NM_SETTING_CDMA_NUMBER, + "#777", + NM_SETTING_CDMA_USERNAME, + "foobar@vzw.com", + NULL); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_no_error(error); + g_assert(success); + g_object_unref(connection); +} + +static void +test_connection_bad_base_types(void) +{ + NMConnection *connection; + NMSetting * setting; + gboolean success; + GError * error = NULL; + + /* Test various non-base connection types to make sure they are rejected; + * using a fake 'wired' connection so the rest of it verifies + */ + + /* Connection setting */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_CONNECTION_SETTING_NAME); + setting = nm_setting_wired_new(); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "connection.type: ")); + g_assert(success == FALSE); + g_object_unref(connection); + g_clear_error(&error); + + /* PPP setting */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_PPP_SETTING_NAME); + setting = nm_setting_wired_new(); + nm_connection_add_setting(connection, setting); + setting = nm_setting_ppp_new(); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "connection.type: ")); + g_assert(success == FALSE); + g_object_unref(connection); + g_clear_error(&error); + + /* Serial setting */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_SERIAL_SETTING_NAME); + setting = nm_setting_wired_new(); + nm_connection_add_setting(connection, setting); + setting = nm_setting_serial_new(); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "connection.type: ")); + g_assert(success == FALSE); + g_object_unref(connection); + g_clear_error(&error); + + /* IP4 setting */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_IP4_CONFIG_SETTING_NAME); + setting = nm_setting_wired_new(); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "connection.type: ")); + g_assert(success == FALSE); + g_object_unref(connection); + g_clear_error(&error); + + /* IP6 setting */ + connection = nm_simple_connection_new(); + add_generic_settings(connection, NM_SETTING_IP6_CONFIG_SETTING_NAME); + setting = nm_setting_wired_new(); + nm_connection_add_setting(connection, setting); + + success = nm_connection_verify(connection, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(g_str_has_prefix(error->message, "connection.type: ")); + g_assert(success == FALSE); + g_object_unref(connection); + g_clear_error(&error); +} + +static void +test_setting_compare_id(void) +{ + gs_unref_object NMSetting *old = NULL, *new = NULL; + gboolean success; + + old = nm_setting_connection_new(); + g_object_set(old, + NM_SETTING_CONNECTION_ID, + "really awesome cool connection", + NM_SETTING_CONNECTION_UUID, + "fbbd59d5-acab-4e30-8f86-258d272617e7", + NM_SETTING_CONNECTION_AUTOCONNECT, + FALSE, + NULL); + + new = nm_setting_duplicate(old); + g_object_set(new, NM_SETTING_CONNECTION_ID, "some different connection id", NULL); + + /* First make sure they are different */ + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(success == FALSE); + + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_IGNORE_ID); + g_assert(success); +} + +static void +test_setting_compare_addresses(void) +{ + gs_unref_object NMSetting *s1 = NULL, *s2 = NULL; + gboolean success; + NMIPAddress * a; + GHashTable * result = NULL; + + s1 = nm_setting_ip4_config_new(); + s2 = nm_setting_ip4_config_new(); + + a = nm_ip_address_new(AF_INET, "192.168.7.5", 24, NULL); + + nm_ip_address_set_attribute(a, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string("xoxoxo")); + nm_setting_ip_config_add_address((NMSettingIPConfig *) s1, a); + + nm_ip_address_set_attribute(a, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string("hello")); + nm_setting_ip_config_add_address((NMSettingIPConfig *) s2, a); + + nm_ip_address_unref(a); + + if (nmtst_get_rand_uint32() % 2) + NM_SWAP(&s1, &s2); + + success = nm_setting_compare(s1, s2, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(!success); + + success = nm_setting_diff(s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result); + g_assert(!success); + nm_clear_pointer(&result, g_hash_table_unref); +} + +static void +test_setting_compare_routes(void) +{ + gs_unref_object NMSetting *s1 = NULL, *s2 = NULL; + gboolean success; + NMIPRoute * r; + GHashTable * result = NULL; + + s1 = nm_setting_ip4_config_new(); + s2 = nm_setting_ip4_config_new(); + + r = nm_ip_route_new(AF_INET, "192.168.12.0", 24, "192.168.11.1", 473, NULL); + + nm_ip_route_set_attribute(r, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string("xoxoxo")); + nm_setting_ip_config_add_route((NMSettingIPConfig *) s1, r); + + nm_ip_route_set_attribute(r, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string("hello")); + nm_setting_ip_config_add_route((NMSettingIPConfig *) s2, r); + + nm_ip_route_unref(r); + + if (nmtst_get_rand_uint32() % 2) + NM_SWAP(&s1, &s2); + + success = nm_setting_compare(s1, s2, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(!success); + + success = nm_setting_diff(s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result); + g_assert(!success); + nm_clear_pointer(&result, g_hash_table_unref); +} + +static void +test_setting_compare_wired_cloned_mac_address(void) +{ + gs_unref_object NMSetting *old = NULL, *new = NULL; + gboolean success; + gs_free char * str1 = NULL; + + old = nm_setting_wired_new(); + g_object_set(old, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "stable", NULL); + + g_assert_cmpstr("stable", ==, nm_setting_wired_get_cloned_mac_address((NMSettingWired *) old)); + g_object_get(old, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); + g_assert_cmpstr("stable", ==, str1); + nm_clear_g_free(&str1); + + new = nm_setting_duplicate(old); + g_object_set(new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL); + + g_assert_cmpstr("11:22:33:44:55:66", + ==, + nm_setting_wired_get_cloned_mac_address((NMSettingWired *) new)); + g_object_get(new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); + g_assert_cmpstr("11:22:33:44:55:66", ==, str1); + nm_clear_g_free(&str1); + + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(!success); + g_clear_object(&new); + + new = nm_setting_duplicate(old); + g_object_set(new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "stable-bia", NULL); + + g_assert_cmpstr("stable-bia", + ==, + nm_setting_wired_get_cloned_mac_address((NMSettingWired *) new)); + g_object_get(new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL); + g_assert_cmpstr("stable-bia", ==, str1); + nm_clear_g_free(&str1); + + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(!success); + g_clear_object(&new); +} + +static void +test_setting_compare_wireless_cloned_mac_address(void) +{ + gs_unref_object NMSetting *old = NULL, *new = NULL; + gboolean success; + gs_free char * str1 = NULL; + + old = nm_setting_wireless_new(); + g_object_set(old, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "stable", NULL); + + g_assert_cmpstr("stable", + ==, + nm_setting_wireless_get_cloned_mac_address((NMSettingWireless *) old)); + g_object_get(old, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); + g_assert_cmpstr("stable", ==, str1); + nm_clear_g_free(&str1); + + new = nm_setting_duplicate(old); + g_object_set(new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL); + + g_assert_cmpstr("11:22:33:44:55:66", + ==, + nm_setting_wireless_get_cloned_mac_address((NMSettingWireless *) new)); + g_object_get(new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); + g_assert_cmpstr("11:22:33:44:55:66", ==, str1); + nm_clear_g_free(&str1); + + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(!success); + g_clear_object(&new); + + new = nm_setting_duplicate(old); + g_object_set(new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "stable-bia", NULL); + + g_assert_cmpstr("stable-bia", + ==, + nm_setting_wireless_get_cloned_mac_address((NMSettingWireless *) new)); + g_object_get(new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL); + g_assert_cmpstr("stable-bia", ==, str1); + nm_clear_g_free(&str1); + + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(!success); + g_clear_object(&new); +} + +static void +test_setting_compare_timestamp(void) +{ + gs_unref_object NMSetting *old = NULL, *new = NULL; + gboolean success; + + old = nm_setting_connection_new(); + g_object_set(old, + NM_SETTING_CONNECTION_ID, + "ignore timestamp connection", + NM_SETTING_CONNECTION_UUID, + "b047a198-0e0a-4f0e-a653-eea09bb35e40", + NM_SETTING_CONNECTION_AUTOCONNECT, + FALSE, + NM_SETTING_CONNECTION_TIMESTAMP, + (guint64) 1234567890, + NULL); + + new = nm_setting_duplicate(old); + g_object_set(new, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 1416316539, NULL); + + /* First make sure they are different */ + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(success == FALSE); + + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP); + g_assert(success); +} + +typedef struct { + NMSettingSecretFlags secret_flags; + NMSettingCompareFlags comp_flags; + gboolean remove_secret; +} TestDataCompareSecrets; + +static TestDataCompareSecrets * +test_data_compare_secrets_new(NMSettingSecretFlags secret_flags, + NMSettingCompareFlags comp_flags, + gboolean remove_secret) +{ + TestDataCompareSecrets *data = g_new0(TestDataCompareSecrets, 1); + + data->secret_flags = secret_flags; + data->comp_flags = comp_flags; + data->remove_secret = remove_secret; + return data; +} + +static void +_test_compare_secrets_check_diff(NMSetting * a, + NMSetting * b, + NMSettingCompareFlags flags, + gboolean exp_same_psk, + gboolean exp_same_psk_flags) +{ + gs_unref_hashtable GHashTable *h = NULL; + NMSettingDiffResult _RESULT_IN_A = NM_SETTING_DIFF_RESULT_IN_A; + NMSettingDiffResult _RESULT_IN_B = NM_SETTING_DIFF_RESULT_IN_B; + gboolean invert_results; + gboolean diff_result; + NMSettingSecretFlags a_psk_flags = + nm_setting_wireless_security_get_psk_flags(NM_SETTING_WIRELESS_SECURITY(a)); + NMSettingSecretFlags b_psk_flags = + nm_setting_wireless_security_get_psk_flags(NM_SETTING_WIRELESS_SECURITY(b)); + const char *a_psk = nm_setting_wireless_security_get_psk(NM_SETTING_WIRELESS_SECURITY(a)); + const char *b_psk = nm_setting_wireless_security_get_psk(NM_SETTING_WIRELESS_SECURITY(b)); + + g_assert(NM_IS_SETTING_WIRELESS_SECURITY(a)); + g_assert(NM_IS_SETTING_WIRELESS_SECURITY(b)); + + invert_results = nmtst_get_rand_bool(); + if (invert_results) { + _RESULT_IN_A = NM_SETTING_DIFF_RESULT_IN_B; + _RESULT_IN_B = NM_SETTING_DIFF_RESULT_IN_A; + } + + diff_result = nm_setting_diff(a, b, flags, invert_results, &h); + + g_assert(exp_same_psk_flags == (a_psk_flags == b_psk_flags)); + + if (nm_streq0(a_psk, b_psk)) + g_assert(exp_same_psk); + else { + if (flags == NM_SETTING_COMPARE_FLAG_EXACT) + g_assert(!exp_same_psk); + else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) { + if (!NM_FLAGS_HAS(a_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED) + && !NM_FLAGS_HAS(b_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) + g_assert(!exp_same_psk); + else if (!NM_FLAGS_HAS(a_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED) + && NM_FLAGS_HAS(b_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) + g_assert(!exp_same_psk); + else + g_assert(exp_same_psk); + } else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) { + if (!NM_FLAGS_HAS(a_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED) + && !NM_FLAGS_HAS(b_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)) + g_assert(!exp_same_psk); + else if (!NM_FLAGS_HAS(a_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED) + && NM_FLAGS_HAS(b_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)) + g_assert(!exp_same_psk); + else + g_assert(exp_same_psk); + } else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) + g_assert(exp_same_psk); + else + g_assert_not_reached(); + } + + g_assert(diff_result == (exp_same_psk && exp_same_psk_flags)); + g_assert(diff_result == (!h)); + + if (!diff_result) { + if (flags == NM_SETTING_COMPARE_FLAG_EXACT) + g_assert(!exp_same_psk); + else if (NM_IN_SET(flags, + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) + && (a_psk_flags != b_psk_flags) + && nm_setting_wireless_security_get_psk_flags(NM_SETTING_WIRELESS_SECURITY(a)) + == NM_SETTING_SECRET_FLAG_NONE) + g_assert(!exp_same_psk); + else + g_assert(exp_same_psk); + + g_assert((!exp_same_psk) == g_hash_table_contains(h, NM_SETTING_WIRELESS_SECURITY_PSK)); + if (!exp_same_psk) { + if (nm_setting_wireless_security_get_psk(NM_SETTING_WIRELESS_SECURITY(a))) + g_assert_cmpint( + GPOINTER_TO_UINT(g_hash_table_lookup(h, NM_SETTING_WIRELESS_SECURITY_PSK)), + ==, + _RESULT_IN_A); + else + g_assert_cmpint( + GPOINTER_TO_UINT(g_hash_table_lookup(h, NM_SETTING_WIRELESS_SECURITY_PSK)), + ==, + _RESULT_IN_B); + } + + g_assert((!exp_same_psk_flags) + == g_hash_table_contains(h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)); + if (!exp_same_psk_flags) { + if (nm_setting_wireless_security_get_psk_flags(NM_SETTING_WIRELESS_SECURITY(a)) + != NM_SETTING_SECRET_FLAG_NONE) + g_assert_cmpint(GPOINTER_TO_UINT( + g_hash_table_lookup(h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)), + ==, + _RESULT_IN_A); + else + g_assert_cmpint(GPOINTER_TO_UINT( + g_hash_table_lookup(h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)), + ==, + _RESULT_IN_B); + } + + g_assert_cmpint(g_hash_table_size(h), ==, (!exp_same_psk) + (!exp_same_psk_flags)); + } + + g_assert(diff_result == nm_setting_compare(a, b, flags)); + g_assert(diff_result == nm_setting_compare(b, a, flags)); +} + +static void +test_setting_compare_secrets(gconstpointer test_data) +{ + const TestDataCompareSecrets *data = test_data; + gs_unref_object NMConnection *conn_old = NULL; + gs_unref_object NMConnection *conn_new = NULL; + gs_unref_object NMSetting *old = NULL; + gs_unref_object NMSetting *new = NULL; + + /* Make sure that a connection with transient/unsaved secrets compares + * successfully to the same connection without those secrets. + */ + + old = nm_setting_wireless_security_new(); + g_object_set(old, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_PSK, + "really cool psk", + NULL); + nm_setting_set_secret_flags(old, NM_SETTING_WIRELESS_SECURITY_PSK, data->secret_flags, NULL); + + new = nm_setting_duplicate(old); + if (data->remove_secret) + g_object_set(new, NM_SETTING_WIRELESS_SECURITY_PSK, NULL, NULL); + + g_assert((!data->remove_secret) == nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT)); + g_assert((!data->remove_secret) == nm_setting_compare(new, old, NM_SETTING_COMPARE_FLAG_EXACT)); + + _test_compare_secrets_check_diff(old, + new, + NM_SETTING_COMPARE_FLAG_EXACT, + !data->remove_secret, + TRUE); + _test_compare_secrets_check_diff(new, + old, + NM_SETTING_COMPARE_FLAG_EXACT, + !data->remove_secret, + TRUE); + + g_assert(nm_setting_compare(old, new, data->comp_flags)); + g_assert(nm_setting_compare(new, old, data->comp_flags)); + + _test_compare_secrets_check_diff(old, new, data->comp_flags, TRUE, TRUE); + _test_compare_secrets_check_diff(new, old, data->comp_flags, TRUE, TRUE); + + /* OK. Try again, but this time not only change the secret, also let the secret flags differ... */ + if (data->secret_flags != NM_SETTING_SECRET_FLAG_NONE) { + nm_setting_set_secret_flags(new, + NM_SETTING_WIRELESS_SECURITY_PSK, + NM_SETTING_SECRET_FLAG_NONE, + NULL); + + _test_compare_secrets_check_diff(old, new, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, FALSE); + _test_compare_secrets_check_diff(new, old, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, FALSE); + + _test_compare_secrets_check_diff(old, new, data->comp_flags, TRUE, FALSE); + _test_compare_secrets_check_diff(new, old, data->comp_flags, FALSE, FALSE); + + nm_setting_set_secret_flags(new, + NM_SETTING_WIRELESS_SECURITY_PSK, + data->secret_flags, + NULL); + } + + conn_old = nmtst_create_minimal_connection("test-compare-secrets", + NULL, + NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + nm_connection_add_setting(conn_old, nm_setting_duplicate(old)); + conn_new = nm_simple_connection_new_clone(conn_old); + nm_connection_add_setting(conn_new, nm_setting_duplicate(new)); + + g_assert((!data->remove_secret) + == nm_connection_compare(conn_old, conn_new, NM_SETTING_COMPARE_FLAG_EXACT)); + g_assert((!data->remove_secret) + == nm_connection_compare(conn_new, conn_old, NM_SETTING_COMPARE_FLAG_EXACT)); + + g_assert(nm_connection_compare(conn_old, conn_new, data->comp_flags)); + g_assert(nm_connection_compare(conn_new, conn_old, data->comp_flags)); +} + +static void +test_setting_compare_vpn_secrets(gconstpointer test_data) +{ + const TestDataCompareSecrets *data = test_data; + gs_unref_object NMSetting *old = NULL, *new = NULL; + gboolean success; + + /* Make sure that a connection with transient/unsaved secrets compares + * successfully to the same connection without those secrets. + */ + + old = nm_setting_vpn_new(); + nm_setting_vpn_add_secret(NM_SETTING_VPN(old), "foobarbaz", "really secret password"); + nm_setting_vpn_add_secret(NM_SETTING_VPN(old), "asdfasdfasdf", "really adfasdfasdfasdf"); + nm_setting_vpn_add_secret(NM_SETTING_VPN(old), "0123456778", "abcdefghijklmnpqrstuvqxyz"); + nm_setting_vpn_add_secret(NM_SETTING_VPN(old), + "borkbork", + "yet another really secret password"); + nm_setting_set_secret_flags(old, "borkbork", data->secret_flags, NULL); + + /* Clear "borkbork" from the duplicated setting */ + new = nm_setting_duplicate(old); + if (data->remove_secret) { + nm_setting_vpn_remove_secret(NM_SETTING_VPN(new), "borkbork"); + + /* First make sure they are different */ + success = nm_setting_compare(old, new, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert(success == FALSE); + } + + success = nm_setting_compare(old, new, data->comp_flags); + g_assert(success); +} + +static void +test_hwaddr_aton_ether_normal(void) +{ + guint8 buf[100]; + guint8 expected[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; + + g_assert(nm_utils_hwaddr_aton("00:11:22:33:44:55", buf, ETH_ALEN) != NULL); + g_assert(memcmp(buf, expected, sizeof(expected)) == 0); +} + +static void +test_hwaddr_aton_ib_normal(void) +{ + guint8 buf[100]; + const char *source = "00:11:22:33:44:55:66:77:88:99:01:12:23:34:45:56:67:78:89:90"; + guint8 expected[INFINIBAND_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x90}; + + g_assert(nm_utils_hwaddr_aton(source, buf, INFINIBAND_ALEN) != NULL); + g_assert(memcmp(buf, expected, sizeof(expected)) == 0); +} + +static void +test_hwaddr_aton_no_leading_zeros(void) +{ + guint8 buf[100]; + guint8 expected[ETH_ALEN] = {0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05}; + + g_assert(nm_utils_hwaddr_aton("0:1a:2B:3:44:5", buf, ETH_ALEN) != NULL); + g_assert(memcmp(buf, expected, sizeof(expected)) == 0); +} + +static void +test_hwaddr_aton_malformed(void) +{ + guint8 buf[100]; + + g_assert(nm_utils_hwaddr_aton("0:1a:2B:3:a@%%", buf, ETH_ALEN) == NULL); +} + +static void +test_hwaddr_equal(void) +{ + const char * string = "00:1a:2b:03:44:05"; + const char * upper_string = "00:1A:2B:03:44:05"; + const char * bad_string = "0:1a:2b:3:44:5"; + const guint8 binary[ETH_ALEN] = {0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05}; + const char * other_string = "1a:2b:03:44:05:00"; + const guint8 other_binary[ETH_ALEN] = {0x1A, 0x2B, 0x03, 0x44, 0x05, 0x00}; + const char * long_string = "00:1a:2b:03:44:05:06:07"; + const guint8 long_binary[8] = {0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05, 0x06, 0x07}; + const char * null_string = "00:00:00:00:00:00"; + const guint8 null_binary[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + g_assert(nm_utils_hwaddr_matches(string, -1, string, -1)); + g_assert(nm_utils_hwaddr_matches(string, -1, upper_string, -1)); + g_assert(nm_utils_hwaddr_matches(string, -1, bad_string, -1)); + g_assert(nm_utils_hwaddr_matches(string, -1, binary, sizeof(binary))); + g_assert(!nm_utils_hwaddr_matches(string, -1, other_string, -1)); + g_assert(!nm_utils_hwaddr_matches(string, -1, other_binary, sizeof(other_binary))); + g_assert(!nm_utils_hwaddr_matches(string, -1, long_string, -1)); + g_assert(!nm_utils_hwaddr_matches(string, -1, long_binary, sizeof(long_binary))); + g_assert(!nm_utils_hwaddr_matches(string, -1, null_string, -1)); + g_assert(!nm_utils_hwaddr_matches(string, -1, null_binary, sizeof(null_binary))); + g_assert(!nm_utils_hwaddr_matches(string, -1, NULL, ETH_ALEN)); + + g_assert(nm_utils_hwaddr_matches(binary, sizeof(binary), string, -1)); + g_assert(nm_utils_hwaddr_matches(binary, sizeof(binary), upper_string, -1)); + g_assert(nm_utils_hwaddr_matches(binary, sizeof(binary), bad_string, -1)); + g_assert(nm_utils_hwaddr_matches(binary, sizeof(binary), binary, sizeof(binary))); + g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), other_string, -1)); + g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), other_binary, sizeof(other_binary))); + g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), long_string, -1)); + g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), long_binary, sizeof(long_binary))); + g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), null_string, -1)); + g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), null_binary, sizeof(null_binary))); + g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), NULL, ETH_ALEN)); + + g_assert(!nm_utils_hwaddr_matches(null_string, -1, string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_string, -1, upper_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_string, -1, bad_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_string, -1, binary, sizeof(binary))); + g_assert(!nm_utils_hwaddr_matches(null_string, -1, other_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_string, -1, other_binary, sizeof(other_binary))); + g_assert(!nm_utils_hwaddr_matches(null_string, -1, long_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_string, -1, long_binary, sizeof(long_binary))); + g_assert(nm_utils_hwaddr_matches(null_string, -1, null_string, -1)); + g_assert(nm_utils_hwaddr_matches(null_string, -1, null_binary, sizeof(null_binary))); + g_assert(nm_utils_hwaddr_matches(null_string, -1, NULL, ETH_ALEN)); + + g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), upper_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), bad_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), binary, sizeof(binary))); + g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), other_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_binary, + sizeof(null_binary), + other_binary, + sizeof(other_binary))); + g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), long_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_binary, + sizeof(null_binary), + long_binary, + sizeof(long_binary))); + g_assert(nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), null_string, -1)); + g_assert(nm_utils_hwaddr_matches(null_binary, + sizeof(null_binary), + null_binary, + sizeof(null_binary))); + g_assert(nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), NULL, ETH_ALEN)); + + g_assert(!nm_utils_hwaddr_matches(NULL, -1, NULL, -1)); + g_assert(!nm_utils_hwaddr_matches(NULL, -1, string, -1)); + g_assert(!nm_utils_hwaddr_matches(string, -1, NULL, -1)); + g_assert(!nm_utils_hwaddr_matches(NULL, -1, null_string, -1)); + g_assert(!nm_utils_hwaddr_matches(null_string, -1, NULL, -1)); + g_assert(!nm_utils_hwaddr_matches(NULL, -1, binary, sizeof(binary))); + g_assert(!nm_utils_hwaddr_matches(binary, sizeof(binary), NULL, -1)); + g_assert(!nm_utils_hwaddr_matches(NULL, -1, null_binary, sizeof(null_binary))); + g_assert(!nm_utils_hwaddr_matches(null_binary, sizeof(null_binary), NULL, -1)); +} + +static void +test_hwaddr_canonical(void) +{ + const char *string = "00:1A:2B:03:44:05"; + const char *lower_string = "00:1a:2b:03:44:05"; + const char *short_string = "0:1a:2b:3:44:5"; + const char *hyphen_string = "00-1a-2b-03-44-05"; + const char *invalid_string = "00:1A:2B"; + char * canonical; + + canonical = nm_utils_hwaddr_canonical(string, ETH_ALEN); + g_assert_cmpstr(canonical, ==, string); + g_free(canonical); + + canonical = nm_utils_hwaddr_canonical(lower_string, ETH_ALEN); + g_assert_cmpstr(canonical, ==, string); + g_free(canonical); + + canonical = nm_utils_hwaddr_canonical(short_string, ETH_ALEN); + g_assert_cmpstr(canonical, ==, string); + g_free(canonical); + + canonical = nm_utils_hwaddr_canonical(hyphen_string, ETH_ALEN); + g_assert_cmpstr(canonical, ==, string); + g_free(canonical); + + canonical = nm_utils_hwaddr_canonical(invalid_string, ETH_ALEN); + g_assert_cmpstr(canonical, ==, NULL); + + canonical = nm_utils_hwaddr_canonical(invalid_string, -1); + g_assert_cmpstr(canonical, ==, invalid_string); + g_free(canonical); +} + +static void +test_connection_changed_cb(NMConnection *connection, gboolean *data) +{ + *data = TRUE; +} + +static guint32 +_netmask_to_prefix(guint32 netmask) +{ + guint32 prefix; + guint8 v; + const guint8 *p = (guint8 *) &netmask; + + if (p[3]) { + prefix = 24; + v = p[3]; + } else if (p[2]) { + prefix = 16; + v = p[2]; + } else if (p[1]) { + prefix = 8; + v = p[1]; + } else { + prefix = 0; + v = p[0]; + } + + while (v) { + prefix++; + v <<= 1; + } + + g_assert_cmpint(prefix, <=, 32); + + /* we re-implemented the netmask-to-prefix code differently. Check + * that they agree. */ + g_assert_cmpint(prefix, ==, nm_utils_ip4_netmask_to_prefix(netmask)); + + return prefix; +} + +static void +test_ip4_prefix_to_netmask(void) +{ + int i; + + for (i = 0; i <= 32; i++) { + guint32 netmask = _nm_utils_ip4_prefix_to_netmask(i); + int plen = _netmask_to_prefix(netmask); + + g_assert_cmpint(i, ==, plen); + { + guint32 msk = 0x80000000; + guint32 netmask2 = 0; + guint32 prefix = i; + while (prefix > 0) { + netmask2 |= msk; + msk >>= 1; + prefix--; + } + g_assert_cmpint(netmask, ==, (guint32) htonl(netmask2)); + } + } +} + +static void +test_ip4_netmask_to_prefix(void) +{ + int i, j; + + GRand *rand = g_rand_new(); + + g_rand_set_seed(rand, 1); + + for (i = 2; i <= 32; i++) { + guint32 netmask = _nm_utils_ip4_prefix_to_netmask(i); + guint32 netmask_lowest_bit = netmask & ~_nm_utils_ip4_prefix_to_netmask(i - 1); + + g_assert_cmpint(i, ==, _netmask_to_prefix(netmask)); + + for (j = 0; j < 2 * i; j++) { + guint32 r = g_rand_int(rand); + guint32 netmask_holey; + guint32 prefix_holey; + + netmask_holey = (netmask & r) | netmask_lowest_bit; + + if (netmask_holey == netmask) + continue; + + /* create an invalid netmask with holes and check that the function + * returns the longest prefix. */ + prefix_holey = _netmask_to_prefix(netmask_holey); + + g_assert_cmpint(i, ==, prefix_holey); + } + } + + g_rand_free(rand); +} + +#define ASSERT_CHANGED(statement) \ + G_STMT_START \ + { \ + changed = FALSE; \ + statement; \ + g_assert(changed); \ + } \ + G_STMT_END + +#define ASSERT_UNCHANGED(statement) \ + G_STMT_START \ + { \ + changed = FALSE; \ + statement; \ + g_assert(!changed); \ + } \ + G_STMT_END + +static void +test_connection_changed_signal(void) +{ + NMConnection *connection; + gboolean changed = FALSE; + + connection = new_test_connection(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + /* Add new setting */ + ASSERT_CHANGED(nm_connection_add_setting(connection, nm_setting_vlan_new())); + + /* Remove existing setting */ + ASSERT_CHANGED(nm_connection_remove_setting(connection, NM_TYPE_SETTING_VLAN)); + + /* Remove non-existing setting */ + ASSERT_UNCHANGED(nm_connection_remove_setting(connection, NM_TYPE_SETTING_VLAN)); + + g_object_unref(connection); +} + +static void +test_setting_connection_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSettingConnection *s_con; + gs_free char * uuid = NULL; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_con = (NMSettingConnection *) nm_setting_connection_new(); + nm_connection_add_setting(connection, NM_SETTING(s_con)); + + ASSERT_CHANGED(g_object_set(s_con, NM_SETTING_CONNECTION_ID, "adfadfasdfaf", NULL)); + + ASSERT_CHANGED(nm_setting_connection_add_permission(s_con, "user", "billsmith", NULL)); + ASSERT_CHANGED(nm_setting_connection_remove_permission(s_con, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx < nm_g_array_len(priv->permissions))); + ASSERT_UNCHANGED(nm_setting_connection_remove_permission(s_con, 1)); + g_test_assert_expected_messages(); + + uuid = nm_utils_uuid_generate(); + ASSERT_CHANGED(nm_setting_connection_add_secondary(s_con, uuid)); + ASSERT_CHANGED(nm_setting_connection_remove_secondary(s_con, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); + ASSERT_UNCHANGED(nm_setting_connection_remove_secondary(s_con, 1)); + g_test_assert_expected_messages(); + + g_object_unref(connection); +} + +static void +test_setting_bond_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSettingBond *s_bond; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_bond = (NMSettingBond *) nm_setting_bond_new(); + nm_connection_add_setting(connection, NM_SETTING(s_bond)); + + ASSERT_CHANGED(nm_setting_bond_add_option(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10")); + ASSERT_CHANGED(nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY)); + ASSERT_UNCHANGED(nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_UPDELAY)); + + g_object_unref(connection); +} + +static void +test_setting_ip4_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSettingIPConfig *s_ip4; + NMIPAddress * addr; + NMIPRoute * route; + GError * error = NULL; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + + ASSERT_CHANGED(nm_setting_ip_config_add_dns(s_ip4, "11.22.0.0")); + ASSERT_CHANGED(nm_setting_ip_config_remove_dns(s_ip4, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns(s_ip4, 1)); + g_test_assert_expected_messages(); + + nm_setting_ip_config_add_dns(s_ip4, "33.44.0.0"); + ASSERT_CHANGED(nm_setting_ip_config_clear_dns(s_ip4)); + + ASSERT_CHANGED(nm_setting_ip_config_add_dns_search(s_ip4, "foobar.com")); + ASSERT_CHANGED(nm_setting_ip_config_remove_dns_search(s_ip4, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_search->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_search(s_ip4, 1)); + g_test_assert_expected_messages(); + + ASSERT_CHANGED(nm_setting_ip_config_add_dns_search(s_ip4, "foobar.com")); + ASSERT_CHANGED(nm_setting_ip_config_clear_dns_searches(s_ip4)); + + addr = nm_ip_address_new(AF_INET, "22.33.0.0", 24, &error); + g_assert_no_error(error); + ASSERT_CHANGED(nm_setting_ip_config_add_address(s_ip4, addr)); + ASSERT_CHANGED(nm_setting_ip_config_remove_address(s_ip4, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->addresses->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_address(s_ip4, 1)); + g_test_assert_expected_messages(); + + nm_setting_ip_config_add_address(s_ip4, addr); + ASSERT_CHANGED(nm_setting_ip_config_clear_addresses(s_ip4)); + + route = nm_ip_route_new(AF_INET, "22.33.0.0", 24, NULL, 0, &error); + g_assert_no_error(error); + + ASSERT_CHANGED(nm_setting_ip_config_add_route(s_ip4, route)); + ASSERT_CHANGED(nm_setting_ip_config_remove_route(s_ip4, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->routes->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_route(s_ip4, 1)); + g_test_assert_expected_messages(); + + nm_setting_ip_config_add_route(s_ip4, route); + ASSERT_CHANGED(nm_setting_ip_config_clear_routes(s_ip4)); + + ASSERT_CHANGED(nm_setting_ip_config_add_dns_option(s_ip4, "debug")); + ASSERT_CHANGED(nm_setting_ip_config_remove_dns_option(s_ip4, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_options->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_option(s_ip4, 1)); + g_test_assert_expected_messages(); + + nm_ip_address_unref(addr); + nm_ip_route_unref(route); + g_object_unref(connection); +} + +static void +test_setting_ip6_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSettingIPConfig *s_ip6; + NMIPAddress * addr; + NMIPRoute * route; + GError * error = NULL; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + nm_connection_add_setting(connection, NM_SETTING(s_ip6)); + + ASSERT_CHANGED(nm_setting_ip_config_add_dns(s_ip6, "1:2:3::4:5:6")); + ASSERT_CHANGED(nm_setting_ip_config_remove_dns(s_ip6, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns(s_ip6, 1)); + g_test_assert_expected_messages(); + + nm_setting_ip_config_add_dns(s_ip6, "1:2:3::4:5:6"); + ASSERT_CHANGED(nm_setting_ip_config_clear_dns(s_ip6)); + + ASSERT_CHANGED(nm_setting_ip_config_add_dns_search(s_ip6, "foobar.com")); + ASSERT_CHANGED(nm_setting_ip_config_remove_dns_search(s_ip6, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_search->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_search(s_ip6, 1)); + g_test_assert_expected_messages(); + + nm_setting_ip_config_add_dns_search(s_ip6, "foobar.com"); + ASSERT_CHANGED(nm_setting_ip_config_clear_dns_searches(s_ip6)); + + addr = nm_ip_address_new(AF_INET6, "1:2:3::4:5:6", 64, &error); + g_assert_no_error(error); + + ASSERT_CHANGED(nm_setting_ip_config_add_address(s_ip6, addr)); + ASSERT_CHANGED(nm_setting_ip_config_remove_address(s_ip6, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->addresses->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_address(s_ip6, 1)); + g_test_assert_expected_messages(); + + nm_setting_ip_config_add_address(s_ip6, addr); + ASSERT_CHANGED(nm_setting_ip_config_clear_addresses(s_ip6)); + + route = nm_ip_route_new(AF_INET6, "1:2:3::4:5:6", 128, NULL, 0, &error); + g_assert_no_error(error); + + ASSERT_CHANGED(nm_setting_ip_config_add_route(s_ip6, route)); + ASSERT_CHANGED(nm_setting_ip_config_remove_route(s_ip6, 0)); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->routes->len)); + ASSERT_UNCHANGED(nm_setting_ip_config_remove_route(s_ip6, 1)); + g_test_assert_expected_messages(); + + nm_setting_ip_config_add_route(s_ip6, route); + ASSERT_CHANGED(nm_setting_ip_config_clear_routes(s_ip6)); + + nm_ip_address_unref(addr); + nm_ip_route_unref(route); + g_object_unref(connection); +} + +static void +test_setting_vlan_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSettingVlan *s_vlan; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_vlan = (NMSettingVlan *) nm_setting_vlan_new(); + nm_connection_add_setting(connection, NM_SETTING(s_vlan)); + + ASSERT_CHANGED(nm_setting_vlan_add_priority(s_vlan, NM_VLAN_INGRESS_MAP, 1, 3)); + ASSERT_CHANGED(nm_setting_vlan_remove_priority(s_vlan, NM_VLAN_INGRESS_MAP, 0)); + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx < g_slist_length(list))); + ASSERT_UNCHANGED(nm_setting_vlan_remove_priority(s_vlan, NM_VLAN_INGRESS_MAP, 1)); + g_test_assert_expected_messages(); + ASSERT_CHANGED(nm_setting_vlan_add_priority_str(s_vlan, NM_VLAN_INGRESS_MAP, "1:3")); + ASSERT_CHANGED(nm_setting_vlan_clear_priorities(s_vlan, NM_VLAN_INGRESS_MAP)); + + ASSERT_CHANGED(nm_setting_vlan_add_priority(s_vlan, NM_VLAN_EGRESS_MAP, 1, 3)); + ASSERT_CHANGED(nm_setting_vlan_remove_priority(s_vlan, NM_VLAN_EGRESS_MAP, 0)); + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx < g_slist_length(list))); + ASSERT_UNCHANGED(nm_setting_vlan_remove_priority(s_vlan, NM_VLAN_EGRESS_MAP, 1)); + g_test_assert_expected_messages(); + ASSERT_CHANGED(nm_setting_vlan_add_priority_str(s_vlan, NM_VLAN_EGRESS_MAP, "1:3")); + ASSERT_CHANGED(nm_setting_vlan_clear_priorities(s_vlan, NM_VLAN_EGRESS_MAP)); + + g_object_unref(connection); +} + +static void +test_setting_vpn_changed_signal(void) +{ + NMConnection *connection; + gboolean changed = FALSE; + NMSettingVpn *s_vpn; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_vpn = (NMSettingVpn *) nm_setting_vpn_new(); + nm_connection_add_setting(connection, NM_SETTING(s_vpn)); + + ASSERT_CHANGED(nm_setting_vpn_add_data_item(s_vpn, "foobar", "baz")); + ASSERT_CHANGED(nm_setting_vpn_remove_data_item(s_vpn, "foobar")); + ASSERT_UNCHANGED(nm_setting_vpn_remove_data_item(s_vpn, "not added")); + + ASSERT_CHANGED(nm_setting_vpn_add_secret(s_vpn, "foobar", "baz")); + ASSERT_CHANGED(nm_setting_vpn_remove_secret(s_vpn, "foobar")); + ASSERT_UNCHANGED(nm_setting_vpn_remove_secret(s_vpn, "not added")); + + g_object_unref(connection); +} + +static void +test_setting_wired_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSettingWired *s_wired; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_wired = (NMSettingWired *) nm_setting_wired_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wired)); + + ASSERT_CHANGED(nm_setting_wired_add_s390_option(s_wired, "portno", "1")); + ASSERT_CHANGED(nm_setting_wired_remove_s390_option(s_wired, "portno")); + ASSERT_UNCHANGED(nm_setting_wired_remove_s390_option(s_wired, "layer2")); + + g_object_unref(connection); +} + +static void +test_setting_wireless_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSettingWireless *s_wifi; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wifi)); + + ASSERT_CHANGED(nm_setting_wireless_add_seen_bssid(s_wifi, "00:11:22:33:44:55")); + + g_object_unref(connection); +} + +static void +test_setting_wireless_security_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSettingWirelessSecurity *s_wsec; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + + /* Protos */ + ASSERT_CHANGED(nm_setting_wireless_security_add_proto(s_wsec, "wpa")); + ASSERT_CHANGED(nm_setting_wireless_security_remove_proto(s_wsec, 0)); + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); + ASSERT_UNCHANGED(nm_setting_wireless_security_remove_proto(s_wsec, 1)); + g_test_assert_expected_messages(); + + nm_setting_wireless_security_add_proto(s_wsec, "wep"); + ASSERT_CHANGED(nm_setting_wireless_security_clear_protos(s_wsec)); + + /* Pairwise ciphers */ + ASSERT_CHANGED(nm_setting_wireless_security_add_pairwise(s_wsec, "tkip")); + ASSERT_CHANGED(nm_setting_wireless_security_remove_pairwise(s_wsec, 0)); + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); + ASSERT_UNCHANGED(nm_setting_wireless_security_remove_pairwise(s_wsec, 1)); + g_test_assert_expected_messages(); + + nm_setting_wireless_security_add_pairwise(s_wsec, "tkip"); + ASSERT_CHANGED(nm_setting_wireless_security_clear_pairwise(s_wsec)); + + /* Group ciphers */ + ASSERT_CHANGED(nm_setting_wireless_security_add_group(s_wsec, "ccmp")); + ASSERT_CHANGED(nm_setting_wireless_security_remove_group(s_wsec, 0)); + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); + ASSERT_UNCHANGED(nm_setting_wireless_security_remove_group(s_wsec, 1)); + g_test_assert_expected_messages(); + + nm_setting_wireless_security_add_group(s_wsec, "tkip"); + ASSERT_CHANGED(nm_setting_wireless_security_clear_groups(s_wsec)); + + /* WEP key secret flags */ + ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec), + "wep-key0", + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NULL))); + ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec), + "wep-key1", + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NULL))); + ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec), + "wep-key2", + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NULL))); + ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec), + "wep-key3", + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NULL))); + + g_object_unref(connection); +} + +static void +test_setting_802_1x_changed_signal(void) +{ + NMConnection * connection; + gboolean changed = FALSE; + NMSetting8021x *s_8021x; + + connection = nm_simple_connection_new(); + g_signal_connect(connection, + NM_CONNECTION_CHANGED, + (GCallback) test_connection_changed_cb, + &changed); + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + nm_connection_add_setting(connection, NM_SETTING(s_8021x)); + + /* EAP methods */ + ASSERT_CHANGED(nm_setting_802_1x_add_eap_method(s_8021x, "tls")); + ASSERT_CHANGED(nm_setting_802_1x_remove_eap_method(s_8021x, 0)); + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); + ASSERT_UNCHANGED(nm_setting_802_1x_remove_eap_method(s_8021x, 1)); + g_test_assert_expected_messages(); + + nm_setting_802_1x_add_eap_method(s_8021x, "ttls"); + ASSERT_CHANGED(nm_setting_802_1x_clear_eap_methods(s_8021x)); + + /* alternate subject matches */ + ASSERT_CHANGED(nm_setting_802_1x_add_altsubject_match(s_8021x, "EMAIL:server@example.com")); + ASSERT_CHANGED(nm_setting_802_1x_remove_altsubject_match(s_8021x, 0)); + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); + ASSERT_UNCHANGED(nm_setting_802_1x_remove_altsubject_match(s_8021x, 1)); + g_test_assert_expected_messages(); + + nm_setting_802_1x_add_altsubject_match(s_8021x, "EMAIL:server@example.com"); + ASSERT_CHANGED(nm_setting_802_1x_clear_altsubject_matches(s_8021x)); + + /* phase2 alternate subject matches */ + ASSERT_CHANGED( + nm_setting_802_1x_add_phase2_altsubject_match(s_8021x, "EMAIL:server@example.com")); + ASSERT_CHANGED(nm_setting_802_1x_remove_phase2_altsubject_match(s_8021x, 0)); + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(elt != NULL)); + ASSERT_UNCHANGED(nm_setting_802_1x_remove_phase2_altsubject_match(s_8021x, 1)); + g_test_assert_expected_messages(); + + nm_setting_802_1x_add_phase2_altsubject_match(s_8021x, "EMAIL:server@example.com"); + ASSERT_CHANGED(nm_setting_802_1x_clear_phase2_altsubject_matches(s_8021x)); + + g_object_unref(connection); +} + +static void +test_setting_old_uuid(void) +{ + gs_unref_object NMSetting *setting = NULL; + + /* NetworkManager-0.9.4.0 generated 40-character UUIDs with no dashes, + * like this one. Test that we maintain compatibility. */ + const char *uuid = "f43bec2cdd60e5da381ebb1eb1fa39f3cc52660c"; + + setting = nm_setting_connection_new(); + g_object_set(G_OBJECT(setting), + NM_SETTING_CONNECTION_ID, + "uuidtest", + NM_SETTING_CONNECTION_UUID, + uuid, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + + nmtst_assert_setting_verifies(NM_SETTING(setting)); +} + +/*****************************************************************************/ + +static void +test_connection_normalize_uuid(void) +{ + gs_unref_object NMConnection *con = NULL; + + con = nmtst_create_minimal_connection("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + + nmtst_assert_connection_verifies_and_normalizable(con); + + g_object_set(nm_connection_get_setting_connection(con), NM_SETTING_CONNECTION_UUID, NULL, NULL); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); +} + +/*****************************************************************************/ + +/* + * Test normalization of interface-name + */ +static void +test_connection_normalize_virtual_iface_name(void) +{ + NMConnection * con = NULL; + NMSettingConnection *s_con; + NMSettingVlan * s_vlan; + GVariant * connection_dict, *setting_dict, *var; + GError * error = NULL; + const char * IFACE_NAME = "iface"; + const char * IFACE_VIRT = "iface-X"; + + con = nmtst_create_minimal_connection("test1", + "22001632-bbb4-4616-b277-363dce3dfb5b", + NM_SETTING_VLAN_SETTING_NAME, + &s_con); + + nm_connection_add_setting(con, + g_object_new(NM_TYPE_SETTING_IP4_CONFIG, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL)); + + nm_connection_add_setting(con, + g_object_new(NM_TYPE_SETTING_IP6_CONFIG, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL)); + + s_vlan = nm_connection_get_setting_vlan(con); + + g_object_set(G_OBJECT(s_vlan), NM_SETTING_VLAN_PARENT, "eth0", NULL); + + g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, IFACE_NAME, NULL); + + g_assert_cmpstr(nm_connection_get_interface_name(con), ==, IFACE_NAME); + + connection_dict = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); + g_object_unref(con); + + /* Serialized form should include vlan.interface-name as well. */ + setting_dict = g_variant_lookup_value(connection_dict, + NM_SETTING_VLAN_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + g_assert(setting_dict != NULL); + var = g_variant_lookup_value(setting_dict, "interface-name", NULL); + g_assert(var != NULL); + g_assert(g_variant_is_of_type(var, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr(g_variant_get_string(var, NULL), ==, IFACE_NAME); + + g_variant_unref(setting_dict); + g_variant_unref(var); + + /* If vlan.interface-name will be ignored. */ + NMTST_VARIANT_EDITOR( + connection_dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_VLAN_SETTING_NAME, + "interface-name", + "s", + ":::this-is-not-a-valid-interface-name:::");); + + con = _connection_new_from_dbus(connection_dict, &error); + nmtst_assert_success(con, error); + g_assert_cmpstr(nm_connection_get_interface_name(con), ==, IFACE_NAME); + g_clear_object(&con); + + /* If vlan.interface-name is valid, but doesn't match, it will be ignored. */ + NMTST_VARIANT_EDITOR(connection_dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_VLAN_SETTING_NAME, + "interface-name", + "s", + IFACE_VIRT);); + + con = _connection_new_from_dbus(connection_dict, &error); + g_assert_no_error(error); + + g_assert_cmpstr(nm_connection_get_interface_name(con), ==, IFACE_NAME); + s_con = nm_connection_get_setting_connection(con); + g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, IFACE_NAME); + g_object_unref(con); + + /* But removing connection.interface-name should result in vlan.connection-name + * being "promoted". + */ + NMTST_VARIANT_EDITOR(connection_dict, + NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME);); + + con = _connection_new_from_dbus(connection_dict, &error); + g_assert_no_error(error); + + g_assert_cmpstr(nm_connection_get_interface_name(con), ==, IFACE_VIRT); + s_con = nm_connection_get_setting_connection(con); + g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, IFACE_VIRT); + g_object_unref(con); + + g_variant_unref(connection_dict); +} + +static void +_test_connection_normalize_type_normalizable_setting( + const char *type, + void (*prepare_normalizable_fcn)(NMConnection *con)) +{ + NMSettingConnection *s_con; + NMSetting * s_base; + GType base_type; + gs_unref_object NMConnection *con = NULL; + gs_free char * id = g_strdup_printf("%s[%s]", G_STRFUNC, type); + + base_type = nm_setting_lookup_type(type); + g_assert(base_type != G_TYPE_INVALID); + g_assert(_nm_setting_type_get_base_type_priority(base_type) != NM_SETTING_PRIORITY_INVALID); + + con = nmtst_create_minimal_connection(id, NULL, NULL, &s_con); + + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + + g_object_set(s_con, NM_SETTING_CONNECTION_TYPE, type, NULL); + + if (prepare_normalizable_fcn) + prepare_normalizable_fcn(con); + + g_assert(!nm_connection_get_setting_by_name(con, type)); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING); + nmtst_connection_normalize(con); + + s_base = nm_connection_get_setting_by_name(con, type); + g_assert(s_base); + g_assert(G_OBJECT_TYPE(s_base) == base_type); +} + +static void +_test_connection_normalize_type_unnormalizable_setting(const char *type) +{ + NMSettingConnection *s_con; + GType base_type; + gs_unref_object NMConnection *con = NULL; + gs_free char * id = g_strdup_printf("%s[%s]", G_STRFUNC, type); + + base_type = nm_setting_lookup_type(type); + g_assert(base_type != G_TYPE_INVALID); + g_assert(_nm_setting_type_get_base_type_priority(base_type) != NM_SETTING_PRIORITY_INVALID); + + con = nmtst_create_minimal_connection(id, NULL, NULL, &s_con); + + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + + g_object_set(s_con, NM_SETTING_CONNECTION_TYPE, type, NULL); + + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING); +} + +static void +_test_connection_normalize_type_normalizable_type(const char *type, + NMSetting *(*add_setting_fcn)(NMConnection *con)) +{ + NMSettingConnection *s_con; + NMSetting * s_base; + GType base_type; + gs_unref_object NMConnection *con = NULL; + gs_free char * id = g_strdup_printf("%s[%s]", G_STRFUNC, type); + + base_type = nm_setting_lookup_type(type); + g_assert(base_type != G_TYPE_INVALID); + g_assert(_nm_setting_type_get_base_type_priority(base_type) != NM_SETTING_PRIORITY_INVALID); + + con = nmtst_create_minimal_connection(id, NULL, NULL, &s_con); + + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + + if (add_setting_fcn) + s_base = add_setting_fcn(con); + else { + s_base = g_object_new(base_type, NULL); + nm_connection_add_setting(con, s_base); + } + + g_assert(!nm_setting_connection_get_connection_type(s_con)); + g_assert(nm_connection_get_setting_by_name(con, type) == s_base); + + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize(con); + + g_assert_cmpstr(nm_connection_get_connection_type(con), ==, type); + g_assert(nm_connection_get_setting_by_name(con, type) == s_base); +} + +static NMSetting * +_add_setting_fcn_adsl(NMConnection *con) +{ + NMSetting *setting; + + setting = g_object_new(NM_TYPE_SETTING_ADSL, + NM_SETTING_ADSL_USERNAME, + "test-user", + NM_SETTING_ADSL_PROTOCOL, + NM_SETTING_ADSL_PROTOCOL_PPPOA, + NM_SETTING_ADSL_ENCAPSULATION, + NM_SETTING_ADSL_ENCAPSULATION_VCMUX, + NULL); + + nm_connection_add_setting(con, setting); + return setting; +} + +static NMSetting * +_add_setting_fcn_bluetooth(NMConnection *con) +{ + NMSetting *setting; + + setting = g_object_new(NM_TYPE_SETTING_BLUETOOTH, + NM_SETTING_BLUETOOTH_BDADDR, + "11:22:33:44:55:66", + NM_SETTING_BLUETOOTH_TYPE, + NM_SETTING_BLUETOOTH_TYPE_PANU, + NULL); + + nm_connection_add_setting(con, setting); + return setting; +} + +static NMSetting * +_add_setting_fcn_bond(NMConnection *con) +{ + NMSetting * setting; + NMSettingConnection *s_con; + + setting = g_object_new(NM_TYPE_SETTING_BOND, NULL); + + nm_connection_add_setting(con, setting); + + s_con = nm_connection_get_setting_connection(con); + + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bond", NULL); + + return setting; +} + +static NMSetting * +_add_setting_fcn_bridge(NMConnection *con) +{ + NMSetting * setting; + NMSettingConnection *s_con; + + setting = g_object_new(NM_TYPE_SETTING_BRIDGE, NULL); + + nm_connection_add_setting(con, setting); + + s_con = nm_connection_get_setting_connection(con); + + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bridge", NULL); + + return setting; +} + +static NMSetting * +_add_setting_fcn_cdma(NMConnection *con) +{ + NMSetting *setting; + + setting = g_object_new(NM_TYPE_SETTING_CDMA, NM_SETTING_CDMA_NUMBER, "test-number", NULL); + + nm_connection_add_setting(con, setting); + return setting; +} + +static NMSetting * +_add_setting_fcn_infiniband(NMConnection *con) +{ + NMSetting *setting; + + setting = g_object_new(NM_TYPE_SETTING_INFINIBAND, + NM_SETTING_INFINIBAND_TRANSPORT_MODE, + "connected", + NULL); + + nm_connection_add_setting(con, setting); + return setting; +} + +static NMSetting * +_add_setting_fcn_olpc_mesh(NMConnection *con) +{ + NMSetting * setting; + const char *ssid_data = "ssid-test"; + GBytes * ssid; + + ssid = g_bytes_new(ssid_data, strlen(ssid_data)); + setting = g_object_new(NM_TYPE_SETTING_OLPC_MESH, + NM_SETTING_OLPC_MESH_SSID, + ssid, + NM_SETTING_OLPC_MESH_CHANNEL, + 1, + NULL); + g_bytes_unref(ssid); + + nm_connection_add_setting(con, setting); + return setting; +} + +static NMSetting * +_add_setting_fcn_team(NMConnection *con) +{ + NMSetting * setting; + NMSettingConnection *s_con; + + setting = g_object_new(NM_TYPE_SETTING_TEAM, NULL); + + nm_connection_add_setting(con, setting); + + s_con = nm_connection_get_setting_connection(con); + + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "test-team", NULL); + + return setting; +} + +static NMSetting * +_add_setting_fcn_vlan(NMConnection *con) +{ + NMSetting *setting; + + setting = g_object_new(NM_TYPE_SETTING_VLAN, NM_SETTING_VLAN_PARENT, "test-parent", NULL); + + nm_connection_add_setting(con, setting); + return setting; +} + +static NMSetting * +_add_setting_fcn_vpn(NMConnection *con) +{ + NMSetting *setting; + + setting = g_object_new(NM_TYPE_SETTING_VPN, + NM_SETTING_VPN_SERVICE_TYPE, + "test-vpn-service-type", + NULL); + + nm_connection_add_setting(con, setting); + return setting; +} + +static NMSetting * +_add_setting_fcn_wimax(NMConnection *con) +{ + NMSetting *setting; + + setting = + g_object_new(NM_TYPE_SETTING_WIMAX, NM_SETTING_WIMAX_NETWORK_NAME, "test-network", NULL); + + nm_connection_add_setting(con, setting); + return setting; +} + +static NMSetting * +_add_setting_fcn_wireless(NMConnection *con) +{ + NMSetting * setting; + const char *ssid_data = "ssid-test"; + GBytes * ssid; + + ssid = g_bytes_new(ssid_data, strlen(ssid_data)); + setting = g_object_new(NM_TYPE_SETTING_WIRELESS, NM_SETTING_WIRELESS_SSID, ssid, NULL); + g_bytes_unref(ssid); + + nm_connection_add_setting(con, setting); + return setting; +} + +static void +_prepare_normalizable_fcn_vlan(NMConnection *con) +{ + nm_connection_add_setting(con, + g_object_new(NM_TYPE_SETTING_WIRED, + NM_SETTING_WIRED_MAC_ADDRESS, + "11:22:33:44:55:66", + NULL)); +} + +static void +test_connection_normalize_type(void) +{ + guint i; + struct { + const char *type; + gboolean normalizable; + NMSetting *(*add_setting_fcn)(NMConnection *con); + void (*prepare_normalizable_fcn)(NMConnection *con); + } types[] = { + {NM_SETTING_GENERIC_SETTING_NAME, TRUE}, + {NM_SETTING_GSM_SETTING_NAME, TRUE}, + {NM_SETTING_WIRED_SETTING_NAME, TRUE}, + {NM_SETTING_VLAN_SETTING_NAME, TRUE, _add_setting_fcn_vlan, _prepare_normalizable_fcn_vlan}, + + {NM_SETTING_ADSL_SETTING_NAME, FALSE, _add_setting_fcn_adsl}, + {NM_SETTING_BLUETOOTH_SETTING_NAME, FALSE, _add_setting_fcn_bluetooth}, + {NM_SETTING_BOND_SETTING_NAME, FALSE, _add_setting_fcn_bond}, + {NM_SETTING_BRIDGE_SETTING_NAME, FALSE, _add_setting_fcn_bridge}, + {NM_SETTING_CDMA_SETTING_NAME, FALSE, _add_setting_fcn_cdma}, + {NM_SETTING_INFINIBAND_SETTING_NAME, FALSE, _add_setting_fcn_infiniband}, + {NM_SETTING_OLPC_MESH_SETTING_NAME, FALSE, _add_setting_fcn_olpc_mesh}, + {NM_SETTING_TEAM_SETTING_NAME, FALSE, _add_setting_fcn_team}, + {NM_SETTING_VLAN_SETTING_NAME, FALSE, _add_setting_fcn_vlan}, + {NM_SETTING_VPN_SETTING_NAME, FALSE, _add_setting_fcn_vpn}, + {NM_SETTING_WIMAX_SETTING_NAME, FALSE, _add_setting_fcn_wimax}, + {NM_SETTING_WIRELESS_SETTING_NAME, FALSE, _add_setting_fcn_wireless}, + {0}, + }; + + for (i = 0; types[i].type; i++) { + const char *type = types[i].type; + + if (types[i].normalizable) + _test_connection_normalize_type_normalizable_setting(type, + types[i].prepare_normalizable_fcn); + else + _test_connection_normalize_type_unnormalizable_setting(type); + _test_connection_normalize_type_normalizable_type(type, types[i].add_setting_fcn); + } +} + +static void +test_connection_normalize_slave_type_1(void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingConnection * s_con; + + con = nmtst_create_minimal_connection("test_connection_normalize_slave_type_1", + "cc4cd5df-45dc-483e-b291-6b76c2338ecb", + NM_SETTING_WIRED_SETTING_NAME, + &s_con); + + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + "invalid-type", + NULL); + + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); + + g_object_set(s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, "bridge", NULL); + + g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING); + nmtst_connection_normalize(con); + g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), + ==, + NM_SETTING_BRIDGE_SETTING_NAME); +} + +static void +test_connection_normalize_slave_type_2(void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingConnection * s_con; + + con = nmtst_create_minimal_connection("test_connection_normalize_slave_type_2", + "40bea008-ca72-439a-946b-e65f827656f9", + NM_SETTING_WIRED_SETTING_NAME, + &s_con); + + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + "invalid-type", + NULL); + + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); + + g_object_set(s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, NULL, NULL); + nm_connection_add_setting(con, nm_setting_bridge_port_new()); + + g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NULL); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize(con); + g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), + ==, + NM_SETTING_BRIDGE_SETTING_NAME); +} + +static void +test_connection_normalize_infiniband_mtu(void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingInfiniband * s_infini; + guint mtu_regular = nmtst_rand_select(2044, 2045, 65520); + + con = nmtst_create_minimal_connection("test_connection_normalize_infiniband_mtu", + NULL, + NM_SETTING_INFINIBAND_SETTING_NAME, + NULL); + + s_infini = nm_connection_get_setting_infiniband(con); + g_object_set(s_infini, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected", NULL); + nmtst_assert_connection_verifies_and_normalizable(con); + + g_object_set(s_infini, + NM_SETTING_INFINIBAND_TRANSPORT_MODE, + "datagram", + NM_SETTING_INFINIBAND_MTU, + (guint) mtu_regular, + NULL); + nmtst_assert_connection_verifies_and_normalizable(con); + nmtst_connection_normalize(con); + g_assert_cmpint(mtu_regular, ==, nm_setting_infiniband_get_mtu(s_infini)); + + g_object_set(s_infini, + NM_SETTING_INFINIBAND_TRANSPORT_MODE, + "datagram", + NM_SETTING_INFINIBAND_MTU, + (guint) 65521, + NULL); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + nmtst_connection_normalize(con); + g_assert_cmpint(65520, ==, nm_setting_infiniband_get_mtu(s_infini)); + + g_object_set(s_infini, + NM_SETTING_INFINIBAND_TRANSPORT_MODE, + "connected", + NM_SETTING_INFINIBAND_MTU, + (guint) mtu_regular, + NULL); + nmtst_assert_connection_verifies_without_normalization(con); + g_assert_cmpint(mtu_regular, ==, nm_setting_infiniband_get_mtu(s_infini)); + + g_object_set(s_infini, + NM_SETTING_INFINIBAND_TRANSPORT_MODE, + "connected", + NM_SETTING_INFINIBAND_MTU, + (guint) 65521, + NULL); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + nmtst_connection_normalize(con); + g_assert_cmpint(65520, ==, nm_setting_infiniband_get_mtu(s_infini)); +} + +static void +test_connection_normalize_gateway_never_default(void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingIPConfig * s_ip4, *s_ip6; + NMIPAddress * addr; + gs_free_error GError *error = NULL; + + con = nmtst_create_minimal_connection("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nmtst_assert_connection_verifies_and_normalizable(con); + + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(s_ip4), + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + + addr = nm_ip_address_new(AF_INET, "1.1.1.1", 24, &error); + g_assert_no_error(error); + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + + g_object_set(s_ip4, + NM_SETTING_IP_CONFIG_GATEWAY, + "1.1.1.254", + NM_SETTING_IP_CONFIG_NEVER_DEFAULT, + FALSE, + NULL); + + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); + + nm_connection_add_setting(con, (NMSetting *) s_ip4); + nm_connection_add_setting(con, (NMSetting *) s_ip6); + nm_connection_add_setting(con, nm_setting_proxy_new()); + + nmtst_assert_connection_verifies_without_normalization(con); + g_assert_cmpstr("1.1.1.254", ==, nm_setting_ip_config_get_gateway(s_ip4)); + + /* Now set never-default to TRUE and check that the gateway is + * removed during normalization + * */ + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_NEVER_DEFAULT, TRUE, NULL); + + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + nmtst_connection_normalize(con); + g_assert_cmpstr(NULL, ==, nm_setting_ip_config_get_gateway(s_ip4)); +} + +static void +test_connection_normalize_may_fail(void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingIPConfig * s_ip4, *s_ip6; + + con = nmtst_create_minimal_connection("test2", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nmtst_assert_connection_verifies_and_normalizable(con); + + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(s_ip4), + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_MAY_FAIL, + FALSE, + NULL); + + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + g_object_set(s_ip6, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_MAY_FAIL, + FALSE, + NULL); + + nm_connection_add_setting(con, (NMSetting *) s_ip4); + nm_connection_add_setting(con, (NMSetting *) s_ip6); + + nmtst_assert_connection_verifies_and_normalizable(con); + + /* Now set method=disabled/ignore and check that may-fail becomes TRUE + * after normalization + * */ + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); + + nmtst_assert_connection_verifies(con); + nmtst_connection_normalize(con); + g_assert_cmpint(nm_setting_ip_config_get_may_fail(s_ip4), ==, TRUE); + g_assert_cmpint(nm_setting_ip_config_get_may_fail(s_ip6), ==, TRUE); +} + +static void +test_connection_normalize_shared_addresses(void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingIPConfig * s_ip4, *s_ip6; + NMIPAddress * addr; + gs_free_error GError *error = NULL; + + con = nmtst_create_minimal_connection("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nmtst_assert_connection_verifies_and_normalizable(con); + + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(s_ip4), + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_SHARED, + NULL); + + addr = nm_ip_address_new(AF_INET, "1.1.1.1", 24, &error); + g_assert_no_error(error); + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); + + nm_connection_add_setting(con, (NMSetting *) s_ip4); + nm_connection_add_setting(con, (NMSetting *) s_ip6); + + nmtst_assert_connection_verifies_and_normalizable(con); + + /* Now we add other addresses and check that they are + * removed during normalization + * */ + addr = nm_ip_address_new(AF_INET, "2.2.2.2", 24, &error); + g_assert_no_error(error); + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + + addr = nm_ip_address_new(AF_INET, "3.3.3.3", 24, &error); + g_assert_no_error(error); + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + nmtst_connection_normalize(con); + g_assert_cmpuint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); + addr = nm_setting_ip_config_get_address(s_ip4, 0); + g_assert_cmpstr(nm_ip_address_get_address(addr), ==, "1.1.1.1"); +} + +static void +test_connection_normalize_ovs_interface_type_system(gconstpointer test_data) +{ + const guint TEST_CASE = GPOINTER_TO_UINT(test_data); + gs_unref_object NMConnection *con = NULL; + NMSettingConnection * s_con; + NMSettingOvsInterface * s_ovs_if; + + con = nmtst_create_minimal_connection("test_connection_normalize_ovs_interface_type_system", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + &s_con); + + switch (TEST_CASE) { + case 1: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING); + + nmtst_connection_normalize(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + s_ovs_if = nm_connection_get_setting_ovs_interface(con); + g_assert(s_ovs_if); + g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "system"); + break; + case 2: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); + nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); + + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + + nmtst_connection_normalize(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); + g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "system"); + break; + case 3: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); + nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); + + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); + nmtst_assert_connection_verifies_without_normalization(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + break; + case 4: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); + nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); + + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); + /* the setting doesn't verify, because the interface-type must be "system". */ + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 5: + g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); + nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); + + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert(s_con == nm_connection_get_setting_connection(con)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), + ==, + NM_SETTING_OVS_PORT_SETTING_NAME); + break; + case 6: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_BRIDGE_SETTING_NAME, + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); + nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); + + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 7: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_BRIDGE_SETTING_NAME, + NULL); + + nm_connection_add_setting(con, nm_setting_bridge_port_new()); + + s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); + nm_connection_add_setting(con, NM_SETTING(s_ovs_if)); + + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + default: + g_assert_not_reached(); + break; + } +} + +static void +test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_data) +{ + const guint TEST_CASE = GPOINTER_TO_UINT(test_data); + gs_unref_object NMConnection *con = NULL; + NMSettingConnection * s_con; + NMSettingOvsInterface * s_ovs_if; + NMSettingOvsPatch * s_ovs_patch; + NMSettingIP4Config * s_ip4; + NMSettingIP6Config * s_ip6; + + con = nmtst_create_minimal_connection( + "test_connection_normalize_ovs_interface_type_ovs_interface", + NULL, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + &s_con); + s_ovs_if = nm_connection_get_setting_ovs_interface(con); + g_assert(s_ovs_if); + + switch (TEST_CASE) { + case 1: + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 2: + g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert(s_con == nm_connection_get_setting_connection(con)); + g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), + ==, + NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal"); + break; + case 3: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert(s_con == nm_connection_get_setting_connection(con)); + g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), + ==, + NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal"); + break; + case 4: + g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); + nmtst_assert_connection_verifies_after_normalization(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert(s_con == nm_connection_get_setting_connection(con)); + g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), + ==, + NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal"); + break; + case 5: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); + nm_connection_add_setting(con, nm_setting_ip4_config_new()); + nm_connection_add_setting(con, nm_setting_ip6_config_new()); + nm_connection_add_setting(con, nm_setting_proxy_new()); + s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(con)); + s_ip6 = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(con)); + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, "auto", NULL); + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, "auto", NULL); + nmtst_assert_connection_verifies_without_normalization(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + break; + case 6: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); + nmtst_assert_connection_verifies_and_normalizable(con); + nmtst_connection_normalize(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert(s_con == nm_connection_get_setting_connection(con)); + g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), + ==, + NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal"); + break; + case 7: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 8: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "bogus", NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 9: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING); + break; + case 10: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); + nm_connection_add_setting(con, nm_setting_ovs_patch_new()); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + break; + case 11: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME, + "adsf", + NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); + nm_connection_add_setting(con, nm_setting_ovs_patch_new()); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY); + break; + case 12: + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME, + "adsf", + NULL); + g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); + s_ovs_patch = NM_SETTING_OVS_PATCH(nm_setting_ovs_patch_new()); + nm_connection_add_setting(con, NM_SETTING(s_ovs_patch)); + g_object_set(s_ovs_patch, NM_SETTING_OVS_PATCH_PEER, "1.2.3.4", NULL); + nmtst_assert_connection_verifies_and_normalizable(con); + nmtst_connection_normalize(con); + nmtst_assert_connection_has_settings(con, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_PATCH_SETTING_NAME); + g_assert(s_con == nm_connection_get_setting_connection(con)); + g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con)); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), + ==, + NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "patch"); + break; + default: + g_assert_not_reached(); + } +} + +static void +test_setting_ip4_gateway(void) +{ + NMConnection * conn; + NMSettingIPConfig *s_ip4; + NMIPAddress * addr; + GVariant * conn_dict, *ip4_dict, *value; + GVariantIter iter; + GVariant * addr_var; + guint32 addr_vals_0[] = {htonl(0xc0a8010a), 0x00000018, htonl(0x00000000)}; + guint32 addr_vals_1[] = {htonl(0xc0a8010b), 0x00000018, htonl(0xc0a80101)}; + GVariantBuilder addrs_builder; + GError * error = NULL; + + nmtst_assert_ip4_address(addr_vals_0[0], "192.168.1.10"); + + /* When serializing on the daemon side, ipv4.gateway is copied to the first + * entry of ipv4.addresses + */ + conn = nmtst_create_minimal_connection("test_setting_ip4_gateway", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + g_object_set(s_ip4, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, + "192.168.1.1", + NULL); + nm_connection_add_setting(conn, NM_SETTING(s_ip4)); + + addr = nm_ip_address_new(AF_INET, "192.168.1.10", 24, &error); + g_assert_no_error(error); + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + + _nm_utils_is_manager_process = TRUE; + conn_dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); + _nm_utils_is_manager_process = FALSE; + g_object_unref(conn); + + ip4_dict = g_variant_lookup_value(conn_dict, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + g_assert(ip4_dict != NULL); + + value = g_variant_lookup_value(ip4_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING); + g_assert(value != NULL); + g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "192.168.1.1"); + g_variant_unref(value); + + value = g_variant_lookup_value(ip4_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE("aau")); + g_assert(value != NULL); + + g_variant_iter_init(&iter, value); + while (g_variant_iter_next(&iter, "@au", &addr_var)) { + const guint32 *addr_array; + gsize length; + + addr_array = g_variant_get_fixed_array(addr_var, &length, sizeof(guint32)); + g_assert_cmpint(length, ==, 3); + nmtst_assert_ip4_address(addr_array[2], "192.168.1.1"); + g_variant_unref(addr_var); + } + g_variant_unref(value); + + g_variant_unref(ip4_dict); + + /* When deserializing an old-style connection, the first non-0 gateway in + * ipv4.addresses is copied to :gateway. + */ + NMTST_VARIANT_EDITOR( + conn_dict, + NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY); + NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-data");); + + conn = _connection_new_from_dbus(conn_dict, &error); + g_assert_no_error(error); + + s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config(conn); + g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.1.1"); + + g_object_unref(conn); + + /* Try again with the gateway in the second address. */ + g_variant_builder_init(&addrs_builder, G_VARIANT_TYPE("aau")); + g_variant_builder_add(&addrs_builder, + "@au", + g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, addr_vals_0, 3, 4)); + g_variant_builder_add(&addrs_builder, + "@au", + g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, addr_vals_1, 3, 4)); + + NMTST_VARIANT_EDITOR(conn_dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP4_CONFIG_SETTING_NAME, + "addresses", + "aau", + &addrs_builder);); + + conn = _connection_new_from_dbus(conn_dict, &error); + g_assert_no_error(error); + g_variant_unref(conn_dict); + + s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config(conn); + g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.1.1"); + + g_object_unref(conn); +} + +static void +test_setting_ip6_gateway(void) +{ + NMConnection * conn; + NMSettingIPConfig *s_ip6; + NMIPAddress * addr; + GVariant * conn_dict, *ip6_dict, *value; + GVariantIter iter; + GVariant * gateway_var; + GVariantBuilder addrs_builder; + guint8 addr_bytes_0[] = {0xab, + 0xcd, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0a}; + guint8 addr_bytes_1[] = {0xab, + 0xcd, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0b}; + guint8 gateway_bytes_1[] = {0xab, + 0xcd, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01}; + GError * error = NULL; + + /* When serializing on the daemon side, ipv6.gateway is copied to the first + * entry of ipv6.addresses + */ + conn = nmtst_create_minimal_connection("test_setting_ip6_gateway", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + g_object_set(s_ip6, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, + "abcd::1", + NULL); + nm_connection_add_setting(conn, NM_SETTING(s_ip6)); + + addr = nm_ip_address_new(AF_INET6, "abcd::10", 64, &error); + g_assert_no_error(error); + nm_setting_ip_config_add_address(s_ip6, addr); + nm_ip_address_unref(addr); + + _nm_utils_is_manager_process = TRUE; + conn_dict = nm_connection_to_dbus(conn, NM_CONNECTION_SERIALIZE_ALL); + _nm_utils_is_manager_process = FALSE; + g_object_unref(conn); + + ip6_dict = g_variant_lookup_value(conn_dict, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_VARIANT_TYPE_SETTING); + g_assert(ip6_dict != NULL); + + value = g_variant_lookup_value(ip6_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING); + g_assert(value != NULL); + g_assert_cmpstr(g_variant_get_string(value, NULL), ==, "abcd::1"); + g_variant_unref(value); + + value = g_variant_lookup_value(ip6_dict, + NM_SETTING_IP_CONFIG_ADDRESSES, + G_VARIANT_TYPE("a(ayuay)")); + g_assert(value != NULL); + + g_variant_iter_init(&iter, value); + while (g_variant_iter_next(&iter, "(@ayu@ay)", NULL, NULL, &gateway_var)) { + const guint8 *gateway_bytes; + gsize length; + + gateway_bytes = g_variant_get_fixed_array(gateway_var, &length, 1); + g_assert_cmpint(length, ==, 16); + nmtst_assert_ip6_address((struct in6_addr *) gateway_bytes, "abcd::1"); + g_variant_unref(gateway_var); + } + g_variant_unref(value); + + g_variant_unref(ip6_dict); + + /* When deserializing an old-style connection, the first non-0 gateway in + * ipv6.addresses is copied to :gateway. + */ + NMTST_VARIANT_EDITOR( + conn_dict, + NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY); + NMTST_VARIANT_DROP_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, "address-data");); + + conn = _connection_new_from_dbus(conn_dict, &error); + g_assert_no_error(error); + + s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config(conn); + g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "abcd::1"); + + g_object_unref(conn); + + /* Try again with the gateway in the second address. */ + g_variant_builder_init(&addrs_builder, G_VARIANT_TYPE("a(ayuay)")); + g_variant_builder_add(&addrs_builder, + "(@ayu@ay)", + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, addr_bytes_0, 16, 1), + 64, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, &in6addr_any, 16, 1)); + g_variant_builder_add(&addrs_builder, + "(@ayu@ay)", + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, addr_bytes_1, 16, 1), + 64, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, gateway_bytes_1, 16, 1)); + + NMTST_VARIANT_EDITOR(conn_dict, + NMTST_VARIANT_CHANGE_PROPERTY(NM_SETTING_IP6_CONFIG_SETTING_NAME, + "addresses", + "a(ayuay)", + &addrs_builder);); + + conn = _connection_new_from_dbus(conn_dict, &error); + g_assert_no_error(error); + g_variant_unref(conn_dict); + + s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config(conn); + g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "abcd::1"); + + g_object_unref(conn); +} + +typedef struct { + const char * str; + const guint8 expected[20]; + const guint expected_len; +} HexItem; + +static void +test_setting_compare_default_strv(void) +{ + gs_unref_object NMConnection *c1 = NULL, *c2 = NULL; + char ** strv; + NMSettingIPConfig * s_ip2, *s_ip1; + gboolean compare; + GHashTable * out_settings = NULL; + + c1 = nmtst_create_minimal_connection("test_compare_default_strv", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + nmtst_assert_connection_verifies_and_normalizable(c1); + nmtst_connection_normalize(c1); + + c2 = nm_simple_connection_new_clone(c1); + nmtst_assert_connection_verifies_without_normalization(c2); + + nmtst_assert_connection_equals(c1, FALSE, c2, FALSE); + + s_ip1 = nm_connection_get_setting_ip4_config(c1); + s_ip2 = nm_connection_get_setting_ip4_config(c2); + + nm_setting_ip_config_clear_dns_options(s_ip2, FALSE); + g_object_get(G_OBJECT(s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL); + g_assert(!strv); + nmtst_assert_connection_equals(c1, FALSE, c2, FALSE); + + nm_setting_ip_config_clear_dns_options(s_ip2, TRUE); + g_object_get(G_OBJECT(s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL); + g_assert(strv && !strv[0]); + g_strfreev(strv); + + compare = nm_setting_diff((NMSetting *) s_ip1, + (NMSetting *) s_ip2, + NM_SETTING_COMPARE_FLAG_EXACT, + FALSE, + &out_settings); + g_assert(!compare); + g_assert(out_settings); + g_assert(g_hash_table_contains(out_settings, NM_SETTING_IP_CONFIG_DNS_OPTIONS)); + g_hash_table_unref(out_settings); + out_settings = NULL; + + compare = nm_connection_diff(c1, c2, NM_SETTING_COMPARE_FLAG_EXACT, &out_settings); + g_assert(!compare); + g_assert(out_settings); + g_hash_table_unref(out_settings); + out_settings = NULL; +} + +/*****************************************************************************/ + +static void +test_setting_user_data(void) +{ + gs_unref_object NMSettingUser *s_user = NULL; + + s_user = NM_SETTING_USER(nm_setting_user_new()); +} + +/*****************************************************************************/ + +typedef union { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; +} SockAddrUnion; + +static void +_sock_addr_endpoint(const char *endpoint, const char *host, gint32 port) +{ + nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL; + const char * s_endpoint; + const char * s_host; + gint32 s_port; + SockAddrUnion sockaddr = {}; + + g_assert(endpoint); + g_assert((!host) == (port == -1)); + g_assert(port >= -1 && port <= G_MAXUINT16); + + ep = nm_sock_addr_endpoint_new(endpoint); + g_assert(ep); + + s_endpoint = nm_sock_addr_endpoint_get_endpoint(ep); + s_host = nm_sock_addr_endpoint_get_host(ep); + s_port = nm_sock_addr_endpoint_get_port(ep); + g_assert_cmpstr(endpoint, ==, s_endpoint); + g_assert_cmpstr(host, ==, s_host); + g_assert_cmpint(port, ==, s_port); + + g_assert(!nm_sock_addr_endpoint_get_fixed_sockaddr(ep, &sockaddr)); + + if (endpoint[0] != ' ') { + gs_free char *endpoint2 = NULL; + + /* also test with a leading space */ + endpoint2 = g_strdup_printf(" %s", endpoint); + _sock_addr_endpoint(endpoint2, host, port); + } + + if (endpoint[0] && endpoint[strlen(endpoint) - 1] != ' ') { + gs_free char *endpoint2 = NULL; + + /* also test with a trailing space */ + endpoint2 = g_strdup_printf("%s ", endpoint); + _sock_addr_endpoint(endpoint2, host, port); + } +} + +static void +_sock_addr_endpoint_fixed(const char *endpoint, const char *host, guint16 port, guint scope_id) +{ + nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL; + const char * s_endpoint; + const char * s_host; + gint32 s_port; + int addr_family; + NMIPAddr addrbin; + SockAddrUnion sockaddr = {}; + + g_assert(endpoint); + g_assert(host); + g_assert(port > 0); + + if (!nm_utils_parse_inaddr_bin(AF_UNSPEC, host, &addr_family, &addrbin)) + g_assert_not_reached(); + + ep = nm_sock_addr_endpoint_new(endpoint); + g_assert(ep); + + s_endpoint = nm_sock_addr_endpoint_get_endpoint(ep); + s_host = nm_sock_addr_endpoint_get_host(ep); + s_port = nm_sock_addr_endpoint_get_port(ep); + g_assert_cmpstr(endpoint, ==, s_endpoint); + g_assert_cmpstr(NULL, !=, s_host); + g_assert_cmpint(port, ==, s_port); + + if (!nm_sock_addr_endpoint_get_fixed_sockaddr(ep, &sockaddr)) + g_assert_not_reached(); + + g_assert_cmpint(sockaddr.sa.sa_family, ==, addr_family); + if (addr_family == AF_INET) { + const SockAddrUnion s = { + .in = + { + .sin_family = AF_INET, + .sin_addr = addrbin.addr4_struct, + .sin_port = htons(port), + }, + }; + + g_assert_cmpint(sockaddr.in.sin_addr.s_addr, ==, addrbin.addr4); + g_assert_cmpint(sockaddr.in.sin_port, ==, htons(port)); + g_assert(memcmp(&s, &sockaddr, sizeof(s.in)) == 0); + } else if (addr_family == AF_INET6) { + const SockAddrUnion s = { + .in6 = + { + .sin6_family = AF_INET6, + .sin6_addr = addrbin.addr6, + .sin6_scope_id = scope_id, + .sin6_port = htons(port), + }, + }; + + g_assert(memcmp(&sockaddr.in6.sin6_addr, &addrbin, sizeof(addrbin.addr6)) == 0); + g_assert_cmpint(sockaddr.in6.sin6_port, ==, htons(port)); + g_assert_cmpint(sockaddr.in6.sin6_scope_id, ==, scope_id); + g_assert_cmpint(sockaddr.in6.sin6_flowinfo, ==, 0); + g_assert(memcmp(&s, &sockaddr, sizeof(s.in6)) == 0); + } else + g_assert_not_reached(); +} + +static void +test_sock_addr_endpoint(void) +{ + _sock_addr_endpoint("", NULL, -1); + _sock_addr_endpoint(":", NULL, -1); + _sock_addr_endpoint("a", NULL, -1); + _sock_addr_endpoint("a:", NULL, -1); + _sock_addr_endpoint(":a", NULL, -1); + _sock_addr_endpoint("[]:a", NULL, -1); + _sock_addr_endpoint("[]a", NULL, -1); + _sock_addr_endpoint("[]:", NULL, -1); + _sock_addr_endpoint("[a]b", NULL, -1); + _sock_addr_endpoint("[a:b", NULL, -1); + _sock_addr_endpoint("[a[:b", NULL, -1); + _sock_addr_endpoint("a:6", "a", 6); + _sock_addr_endpoint("a:6", "a", 6); + _sock_addr_endpoint("[a]:6", "a", 6); + _sock_addr_endpoint("[a]:6", "a", 6); + _sock_addr_endpoint("[a]:655", "a", 655); + _sock_addr_endpoint("[ab]:][6", NULL, -1); + _sock_addr_endpoint("[ab]:]:[6", NULL, -1); + _sock_addr_endpoint("[a[]:b", NULL, -1); + _sock_addr_endpoint("[192.169.6.x]:6", "192.169.6.x", 6); + _sock_addr_endpoint("[192.169.6.x]:0", NULL, -1); + _sock_addr_endpoint("192.169.6.7:0", NULL, -1); + + _sock_addr_endpoint_fixed("192.169.6.7:6", "192.169.6.7", 6, 0); + _sock_addr_endpoint_fixed("[192.169.6.7]:6", "192.169.6.7", 6, 0); + _sock_addr_endpoint_fixed("[a:b::]:6", "a:b::", 6, 0); + _sock_addr_endpoint_fixed("[a:b::%7]:6", "a:b::", 6, 7); + _sock_addr_endpoint_fixed("a:b::1%75:6", "a:b::1", 6, 75); + _sock_addr_endpoint_fixed("a:b::1%0:64", "a:b::1", 64, 0); +} + +/*****************************************************************************/ + +static void +test_hexstr2bin(void) +{ + static const HexItem items[] = { + {"aaBBCCddDD10496a", {0xaa, 0xbb, 0xcc, 0xdd, 0xdd, 0x10, 0x49, 0x6a}, 8}, + {"aa:bb:cc:dd:10:49:6a", {0xaa, 0xbb, 0xcc, 0xdd, 0x10, 0x49, 0x6a}, 7}, + {"0xccddeeff", {0xcc, 0xdd, 0xee, 0xff}, 4}, + {"1:2:66:77:80", {0x01, 0x02, 0x66, 0x77, 0x80}, 5}, + {"e", {0x0e}, 1}, + {"ef", {0xef}, 1}, + {"efa"}, + {"efad", {0xef, 0xad}, 2}, + {"ef:a", {0xef, 0x0a}, 2}, + {"aabb1199:"}, + {":aabb1199"}, + {"aabb$$dd"}, + {"aab:ccc:ddd"}, + {"aab::ccc:ddd"}, + }; + guint i; + + for (i = 0; i < G_N_ELEMENTS(items); i++) { + gs_unref_bytes GBytes *b = NULL; + + b = nm_utils_hexstr2bin(items[i].str); + if (items[i].expected_len) + g_assert(b); + else + g_assert(!b); + g_assert(nm_utils_gbytes_equal_mem(b, items[i].expected, items[i].expected_len)); + } +} + +/*****************************************************************************/ + +static void +_do_strquote(const char *str, gsize buf_len, const char *expected) +{ + char canary = (char) nmtst_get_rand_uint32(); + gs_free char *buf_full = g_malloc(buf_len + 2); + char * buf = &buf_full[1]; + const char * b; + + buf[-1] = canary; + buf[buf_len] = canary; + + if (buf_len == 0) { + b = nm_strquote(NULL, 0, str); + g_assert(b == NULL); + g_assert(expected == NULL); + b = nm_strquote(buf, 0, str); + g_assert(b == buf); + } else { + b = nm_strquote(buf, buf_len, str); + g_assert(b == buf); + g_assert(strlen(b) < buf_len); + g_assert_cmpstr(expected, ==, b); + } + + g_assert(buf[-1] == canary); + g_assert(buf[buf_len] == canary); +} + +static void +test_nm_strquote(void) +{ + _do_strquote(NULL, 0, NULL); + _do_strquote("", 0, NULL); + _do_strquote("a", 0, NULL); + _do_strquote("ab", 0, NULL); + + _do_strquote(NULL, 1, ""); + _do_strquote(NULL, 2, "("); + _do_strquote(NULL, 3, "(n"); + _do_strquote(NULL, 4, "(nu"); + _do_strquote(NULL, 5, "(nul"); + _do_strquote(NULL, 6, "(null"); + _do_strquote(NULL, 7, "(null)"); + _do_strquote(NULL, 8, "(null)"); + _do_strquote(NULL, 100, "(null)"); + + _do_strquote("", 1, ""); + _do_strquote("", 2, "^"); + _do_strquote("", 3, "\"\""); + _do_strquote("", 4, "\"\""); + _do_strquote("", 5, "\"\""); + _do_strquote("", 100, "\"\""); + + _do_strquote("a", 1, ""); + _do_strquote("a", 2, "^"); + _do_strquote("a", 3, "\"^"); + _do_strquote("a", 4, "\"a\""); + _do_strquote("a", 5, "\"a\""); + _do_strquote("a", 6, "\"a\""); + _do_strquote("a", 100, "\"a\""); + + _do_strquote("ab", 1, ""); + _do_strquote("ab", 2, "^"); + _do_strquote("ab", 3, "\"^"); + _do_strquote("ab", 4, "\"a^"); + _do_strquote("ab", 5, "\"ab\""); + _do_strquote("ab", 6, "\"ab\""); + _do_strquote("ab", 7, "\"ab\""); + _do_strquote("ab", 100, "\"ab\""); + + _do_strquote("abc", 1, ""); + _do_strquote("abc", 2, "^"); + _do_strquote("abc", 3, "\"^"); + _do_strquote("abc", 4, "\"a^"); + _do_strquote("abc", 5, "\"ab^"); + _do_strquote("abc", 6, "\"abc\""); + _do_strquote("abc", 7, "\"abc\""); + _do_strquote("abc", 100, "\"abc\""); +} + +/*****************************************************************************/ + +#define UUID_NS_ZERO "00000000-0000-0000-0000-000000000000" +#define UUID_NS_DNS "6ba7b810-9dad-11d1-80b4-00c04fd430c8" +#define UUID_NS_URL "6ba7b811-9dad-11d1-80b4-00c04fd430c8" +#define UUID_NS_OID "6ba7b812-9dad-11d1-80b4-00c04fd430c8" +#define UUID_NS_X500 "6ba7b814-9dad-11d1-80b4-00c04fd430c8" + +static const NMUuid * +_uuid(const char *str) +{ + static NMUuid u; + + g_assert(str); + g_assert(_nm_utils_uuid_parse(str, &u)); + return &u; +} + +static void +_test_uuid(int uuid_type, + const char *expected_uuid, + const char *str, + gssize slen, + gpointer type_args) +{ + gs_free char *uuid_test = NULL; + + uuid_test = nm_utils_uuid_generate_from_string(str, slen, uuid_type, type_args); + + g_assert(uuid_test); + g_assert(nm_utils_is_uuid(uuid_test)); + + if (!nm_streq(uuid_test, expected_uuid)) { + g_error("UUID test failed: type=%d; text=%s, len=%lld, ns=%s, uuid=%s, expected=%s", + uuid_type, + str, + (long long) slen, + NM_IN_SET(uuid_type, NM_UTILS_UUID_TYPE_VERSION3, NM_UTILS_UUID_TYPE_VERSION5) + ? (((const char *) type_args) ?: "(all-zero)") + : (type_args ? "(unknown)" : "(null)"), + uuid_test, + expected_uuid); + } + + if (slen < 0) { + /* also test that passing slen==-1 yields the same result as passing strlen(str). */ + _test_uuid(uuid_type, expected_uuid, str, strlen(str), type_args); + } else if (str && slen == 0) { + /* also test if we accept NULL for slen==0 */ + _test_uuid(uuid_type, expected_uuid, NULL, 0, type_args); + } + + if (NM_IN_SET(uuid_type, NM_UTILS_UUID_TYPE_VERSION3, NM_UTILS_UUID_TYPE_VERSION5) + && !type_args) { + /* For version3 and version5, a missing @type_args is equal to UUID_NS_ZERO */ + _test_uuid(uuid_type, expected_uuid, str, slen, UUID_NS_ZERO); + } +} + +typedef struct { + const char *uuid3; + const char *uuid5; +} ExpectedUuids; + +static void +test_nm_utils_uuid_generate_from_string(void) +{ + const ExpectedUuids zero_uuids[] = { + { + .uuid3 = "19826852-5007-3022-a72a-212f66e9fac3", + .uuid5 = "b6c54489-38a0-5f50-a60a-fd8d76219cae", + }, + { + .uuid3 = "9153af2e-fc8e-34f3-9e8b-81f73b33d0cb", + .uuid5 = "11116e73-1c03-5de6-9130-5f9925ae8ab4", + }, + { + .uuid3 = "2f06a3ae-d78d-30d7-b898-088a0e0b76f6", + .uuid5 = "1087ebe8-1ef8-5d97-8873-735b4949004d", + }, + { + .uuid3 = "aca948e0-1468-3a51-9f2e-c688a484efd7", + .uuid5 = "7e57d004-2b97-5e7a-b45f-5387367791cd", + }, + { + .uuid3 = "b74e537a-53e8-3808-9abd-58546a6542bd", + .uuid5 = "1dd80df1-492c-5dc5-aec2-6bf0e104f923", + }, + { + .uuid3 = "1b00958a-7d76-3d08-8aba-c66c5828658c", + .uuid5 = "f797f61e-a392-5acf-af25-b46057f1c8e8", + }, + { + .uuid3 = "7ba18f7d-c9cf-3b48-a89e-ad79243135cc", + .uuid5 = "e02c9780-2fc5-5d57-b92f-4cc3a64bff16", + }, + { + .uuid3 = "9baf0978-1a60-35c5-9e9b-bec8d259fd4e", + .uuid5 = "94167980-f909-527e-a4af-bc3155f586d3", + }, + { + .uuid3 = "588668c0-7631-39c7-9976-c7d414adf7ba", + .uuid5 = "9e3eefda-b56e-56bd-8a3a-0b8009d4a536", + }, + { + .uuid3 = "8edb3613-9612-3b32-9dd7-0a01aa8ed453", + .uuid5 = "9b75648e-d38c-54e8-adee-1fb295a079c9", + }, + { + .uuid3 = "f3b34394-63a5-3773-9014-1f8a50d765b8", + .uuid5 = "dd56b598-9e74-58c3-b3e8-2c623780b8ed", + }, + { + .uuid3 = "0572965f-05b8-342b-b225-d5c29d449eee", + .uuid5 = "5666449a-fb7e-55b7-ae9f-0552e6513a10", + }, + { + .uuid3 = "6f7177c3-77b0-3f42-82a8-7031e25fcccf", + .uuid5 = "10b38db9-82fc-528e-9ddb-1f09b7dbf907", + }, + { + .uuid3 = "d1e0f845-bc1b-368c-b8c8-49ab0b9e486b", + .uuid5 = "85492596-9468-5845-9c7f-d4ae999cb751", + }, + { + .uuid3 = "46371ea3-c8a3-34d8-b2cf-2fa90bda4378", + .uuid5 = "22b1c0dd-aa5d-54a4-8768-5adfd0d112bd", + }, + { + .uuid3 = "f1e6b499-9b68-343b-a5c5-ece7acc49a68", + .uuid5 = "9cc429f8-200e-52a3-9e3b-ef134afa1e29", + }, + { + .uuid3 = "9ed06458-c712-31dd-aba5-6cf79879fabe", + .uuid5 = "3949f95c-5d76-5ee2-af60-8e2d8fcf649d", + }, + { + .uuid3 = "4ddd5cd7-bc83-36aa-909c-4e660f57c830", + .uuid5 = "0e994a02-069b-58fb-b3a4-d7dc94e90fca", + }, + { + .uuid3 = "335fa537-0909-395d-a696-6f41827dcbeb", + .uuid5 = "17db3a41-de9b-5c6b-904d-833943209b3c", + }, + { + .uuid3 = "dbd58444-05ad-3edd-adc7-4393ecbcb43c", + .uuid5 = "1bd906f2-05f9-5ab5-a39a-4c17a188f886", + }, + { + .uuid3 = "a1c62d82-d13c-361b-8f4e-ca91bc2f7fc5", + .uuid5 = "ce6550fd-95b7-57e4-9aa7-461522666be4", + }, + { + .uuid3 = "e943d83e-3f82-307f-81ed-b7a7bcd0743e", + .uuid5 = "04aa09ee-b420-57ac-8a23-5d99907fb0a1", + }, + { + .uuid3 = "cabf46dd-9f09-375c-8f6e-f2a8cf114709", + .uuid5 = "8ece2c62-0c31-5c55-b7c6-155381e3780e", + }, + { + .uuid3 = "19beddf3-f2fb-340f-96ac-4f394960b7a7", + .uuid5 = "5762a9f9-9a21-59ab-b0d2-2cb90027ef7f", + }, + { + .uuid3 = "08d835c2-f4ca-394c-ba7f-2494d8b60c6c", + .uuid5 = "23c8409d-4b5f-5b6a-b946-41e49bad6c78", + }, + { + .uuid3 = "3b8c6847-5331-35bf-9cd9-ced50e53cd7c", + .uuid5 = "e8e396be-95d5-5569-8edc-e0b64c2b7613", + }, + { + .uuid3 = "e601f160-484b-3254-8f3b-0a25c7203d8a", + .uuid5 = "bc8b3cbc-ad5b-5808-a1b0-e0f7a1ad68a3", + }, + { + .uuid3 = "e5e492ed-5349-379d-b7de-a370a51e44a3", + .uuid5 = "62c5ed3f-9afa-59ad-874f-a9dd8afc69d4", + }, + { + .uuid3 = "c40111f6-fe97-305e-bfce-7db730c3d2ec", + .uuid5 = "66877a72-7243-59ed-b9e3-b5023b6da9c2", + }, + { + .uuid3 = "21e18ea8-95c2-362b-9ca9-25d6a0ff2dff", + .uuid5 = "49a49eee-7e86-5d66-837a-8a8810cb5562", + }, + { + .uuid3 = "adab623b-1343-307f-80d8-58d005376ad9", + .uuid5 = "e4a2a7ed-3bf3-53cf-a2bb-154dbb39a38c", + }, + { + .uuid3 = "67e9fc7c-dafe-356d-ac1a-a63ce3f44813", + .uuid5 = "50cacfc9-f5d2-52dd-897c-a25a0927b816", + }, + { + .uuid3 = "36cc7f20-126c-3e40-94e7-737ac7486547", + .uuid5 = "ca629991-3f2b-5e86-9bb7-37a335f7d809", + }, + { + .uuid3 = "fe282996-ac5e-3d13-b478-5def30007a8e", + .uuid5 = "c1adf8a7-f72a-58ae-82d5-d18807f12e2e", + }, + { + .uuid3 = "3bfe339c-05ae-3233-a1a5-ebf1ead589db", + .uuid5 = "6120c3cd-24e1-5ce4-987b-f8bfee2e4633", + }, + { + .uuid3 = "d1d90bc7-da4a-3cd7-a7c8-a1a89765d8ee", + .uuid5 = "433d6a26-c319-5fcf-9a30-5ec6ad59d109", + }, + { + .uuid3 = "10b88a02-0102-359b-81e9-7e3b0ff7d25e", + .uuid5 = "77d228d9-1b96-59e2-a07e-a8fdd4f62884", + }, + { + .uuid3 = "7da5e4f2-6df0-3aca-a1b0-b7f8b1340e1d", + .uuid5 = "698259bf-a32b-5e00-9ec6-88b12278c4ad", + }, + { + .uuid3 = "cbe24d98-ca20-3058-86b6-24a6b36ceff0", + .uuid5 = "60dbca63-704f-5666-9f64-f4e1a630c4aa", + }, + { + .uuid3 = "04d84e6a-b793-3993-afbf-bae7cfc42b49", + .uuid5 = "79d63ec0-a39d-557d-8299-f4c97acfadc3", + }, + { + .uuid3 = "fdd157d8-a537-350a-9cc9-1930e8666c63", + .uuid5 = "7df7f75e-a146-5a76-828b-bac052db312b", + }, + { + .uuid3 = "0bea36bb-24a7-3ee6-a98d-116433c14cd4", + .uuid5 = "2bcca2e9-2879-53e3-b09d-cbbfd58771b2", + }, + { + .uuid3 = "52b040a4-1b84-32d2-b758-f82386f7e0f0", + .uuid5 = "cb7bdca3-e9f7-50cd-b72e-73cb9ff24f62", + }, + { + .uuid3 = "0f0a4e26-e034-3021-acf2-4e886af43092", + .uuid5 = "8e428e2b-5da3-5368-b760-5ca07ccbd819", + }, + { + .uuid3 = "819d3cd1-afe5-3e4a-9f0c-945e25d09879", + .uuid5 = "f340ef4d-139c-567a-b0fc-7c495336674e", + }, + { + .uuid3 = "e7df1a3b-c9f8-3e5a-88d6-ba72b2a0f27b", + .uuid5 = "7e3f5fd2-3c93-58d6-9f35-6e0192445b11", + }, + { + .uuid3 = "0854bedf-74ba-3f2b-b823-dc2c90d27c76", + .uuid5 = "bc112b6b-c5de-5ee9-b816-808792743a20", + }, + { + .uuid3 = "a1b8c3ba-f821-32ef-a3fd-b97b3855efa8", + .uuid5 = "47f8f82d-9fcd-553c-90c5-3f3cb3ad00ad", + }, + { + .uuid3 = "9458f819-079b-3033-9430-ba10f576c067", + .uuid5 = "bee5c091-5f01-51fa-86bb-e9488fd3b4da", + }, + { + .uuid3 = "8e1f240a-e386-3e00-866a-6f9da1e3503f", + .uuid5 = "8ea92cea-d741-566f-a44a-d51e65b4c5e4", + }, + }; + const ExpectedUuids dns_uuids[] = { + { + .uuid3 = "4385125b-dd1e-3025-880f-3311517cc8d5", + .uuid5 = "6af613b6-569c-5c22-9c37-2ed93f31d3af", + }, + { + .uuid3 = "afd0b036-625a-3aa8-b639-9dc8c8fff0ff", + .uuid5 = "b04965e6-a9bb-591f-8f8a-1adcb2c8dc39", + }, + { + .uuid3 = "9c45c2f1-1761-3daa-ad31-1ff8703ae846", + .uuid5 = "4b166dbe-d99d-5091-abdd-95b83330ed3a", + }, + { + .uuid3 = "15e0ba07-10e4-3d7f-aaff-c00fed873c88", + .uuid5 = "98123fde-012f-5ff3-8b50-881449dac91a", + }, + { + .uuid3 = "bc27b4db-bc0f-34f9-ae8e-4b72f2d51b60", + .uuid5 = "6ed955c6-506a-5343-9be4-2c0afae02eef", + }, + { + .uuid3 = "7586bfed-b8b8-3bb3-9c95-09a4a79dc0f7", + .uuid5 = "c8691da2-158a-5ed6-8537-0e6f140801f2", + }, + { + .uuid3 = "881430b6-8d28-3175-b87d-e81f2f5978c6", + .uuid5 = "a6c4fc8f-6950-51de-a9ae-2c519c465071", + }, + { + .uuid3 = "24075675-98ae-354e-89ca-0126a9ad36e3", + .uuid5 = "a9f96b98-dd44-5216-ab0d-dbfc6b262edf", + }, + { + .uuid3 = "2c269ea4-dbfd-32dd-9bd7-a5c22677d18b", + .uuid5 = "e99caacd-6c45-5906-bd9f-b79e62f25963", + }, + { + .uuid3 = "44eb0948-118f-3f28-87e4-f61c8f889aba", + .uuid5 = "e4d80b30-151e-51b5-9f4f-18a3b82718e6", + }, + { + .uuid3 = "fc72beeb-f790-36ee-a73d-33888c9d8880", + .uuid5 = "0159d6c7-973f-5e7a-a9a0-d195d0ea6fe2", + }, + { + .uuid3 = "1e46afa2-6176-3cd3-9750-3015846723df", + .uuid5 = "7fef88f7-411d-5669-b42d-bf5fc7f9b58b", + }, + { + .uuid3 = "0042b01d-95bd-343f-bd9f-3186bfd63508", + .uuid5 = "52524d6e-10dc-5261-aa36-8b2efcbaa5f0", + }, + { + .uuid3 = "115ff52f-d605-3b4b-98fe-c0ea57f4930c", + .uuid5 = "91c274f2-9a0d-5ce6-ac3d-7529f452df21", + }, + { + .uuid3 = "ed0221e8-ac7d-393b-821d-25183567885b", + .uuid5 = "0ff1e264-520d-543a-87dd-181a491e667e", + }, + { + .uuid3 = "508ef333-85a6-314c-bcf3-17ddc32b2216", + .uuid5 = "23986425-d3a5-5e13-8bab-299745777a8d", + }, + { + .uuid3 = "a4715ee0-524a-37cc-beb2-a0b5030757b7", + .uuid5 = "c15b38c9-9a3e-543c-a703-dd742f25b4d5", + }, + { + .uuid3 = "d1c72756-aaec-3470-a2f2-97415f44d72f", + .uuid5 = "db680066-c83d-5ed7-89a4-1d79466ea62d", + }, + { + .uuid3 = "7aec2f01-586e-3d53-b8f3-6cf7e6b649a4", + .uuid5 = "cadb7952-2bba-5609-88d4-8e47ec4e7920", + }, + { + .uuid3 = "3d234b88-8d6f-319a-91ea-edb6059fc825", + .uuid5 = "35140057-a2a4-5adb-a500-46f8ed8b66a9", + }, + { + .uuid3 = "d2568554-93ec-30c7-9e15-f383be19e5bb", + .uuid5 = "66e549b7-01e2-5d07-98d5-430f74d8d3b2", + }, + { + .uuid3 = "800e59a7-dd0f-3114-8e58-ab7e213895ca", + .uuid5 = "292c8e99-2378-55aa-83d8-350e0ac3f1cc", + }, + { + .uuid3 = "3b7d03f0-e067-3d72-84f4-e410ac36ef57", + .uuid5 = "0e3b230a-0509-55d8-96a0-9875f387a2be", + }, + { + .uuid3 = "8762be68-de95-391a-94a0-c5fd0446e037", + .uuid5 = "4c507660-a83b-55c0-9b2b-83eccb07723d", + }, + { + .uuid3 = "2bd8b4c9-01af-3cd0-aced-94ee6e2004b8", + .uuid5 = "a1b9b633-da11-58be-b1a9-5cfa2848f186", + }, + { + .uuid3 = "a627d6a4-394a-33f5-b68e-22bfb6488d01", + .uuid5 = "c2708a8b-120a-56f5-a30d-990048af87cc", + }, + { + .uuid3 = "6a592510-17d9-3925-b321-4a8d4927f8d0", + .uuid5 = "e7263999-68b6-5a23-b530-af25b7efd632", + }, + { + .uuid3 = "9ee72491-59c4-333c-bb93-fe733a842fdb", + .uuid5 = "ce1ae2d5-3454-5952-97ff-36ff935bcfe9", + }, + { + .uuid3 = "2591c62c-0a9d-3c28-97bc-fa0401556a3c", + .uuid5 = "33677b87-bc8d-5ff6-9a25-fe60225e4bf0", + }, + { + .uuid3 = "7912be1e-4562-373b-92e2-3d6d2123bc8e", + .uuid5 = "ed2305ae-e8f9-5387-b860-3d80ae6c02f7", + }, + { + .uuid3 = "09370cda-89a4-3a48-b592-9c0486e0d5e4", + .uuid5 = "604ed872-ae2d-5d91-8e3e-572f3a3aaaa5", + }, + { + .uuid3 = "de5980d3-a137-373c-850b-ca3e5f100779", + .uuid5 = "8f8173d9-2f8d-5636-a693-24d9f79ba651", + }, + { + .uuid3 = "9441501d-f633-365a-8955-9df443edc762", + .uuid5 = "36eb8d4d-b854-51f1-9fdf-3735964225d5", + }, + { + .uuid3 = "434ada18-13ce-3c08-8b40-a1a1ae030569", + .uuid5 = "3493b6ca-f84b-56a9-97cc-c0bd1c46c4c0", + }, + { + .uuid3 = "a13b6160-bd23-3710-a150-41d800dd30b4", + .uuid5 = "f413ea13-fcd9-5b44-9d22-1fa1f7b063a5", + }, + { + .uuid3 = "73a67c12-c5f0-3288-ad6a-c78aea0917b0", + .uuid5 = "f468d924-d23b-56c2-b90f-3d1cf4b45337", + }, + { + .uuid3 = "a126ee4f-a222-357d-b71b-7d3f226c559f", + .uuid5 = "8828c9d6-ed76-5c09-bf64-ba9e9cd90896", + }, + { + .uuid3 = "48f4f36b-b015-3137-9b6e-351bb175c7f7", + .uuid5 = "facb7618-55ca-5c30-9cba-fd567b6c0611", + }, + { + .uuid3 = "3fe8f6a3-fe4a-3487-89d6-dd06c6ad02e3", + .uuid5 = "96f3de0e-6412-5434-b406-67ef3352ab85", + }, + { + .uuid3 = "d68fa2d4-adc9-3b20-ac77-42585cd1d59f", + .uuid5 = "9ebacb89-40ab-52b3-93a2-9054611d8f55", + }, + { + .uuid3 = "819f86a3-31d5-3e72-a83e-142c3a3e4832", + .uuid5 = "681046ff-9129-5ade-b11c-769864e02184", + }, + { + .uuid3 = "9957b433-ddc8-3113-a3e6-5512cf13dab1", + .uuid5 = "c13d0b5d-1ca3-57b6-a23f-8586bca44928", + }, + { + .uuid3 = "5aab6e0c-b7d3-379c-92e3-2bfbb5572511", + .uuid5 = "7c411b5e-9d3f-50b5-9c28-62096e41c4ed", + }, + { + .uuid3 = "11c8ff30-3a7d-3547-80a7-d61b8abeeda8", + .uuid5 = "f825aafe-6696-5121-b263-6b2c408b7f43", + }, + { + .uuid3 = "98799b9f-1c5e-30b3-930f-e412b862cbe4", + .uuid5 = "f2b4caea-61c3-5bed-8ce7-d8b9d16e129e", + }, + { + .uuid3 = "9bdf2544-31d8-3555-94b0-6a749118a996", + .uuid5 = "3593855a-6557-5736-8cab-172c6987f949", + }, + { + .uuid3 = "ddcfb9b3-e990-3985-9021-546a2711e7e5", + .uuid5 = "36392431-d554-5385-b876-7bc6e1cb26b3", + }, + { + .uuid3 = "190d7a78-1484-3136-80a6-40f28852785c", + .uuid5 = "7e645493-0898-5501-8155-e8578b4f5224", + }, + { + .uuid3 = "6ed693e4-7dc0-3210-856b-a6eb4cc73e13", + .uuid5 = "14dc6a81-0491-5683-baaf-7582a61c5798", + }, + { + .uuid3 = "b6a14b21-e73a-3ce2-9076-a804c434f5c6", + .uuid5 = "883e0a9c-e3b3-5f9c-8073-2913cbbb99ec", + }, + }; + char i_str[30]; + guint i; + + _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, "d41d8cd9-8f00-b204-e980-0998ecf8427e", "", -1, NULL); + _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, "0cc175b9-c0f1-b6a8-31c3-99e269772661", "a", -1, NULL); + _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, "098f6bcd-4621-d373-cade-4e832627b4f6", "test", -1, NULL); + _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, "70350f60-27bc-e371-3f6b-76473084309b", "a\0b", 3, NULL); + _test_uuid(NM_UTILS_UUID_TYPE_LEGACY, + "59c0547b-7fe2-1c15-2cce-e328e8bf6742", + "/etc/NetworkManager/system-connections/em1", + -1, + NULL); + + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, "4ae71336-e44b-39bf-b9d2-752e234818a5", "", -1, NULL); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, "0531103a-d8fc-3dd4-b972-d98e4750994e", "a", -1, NULL); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "96e17d7a-ac89-38cf-95e1-bf5098da34e1", + "test", + -1, + NULL); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "8156568e-4ae6-3f34-a93e-18e2c6cbbf78", + "a\0b", + 3, + NULL); + + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "c87ee674-4ddc-3efe-a74e-dfe25da5d7b3", + "", + -1, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "4c104dd0-4821-30d5-9ce3-0e7a1f8b7c0d", + "a", + -1, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "45a113ac-c7f2-30b0-90a5-a399ab912716", + "test", + -1, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "002a0ada-f547-375a-bab5-896a11d1927e", + "a\0b", + 3, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "9a75f5f2-195e-31a9-9d07-8c18b5d3b285", + "test123", + -1, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "ec794efe-a384-3b11-a0b6-ec8995bc6acc", + "x", + -1, + UUID_NS_DNS); + + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "a7650b9f-f19f-5300-8a13-91160ea8de2c", + "a\0b", + 3, + NULL); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "4f3f2898-69e3-5a0d-820a-c4e87987dbce", + "a", + -1, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "05b16a01-46c6-56dd-bd6e-c6dfb4a1427a", + "x", + -1, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "c9ed566a-6b79-5d3a-b2b7-96a936b48cf3", + "test123", + -1, + UUID_NS_DNS); + + for (i = 0; i < G_N_ELEMENTS(zero_uuids); i++) { + nm_sprintf_buf(i_str, "%u", i), + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, zero_uuids[i].uuid3, i_str, -1, NULL); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, zero_uuids[i].uuid5, i_str, -1, NULL); + } + for (i = 0; i < G_N_ELEMENTS(dns_uuids); i++) { + nm_sprintf_buf(i_str, "%u", i), + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, dns_uuids[i].uuid3, i_str, -1, UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, dns_uuids[i].uuid5, i_str, -1, UUID_NS_DNS); + } + + /* examples from cpython unit tests: */ + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "6fa459ea-ee8a-3ca4-894e-db77e160355e", + "python.org", + -1, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "886313e1-3b8a-5372-9b90-0c9aee199e5d", + "python.org", + -1, + UUID_NS_DNS); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "9fe8e8c4-aaa8-32a9-a55c-4535a88b748d", + "http://python.org/", + -1, + UUID_NS_URL); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "4c565f0d-3f5a-5890-b41b-20cf47701c5e", + "http://python.org/", + -1, + UUID_NS_URL); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "dd1a1cef-13d5-368a-ad82-eca71acd4cd1", + "1.3.6.1", + -1, + UUID_NS_OID); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "1447fa61-5277-5fef-a9b3-fbc6e44f4af3", + "1.3.6.1", + -1, + UUID_NS_OID); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION3, + "658d3002-db6b-3040-a1d1-8ddd7d189a4d", + "c=ca", + -1, + UUID_NS_X500); + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "cc957dd1-a972-5349-98cd-874190002798", + "c=ca", + -1, + UUID_NS_X500); + + _test_uuid(NM_UTILS_UUID_TYPE_VERSION5, + "74738ff5-5367-5958-9aee-98fffdcd1876", + "www.example.org", + -1, + UUID_NS_DNS); +} + +/*****************************************************************************/ + +static void +__test_uuid(const char *expected_uuid, const char *str, gssize slen, char *uuid_test) +{ + g_assert(uuid_test); + g_assert(nm_utils_is_uuid(uuid_test)); + + if (strcmp(uuid_test, expected_uuid)) { + g_error("UUID test failed (1): text=%s, len=%lld, expected=%s, uuid_test=%s", + str, + (long long) slen, + expected_uuid, + uuid_test); + } + g_free(uuid_test); + + uuid_test = nm_utils_uuid_generate_from_string(str, + slen, + NM_UTILS_UUID_TYPE_VERSION3, + NM_UTILS_UUID_NS); + + g_assert(uuid_test); + g_assert(nm_utils_is_uuid(uuid_test)); + + if (strcmp(uuid_test, expected_uuid)) { + g_error("UUID test failed (2): text=%s; len=%lld, expected=%s, uuid2=%s", + str, + (long long) slen, + expected_uuid, + uuid_test); + } + g_free(uuid_test); +} + +#define _test_uuid(expected_uuid, str, strlen, ...) \ + __test_uuid(expected_uuid, str, strlen, _nm_utils_uuid_generate_from_strings(__VA_ARGS__, NULL)) + +static void +test_nm_utils_uuid_generate_from_strings(void) +{ + const NMUuid uuid0 = {}; + + g_assert_cmpmem(&uuid0, sizeof(uuid0), _uuid("00000000-0000-0000-0000-000000000000"), 16); + + g_assert(nm_utils_uuid_is_null(NULL)); + g_assert(nm_utils_uuid_is_null(&uuid0)); + g_assert(nm_utils_uuid_is_null(_uuid("00000000-0000-0000-0000-000000000000"))); + g_assert(!nm_utils_uuid_is_null(_uuid("10000000-0000-0000-0000-000000000000"))); + + _test_uuid("b07c334a-399b-32de-8d50-58e4e08f98e3", "", 0, NULL); + _test_uuid("b8a426cb-bcb5-30a3-bd8f-6786fea72df9", "\0", 1, ""); + _test_uuid("12a4a982-7aae-39e1-951e-41aeb1250959", "a\0", 2, "a"); + _test_uuid("69e22c7e-f89f-3a43-b239-1cb52ed8db69", "aa\0", 3, "aa"); + _test_uuid("59829fd3-5ad5-3d90-a7b0-4911747e4088", "\0\0", 2, "", ""); + _test_uuid("01ad0e06-6c50-3384-8d86-ddab81421425", "a\0\0", 3, "a", ""); + _test_uuid("e1ed8647-9ed3-3ec8-8c6d-e8204524d71d", "aa\0\0", 4, "aa", ""); + _test_uuid("fb1c7cd6-275c-3489-9382-83b900da8af0", "\0a\0", 3, "", "a"); + _test_uuid("5d79494e-c4ba-31a6-80a2-d6016ccd7e17", "a\0a\0", 4, "a", "a"); + _test_uuid("fd698d86-1b60-3ebe-855f-7aada9950a8d", "aa\0a\0", 5, "aa", "a"); + _test_uuid("8c573b48-0f01-30ba-bb94-c5f59f4fe517", "\0aa\0", 4, "", "aa"); + _test_uuid("2bdd3d46-eb83-3c53-a41b-a724d04b5544", "a\0aa\0", 5, "a", "aa"); + _test_uuid("13d4b780-07c1-3ba7-b449-81c4844ef039", "aa\0aa\0", 6, "aa", "aa"); + _test_uuid("dd265bf7-c05a-3037-9939-b9629858a477", "a\0b\0", 4, "a", "b"); +} + +/*****************************************************************************/ + +static void +test_nm_utils_ascii_str_to_int64_check(const char *str, + guint base, + gint64 min, + gint64 max, + gint64 fallback, + int exp_errno, + gint64 exp_val) +{ + gint64 v; + + errno = 1; + v = _nm_utils_ascii_str_to_int64(str, base, min, max, fallback); + g_assert_cmpint(errno, ==, exp_errno); + g_assert_cmpint(v, ==, exp_val); +} + +static void +test_nm_utils_ascii_str_to_int64_do(const char *str, + guint base, + gint64 min, + gint64 max, + gint64 fallback, + int exp_errno, + gint64 exp_val) +{ + const char * sign = ""; + const char * val; + static const char *whitespaces[] = { + "", + " ", + "\r\n\t", + " \r\n\t ", + " \r\n\t \t\r\n\t", + NULL, + }; + static const char *nulls[] = { + "", + "0", + "00", + "0000", + "0000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000", + NULL, + }; + const char **ws_pre, **ws_post, **null; + guint i; + + if (str == NULL || exp_errno != 0) { + test_nm_utils_ascii_str_to_int64_check(str, base, min, max, fallback, exp_errno, exp_val); + return; + } + + if (strncmp(str, "-", 1) == 0) + sign = "-"; + + val = str + strlen(sign); + + for (ws_pre = whitespaces; *ws_pre; ws_pre++) { + for (ws_post = whitespaces; *ws_post; ws_post++) { + for (null = nulls; *null; null++) { + for (i = 0;; i++) { + char * s; + const char *str_base = ""; + + if (base == 16) { + if (i == 1) + str_base = "0x"; + else if (i > 1) + break; + } else if (base == 8) { + if (i == 1) + str_base = "0"; + else if (i > 1) + break; + } else if (base == 0) { + if (i > 0) + break; + /* with base==0, a leading zero would be interpreted as octal. Only test without *null */ + if ((*null)[0]) + break; + } else { + if (i > 0) + break; + } + + s = g_strdup_printf("%s%s%s%s%s%s", + *ws_pre, + sign, + str_base, + *null, + val, + *ws_post); + + test_nm_utils_ascii_str_to_int64_check(s, + base, + min, + max, + fallback, + exp_errno, + exp_val); + g_free(s); + } + } + } + } +} + +static void +test_nm_utils_ascii_str_to_int64(void) +{ + test_nm_utils_ascii_str_to_int64_do(NULL, 10, 0, 10000, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do("", 10, 0, 10000, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do("1x", 10, 0, 10000, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do("4711", 10, 0, 10000, -1, 0, 4711); + test_nm_utils_ascii_str_to_int64_do("10000", 10, 0, 10000, -1, 0, 10000); + test_nm_utils_ascii_str_to_int64_do("10001", 10, 0, 10000, -1, ERANGE, -1); + test_nm_utils_ascii_str_to_int64_do("FF", 16, 0, 10000, -1, 0, 255); + test_nm_utils_ascii_str_to_int64_do("FF", 10, 0, 10000, -2, EINVAL, -2); + test_nm_utils_ascii_str_to_int64_do("9223372036854775807", + 10, + 0, + G_MAXINT64, + -2, + 0, + G_MAXINT64); + test_nm_utils_ascii_str_to_int64_do("7FFFFFFFFFFFFFFF", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64); + test_nm_utils_ascii_str_to_int64_do("9223372036854775808", 10, 0, G_MAXINT64, -2, ERANGE, -2); + test_nm_utils_ascii_str_to_int64_do("-9223372036854775808", + 10, + G_MININT64, + 0, + -2, + 0, + G_MININT64); + test_nm_utils_ascii_str_to_int64_do("-9223372036854775808", + 10, + G_MININT64 + 1, + 0, + -2, + ERANGE, + -2); + test_nm_utils_ascii_str_to_int64_do("-9223372036854775809", 10, G_MININT64, 0, -2, ERANGE, -2); + test_nm_utils_ascii_str_to_int64_do("1.0", 10, 1, 1, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do("1x0", 16, -10, 10, -100, EINVAL, -100); + test_nm_utils_ascii_str_to_int64_do("0", 16, -10, 10, -100, 0, 0); + test_nm_utils_ascii_str_to_int64_do("10001111", 2, -1000, 1000, -100000, 0, 0x8F); + test_nm_utils_ascii_str_to_int64_do("-10001111", 2, -1000, 1000, -100000, 0, -0x8F); + test_nm_utils_ascii_str_to_int64_do("1111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7F); + test_nm_utils_ascii_str_to_int64_do("111111111111111", + 2, + G_MININT64, + G_MAXINT64, + -1, + 0, + 0x7FFF); + test_nm_utils_ascii_str_to_int64_do("11111111111111111111111111111111111111111111111", + 2, + G_MININT64, + G_MAXINT64, + -1, + 0, + 0x7FFFFFFFFFFF); + test_nm_utils_ascii_str_to_int64_do( + "111111111111111111111111111111111111111111111111111111111111111", + 2, + G_MININT64, + G_MAXINT64, + -1, + 0, + 0x7FFFFFFFFFFFFFFF); + test_nm_utils_ascii_str_to_int64_do( + "100000000000000000000000000000000000000000000000000000000000000", + 2, + G_MININT64, + G_MAXINT64, + -1, + 0, + 0x4000000000000000); + test_nm_utils_ascii_str_to_int64_do( + "1000000000000000000000000000000000000000000000000000000000000000", + 2, + G_MININT64, + G_MAXINT64, + -1, + ERANGE, + -1); + test_nm_utils_ascii_str_to_int64_do( + "-100000000000000000000000000000000000000000000000000000000000000", + 2, + G_MININT64, + G_MAXINT64, + -1, + 0, + -0x4000000000000000); + test_nm_utils_ascii_str_to_int64_do( + "111111111111111111111111111111111111111111111111111111111111111", + 2, + G_MININT64, + G_MAXINT64, + -1, + 0, + 0x7FFFFFFFFFFFFFFF); + test_nm_utils_ascii_str_to_int64_do( + "-100000000000000000000000000000000000000000000000000000000000000", + 2, + G_MININT64, + G_MAXINT64, + -1, + 0, + -0x4000000000000000); + test_nm_utils_ascii_str_to_int64_do("0x70", 10, G_MININT64, G_MAXINT64, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do("4711", 0, G_MININT64, G_MAXINT64, -1, 0, 4711); + test_nm_utils_ascii_str_to_int64_do("04711", 0, G_MININT64, G_MAXINT64, -1, 0, 04711); + test_nm_utils_ascii_str_to_int64_do("0x4711", 0, G_MININT64, G_MAXINT64, -1, 0, 0x4711); + test_nm_utils_ascii_str_to_int64_do("080", 0, G_MININT64, G_MAXINT64, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do("070", 0, G_MININT64, G_MAXINT64, -1, 0, 7 * 8); + test_nm_utils_ascii_str_to_int64_do("0x70", 0, G_MININT64, G_MAXINT64, -1, 0, 0x70); + + g_assert_cmpint(21, ==, _nm_utils_ascii_str_to_int64("025", 0, 0, 1000, -1)); + g_assert_cmpint(21, ==, _nm_utils_ascii_str_to_int64("0025", 0, 0, 1000, -1)); + g_assert_cmpint(25, ==, _nm_utils_ascii_str_to_int64("025", 10, 0, 1000, -1)); + g_assert_cmpint(25, ==, _nm_utils_ascii_str_to_int64("0025", 10, 0, 1000, -1)); +} + +/*****************************************************************************/ + +static void +test_nm_utils_strstrdictkey(void) +{ +#define _VALUES_STATIC(_v1, _v2) \ + { \ + .v1 = _v1, .v2 = _v2, .v_static = _nm_utils_strstrdictkey_static(_v1, _v2), \ + } + const struct { + const char * v1; + const char * v2; + NMUtilsStrStrDictKey *v_static; + } * val1, *val2, + values[] = { + {NULL, NULL}, + {"", NULL}, + {NULL, ""}, + {"a", NULL}, + {NULL, "a"}, + _VALUES_STATIC("", ""), + _VALUES_STATIC("a", ""), + _VALUES_STATIC("", "a"), + _VALUES_STATIC("a", "b"), + }; + guint i, j; + + for (i = 0; i < G_N_ELEMENTS(values); i++) { + gs_free NMUtilsStrStrDictKey *key1 = NULL; + + val1 = &values[i]; + + key1 = _nm_utils_strstrdictkey_create(val1->v1, val1->v2); + if (val1->v_static) { + g_assert(_nm_utils_strstrdictkey_equal(key1, val1->v_static)); + g_assert(_nm_utils_strstrdictkey_equal(val1->v_static, key1)); + g_assert_cmpint(_nm_utils_strstrdictkey_hash(key1), + ==, + _nm_utils_strstrdictkey_hash(val1->v_static)); + } + + for (j = 0; j < G_N_ELEMENTS(values); j++) { + gs_free NMUtilsStrStrDictKey *key2 = NULL; + + val2 = &values[j]; + key2 = _nm_utils_strstrdictkey_create(val2->v1, val2->v2); + if (i != j) { + g_assert(!_nm_utils_strstrdictkey_equal(key1, key2)); + g_assert(!_nm_utils_strstrdictkey_equal(key2, key1)); + } + } + } +} + +/*****************************************************************************/ + +static guint +_g_strv_length(gconstpointer arr) +{ + return arr ? g_strv_length((char **) arr) : 0; +} + +static void +test_nm_ptrarray_len(void) +{ +#define _PTRARRAY_cmp(len, arr) \ + G_STMT_START \ + { \ + g_assert_cmpint(len, ==, NM_PTRARRAY_LEN(arr)); \ + g_assert_cmpint(len, ==, _g_strv_length(arr)); \ + } \ + G_STMT_END +#define _PTRARRAY_LEN0(T) \ + G_STMT_START \ + { \ + T ** vnull = NULL; \ + T *const * vnull1 = NULL; \ + T *const *const vnull2 = NULL; \ + T * v0[] = {NULL}; \ + T *const * v01 = v0; \ + T *const *const v02 = v0; \ + T **const v03 = v0; \ + \ + _PTRARRAY_cmp(0, vnull); \ + _PTRARRAY_cmp(0, vnull1); \ + _PTRARRAY_cmp(0, vnull2); \ + _PTRARRAY_cmp(0, v0); \ + _PTRARRAY_cmp(0, v01); \ + _PTRARRAY_cmp(0, v02); \ + _PTRARRAY_cmp(0, v03); \ + } \ + G_STMT_END + + _PTRARRAY_LEN0(char); + _PTRARRAY_LEN0(const char); + _PTRARRAY_LEN0(int); + _PTRARRAY_LEN0(const int); + _PTRARRAY_LEN0(void *); + _PTRARRAY_LEN0(void); + _PTRARRAY_LEN0(const void); + +#define _PTRARRAY_LENn(T) \ + G_STMT_START \ + { \ + T x[5] = {0}; \ + \ + T * v1[] = {&x[0], NULL}; \ + T *const * v11 = v1; \ + T *const *const v12 = v1; \ + T **const v13 = v1; \ + \ + T * v2[] = {&x[0], &x[1], NULL}; \ + T *const * v21 = v2; \ + T *const *const v22 = v2; \ + T **const v23 = v2; \ + \ + _PTRARRAY_cmp(1, v1); \ + _PTRARRAY_cmp(1, v11); \ + _PTRARRAY_cmp(1, v12); \ + _PTRARRAY_cmp(1, v13); \ + \ + _PTRARRAY_cmp(2, v2); \ + _PTRARRAY_cmp(2, v21); \ + _PTRARRAY_cmp(2, v22); \ + _PTRARRAY_cmp(2, v23); \ + } \ + G_STMT_END + + _PTRARRAY_LENn(char); + _PTRARRAY_LENn(const char); + _PTRARRAY_LENn(int); + _PTRARRAY_LENn(const int); + _PTRARRAY_LENn(void *); +} + +/*****************************************************************************/ + +static void +test_nm_utils_dns_option_validate_do(char * option, + gboolean ipv6, + const NMUtilsDNSOptionDesc *descs, + gboolean exp_result, + char * exp_name, + gboolean exp_value) +{ + char * name; + long value = 0; + gboolean result; + + result = _nm_utils_dns_option_validate(option, &name, &value, ipv6, descs); + + g_assert(result == exp_result); + g_assert_cmpstr(name, ==, exp_name); + g_assert(value == exp_value); + + g_free(name); +} + +static const NMUtilsDNSOptionDesc opt_descs[] = { + /* name num ipv6 */ + {"opt1", FALSE, FALSE}, + {"opt2", TRUE, FALSE}, + {"opt3", FALSE, TRUE}, + {"opt4", TRUE, TRUE}, + {NULL, FALSE, FALSE}}; + +static void +test_nm_utils_dns_option_validate(void) +{ + /* opt ipv6 descs result name value */ + test_nm_utils_dns_option_validate_do("", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do(":", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do(":1", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do(":val", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt", FALSE, NULL, TRUE, "opt", -1); + test_nm_utils_dns_option_validate_do("opt:", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt:12", FALSE, NULL, TRUE, "opt", 12); + test_nm_utils_dns_option_validate_do("opt:12 ", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt:val", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt:2val", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt:2:3", FALSE, NULL, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt-6", FALSE, NULL, TRUE, "opt-6", -1); + + test_nm_utils_dns_option_validate_do("opt1", FALSE, opt_descs, TRUE, "opt1", -1); + test_nm_utils_dns_option_validate_do("opt1", TRUE, opt_descs, TRUE, "opt1", -1); + test_nm_utils_dns_option_validate_do("opt1:3", FALSE, opt_descs, FALSE, NULL, -1); + + test_nm_utils_dns_option_validate_do("opt2", FALSE, opt_descs, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt2:5", FALSE, opt_descs, TRUE, "opt2", 5); + + test_nm_utils_dns_option_validate_do("opt3", FALSE, opt_descs, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt3", TRUE, opt_descs, TRUE, "opt3", -1); + + test_nm_utils_dns_option_validate_do("opt4", FALSE, opt_descs, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt4", TRUE, opt_descs, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt4:40", FALSE, opt_descs, FALSE, NULL, -1); + test_nm_utils_dns_option_validate_do("opt4:40", TRUE, opt_descs, TRUE, "opt4", 40); +} + +static void +test_nm_utils_dns_option_find_idx(void) +{ + GPtrArray *options; + + options = g_ptr_array_new(); + + g_ptr_array_add(options, "debug"); + g_ptr_array_add(options, "timeout:5"); + g_ptr_array_add(options, "edns0"); + + g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "debug"), ==, 0); + g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "debug:1"), ==, 0); + g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout"), ==, 1); + g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout:5"), ==, 1); + g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout:2"), ==, 1); + g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "edns0"), ==, 2); + g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "rotate"), ==, -1); + g_assert_cmpint(_nm_utils_dns_option_find_idx(options, ""), ==, -1); + + g_ptr_array_free(options, TRUE); +} + +/*****************************************************************************/ + +static void +_json_config_check_valid(const char *conf, gboolean expected) +{ + gs_free_error GError *error = NULL; + gboolean res; + + res = nm_utils_is_json_object(conf, &error); + g_assert_cmpint(res, ==, expected); + g_assert(res || error); +} + +static void +test_nm_utils_check_valid_json(void) +{ + _json_config_check_valid(NULL, FALSE); + _json_config_check_valid("", FALSE); + + /* Without JSON library everything except empty string is considered valid */ + nmtst_json_vt_reset(FALSE); + _json_config_check_valid("{ }", TRUE); + _json_config_check_valid("{'%!-a1} ", TRUE); + _json_config_check_valid(" {'%!-a1}", TRUE); + _json_config_check_valid("{'%!-a1", FALSE); + + if (nmtst_json_vt_reset(TRUE)) { + _json_config_check_valid("{ }", TRUE); + _json_config_check_valid("{ \"a\" : 1 }", TRUE); + _json_config_check_valid("{ \"a\" : }", FALSE); + } +} + +static void +_team_config_equal_check(const char *conf1, + const char *conf2, + gboolean port_config, + gboolean expected) +{ + nm_auto_free_team_setting NMTeamSetting *team_a = NULL; + nm_auto_free_team_setting NMTeamSetting *team_b = NULL; + gboolean is_same; + + if (nmtst_get_rand_bool()) + NM_SWAP(&conf1, &conf2); + + if (!nm_streq0(conf1, conf2)) { + _team_config_equal_check(conf1, conf1, port_config, TRUE); + _team_config_equal_check(conf2, conf2, port_config, TRUE); + } + + team_a = nm_team_setting_new(port_config, conf1); + team_b = nm_team_setting_new(port_config, conf2); + + is_same = (nm_team_setting_cmp(team_a, team_b, TRUE) == 0); + g_assert_cmpint(is_same, ==, expected); + + if (nm_streq0(conf1, conf2)) { + g_assert_cmpint(nm_team_setting_cmp(team_a, team_b, FALSE), ==, 0); + g_assert(expected); + } else + g_assert_cmpint(nm_team_setting_cmp(team_a, team_b, FALSE), !=, 0); +} + +static void +test_nm_utils_team_config_equal(void) +{ + int with_json_vt; + + for (with_json_vt = 0; with_json_vt < 2; with_json_vt++) { + const NMJsonVt *vt; + + vt = nmtst_json_vt_reset(!!with_json_vt); + + _team_config_equal_check("", "", TRUE, TRUE); + _team_config_equal_check("", " ", TRUE, TRUE); + _team_config_equal_check("{}", "{ }", TRUE, TRUE); + _team_config_equal_check("{}", "{", TRUE, TRUE); + _team_config_equal_check("{ \"a\": 1 }", "{ \"a\": 1 }", TRUE, TRUE); + _team_config_equal_check("{ \"a\": 1 }", "{ \"a\": 1 }", TRUE, TRUE); + + /* team config */ + _team_config_equal_check("{ }", "{ \"runner\" : { \"name\" : \"random\"} }", FALSE, !vt); + _team_config_equal_check("{ \"runner\" : { \"name\" : \"roundrobin\"} }", + "{ \"runner\" : { \"name\" : \"random\"} }", + FALSE, + !vt); + _team_config_equal_check("{ \"runner\" : { \"name\" : \"random\"} }", + "{ \"runner\" : { \"name\" : \"random\"} }", + FALSE, + TRUE); + _team_config_equal_check("{ \"runner\" : { \"name\" : \"loadbalance\"} }", + "{ \"runner\" : { \"name\" : \"loadbalance\"} }", + FALSE, + TRUE); + _team_config_equal_check( + "{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth0\" : {} } }", + "{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth1\" : {} } }", + FALSE, + TRUE); + _team_config_equal_check("{ \"runner\" : { \"name\" : \"lacp\"} }", + "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\", " + "\"ipv4\", \"ipv6\" ] } }", + FALSE, + !vt); + _team_config_equal_check("{ \"runner\" : { \"name\" : \"roundrobin\"} }", + "{ \"runner\" : { \"name\" : \"roundrobin\", \"tx_hash\" : [ " + "\"eth\", \"ipv4\", \"ipv6\" ] } }", + FALSE, + !vt); + _team_config_equal_check( + "{ \"runner\" : { \"name\" : \"lacp\"} }", + "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\" ] } }", + FALSE, + !vt); + + /* team port config */ + _team_config_equal_check("{ }", + "{ \"link_watch\" : { \"name\" : \"ethtool\"} }", + TRUE, + !vt); + _team_config_equal_check("{ }", + "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", + TRUE, + TRUE); + _team_config_equal_check("{ \"link_watch\" : { \"name\" : \"ethtool\"} }", + "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", + TRUE, + !vt); + _team_config_equal_check("{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", + "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", + TRUE, + TRUE); + _team_config_equal_check( + "{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth0\" : {} } }", + "{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth1\" : {} } }", + TRUE, + TRUE); + } + + nmtst_json_vt_reset(TRUE); +} + +/*****************************************************************************/ + +enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED { + _DUMMY_1 = -1, +}; + +enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED { + _DUMMY_2, +}; + +enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64 { + _DUMMY_3 = (1LL << 40), +}; + +enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64 { + _DUMMY_4a = -1, + _DUMMY_4b = (1LL << 40), +}; + +#define test_nm_utils_is_power_of_two_do(type, x, expect) \ + G_STMT_START \ + { \ + typeof(x) x1 = (x); \ + type x2 = (type) x1; \ + gboolean val; \ + \ + val = nm_utils_is_power_of_two(x1); \ + g_assert_cmpint(expect, ==, val); \ + if (x1 != 0) \ + g_assert_cmpint(val, ==, nm_utils_is_power_of_two_or_zero(x1)); \ + else { \ + g_assert(nm_utils_is_power_of_two_or_zero(x1)); \ + g_assert(!val); \ + } \ + if (((typeof(x1)) x2) == x1 && ((typeof(x2)) x1) == x2 && x2 > 0) { \ + /* x2 equals @x, and is positive. Compare to @expect */ \ + g_assert_cmpint(expect, ==, nm_utils_is_power_of_two(x2)); \ + } else if (!(x2 > 0)) { \ + /* a non positive value is always FALSE. */ \ + g_assert_cmpint(FALSE, ==, nm_utils_is_power_of_two(x2)); \ + } \ + if (x2) { \ + x2 = -x2; \ + if (!(x2 > 0)) { \ + /* for negative values, we return FALSE. */ \ + g_assert_cmpint(FALSE, ==, nm_utils_is_power_of_two(x2)); \ + } \ + } \ + } \ + G_STMT_END + +static void +test_nm_utils_is_power_of_two(void) +{ + guint64 xyes, xno; + int i, j; + GRand * rand = nmtst_get_rand(); + int numbits; + + g_assert(!nm_utils_is_power_of_two(0)); + g_assert(nm_utils_is_power_of_two_or_zero(0)); + + for (i = -1; i < 64; i++) { + /* find a (positive) x which is a power of two. */ + if (i == -1) + xyes = 0; + else { + xyes = (((guint64) 1) << i); + g_assert(xyes != 0); + } + + xno = xyes; + if (xyes != 0) { +again: + /* Find another @xno, that is not a power of two. Do that, + * by randomly setting bits. */ + numbits = g_rand_int_range(rand, 1, 65); + while (xno != ~((guint64) 0) && numbits > 0) { + guint64 v = (((guint64) 1) << g_rand_int_range(rand, 0, 64)); + + if ((xno | v) != xno) { + xno |= v; + --numbits; + } + } + if (xno == xyes) + goto again; + } + + for (j = 0; j < 2; j++) { + gboolean expect = j == 0; + guint64 x = expect ? xyes : xno; + + if (expect && xyes == 0) + continue; + + /* check if @x is as @expect, when casted to a certain data type. */ + test_nm_utils_is_power_of_two_do(gint8, x, expect); + test_nm_utils_is_power_of_two_do(guint8, x, expect); + test_nm_utils_is_power_of_two_do(gint16, x, expect); + test_nm_utils_is_power_of_two_do(guint16, x, expect); + test_nm_utils_is_power_of_two_do(gint32, x, expect); + test_nm_utils_is_power_of_two_do(guint32, x, expect); + test_nm_utils_is_power_of_two_do(gint64, x, expect); + test_nm_utils_is_power_of_two_do(guint64, x, expect); + test_nm_utils_is_power_of_two_do(char, x, expect); + test_nm_utils_is_power_of_two_do(unsigned char, x, expect); + test_nm_utils_is_power_of_two_do(signed char, x, expect); + test_nm_utils_is_power_of_two_do(enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED, x, expect); + test_nm_utils_is_power_of_two_do(enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED, x, expect); + test_nm_utils_is_power_of_two_do(enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64, x, expect); + test_nm_utils_is_power_of_two_do(enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64, x, expect); + } + } +} + +/*****************************************************************************/ + +static int +_test_find_binary_search_cmp(gconstpointer a, gconstpointer b, gpointer dummy) +{ + int ia, ib; + + ia = GPOINTER_TO_INT(a); + ib = GPOINTER_TO_INT(b); + + if (ia == ib) + return 0; + if (ia < ib) + return -1; + return 1; +} + +static void +_test_find_binary_search_do(const int *array, gsize len) +{ + gsize i; + gssize idx, idx_first, idx_last; + gs_free gconstpointer *parray = g_new(gconstpointer, len); + const int NEEDLE = 0; + gconstpointer pneedle = GINT_TO_POINTER(NEEDLE); + gssize expected_result; + + for (i = 0; i < len; i++) + parray[i] = GINT_TO_POINTER(array[i]); + + expected_result = _nm_utils_ptrarray_find_first(parray, len, pneedle); + + idx = nm_utils_ptrarray_find_binary_search(parray, + len, + pneedle, + _test_find_binary_search_cmp, + NULL, + &idx_first, + &idx_last); + if (expected_result >= 0) { + g_assert_cmpint(expected_result, ==, idx); + } else { + gssize idx2 = ~idx; + g_assert_cmpint(idx, <, 0); + + g_assert(idx2 >= 0); + g_assert(idx2 <= len); + g_assert(idx2 - 1 < 0 || _test_find_binary_search_cmp(parray[idx2 - 1], pneedle, NULL) < 0); + g_assert(idx2 >= len || _test_find_binary_search_cmp(parray[idx2], pneedle, NULL) > 0); + } + g_assert_cmpint(idx, ==, idx_first); + g_assert_cmpint(idx, ==, idx_last); + for (i = 0; i < len; i++) { + int cmp; + + cmp = _test_find_binary_search_cmp(parray[i], pneedle, NULL); + if (cmp == 0) { + g_assert(pneedle == parray[i]); + g_assert(idx >= 0); + g_assert(i == idx); + } else { + g_assert(pneedle != parray[i]); + if (cmp < 0) { + if (idx < 0) + g_assert(i < ~idx); + else + g_assert(i < idx); + } else { + if (idx < 0) + g_assert(i >= ~idx); + else + g_assert(i >= idx); + } + } + } +} + +static void +_test_find_binary_search_do_uint32(const int *int_array, gsize len) +{ + gssize idx; + const int OFFSET = 100; + const int NEEDLE = 0 + OFFSET; + gssize expected_result = -1; + guint32 array[30]; + + g_assert(len <= G_N_ELEMENTS(array)); + + /* the test data has negative values. Shift them... */ + for (idx = 0; idx < len; idx++) { + int v = int_array[idx]; + + g_assert(v > -OFFSET); + g_assert(v < OFFSET); + g_assert(idx == 0 || v > int_array[idx - 1]); + array[idx] = (guint32)(int_array[idx] + OFFSET); + if (array[idx] == NEEDLE) + expected_result = idx; + } + + idx = nm_utils_array_find_binary_search(array, + sizeof(guint32), + len, + &NEEDLE, + nm_cmp_uint32_p_with_data, + NULL); + if (expected_result >= 0) + g_assert_cmpint(expected_result, ==, idx); + else { + gssize idx2 = ~idx; + g_assert_cmpint(idx, <, 0); + + g_assert(idx2 >= 0); + g_assert(idx2 <= len); + g_assert(idx2 - 1 < 0 || array[idx2 - 1] < NEEDLE); + g_assert(idx2 >= len || array[idx2] > NEEDLE); + } +} +#define test_find_binary_search_do(...) \ + G_STMT_START \ + { \ + const int _array[] = {__VA_ARGS__}; \ + _test_find_binary_search_do(_array, G_N_ELEMENTS(_array)); \ + _test_find_binary_search_do_uint32(_array, G_N_ELEMENTS(_array)); \ + } \ + G_STMT_END + +static void +test_nm_utils_ptrarray_find_binary_search(void) +{ + test_find_binary_search_do(0); + test_find_binary_search_do(-1, 0); + test_find_binary_search_do(-2, -1, 0); + test_find_binary_search_do(-3, -2, -1, 0); + test_find_binary_search_do(0, 1); + test_find_binary_search_do(0, 1, 2); + test_find_binary_search_do(-1, 0, 1, 2); + test_find_binary_search_do(-2, -1, 0, 1, 2); + test_find_binary_search_do(-3, -2, -1, 0, 1, 2); + test_find_binary_search_do(-3, -2, -1, 0, 1, 2); + test_find_binary_search_do(-3, -2, -1, 0, 1, 2, 3); + test_find_binary_search_do(-3, -2, -1, 0, 1, 2, 3, 4); + + test_find_binary_search_do(-1); + test_find_binary_search_do(-2, -1); + test_find_binary_search_do(-3, -2, -1); + test_find_binary_search_do(1); + test_find_binary_search_do(1, 2); + test_find_binary_search_do(-1, 1, 2); + test_find_binary_search_do(-2, -1, 1, 2); + test_find_binary_search_do(-3, -2, -1, 1, 2); + test_find_binary_search_do(-3, -2, -1, 1, 2); + test_find_binary_search_do(-3, -2, -1, 1, 2, 3); + test_find_binary_search_do(-3, -2, -1, 1, 2, 3, 4); +} + +/*****************************************************************************/ + +#define BIN_SEARCH_W_DUPS_LEN 100 +#define BIN_SEARCH_W_DUPS_JITTER 10 + +static int +_test_bin_search2_cmp(gconstpointer pa, gconstpointer pb, gpointer user_data) +{ + int a = GPOINTER_TO_INT(pa); + int b = GPOINTER_TO_INT(pb); + + g_assert(a >= 0 && a <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER); + g_assert(b >= 0 && b <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER); + NM_CMP_DIRECT(a, b); + return 0; +} + +static int +_test_bin_search2_cmp_p(gconstpointer pa, gconstpointer pb, gpointer user_data) +{ + return _test_bin_search2_cmp(*((gpointer *) pa), *((gpointer *) pb), NULL); +} + +static void +test_nm_utils_ptrarray_find_binary_search_with_duplicates(void) +{ + gssize idx, idx2, idx_first2, idx_first, idx_last; + int i_test, i_len, i; + gssize j; + gconstpointer arr[BIN_SEARCH_W_DUPS_LEN]; + const int N_TEST = 10; + + for (i_test = 0; i_test < N_TEST; i_test++) { + for (i_len = 0; i_len < BIN_SEARCH_W_DUPS_LEN; i_len++) { + /* fill with random numbers... surely there are some duplicates + * there... or maybe even there are none... */ + for (i = 0; i < i_len; i++) + arr[i] = + GINT_TO_POINTER(nmtst_get_rand_uint32() % (i_len + BIN_SEARCH_W_DUPS_JITTER)); + g_qsort_with_data(arr, i_len, sizeof(gpointer), _test_bin_search2_cmp_p, NULL); + for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) { + gconstpointer p = GINT_TO_POINTER(i); + + idx = nm_utils_ptrarray_find_binary_search(arr, + i_len, + p, + _test_bin_search2_cmp, + NULL, + &idx_first, + &idx_last); + + idx_first2 = _nm_utils_ptrarray_find_first(arr, i_len, p); + + idx2 = nm_utils_array_find_binary_search(arr, + sizeof(gpointer), + i_len, + &p, + _test_bin_search2_cmp_p, + NULL); + g_assert_cmpint(idx, ==, idx2); + + if (idx_first2 < 0) { + g_assert_cmpint(idx, <, 0); + g_assert_cmpint(idx, ==, idx_first); + g_assert_cmpint(idx, ==, idx_last); + idx = ~idx; + g_assert_cmpint(idx, >=, 0); + g_assert_cmpint(idx, <=, i_len); + if (i_len == 0) + g_assert_cmpint(idx, ==, 0); + else { + g_assert(idx == i_len || GPOINTER_TO_INT(arr[idx]) > i); + g_assert(idx == 0 || GPOINTER_TO_INT(arr[idx - 1]) < i); + } + } else { + g_assert_cmpint(idx_first, ==, idx_first2); + g_assert_cmpint(idx_first, >=, 0); + g_assert_cmpint(idx_last, <, i_len); + g_assert_cmpint(idx_first, <=, idx_last); + g_assert_cmpint(idx, >=, idx_first); + g_assert_cmpint(idx, <=, idx_last); + for (j = idx_first; j < idx_last; j++) + g_assert(GPOINTER_TO_INT(arr[j]) == i); + g_assert(idx_first == 0 || GPOINTER_TO_INT(arr[idx_first - 1]) < i); + g_assert(idx_last == i_len - 1 || GPOINTER_TO_INT(arr[idx_last + 1]) > i); + } + } + } + } +} + +/*****************************************************************************/ + +static void +_test_nm_utils_enum_to_str_do_full(GType type, + int flags, + const char * exp_str, + const NMUtilsEnumValueInfo *value_infos) +{ + gs_free char *str = NULL; + int flags2; + gs_free char *err_token = NULL; + gboolean result; + + g_assert(exp_str); + + str = _nm_utils_enum_to_str_full(type, flags, ", ", value_infos); + g_assert_cmpstr(str, ==, exp_str); + + if (!value_infos) { + gs_free char *str2 = NULL; + + str2 = nm_utils_enum_to_str(type, flags); + g_assert_cmpstr(str2, ==, exp_str); + } + + result = _nm_utils_enum_from_str_full(type, str, &flags2, &err_token, value_infos); + g_assert(result == TRUE); + g_assert_cmpint(flags2, ==, flags); + g_assert_cmpstr(err_token, ==, NULL); +} + +#define _test_nm_utils_enum_to_str_do(...) _test_nm_utils_enum_to_str_do_full(__VA_ARGS__, NULL) + +static void +_test_nm_utils_enum_from_str_do_full(GType type, + const char * str, + gboolean exp_result, + int exp_flags, + const char * exp_err_token, + const NMUtilsEnumValueInfo *value_infos) +{ + int flags; + gs_free char *err_token = NULL; + gboolean result; + + result = _nm_utils_enum_from_str_full(type, str, &flags, &err_token, value_infos); + + g_assert(result == exp_result); + g_assert_cmpint(flags, ==, exp_flags); + g_assert_cmpstr(err_token, ==, exp_err_token); + + if (!value_infos) { + int flags2; + gs_free char *err_token2 = NULL; + gboolean result2; + + result2 = nm_utils_enum_from_str(type, str, &flags2, &err_token2); + g_assert(result2 == exp_result); + g_assert_cmpint(flags2, ==, exp_flags); + g_assert_cmpstr(err_token2, ==, exp_err_token); + } + + if (result) { + int flags2; + gs_free char *str2 = NULL; + gs_free char *err_token2 = NULL; + + str2 = _nm_utils_enum_to_str_full(type, flags, ", ", value_infos); + g_assert(str2); + + result = _nm_utils_enum_from_str_full(type, str2, &flags2, &err_token2, value_infos); + g_assert(result == TRUE); + g_assert_cmpint(flags2, ==, flags); + g_assert_cmpstr(err_token, ==, NULL); + } +} + +#define _test_nm_utils_enum_from_str_do(...) _test_nm_utils_enum_from_str_do_full(__VA_ARGS__, NULL) + +static void +_test_nm_utils_enum_get_values_do(GType type, int from, int to, const char *exp_str) +{ + gs_free const char **strv = NULL; + gs_free char * str = NULL; + + g_assert(exp_str); + + strv = nm_utils_enum_get_values(type, from, to); + g_assert(strv); + str = g_strjoinv(",", (char **) strv); + g_assert_cmpstr(str, ==, exp_str); +} + +static void +test_nm_utils_enum(void) +{ + GType bool_enum = nm_test_general_bool_enum_get_type(); + GType meta_flags = nm_test_general_meta_flags_get_type(); + GType color_flags = nm_test_general_color_flags_get_type(); + static const NMUtilsEnumValueInfo color_value_infos[] = { + { + .nick = "nick-4d", + .value = 0x4D, + }, + { + .nick = "nick-5", + .value = 5, + }, + { + .nick = "nick-red", + .value = NM_TEST_GENERAL_COLOR_FLAGS_RED, + }, + {0}, + }; + + _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes"); + _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown"); + _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, "4"); + _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_67, "67"); + _test_nm_utils_enum_to_str_do(bool_enum, NM_TEST_GENERAL_BOOL_ENUM_46, "64"); + + _test_nm_utils_enum_to_str_do(meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "none"); + _test_nm_utils_enum_to_str_do(meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz"); + _test_nm_utils_enum_to_str_do(meta_flags, + NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAR + | NM_TEST_GENERAL_META_FLAGS_BAZ, + "foo, bar, baz"); + _test_nm_utils_enum_to_str_do(meta_flags, 0xFF, "foo, bar, baz, 0xf8"); + _test_nm_utils_enum_to_str_do(meta_flags, NM_TEST_GENERAL_META_FLAGS_0x8, "0x8"); + _test_nm_utils_enum_to_str_do(meta_flags, NM_TEST_GENERAL_META_FLAGS_0x4, "0x10"); + + _test_nm_utils_enum_to_str_do(color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red"); + _test_nm_utils_enum_to_str_do(color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "0x1"); + _test_nm_utils_enum_to_str_do(color_flags, + NM_TEST_GENERAL_COLOR_FLAGS_RED + | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + "red, green"); + + _test_nm_utils_enum_to_str_do_full(color_flags, + NM_TEST_GENERAL_COLOR_FLAGS_RED + | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + "nick-red, green", + color_value_infos); + + _test_nm_utils_enum_to_str_do_full(color_flags, + 0x4D | NM_TEST_GENERAL_COLOR_FLAGS_RED + | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + "nick-4d", + color_value_infos); + + _test_nm_utils_enum_to_str_do_full(color_flags, + 5 | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + "nick-5, green", + color_value_infos); + + _test_nm_utils_enum_from_str_do(bool_enum, "", FALSE, 0, NULL); + _test_nm_utils_enum_from_str_do(bool_enum, " ", FALSE, 0, NULL); + _test_nm_utils_enum_from_str_do(bool_enum, "invalid", FALSE, 0, "invalid"); + _test_nm_utils_enum_from_str_do(bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL); + _test_nm_utils_enum_from_str_do(bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL); + _test_nm_utils_enum_from_str_do(bool_enum, "yes,no", FALSE, 0, "yes,no"); + + _test_nm_utils_enum_from_str_do(meta_flags, "", TRUE, 0, NULL); + _test_nm_utils_enum_from_str_do(meta_flags, " ", TRUE, 0, NULL); + _test_nm_utils_enum_from_str_do(meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL); + _test_nm_utils_enum_from_str_do(meta_flags, + "foo,baz", + TRUE, + NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAZ, + NULL); + _test_nm_utils_enum_from_str_do(meta_flags, + "foo, baz", + TRUE, + NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAZ, + NULL); + _test_nm_utils_enum_from_str_do(meta_flags, + "foo,,bar", + TRUE, + NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAR, + NULL); + _test_nm_utils_enum_from_str_do(meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux"); + _test_nm_utils_enum_from_str_do(meta_flags, + "foo,0x6", + TRUE, + NM_TEST_GENERAL_META_FLAGS_FOO | 0x6, + NULL); + _test_nm_utils_enum_from_str_do(meta_flags, "0x30,0x08,foo", TRUE, 0x39, NULL); + + _test_nm_utils_enum_from_str_do(color_flags, + "green", + TRUE, + NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + NULL); + _test_nm_utils_enum_from_str_do(color_flags, + "blue,red", + TRUE, + NM_TEST_GENERAL_COLOR_FLAGS_BLUE + | NM_TEST_GENERAL_COLOR_FLAGS_RED, + NULL); + _test_nm_utils_enum_from_str_do(color_flags, "blue,white", FALSE, 0, "white"); + + _test_nm_utils_enum_from_str_do_full(color_flags, + "nick-red", + TRUE, + NM_TEST_GENERAL_COLOR_FLAGS_RED, + NULL, + color_value_infos); + + _test_nm_utils_enum_from_str_do_full(color_flags, "0x4D", TRUE, 0x4D, NULL, color_value_infos); + + _test_nm_utils_enum_from_str_do_full(color_flags, + "green,nick-4d", + TRUE, + 0x4D | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + NULL, + color_value_infos); + + _test_nm_utils_enum_from_str_do_full(color_flags, + "nick-4d,nick-red,nick-5,green,nick-red", + TRUE, + 0x4D | NM_TEST_GENERAL_COLOR_FLAGS_GREEN, + NULL, + color_value_infos); + + _test_nm_utils_enum_from_str_do_full(NM_TYPE_SETTING_CONNECTION_LLMNR, + "-1", + TRUE, + -1, + NULL, + NULL); + + _test_nm_utils_enum_from_str_do_full(NM_TYPE_SETTING_CONNECTION_LLMNR, + "-0x1", + TRUE, + -1, + NULL, + NULL); + + _test_nm_utils_enum_get_values_do(bool_enum, 0, G_MAXINT, "no,yes,maybe,unknown,67,64"); + _test_nm_utils_enum_get_values_do(bool_enum, + NM_TEST_GENERAL_BOOL_ENUM_YES, + NM_TEST_GENERAL_BOOL_ENUM_MAYBE, + "yes,maybe"); + _test_nm_utils_enum_get_values_do(meta_flags, 0, G_MAXINT, "none,foo,bar,baz,0x8,0x10"); + _test_nm_utils_enum_get_values_do(color_flags, 0, G_MAXINT, "blue,red,green"); +} + +/*****************************************************************************/ + +static void +_do_test_utils_str_utf8safe_unescape(const char *str, const char *expected, gsize expected_len) +{ + gsize l; + const char * s; + gs_free gpointer buf_free_1 = NULL; + gs_free char * str_free_1 = NULL; + + s = nm_utils_buf_utf8safe_unescape(str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &l, &buf_free_1); + g_assert_cmpint(expected_len, ==, l); + g_assert_cmpstr(s, ==, expected); + + if (str == NULL) { + g_assert(!s); + g_assert(!buf_free_1); + g_assert_cmpint(l, ==, 0); + } else { + g_assert(s); + if (!strchr(str, '\\')) { + g_assert(!buf_free_1); + g_assert(s == str); + g_assert_cmpint(l, ==, strlen(str)); + } else { + g_assert(buf_free_1); + g_assert(s == buf_free_1); + g_assert(memcmp(s, expected, expected_len) == 0); + } + } + + if (expected && l == strlen(expected)) { + /* there are no embedded NULs. Check that nm_utils_str_utf8safe_unescape() yields the same result. */ + s = nm_utils_str_utf8safe_unescape(str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_1); + g_assert_cmpstr(s, ==, expected); + if (strchr(str, '\\')) { + g_assert(str_free_1 != str); + g_assert(s == str_free_1); + } else + g_assert(s == str); + } +} + +#define do_test_utils_str_utf8safe_unescape(str, expected) \ + _do_test_utils_str_utf8safe_unescape("" str "", expected, NM_STRLEN(expected)) + +static void +_do_test_utils_str_utf8safe(const char * str, + gsize str_len, + const char * expected, + NMUtilsStrUtf8SafeFlags flags) +{ + const char * str_safe; + const char * buf_safe; + const char * s; + gs_free char *str_free_1 = NULL; + gs_free char *str_free_2 = NULL; + gs_free char *str_free_3 = NULL; + gs_free char *str_free_4 = NULL; + gs_free char *str_free_5 = NULL; + gs_free char *str_free_6 = NULL; + gs_free char *str_free_7 = NULL; + gs_free char *str_free_8 = NULL; + gboolean str_has_nul = FALSE; +#define RND_FLAG \ + ((nmtst_get_rand_bool()) ? NM_UTILS_STR_UTF8_SAFE_FLAG_NONE \ + : NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET) + + buf_safe = nm_utils_buf_utf8safe_escape(str, str_len, flags | RND_FLAG, &str_free_1); + + str_safe = nm_utils_str_utf8safe_escape(str, flags | RND_FLAG, &str_free_2); + + if (str_len == 0) { + g_assert(buf_safe == NULL); + g_assert(str_free_1 == NULL); + g_assert(str_safe == str); + g_assert(str == NULL || str[0] == '\0'); + g_assert(str_free_2 == NULL); + } else if (str_len == strlen(str)) { + g_assert(buf_safe); + g_assert_cmpstr(buf_safe, ==, str_safe); + + /* nm_utils_buf_utf8safe_escape() can only return a pointer equal to the input string, + * if and only if str_len is negative. Otherwise, the input str won't be NUL terminated + * and cannot be returned. */ + g_assert(buf_safe != str); + g_assert(buf_safe == str_free_1); + } else + str_has_nul = TRUE; + + str_free_3 = nm_utils_str_utf8safe_escape_cp(str, flags | RND_FLAG); + g_assert_cmpstr(str_free_3, ==, str_safe); + g_assert((!str && !str_free_3) || (str != str_free_3)); + + if (str_len > 0) + _do_test_utils_str_utf8safe_unescape(buf_safe, str, str_len); + + if (expected == NULL) { + g_assert(!str_has_nul); + + g_assert(str_safe == str); + g_assert(!str_free_2); + if (str) { + g_assert(!strchr(str, '\\')); + g_assert(g_utf8_validate(str, -1, NULL)); + } + + g_assert(str + == nm_utils_str_utf8safe_unescape(str_safe, + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, + &str_free_4)); + g_assert(!str_free_4); + + str_free_5 = nm_utils_str_utf8safe_unescape_cp(str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + if (str) { + g_assert(str_free_5 != str); + g_assert_cmpstr(str_free_5, ==, str); + } else + g_assert(!str_free_5); + return; + } + + if (!str_has_nul) { + g_assert(str); + g_assert(str_safe != str); + g_assert(str_safe == str_free_2); + g_assert(strchr(str, '\\') || !g_utf8_validate(str, -1, NULL) + || (NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) + && NM_STRCHAR_ANY(str, ch, (guchar) ch >= 127)) + || (NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) + && NM_STRCHAR_ANY(str, ch, (guchar) ch < ' '))); + g_assert(g_utf8_validate(str_safe, -1, NULL)); + + str_free_6 = g_strcompress(str_safe); + g_assert_cmpstr(str, ==, str_free_6); + + str_free_7 = nm_utils_str_utf8safe_unescape_cp(str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + g_assert(str_free_7 != str); + g_assert_cmpstr(str_free_7, ==, str); + + s = nm_utils_str_utf8safe_unescape(str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_8); + g_assert(str_free_8 != str); + g_assert(s == str_free_8); + g_assert_cmpstr(str_free_8, ==, str); + + g_assert_cmpstr(str_safe, ==, expected); + + return; + } + + g_assert_cmpstr(buf_safe, ==, expected); +} +#define do_test_utils_str_utf8safe(str, expected, flags) \ + _do_test_utils_str_utf8safe("" str "", NM_STRLEN(str), expected, flags) + +static void +test_utils_str_utf8safe(void) +{ + _do_test_utils_str_utf8safe(NULL, 0, NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + + do_test_utils_str_utf8safe("", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\\", "\\\\", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\\a", "\\\\a", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\314", "\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\314\315x\315\315x", + "\\314\\315x\\315\\315x", + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\314\315xx", "\\314\\315xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\314xx", "\\314xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\xa0", "\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\xe2\x91\xa0", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\xe2\xe2\x91\xa0", + "\\342\xe2\x91\xa0", + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\xe2\xe2\x91\xa0\xa0", + "\\342\xe2\x91\xa0\\240", + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("a", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("ab", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("ab\314", "ab\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("ab\314adsf", "ab\\314adsf", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("abadsf", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("abäb", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("x\xa0", "x\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("Ä\304ab\\äb", "Ä\\304ab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("Äab\\äb", "Äab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("ÄÄab\\äb", "ÄÄab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("㈞abä㈞b", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("abäb", + "ab\\303\\244b", + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII); + do_test_utils_str_utf8safe("ab\ab", "ab\\007b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL); + + do_test_utils_str_utf8safe("\0", "\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\0a\0", "\\000a\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\\\0", "\\\\\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\n\0", "\n\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe("\n\0", "\\012\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL); + + do_test_utils_str_utf8safe_unescape("\n\\0", "\n\0"); + do_test_utils_str_utf8safe_unescape("\n\\01", "\n\01"); + do_test_utils_str_utf8safe_unescape("\n\\012", "\n\012"); + do_test_utils_str_utf8safe_unescape("\n\\.", "\n."); + do_test_utils_str_utf8safe_unescape("\\n\\.3\\r", "\n.3\r"); +} + +/*****************************************************************************/ + +static int +_test_nm_in_set_get(int *call_counter, gboolean allow_called, int value) +{ + g_assert(call_counter); + *call_counter += 1; + if (!allow_called) + g_assert_not_reached(); + return value; +} + +static void +_test_nm_in_set_assert(int *call_counter, int expected) +{ + g_assert(call_counter); + g_assert_cmpint(expected, ==, *call_counter); + *call_counter = 0; +} + +static void +test_nm_in_set(void) +{ + int call_counter = 0; + +#define G(x) _test_nm_in_set_get(&call_counter, TRUE, x) +#define N(x) _test_nm_in_set_get(&call_counter, FALSE, x) +#define _ASSERT(expected, expr) \ + G_STMT_START \ + { \ + _test_nm_in_set_assert(&call_counter, 0); \ + g_assert(expr); \ + _test_nm_in_set_assert(&call_counter, (expected)); \ + } \ + G_STMT_END + _ASSERT(1, !NM_IN_SET(-1, G(1))); + _ASSERT(1, NM_IN_SET(-1, G(-1))); + + _ASSERT(2, !NM_IN_SET(-1, G(1), G(2))); + _ASSERT(1, NM_IN_SET(-1, G(-1), N(2))); + _ASSERT(2, NM_IN_SET(-1, G(1), G(-1))); + _ASSERT(1, NM_IN_SET(-1, G(-1), N(-1))); + + _ASSERT(3, !NM_IN_SET(-1, G(1), G(2), G(3))); + _ASSERT(1, NM_IN_SET(-1, G(-1), N(2), N(3))); + _ASSERT(2, NM_IN_SET(-1, G(1), G(-1), N(3))); + _ASSERT(3, NM_IN_SET(-1, G(1), G(2), G(-1))); + _ASSERT(2, NM_IN_SET(-1, G(1), G(-1), N(-1))); + _ASSERT(1, NM_IN_SET(-1, G(-1), N(2), N(-1))); + _ASSERT(1, NM_IN_SET(-1, G(-1), N(-1), N(3))); + _ASSERT(1, NM_IN_SET(-1, G(-1), N(-1), N(-1))); + + _ASSERT(4, !NM_IN_SET(-1, G(1), G(2), G(3), G(4))); + _ASSERT(1, NM_IN_SET(-1, G(-1), N(2), N(3), N(4))); + _ASSERT(2, NM_IN_SET(-1, G(1), G(-1), N(3), N(4))); + _ASSERT(3, NM_IN_SET(-1, G(1), G(2), G(-1), N(4))); + _ASSERT(4, NM_IN_SET(-1, G(1), G(2), G(3), G(-1))); + + _ASSERT(4, NM_IN_SET(-1, G(1), G(2), G(3), G(-1), G(5))); + _ASSERT(5, NM_IN_SET(-1, G(1), G(2), G(3), G(4), G(-1))); + _ASSERT(6, NM_IN_SET(-1, G(1), G(2), G(3), G(4), G(5), G(-1))); + + _ASSERT(1, !NM_IN_SET_SE(-1, G(1))); + _ASSERT(1, NM_IN_SET_SE(-1, G(-1))); + + _ASSERT(2, !NM_IN_SET_SE(-1, G(1), G(2))); + _ASSERT(2, NM_IN_SET_SE(-1, G(-1), G(2))); + _ASSERT(2, NM_IN_SET_SE(-1, G(1), G(-1))); + _ASSERT(2, NM_IN_SET_SE(-1, G(-1), G(-1))); + + _ASSERT(3, !NM_IN_SET_SE(-1, G(1), G(2), G(3))); + _ASSERT(3, NM_IN_SET_SE(-1, G(-1), G(2), G(3))); + _ASSERT(3, NM_IN_SET_SE(-1, G(1), G(-1), G(3))); + _ASSERT(3, NM_IN_SET_SE(-1, G(1), G(2), G(-1))); + _ASSERT(3, NM_IN_SET_SE(-1, G(1), G(-1), G(-1))); + _ASSERT(3, NM_IN_SET_SE(-1, G(-1), G(2), G(-1))); + _ASSERT(3, NM_IN_SET_SE(-1, G(-1), G(-1), G(3))); + _ASSERT(3, NM_IN_SET_SE(-1, G(-1), G(-1), G(-1))); + + _ASSERT(4, !NM_IN_SET_SE(-1, G(1), G(2), G(3), G(4))); + _ASSERT(4, NM_IN_SET_SE(-1, G(-1), G(2), G(3), G(4))); + _ASSERT(4, NM_IN_SET_SE(-1, G(1), G(-1), G(3), G(4))); + _ASSERT(4, NM_IN_SET_SE(-1, G(1), G(2), G(-1), G(4))); + _ASSERT(4, NM_IN_SET_SE(-1, G(1), G(2), G(3), G(-1))); + + _ASSERT(5, NM_IN_SET_SE(-1, G(1), G(2), G(3), G(-1), G(5))); + _ASSERT(6, NM_IN_SET_SE(-1, G(1), G(2), G(3), G(4), G(5), G(-1))); + + g_assert(!NM_IN_SET(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)); +#undef G +#undef N +#undef _ASSERT +} + +/*****************************************************************************/ + +static const char * +_test_nm_in_set_getstr(int *call_counter, gboolean allow_called, const char *value) +{ + g_assert(call_counter); + *call_counter += 1; + if (!allow_called) + g_assert_not_reached(); + return value; +} + +static void +test_nm_in_strset(void) +{ + int call_counter = 0; + +#define G(x) _test_nm_in_set_getstr(&call_counter, TRUE, x) +#define N(x) _test_nm_in_set_getstr(&call_counter, FALSE, x) +#define _ASSERT(expected, expr) \ + G_STMT_START \ + { \ + _test_nm_in_set_assert(&call_counter, 0); \ + g_assert(expr); \ + _test_nm_in_set_assert(&call_counter, (expected)); \ + } \ + G_STMT_END + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL))); + _ASSERT(1, !NM_IN_STRSET("a", G(NULL))); + _ASSERT(1, !NM_IN_STRSET(NULL, G("a"))); + + _ASSERT(1, NM_IN_STRSET_SE(NULL, G(NULL))); + _ASSERT(1, !NM_IN_STRSET_SE("a", G(NULL))); + _ASSERT(1, !NM_IN_STRSET_SE(NULL, G("a"))); + + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N(NULL))); + _ASSERT(2, !NM_IN_STRSET("a", G(NULL), G(NULL))); + _ASSERT(2, NM_IN_STRSET(NULL, G("a"), G(NULL))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("a"))); + _ASSERT(2, NM_IN_STRSET("a", G(NULL), G("a"))); + _ASSERT(2, !NM_IN_STRSET(NULL, G("a"), G("a"))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("b"))); + _ASSERT(2, !NM_IN_STRSET("a", G(NULL), G("b"))); + _ASSERT(2, !NM_IN_STRSET(NULL, G("a"), G("b"))); + + _ASSERT(2, NM_IN_STRSET_SE(NULL, G(NULL), G(NULL))); + _ASSERT(2, !NM_IN_STRSET_SE("a", G(NULL), G(NULL))); + _ASSERT(2, NM_IN_STRSET_SE(NULL, G("a"), G(NULL))); + _ASSERT(2, NM_IN_STRSET_SE(NULL, G(NULL), G("a"))); + _ASSERT(2, NM_IN_STRSET_SE("a", G(NULL), G("a"))); + _ASSERT(2, !NM_IN_STRSET_SE(NULL, G("a"), G("a"))); + _ASSERT(2, NM_IN_STRSET_SE(NULL, G(NULL), G("b"))); + _ASSERT(2, !NM_IN_STRSET_SE("a", G(NULL), G("b"))); + _ASSERT(2, !NM_IN_STRSET_SE(NULL, G("a"), G("b"))); + + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N(NULL), N(NULL))); + _ASSERT(3, !NM_IN_STRSET("a", G(NULL), G(NULL), G(NULL))); + _ASSERT(2, NM_IN_STRSET(NULL, G("a"), G(NULL), N(NULL))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("a"), N(NULL))); + _ASSERT(2, NM_IN_STRSET("a", G(NULL), G("a"), N(NULL))); + _ASSERT(3, NM_IN_STRSET(NULL, G("a"), G("a"), G(NULL))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("b"), N(NULL))); + _ASSERT(3, !NM_IN_STRSET("a", G(NULL), G("b"), G(NULL))); + _ASSERT(3, NM_IN_STRSET(NULL, G("a"), G("b"), G(NULL))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N(NULL), N("a"))); + _ASSERT(3, NM_IN_STRSET("a", G(NULL), G(NULL), G("a"))); + _ASSERT(2, NM_IN_STRSET(NULL, G("a"), G(NULL), N("a"))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("a"), N("a"))); + _ASSERT(2, NM_IN_STRSET("a", G(NULL), G("a"), N("a"))); + _ASSERT(3, !NM_IN_STRSET(NULL, G("a"), G("a"), G("a"))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("b"), N("a"))); + _ASSERT(3, NM_IN_STRSET("a", G(NULL), G("b"), G("a"))); + _ASSERT(3, !NM_IN_STRSET(NULL, G("a"), G("b"), G("a"))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N(NULL), N("b"))); + _ASSERT(3, !NM_IN_STRSET("a", G(NULL), G(NULL), G("b"))); + _ASSERT(2, NM_IN_STRSET(NULL, G("a"), G(NULL), N("b"))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("a"), N("b"))); + _ASSERT(2, NM_IN_STRSET("a", G(NULL), G("a"), N("b"))); + _ASSERT(3, !NM_IN_STRSET(NULL, G("a"), G("a"), G("b"))); + _ASSERT(1, NM_IN_STRSET(NULL, G(NULL), N("b"), N("b"))); + _ASSERT(3, !NM_IN_STRSET("a", G(NULL), G("b"), G("b"))); + _ASSERT(3, !NM_IN_STRSET(NULL, G("a"), G("b"), G("b"))); + + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G(NULL), G(NULL))); + _ASSERT(3, !NM_IN_STRSET_SE("a", G(NULL), G(NULL), G(NULL))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G(NULL), G(NULL))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("a"), G(NULL))); + _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G("a"), G(NULL))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G("a"), G(NULL))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("b"), G(NULL))); + _ASSERT(3, !NM_IN_STRSET_SE("a", G(NULL), G("b"), G(NULL))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G("b"), G(NULL))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G(NULL), G("a"))); + _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G(NULL), G("a"))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G(NULL), G("a"))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("a"), G("a"))); + _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G("a"), G("a"))); + _ASSERT(3, !NM_IN_STRSET_SE(NULL, G("a"), G("a"), G("a"))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("b"), G("a"))); + _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G("b"), G("a"))); + _ASSERT(3, !NM_IN_STRSET_SE(NULL, G("a"), G("b"), G("a"))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G(NULL), G("b"))); + _ASSERT(3, !NM_IN_STRSET_SE("a", G(NULL), G(NULL), G("b"))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G("a"), G(NULL), G("b"))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("a"), G("b"))); + _ASSERT(3, NM_IN_STRSET_SE("a", G(NULL), G("a"), G("b"))); + _ASSERT(3, !NM_IN_STRSET_SE(NULL, G("a"), G("a"), G("b"))); + _ASSERT(3, NM_IN_STRSET_SE(NULL, G(NULL), G("b"), G("b"))); + _ASSERT(3, !NM_IN_STRSET_SE("a", G(NULL), G("b"), G("b"))); + _ASSERT(3, !NM_IN_STRSET_SE(NULL, G("a"), G("b"), G("b"))); + + _ASSERT(3, NM_IN_STRSET("a", G(NULL), G("b"), G("a"), N("a"))); + _ASSERT(4, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("a"))); + _ASSERT(4, !NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"))); + + _ASSERT(4, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("a"), N("a"))); + _ASSERT(5, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("a"))); + _ASSERT(5, !NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("e"))); + + _ASSERT(5, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("a"), N("a"))); + _ASSERT(6, NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("e"), G("a"))); + _ASSERT(6, !NM_IN_STRSET("a", G(NULL), G("b"), G("c"), G("d"), G("e"), G("f"))); + + g_assert(!NM_IN_STRSET(NULL, + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16")); + g_assert(!NM_IN_STRSET("_", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16")); + g_assert(NM_IN_STRSET("10", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16")); +#undef G +#undef N +#undef _ASSERT +} + +static void +test_route_attributes_parse(void) +{ + GHashTable *ht; + GError * error = NULL; + GVariant * variant; + + ht = nm_utils_parse_variant_attributes("mtu=1400 src=1.2.3.4 cwnd=14", + ' ', + '=', + FALSE, + nm_ip_route_get_variant_attribute_spec(), + &error); + g_assert_no_error(error); + g_assert(ht); + g_hash_table_unref(ht); + + ht = nm_utils_parse_variant_attributes("mtu=1400 src=1.2.3.4 cwnd=14 \\", + ' ', + '=', + FALSE, + nm_ip_route_get_variant_attribute_spec(), + &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED); + g_assert(!ht); + g_clear_error(&error); + + ht = nm_utils_parse_variant_attributes("mtu.1400 src.1\\.2\\.3\\.4 ", + ' ', + '.', + FALSE, + nm_ip_route_get_variant_attribute_spec(), + &error); + g_assert(ht); + g_assert_no_error(error); + variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_MTU); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); + g_assert_cmpuint(g_variant_get_uint32(variant), ==, 1400); + + variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_SRC); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr(g_variant_get_string(variant, NULL), ==, "1.2.3.4"); + g_hash_table_unref(ht); + + ht = nm_utils_parse_variant_attributes("from:fd01\\:\\:42\\/64/initrwnd:21", + '/', + ':', + FALSE, + nm_ip_route_get_variant_attribute_spec(), + &error); + g_assert(ht); + g_assert_no_error(error); + variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_INITRWND); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); + g_assert_cmpuint(g_variant_get_uint32(variant), ==, 21); + + variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_FROM); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr(g_variant_get_string(variant, NULL), ==, "fd01::42/64"); + g_hash_table_unref(ht); +} + +static void +test_route_attributes_format(void) +{ + gs_unref_hashtable GHashTable *ht = NULL; + char * str; + + ht = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref); + + str = nm_utils_format_variant_attributes(NULL, ' ', '='); + g_assert_cmpstr(str, ==, NULL); + + str = nm_utils_format_variant_attributes(ht, ' ', '='); + g_assert_cmpstr(str, ==, NULL); + + g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32(5000)); + g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_INITRWND, g_variant_new_uint32(20)); + g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, g_variant_new_boolean(TRUE)); + g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_SRC, g_variant_new_string("aaaa:bbbb::1")); + str = nm_utils_format_variant_attributes(ht, ' ', '='); + g_assert_cmpstr(str, ==, "initrwnd=20 lock-mtu=true mtu=5000 src=aaaa:bbbb::1"); + g_hash_table_remove_all(ht); + g_free(str); + + g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32(30000)); + g_hash_table_insert(ht, NM_IP_ROUTE_ATTRIBUTE_INITCWND, g_variant_new_uint32(21)); + g_hash_table_insert(ht, + NM_IP_ROUTE_ATTRIBUTE_FROM, + g_variant_new_string("aaaa:bbbb:cccc:dddd::/64")); + str = nm_utils_format_variant_attributes(ht, '/', ':'); + g_assert_cmpstr(str, ==, "from:aaaa\\:bbbb\\:cccc\\:dddd\\:\\:\\/64/initcwnd:21/window:30000"); + g_hash_table_remove_all(ht); + g_free(str); +} + +/*****************************************************************************/ + +static void +test_variant_attribute_spec(void) +{ + const NMVariantAttributeSpec *const *const specs_list[] = { + nm_ip_route_get_variant_attribute_spec(), + }; + int i_specs; + + for (i_specs = 0; i_specs < G_N_ELEMENTS(specs_list); i_specs++) { + const NMVariantAttributeSpec *const *const specs = specs_list[i_specs]; + gsize len; + gsize i; + + g_assert(specs); + + len = NM_PTRARRAY_LEN(specs); + g_assert_cmpint(len, >, 0u); + + _nmtst_variant_attribute_spec_assert_sorted(specs, len); + for (i = 0; i < len; i++) + g_assert(specs[i] + == _nm_variant_attribute_spec_find_binary_search(specs, len, specs[i]->name)); + g_assert(!_nm_variant_attribute_spec_find_binary_search(specs, len, "bogus")); + } +} + +/*****************************************************************************/ + +static gboolean +do_test_nm_set_out_called(int *call_count) +{ + (*call_count)++; + return TRUE; +} + +static void +test_nm_set_out(void) +{ + gboolean val; + gboolean *p_val; + int call_count; + + /* NM_SET_OUT() has an unexpected non-function like behavior + * wrt. side-effects of the value argument. Test it */ + + p_val = &val; + call_count = 0; + NM_SET_OUT(p_val, do_test_nm_set_out_called(&call_count)); + g_assert_cmpint(call_count, ==, 1); + + p_val = NULL; + call_count = 0; + NM_SET_OUT(p_val, do_test_nm_set_out_called(&call_count)); + g_assert_cmpint(call_count, ==, 0); + + /* test that we successfully re-defined _G_BOOLEAN_EXPR() */ +#define _T1(a) \ + ({ \ + g_assert(a > 2); \ + a; \ + }) + g_assert(_T1(3) > 1); +#undef _T1 +} + +/*****************************************************************************/ + +static void +test_get_start_time_for_pid(void) +{ + guint64 x_start_time; + char x_state; + pid_t x_ppid; + + x_start_time = nm_utils_get_start_time_for_pid(getpid(), &x_state, &x_ppid); + + g_assert(x_start_time > 0); + g_assert(x_ppid == getppid()); + g_assert(!NM_IN_SET(x_state, '\0', ' ')); +} + +/*****************************************************************************/ + +static void +test_nm_va_args_macros(void) +{ +#define GET_NARG_1(...) NM_NARG(__VA_ARGS__) + + g_assert_cmpint(0, ==, GET_NARG_1()); + g_assert_cmpint(1, ==, GET_NARG_1(x)); + g_assert_cmpint(2, ==, GET_NARG_1(, )); + g_assert_cmpint(2, ==, GET_NARG_1(, x)); + g_assert_cmpint(2, ==, GET_NARG_1(x, )); + g_assert_cmpint(2, ==, GET_NARG_1(x, x)); + g_assert_cmpint(3, ==, GET_NARG_1(, , )); + g_assert_cmpint(3, ==, GET_NARG_1(, , x)); + g_assert_cmpint(3, ==, GET_NARG_1(, x, )); + g_assert_cmpint(3, ==, GET_NARG_1(, x, x)); + g_assert_cmpint(3, ==, GET_NARG_1(x, , )); + g_assert_cmpint(3, ==, GET_NARG_1(x, , x)); + g_assert_cmpint(3, ==, GET_NARG_1(x, x, )); + g_assert_cmpint(3, ==, GET_NARG_1(x, x, x)); + g_assert_cmpint(4, ==, GET_NARG_1(, , , )); + g_assert_cmpint(4, ==, GET_NARG_1(, , , x)); + g_assert_cmpint(4, ==, GET_NARG_1(, , x, )); + g_assert_cmpint(4, ==, GET_NARG_1(, , x, x)); + g_assert_cmpint(4, ==, GET_NARG_1(, x, , )); + g_assert_cmpint(4, ==, GET_NARG_1(, x, , x)); + g_assert_cmpint(4, ==, GET_NARG_1(, x, x, )); + g_assert_cmpint(4, ==, GET_NARG_1(, x, x, x)); + g_assert_cmpint(4, ==, GET_NARG_1(x, , , )); + g_assert_cmpint(4, ==, GET_NARG_1(x, , , x)); + g_assert_cmpint(4, ==, GET_NARG_1(x, , x, )); + g_assert_cmpint(4, ==, GET_NARG_1(x, , x, x)); + g_assert_cmpint(4, ==, GET_NARG_1(x, x, , )); + g_assert_cmpint(4, ==, GET_NARG_1(x, x, , x)); + g_assert_cmpint(4, ==, GET_NARG_1(x, x, x, )); + g_assert_cmpint(4, ==, GET_NARG_1(x, x, x, x)); + + g_assert_cmpint(5, ==, GET_NARG_1(x, x, x, x, x)); + g_assert_cmpint(6, ==, GET_NARG_1(x, x, x, x, x, x)); + g_assert_cmpint(7, ==, GET_NARG_1(x, x, x, x, x, x, x)); + g_assert_cmpint(8, ==, GET_NARG_1(x, x, x, x, x, x, x, x)); + g_assert_cmpint(9, ==, GET_NARG_1(x, x, x, x, x, x, x, x, x)); + g_assert_cmpint(10, ==, GET_NARG_1(x, x, x, x, x, x, x, x, x, x)); + + G_STATIC_ASSERT_EXPR(0 == GET_NARG_1()); + G_STATIC_ASSERT_EXPR(1 == GET_NARG_1(x)); + G_STATIC_ASSERT_EXPR(2 == GET_NARG_1(x, x)); +} + +/*****************************************************************************/ + +static void +test_ethtool_offload(void) +{ + const NMEthtoolData *d; + + g_assert_cmpint(nm_ethtool_id_get_by_name("invalid"), ==, NM_ETHTOOL_ID_UNKNOWN); + g_assert_cmpint(nm_ethtool_id_get_by_name("feature-rx"), ==, NM_ETHTOOL_ID_FEATURE_RX); + + d = nm_ethtool_data_get_by_optname(NM_ETHTOOL_OPTNAME_FEATURE_RXHASH); + g_assert(d); + g_assert_cmpint(d->id, ==, NM_ETHTOOL_ID_FEATURE_RXHASH); + g_assert_cmpstr(d->optname, ==, NM_ETHTOOL_OPTNAME_FEATURE_RXHASH); + + /* these features are NETIF_F_NEVER_CHANGE: */ + g_assert(!nm_ethtool_data_get_by_optname("feature-netns-local")); + g_assert(!nm_ethtool_data_get_by_optname("feature-tx-lockless")); + g_assert(!nm_ethtool_data_get_by_optname("feature-vlan-challenged")); +} + +/*****************************************************************************/ + +typedef struct { + GMainLoop * loop1; + GMainContext *c2; + GSource * extra_sources[2]; + bool got_signal[5]; + int fd_2; +} IntegData; + +static gboolean +_test_integrate_cb_handle(IntegData *d, int signal) +{ + int i; + + g_assert(d); + g_assert(signal >= 0); + g_assert(signal < G_N_ELEMENTS(d->got_signal)); + + g_assert(!d->got_signal[signal]); + d->got_signal[signal] = TRUE; + + for (i = 0; i < G_N_ELEMENTS(d->got_signal); i++) { + if (!d->got_signal[i]) + break; + } + if (i == G_N_ELEMENTS(d->got_signal)) + g_main_loop_quit(d->loop1); + return G_SOURCE_REMOVE; +} + +static gboolean +_test_integrate_cb_timeout_1(gpointer user_data) +{ + return _test_integrate_cb_handle(user_data, 0); +} + +static gboolean +_test_integrate_cb_fd_2(int fd, GIOCondition condition, gpointer user_data) + +{ + IntegData *d = user_data; + + g_assert(d->got_signal[1]); + g_assert(d->got_signal[2]); + g_assert(d->got_signal[3]); + g_assert(d->extra_sources[0]); + g_assert(d->extra_sources[1]); + + return _test_integrate_cb_handle(d, 4); +} + +static gboolean +_test_integrate_cb_idle_2(gpointer user_data) +{ + IntegData *d = user_data; + GSource * extra_source; + + g_assert(d->got_signal[1]); + g_assert(d->got_signal[2]); + g_assert(d->extra_sources[0]); + g_assert(!d->extra_sources[1]); + + extra_source = nm_g_unix_fd_source_new(d->fd_2, + G_IO_IN, + G_PRIORITY_DEFAULT, + _test_integrate_cb_fd_2, + d, + NULL); + g_source_attach(extra_source, d->c2); + + d->extra_sources[1] = extra_source; + + return _test_integrate_cb_handle(d, 3); +} + +static gboolean +_test_integrate_cb_idle_1(gpointer user_data) +{ + IntegData *d = user_data; + GSource * extra_source; + + g_assert(d->got_signal[2]); + g_assert(!d->extra_sources[0]); + + extra_source = g_idle_source_new(); + g_source_set_callback(extra_source, _test_integrate_cb_idle_2, d, NULL); + g_source_attach(extra_source, d->c2); + + d->extra_sources[0] = extra_source; + + return _test_integrate_cb_handle(d, 1); +} + +static gboolean +_test_integrate_cb_fd_1(int fd, GIOCondition condition, gpointer user_data) + +{ + IntegData *d = user_data; + + g_assert(!d->got_signal[1]); + return _test_integrate_cb_handle(d, 2); +} + +static gboolean +_test_integrate_maincontext_cb_idle1(gpointer user_data) +{ + guint32 *p_count = user_data; + + g_assert(*p_count < 5); + (*p_count)++; + return G_SOURCE_CONTINUE; +} + +static void +test_integrate_maincontext(gconstpointer test_data) +{ + const guint TEST_IDX = GPOINTER_TO_UINT(test_data); + GMainContext * c1 = g_main_context_default(); + nm_auto_unref_gmaincontext GMainContext *c2 = g_main_context_new(); + nm_auto_destroy_and_unref_gsource GSource *integ_source = NULL; + + integ_source = nm_utils_g_main_context_create_integrate_source(c2); + g_source_attach(integ_source, c1); + + if (TEST_IDX == 1) { + nm_auto_destroy_and_unref_gsource GSource *idle_source_1 = NULL; + guint32 count = 0; + + idle_source_1 = g_idle_source_new(); + g_source_set_callback(idle_source_1, _test_integrate_maincontext_cb_idle1, &count, NULL); + g_source_attach(idle_source_1, c2); + + nmtst_main_context_iterate_until_assert(c1, 2000, count == 5); + } + + if (TEST_IDX == 2) { + nm_auto_destroy_and_unref_gsource GSource *main_timeout_source = NULL; + nm_auto_destroy_and_unref_gsource GSource *timeout_source_1 = NULL; + nm_auto_destroy_and_unref_gsource GSource *idle_source_1 = NULL; + nm_auto_destroy_and_unref_gsource GSource *fd_source_1 = NULL; + nm_auto_unref_gmainloop GMainLoop *loop1 = NULL; + nm_auto_close int fd_1 = -1; + nm_auto_close int fd_2 = -1; + IntegData d; + int i; + + main_timeout_source = g_timeout_source_new(3000); + g_source_set_callback(main_timeout_source, nmtst_g_source_assert_not_called, NULL, NULL); + g_source_attach(main_timeout_source, c1); + + loop1 = g_main_loop_new(c1, FALSE); + + d = (IntegData){ + .loop1 = loop1, + .c2 = c2, + }; + + fd_1 = open("/dev/null", O_RDONLY | O_CLOEXEC); + g_assert(fd_1 >= 0); + fd_source_1 = nm_g_unix_fd_source_new(fd_1, + G_IO_IN, + G_PRIORITY_DEFAULT, + _test_integrate_cb_fd_1, + &d, + NULL); + g_source_attach(fd_source_1, c2); + + fd_2 = open("/dev/null", O_RDONLY | O_CLOEXEC); + g_assert(fd_2 >= 0); + d.fd_2 = fd_2; + + idle_source_1 = g_idle_source_new(); + g_source_set_callback(idle_source_1, _test_integrate_cb_idle_1, &d, NULL); + g_source_attach(idle_source_1, c2); + + timeout_source_1 = g_timeout_source_new(5); + g_source_set_callback(timeout_source_1, _test_integrate_cb_timeout_1, &d, NULL); + g_source_attach(timeout_source_1, c2); + + g_main_loop_run(loop1); + + for (i = 0; i < G_N_ELEMENTS(d.extra_sources); i++) { + g_assert(d.extra_sources[i]); + nm_clear_pointer(&d.extra_sources[i], nm_g_source_destroy_and_unref); + } + } +} + +/*****************************************************************************/ + +static void +test_nm_ip_addr_zero(void) +{ + in_addr_t a4 = nmtst_inet4_from_string("0.0.0.0"); + struct in6_addr a6 = *nmtst_inet6_from_string("::"); + char buf[NM_UTILS_INET_ADDRSTRLEN]; + NMIPAddr a = NM_IP_ADDR_INIT; + + g_assert(memcmp(&a, &nm_ip_addr_zero, sizeof(a)) == 0); + + g_assert(IN6_IS_ADDR_UNSPECIFIED(&nm_ip_addr_zero.addr6)); + g_assert(memcmp(&nm_ip_addr_zero.addr6, &in6addr_any, sizeof(in6addr_any)) == 0); + + g_assert(memcmp(&nm_ip_addr_zero, &a4, sizeof(a4)) == 0); + g_assert(memcmp(&nm_ip_addr_zero, &a6, sizeof(a6)) == 0); + + g_assert_cmpstr(_nm_utils_inet4_ntop(nm_ip_addr_zero.addr4, buf), ==, "0.0.0.0"); + g_assert_cmpstr(_nm_utils_inet6_ntop(&nm_ip_addr_zero.addr6, buf), ==, "::"); + + g_assert_cmpstr(nm_utils_inet_ntop(AF_INET, &nm_ip_addr_zero, buf), ==, "0.0.0.0"); + g_assert_cmpstr(nm_utils_inet_ntop(AF_INET6, &nm_ip_addr_zero, buf), ==, "::"); + + G_STATIC_ASSERT_EXPR(sizeof(a) == sizeof(a.array)); +} + +static void +test_connection_ovs_ifname(gconstpointer test_data) +{ + const guint TEST_CASE = GPOINTER_TO_UINT(test_data); + gs_unref_object NMConnection *con = NULL; + NMSettingConnection * s_con = NULL; + NMSettingOvsBridge * s_ovs_bridge = NULL; + NMSettingOvsPort * s_ovs_port = NULL; + NMSettingOvsInterface * s_ovs_iface = NULL; + NMSettingOvsPatch * s_ovs_patch = NULL; + const char * ovs_iface_type = NULL; + + switch (TEST_CASE) { + case 1: + con = nmtst_create_minimal_connection("test_connection_ovs_ifname_bridge", + NULL, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + &s_con); + s_ovs_bridge = nm_connection_get_setting_ovs_bridge(con); + g_assert(s_ovs_bridge); + break; + case 2: + con = nmtst_create_minimal_connection("test_connection_ovs_ifname_port", + NULL, + NM_SETTING_OVS_PORT_SETTING_NAME, + &s_con); + + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NULL); + + s_ovs_port = nm_connection_get_setting_ovs_port(con); + g_assert(s_ovs_port); + break; + case 3: + con = nmtst_create_minimal_connection("test_connection_ovs_ifname_interface_patch", + NULL, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + &s_con); + s_ovs_iface = nm_connection_get_setting_ovs_interface(con); + g_assert(s_ovs_iface); + + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + g_object_set(s_ovs_iface, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL); + + s_ovs_patch = NM_SETTING_OVS_PATCH(nm_setting_ovs_patch_new()); + g_assert(s_ovs_patch); + + g_object_set(s_ovs_patch, NM_SETTING_OVS_PATCH_PEER, "1.2.3.4", NULL); + + nm_connection_add_setting(con, NM_SETTING(s_ovs_patch)); + s_ovs_patch = nm_connection_get_setting_ovs_patch(con); + g_assert(s_ovs_patch); + ovs_iface_type = "patch"; + break; + case 4: + con = nmtst_create_minimal_connection("test_connection_ovs_ifname_interface_internal", + NULL, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + &s_con); + s_ovs_iface = nm_connection_get_setting_ovs_interface(con); + g_assert(s_ovs_iface); + + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + g_object_set(s_ovs_iface, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL); + ovs_iface_type = "internal"; + break; + case 5: + con = nmtst_create_minimal_connection("test_connection_ovs_ifname_interface_system", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + &s_con); + + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + s_ovs_iface = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new()); + g_assert(s_ovs_iface); + + g_object_set(s_ovs_iface, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL); + + nm_connection_add_setting(con, NM_SETTING(s_ovs_iface)); + s_ovs_iface = nm_connection_get_setting_ovs_interface(con); + g_assert(s_ovs_iface); + + ovs_iface_type = "system"; + break; + case 6: + con = nmtst_create_minimal_connection("test_connection_ovs_ifname_interface_dpdk", + NULL, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + &s_con); + s_ovs_iface = nm_connection_get_setting_ovs_interface(con); + g_assert(s_ovs_iface); + + g_object_set(s_con, + NM_SETTING_CONNECTION_MASTER, + "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + g_object_set(s_ovs_iface, NM_SETTING_OVS_INTERFACE_TYPE, "dpdk", NULL); + ovs_iface_type = "dpdk"; + break; + } + + if (!nm_streq0(ovs_iface_type, "system")) { + /* wrong: contains backward slash */ + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs\\0", NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + /* wrong: contains forward slash */ + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs/0", NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + } + + /* wrong: contains space */ + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs 0", NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + /* good */ + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs0", NULL); + nmtst_assert_connection_verifies(con); + + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs-br0", NULL); + nmtst_assert_connection_verifies(con); + + /* good if bridge, port, or patch interface */ + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs123123123123130123123", NULL); + + if (!ovs_iface_type || nm_streq(ovs_iface_type, "patch")) + nmtst_assert_connection_verifies(con); + else { + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + } +} + +/*****************************************************************************/ + +static gboolean +_strsplit_quoted_char_needs_escaping(char ch) +{ + return NM_IN_SET(ch, '\'', '\"', '\\') || strchr(NM_ASCII_WHITESPACES, ch); +} + +static char * +_strsplit_quoted_create_str_rand(gssize len) +{ + NMStrBuf strbuf = NM_STR_BUF_INIT(nmtst_get_rand_uint32() % 200, nmtst_get_rand_bool()); + + g_assert(len >= -1); + + if (len == -1) + len = nmtst_get_rand_word_length(NULL); + + while (len-- > 0) { + char ch; + + ch = nmtst_rand_select('a', ' ', '\\', '"', '\'', nmtst_get_rand_uint32() % 255 + 1); + g_assert(ch); + nm_str_buf_append_c(&strbuf, ch); + } + + if (!strbuf.allocated) + nm_str_buf_maybe_expand(&strbuf, 1, nmtst_get_rand_bool()); + return nm_str_buf_finalize(&strbuf, NULL); +} + +static char ** +_strsplit_quoted_create_strv_rand(void) +{ + guint len = nmtst_get_rand_word_length(NULL); + char **ptr; + guint i; + + ptr = g_new(char *, len + 1); + for (i = 0; i < len; i++) + ptr[i] = _strsplit_quoted_create_str_rand(-1); + ptr[i] = NULL; + return ptr; +} + +static char * +_strsplit_quoted_join_strv_rand(const char *const *strv) +{ + NMStrBuf strbuf = NM_STR_BUF_INIT(nmtst_get_rand_uint32() % 200, nmtst_get_rand_bool()); + char * result; + gsize l; + gsize l2; + gsize * p_l2 = nmtst_get_rand_bool() ? &l2 : NULL; + gsize i; + + g_assert(strv); + + nm_str_buf_append_c_repeated(&strbuf, ' ', nmtst_get_rand_word_length(NULL) / 4); + for (i = 0; strv[i]; i++) { + const char *s = strv[i]; + gsize j; + char quote; + + nm_str_buf_append_c_repeated(&strbuf, ' ', 1 + nmtst_get_rand_word_length(NULL) / 4); + + j = 0; + quote = '\0'; + while (TRUE) { + char ch = s[j++]; + + /* extract_first_word*/ + if (quote != '\0') { + if (ch == '\0') { + nm_str_buf_append_c(&strbuf, quote); + break; + } + if (ch == quote || ch == '\\' || nmtst_get_rand_uint32() % 5 == 0) + nm_str_buf_append_c(&strbuf, '\\'); + nm_str_buf_append_c(&strbuf, ch); + if (nmtst_get_rand_uint32() % 3 == 0) { + nm_str_buf_append_c(&strbuf, quote); + quote = '\0'; + goto next_maybe_quote; + } + continue; + } + + if (ch == '\0') { + if (s == strv[i]) { + quote = nmtst_rand_select('\'', '"'); + nm_str_buf_append_c_repeated(&strbuf, quote, 2); + } + break; + } + + if (_strsplit_quoted_char_needs_escaping(ch) || nmtst_get_rand_uint32() % 5 == 0) + nm_str_buf_append_c(&strbuf, '\\'); + + nm_str_buf_append_c(&strbuf, ch); + +next_maybe_quote: + if (nmtst_get_rand_uint32() % 5 == 0) { + quote = nmtst_rand_select('\'', '\"'); + nm_str_buf_append_c(&strbuf, quote); + if (nmtst_get_rand_uint32() % 5 == 0) { + nm_str_buf_append_c(&strbuf, quote); + quote = '\0'; + } + } + } + } + nm_str_buf_append_c_repeated(&strbuf, ' ', nmtst_get_rand_word_length(NULL) / 4); + + nm_str_buf_maybe_expand(&strbuf, 1, nmtst_get_rand_bool()); + + l = strbuf.len; + result = nm_str_buf_finalize(&strbuf, p_l2); + g_assert(!p_l2 || l == *p_l2); + g_assert(strlen(result) == l); + return result; +} + +static void +_strsplit_quoted_assert_strv(const char * topic, + const char * str, + const char *const *strv1, + const char *const *strv2) +{ + nm_auto_str_buf NMStrBuf s1 = {}; + nm_auto_str_buf NMStrBuf s2 = {}; + gs_free char * str_escaped = NULL; + int i; + + g_assert(str); + g_assert(strv1); + g_assert(strv2); + + if (nm_utils_strv_equal(strv1, strv2)) + return; + + for (i = 0; strv1[i]; i++) { + gs_free char *s = g_strescape(strv1[i], NULL); + + g_print(">>> [%s] strv1[%d] = \"%s\"\n", topic, i, s); + if (i > 0) + nm_str_buf_append_c(&s1, ' '); + nm_str_buf_append_printf(&s1, "\"%s\"", s); + } + + for (i = 0; strv2[i]; i++) { + gs_free char *s = g_strescape(strv2[i], NULL); + + g_print(">>> [%s] strv2[%d] = \"%s\"\n", topic, i, s); + if (i > 0) + nm_str_buf_append_c(&s2, ' '); + nm_str_buf_append_printf(&s2, "\"%s\"", s); + } + + nm_str_buf_maybe_expand(&s1, 1, FALSE); + nm_str_buf_maybe_expand(&s2, 1, FALSE); + + str_escaped = g_strescape(str, NULL); + g_error("compared words differs: [%s] str=\"%s\"; strv1=%s; strv2=%s", + topic, + str_escaped, + nm_str_buf_get_str(&s1), + nm_str_buf_get_str(&s2)); +} + +static void +_strsplit_quoted_test(const char *str, const char *const *strv_expected) +{ + gs_strfreev char **strv_systemd = NULL; + gs_strfreev char **strv_nm = NULL; + int r; + + g_assert(str); + + r = nmtst_systemd_extract_first_word_all(str, &strv_systemd); + g_assert_cmpint(r, ==, 1); + g_assert(strv_systemd); + + if (!strv_expected) + strv_expected = (const char *const *) strv_systemd; + + _strsplit_quoted_assert_strv("systemd", str, strv_expected, (const char *const *) strv_systemd); + + strv_nm = nm_utils_strsplit_quoted(str); + g_assert(strv_nm); + _strsplit_quoted_assert_strv("nm", str, strv_expected, (const char *const *) strv_nm); +} + +static void +test_strsplit_quoted(void) +{ + int i_run; + + _strsplit_quoted_test("", NM_MAKE_STRV()); + _strsplit_quoted_test(" ", NM_MAKE_STRV()); + _strsplit_quoted_test(" ", NM_MAKE_STRV()); + _strsplit_quoted_test(" \t", NM_MAKE_STRV()); + _strsplit_quoted_test("a b", NM_MAKE_STRV("a", "b")); + _strsplit_quoted_test("a\\ b", NM_MAKE_STRV("a b")); + _strsplit_quoted_test(" a\\ \"b\"", NM_MAKE_STRV("a b")); + _strsplit_quoted_test(" a\\ \"b\" c \n", NM_MAKE_STRV("a b", "c")); + + for (i_run = 0; i_run < 1000; i_run++) { + gs_strfreev char **strv = NULL; + gs_free char * str = NULL; + + /* create random strv array and join them carefully so that splitting + * them will yield the original value. */ + strv = _strsplit_quoted_create_strv_rand(); + str = _strsplit_quoted_join_strv_rand((const char *const *) strv); + _strsplit_quoted_test(str, (const char *const *) strv); + } + + /* Create random words and assert that systemd and our implementation can + * both split them (and in the exact same way). */ + for (i_run = 0; i_run < 1000; i_run++) { + gs_free char *s = _strsplit_quoted_create_str_rand(nmtst_get_rand_uint32() % 150); + + _strsplit_quoted_test(s, NULL); + } +} + +/*****************************************************************************/ + +static void +_do_wifi_ghz_freqs(const guint *freqs, const char *band) +{ + int len; + int j; + int i; + + g_assert(NM_IN_STRSET(band, "a", "bg")); + g_assert(freqs); + g_assert(freqs[0] != 0); + + for (i = 0; freqs[i]; i++) { + for (j = 0; j < i; j++) + g_assert(freqs[i] != freqs[j]); + } + len = i; + + g_assert(nm_utils_wifi_freq_to_channel(0) == 0); + g_assert(nm_utils_wifi_channel_to_freq(0, "bg") == -1); + g_assert(nm_utils_wifi_channel_to_freq(0, "foo") == 0); + g_assert(!nm_utils_wifi_is_channel_valid(0, "bg")); + g_assert(!nm_utils_wifi_is_channel_valid(0, "foo")); + + for (i = 0; i < len; i++) { + guint freq = freqs[i]; + guint32 chan; + guint32 freq2; + + chan = nm_utils_wifi_freq_to_channel(freq); + g_assert(chan != 0); + + freq2 = nm_utils_wifi_channel_to_freq(chan, band); + g_assert(freq2 == freq); + + g_assert(nm_utils_wifi_is_channel_valid(chan, band)); + } + + g_assert(freqs[len] == 0); +} + +static void +test_nm_utils_wifi_ghz_freqs(void) +{ + _do_wifi_ghz_freqs(nm_utils_wifi_2ghz_freqs(), "bg"); + _do_wifi_ghz_freqs(nm_utils_wifi_5ghz_freqs(), "a"); +} + +/*****************************************************************************/ + +static void +test_vpn_connection_state_reason(void) +{ +#define ASSERT(v1, v2) \ + G_STMT_START \ + { \ + G_STATIC_ASSERT((gint64)(v1) == v2); \ + G_STATIC_ASSERT((gint64)(v2) == v1); \ + \ + nm_assert(((NMActiveConnectionStateReason)(int) (v1)) == v2); \ + nm_assert(((NMVpnConnectionStateReason)(int) (v2)) == v1); \ + } \ + G_STMT_END + + ASSERT(NM_VPN_CONNECTION_STATE_REASON_UNKNOWN, NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_NONE, NM_ACTIVE_CONNECTION_STATE_REASON_NONE); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED, + NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED, + NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, + NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT, + NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT, + NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED, + NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED, + NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED); + ASSERT(NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED, + NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED); +} + +/*****************************************************************************/ + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init(&argc, &argv, TRUE); + + g_test_add_func("/core/general/test_nm_ascii_spaces", test_nm_ascii_spaces); + g_test_add_func("/core/general/test_wired_wake_on_lan_enum", test_wired_wake_on_lan_enum); + g_test_add_func("/core/general/test_nm_hash", test_nm_hash); + g_test_add_func("/core/general/test_nm_g_slice_free_fcn", test_nm_g_slice_free_fcn); + g_test_add_func("/core/general/test_c_list_sort", test_c_list_sort); + g_test_add_func("/core/general/test_dedup_multi", test_dedup_multi); + g_test_add_func("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe); + g_test_add_func("/core/general/test_nm_utils_strsplit_set", test_nm_utils_strsplit_set); + g_test_add_func("/core/general/test_nm_utils_escaped_tokens", test_nm_utils_escaped_tokens); + g_test_add_func("/core/general/test_nm_in_set", test_nm_in_set); + g_test_add_func("/core/general/test_nm_in_strset", test_nm_in_strset); + g_test_add_func("/core/general/test_setting_vpn_items", test_setting_vpn_items); + g_test_add_func("/core/general/test_setting_vpn_update_secrets", + test_setting_vpn_update_secrets); + g_test_add_func("/core/general/test_setting_vpn_modify_during_foreach", + test_setting_vpn_modify_during_foreach); + g_test_add_func("/core/general/test_setting_ip4_config_labels", test_setting_ip4_config_labels); + g_test_add_func("/core/general/test_setting_ip4_config_address_data", + test_setting_ip4_config_address_data); + g_test_add_func("/core/general/test_setting_ip_route_attributes", + test_setting_ip_route_attributes); + g_test_add_func("/core/general/test_setting_gsm_apn_spaces", test_setting_gsm_apn_spaces); + g_test_add_func("/core/general/test_setting_gsm_apn_bad_chars", test_setting_gsm_apn_bad_chars); + g_test_add_func("/core/general/test_setting_gsm_apn_underscore", + test_setting_gsm_apn_underscore); + g_test_add_func("/core/general/test_setting_gsm_without_number", + test_setting_gsm_without_number); + g_test_add_func("/core/general/test_setting_gsm_sim_operator_id", + test_setting_gsm_sim_operator_id); + g_test_add_func("/core/general/test_setting_to_dbus_all", test_setting_to_dbus_all); + g_test_add_func("/core/general/test_setting_to_dbus_no_secrets", + test_setting_to_dbus_no_secrets); + g_test_add_func("/core/general/test_setting_to_dbus_only_secrets", + test_setting_to_dbus_only_secrets); + g_test_add_func("/core/general/test_setting_to_dbus_transform", test_setting_to_dbus_transform); + g_test_add_func("/core/general/test_setting_to_dbus_enum", test_setting_to_dbus_enum); + g_test_add_func("/core/general/test_setting_compare_id", test_setting_compare_id); + g_test_add_func("/core/general/test_setting_compare_addresses", test_setting_compare_addresses); + g_test_add_func("/core/general/test_setting_compare_routes", test_setting_compare_routes); + g_test_add_func("/core/general/test_setting_compare_wired_cloned_mac_address", + test_setting_compare_wired_cloned_mac_address); + g_test_add_func("/core/general/test_setting_compare_wirless_cloned_mac_address", + test_setting_compare_wireless_cloned_mac_address); + g_test_add_func("/core/general/test_setting_compare_timestamp", test_setting_compare_timestamp); +#define ADD_FUNC(name, func, secret_flags, comp_flags, remove_secret) \ + g_test_add_data_func_full( \ + "/core/general/" G_STRINGIFY(func) "_" name, \ + test_data_compare_secrets_new(secret_flags, comp_flags, remove_secret), \ + func, \ + g_free) + ADD_FUNC("agent_owned", + test_setting_compare_secrets, + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, + TRUE); + ADD_FUNC("not_saved", + test_setting_compare_secrets, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, + TRUE); + ADD_FUNC("secrets", + test_setting_compare_secrets, + NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, + TRUE); + ADD_FUNC("exact", + test_setting_compare_secrets, + NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_COMPARE_FLAG_EXACT, + FALSE); + ADD_FUNC("agent_owned", + test_setting_compare_vpn_secrets, + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, + TRUE); + ADD_FUNC("not_saved", + test_setting_compare_vpn_secrets, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, + TRUE); + ADD_FUNC("secrets", + test_setting_compare_vpn_secrets, + NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, + TRUE); + ADD_FUNC("exact", + test_setting_compare_vpn_secrets, + NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_COMPARE_FLAG_EXACT, + FALSE); + g_test_add_func("/core/general/test_setting_old_uuid", test_setting_old_uuid); + + g_test_add_func("/core/general/test_connection_to_dbus_setting_name", + test_connection_to_dbus_setting_name); + g_test_add_func("/core/general/test_connection_to_dbus_deprecated_props", + test_connection_to_dbus_deprecated_props); + g_test_add_func("/core/general/test_setting_new_from_dbus", test_setting_new_from_dbus); + g_test_add_func("/core/general/test_setting_new_from_dbus_transform", + test_setting_new_from_dbus_transform); + g_test_add_func("/core/general/test_setting_new_from_dbus_enum", + test_setting_new_from_dbus_enum); + g_test_add_func("/core/general/test_setting_new_from_dbus_bad", test_setting_new_from_dbus_bad); + g_test_add_func("/core/general/test_connection_replace_settings", + test_connection_replace_settings); + g_test_add_func("/core/general/test_connection_replace_settings_from_connection", + test_connection_replace_settings_from_connection); + g_test_add_func("/core/general/test_connection_replace_settings_bad", + test_connection_replace_settings_bad); + g_test_add_func("/core/general/test_connection_new_from_dbus", test_connection_new_from_dbus); + g_test_add_func("/core/general/test_connection_normalize_virtual_iface_name", + test_connection_normalize_virtual_iface_name); + g_test_add_func("/core/general/test_connection_normalize_uuid", test_connection_normalize_uuid); + g_test_add_func("/core/general/test_connection_normalize_type", test_connection_normalize_type); + g_test_add_func("/core/general/test_connection_normalize_slave_type_1", + test_connection_normalize_slave_type_1); + g_test_add_func("/core/general/test_connection_normalize_slave_type_2", + test_connection_normalize_slave_type_2); + g_test_add_func("/core/general/test_connection_normalize_infiniband_mtu", + test_connection_normalize_infiniband_mtu); + g_test_add_func("/core/general/test_connection_normalize_gateway_never_default", + test_connection_normalize_gateway_never_default); + g_test_add_func("/core/general/test_connection_normalize_may_fail", + test_connection_normalize_may_fail); + g_test_add_func("/core/general/test_connection_normalize_shared_addresses", + test_connection_normalize_shared_addresses); + g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/1", + GUINT_TO_POINTER(1), + test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/2", + GUINT_TO_POINTER(2), + test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/3", + GUINT_TO_POINTER(3), + test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/4", + GUINT_TO_POINTER(4), + test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/5", + GUINT_TO_POINTER(5), + test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/6", + GUINT_TO_POINTER(6), + test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func("/core/general/test_connection_normalize_ovs_interface_type_system/7", + GUINT_TO_POINTER(7), + test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/1", + GUINT_TO_POINTER(1), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/2", + GUINT_TO_POINTER(2), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/3", + GUINT_TO_POINTER(3), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/4", + GUINT_TO_POINTER(4), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/5", + GUINT_TO_POINTER(5), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/6", + GUINT_TO_POINTER(6), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/7", + GUINT_TO_POINTER(7), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/8", + GUINT_TO_POINTER(8), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/9", + GUINT_TO_POINTER(9), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/10", + GUINT_TO_POINTER(10), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/11", + GUINT_TO_POINTER(11), + test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func( + "/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/12", + GUINT_TO_POINTER(12), + test_connection_normalize_ovs_interface_type_ovs_interface); + + g_test_add_data_func("/core/general/test_connection_ovs_ifname/1", + GUINT_TO_POINTER(1), + test_connection_ovs_ifname); + g_test_add_data_func("/core/general/test_connection_ovs_ifname/2", + GUINT_TO_POINTER(2), + test_connection_ovs_ifname); + g_test_add_data_func("/core/general/test_connection_ovs_ifname/3", + GUINT_TO_POINTER(3), + test_connection_ovs_ifname); + g_test_add_data_func("/core/general/test_connection_ovs_ifname/4", + GUINT_TO_POINTER(4), + test_connection_ovs_ifname); + g_test_add_data_func("/core/general/test_connection_ovs_ifname/5", + GUINT_TO_POINTER(5), + test_connection_ovs_ifname); + g_test_add_data_func("/core/general/test_connection_ovs_ifname/6", + GUINT_TO_POINTER(6), + test_connection_ovs_ifname); + + g_test_add_func("/core/general/test_setting_connection_permissions_helpers", + test_setting_connection_permissions_helpers); + g_test_add_func("/core/general/test_setting_connection_permissions_property", + test_setting_connection_permissions_property); + + g_test_add_func("/core/general/test_connection_compare_same", test_connection_compare_same); + g_test_add_func("/core/general/test_connection_compare_key_only_in_a", + test_connection_compare_key_only_in_a); + g_test_add_func("/core/general/test_connection_compare_setting_only_in_a", + test_connection_compare_setting_only_in_a); + g_test_add_func("/core/general/test_connection_compare_key_only_in_b", + test_connection_compare_key_only_in_b); + g_test_add_func("/core/general/test_connection_compare_setting_only_in_b", + test_connection_compare_setting_only_in_b); + + g_test_add_func("/core/general/test_connection_diff_a_only", test_connection_diff_a_only); + g_test_add_func("/core/general/test_connection_diff_same", test_connection_diff_same); + g_test_add_func("/core/general/test_connection_diff_different", test_connection_diff_different); + g_test_add_func("/core/general/test_connection_diff_no_secrets", + test_connection_diff_no_secrets); + g_test_add_func("/core/general/test_connection_diff_inferrable", + test_connection_diff_inferrable); + g_test_add_func("/core/general/test_connection_good_base_types", + test_connection_good_base_types); + g_test_add_func("/core/general/test_connection_bad_base_types", test_connection_bad_base_types); + + g_test_add_func("/core/general/test_hwaddr_aton_ether_normal", test_hwaddr_aton_ether_normal); + g_test_add_func("/core/general/test_hwaddr_aton_ib_normal", test_hwaddr_aton_ib_normal); + g_test_add_func("/core/general/test_hwaddr_aton_no_leading_zeros", + test_hwaddr_aton_no_leading_zeros); + g_test_add_func("/core/general/test_hwaddr_aton_malformed", test_hwaddr_aton_malformed); + g_test_add_func("/core/general/test_hwaddr_equal", test_hwaddr_equal); + g_test_add_func("/core/general/test_hwaddr_canonical", test_hwaddr_canonical); + + g_test_add_func("/core/general/test_ip4_prefix_to_netmask", test_ip4_prefix_to_netmask); + g_test_add_func("/core/general/test_ip4_netmask_to_prefix", test_ip4_netmask_to_prefix); + + g_test_add_func("/core/general/test_connection_changed_signal", test_connection_changed_signal); + g_test_add_func("/core/general/test_setting_connection_changed_signal", + test_setting_connection_changed_signal); + g_test_add_func("/core/general/test_setting_bond_changed_signal", + test_setting_bond_changed_signal); + g_test_add_func("/core/general/test_setting_ip4_changed_signal", + test_setting_ip4_changed_signal); + g_test_add_func("/core/general/test_setting_ip6_changed_signal", + test_setting_ip6_changed_signal); + g_test_add_func("/core/general/test_setting_vlan_changed_signal", + test_setting_vlan_changed_signal); + g_test_add_func("/core/general/test_setting_vpn_changed_signal", + test_setting_vpn_changed_signal); + g_test_add_func("/core/general/test_setting_wired_changed_signal", + test_setting_wired_changed_signal); + g_test_add_func("/core/general/test_setting_wireless_changed_signal", + test_setting_wireless_changed_signal); + g_test_add_func("/core/general/test_setting_wireless_security_changed_signal", + test_setting_wireless_security_changed_signal); + g_test_add_func("/core/general/test_setting_802_1x_changed_signal", + test_setting_802_1x_changed_signal); + g_test_add_func("/core/general/test_setting_ip4_gateway", test_setting_ip4_gateway); + g_test_add_func("/core/general/test_setting_ip6_gateway", test_setting_ip6_gateway); + g_test_add_func("/core/general/test_setting_compare_default_strv", + test_setting_compare_default_strv); + g_test_add_func("/core/general/test_setting_user_data", test_setting_user_data); + + g_test_add_func("/core/general/test_sock_addr_endpoint", test_sock_addr_endpoint); + + g_test_add_func("/core/general/hexstr2bin", test_hexstr2bin); + g_test_add_func("/core/general/nm_strquote", test_nm_strquote); + g_test_add_func("/core/general/test_nm_utils_uuid_generate_from_string", + test_nm_utils_uuid_generate_from_string); + g_test_add_func("/core/general/_nm_utils_uuid_generate_from_strings", + test_nm_utils_uuid_generate_from_strings); + + g_test_add_func("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64); + g_test_add_func("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two); + g_test_add_func("/core/general/nm_utils_ptrarray_find_binary_search", + test_nm_utils_ptrarray_find_binary_search); + g_test_add_func("/core/general/nm_utils_ptrarray_find_binary_search_with_duplicates", + test_nm_utils_ptrarray_find_binary_search_with_duplicates); + g_test_add_func("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey); + g_test_add_func("/core/general/nm_ptrarray_len", test_nm_ptrarray_len); + + g_test_add_func("/core/general/_nm_utils_dns_option_validate", + test_nm_utils_dns_option_validate); + g_test_add_func("/core/general/_nm_utils_dns_option_find_idx", + test_nm_utils_dns_option_find_idx); + g_test_add_func("/core/general/_nm_utils_validate_json", test_nm_utils_check_valid_json); + g_test_add_func("/core/general/_nm_utils_team_config_equal", test_nm_utils_team_config_equal); + g_test_add_func("/core/general/test_nm_utils_enum", test_nm_utils_enum); + g_test_add_func("/core/general/nm-set-out", test_nm_set_out); + g_test_add_func("/core/general/route_attributes/parse", test_route_attributes_parse); + g_test_add_func("/core/general/route_attributes/format", test_route_attributes_format); + g_test_add_func("/core/general/test_variant_attribute_spec", test_variant_attribute_spec); + + g_test_add_func("/core/general/get_start_time_for_pid", test_get_start_time_for_pid); + g_test_add_func("/core/general/test_nm_va_args_macros", test_nm_va_args_macros); + g_test_add_func("/core/general/test_ethtool_offload", test_ethtool_offload); + + g_test_add_data_func("/core/general/test_integrate_maincontext/1", + GUINT_TO_POINTER(1), + test_integrate_maincontext); + g_test_add_data_func("/core/general/test_integrate_maincontext/2", + GUINT_TO_POINTER(2), + test_integrate_maincontext); + + g_test_add_func("/core/general/test_nm_ip_addr_zero", test_nm_ip_addr_zero); + g_test_add_func("/core/general/test_nm_utils_wifi_ghz_freqs", test_nm_utils_wifi_ghz_freqs); + + g_test_add_func("/core/general/test_strsplit_quoted", test_strsplit_quoted); + g_test_add_func("/core/general/test_vpn_connection_state_reason", + test_vpn_connection_state_reason); + + return g_test_run(); +} diff --git a/src/libnm-core-impl/tests/test-keyfile.c b/src/libnm-core-impl/tests/test-keyfile.c new file mode 100644 index 0000000000..755a40ae29 --- /dev/null +++ b/src/libnm-core-impl/tests/test-keyfile.c @@ -0,0 +1,909 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-glib-aux/nm-json-aux.h" +#include "libnm-core-intern/nm-keyfile-utils.h" +#include "libnm-core-intern/nm-keyfile-internal.h" +#include "nm-simple-connection.h" +#include "nm-setting-connection.h" +#include "nm-setting-wired.h" +#include "nm-setting-8021x.h" +#include "nm-setting-team.h" +#include "nm-setting-user.h" +#include "nm-setting-proxy.h" + +#include "nm-utils/nm-test-utils.h" + +#define TEST_CERT_DIR NM_BUILD_SRCDIR "/src/libnm-core-impl/tests/certs" +#define TEST_WIRED_TLS_CA_CERT TEST_CERT_DIR "/test-ca-cert.pem" +#define TEST_WIRED_TLS_PRIVKEY TEST_CERT_DIR "/test-key-and-cert.pem" +#define TEST_WIRED_TLS_TPM2KEY TEST_CERT_DIR "/test-tpm2wrapped-key.pem" + +/*****************************************************************************/ + +static void +do_test_encode_key_full(GKeyFile * kf, + const char *name, + const char *key, + const char *key_decode_encode) +{ + gs_free char *to_free1 = NULL; + gs_free char *to_free2 = NULL; + const char * key2; + const char * name2; + + g_assert(key); + + if (name) { + key2 = nm_keyfile_key_encode(name, &to_free1); + g_assert(key2); + g_assert(NM_STRCHAR_ALL(key2, ch, (guchar) ch < 127)); + g_assert_cmpstr(key2, ==, key); + + /* try to add the encoded key to the keyfile. We expect + * no g_critical warning about invalid key. */ + g_key_file_set_value(kf, "group", key, "dummy"); + } + + name2 = nm_keyfile_key_decode(key, &to_free2); + if (name) + g_assert_cmpstr(name2, ==, name); + else { + key2 = nm_keyfile_key_encode(name2, &to_free1); + g_assert(key2); + g_assert(NM_STRCHAR_ALL(key2, ch, (guchar) ch < 127)); + if (key_decode_encode) + g_assert_cmpstr(key2, ==, key_decode_encode); + g_key_file_set_value(kf, "group", key2, "dummy"); + } +} + +#define do_test_encode_key_bijection(kf, name, key) \ + do_test_encode_key_full(kf, "" name, "" key, NULL) +#define do_test_encode_key_identity(kf, name) do_test_encode_key_full(kf, "" name, "" name, NULL) +#define do_test_encode_key_decode_surjection(kf, key, key_decode_encode) \ + do_test_encode_key_full(kf, NULL, "" key, "" key_decode_encode) + +static void +test_encode_key(void) +{ + nm_auto_unref_keyfile GKeyFile *kf = g_key_file_new(); + + do_test_encode_key_identity(kf, "a"); + do_test_encode_key_bijection(kf, "", "\\00"); + do_test_encode_key_bijection(kf, " ", "\\20"); + do_test_encode_key_bijection(kf, "\\ ", "\\\\20"); + do_test_encode_key_identity(kf, "\\0"); + do_test_encode_key_identity(kf, "\\a"); + do_test_encode_key_identity(kf, "\\0g"); + do_test_encode_key_bijection(kf, "\\0f", "\\5C0f"); + do_test_encode_key_bijection(kf, "\\0f ", "\\5C0f\\20"); + do_test_encode_key_bijection(kf, " \\0f ", "\\20\\5C0f\\20"); + do_test_encode_key_bijection(kf, "\xF5", "\\F5"); + do_test_encode_key_bijection(kf, "\x7F", "\\7F"); + do_test_encode_key_bijection(kf, "\x1f", "\\1F"); + do_test_encode_key_bijection(kf, " ", "\\20\\20"); + do_test_encode_key_bijection(kf, " ", "\\20 \\20"); + do_test_encode_key_decode_surjection(kf, "f\\20c", "f c"); + do_test_encode_key_decode_surjection(kf, "\\20\\20\\20", "\\20 \\20"); + + do_test_encode_key_bijection(kf, "\t", "\\09"); + do_test_encode_key_bijection(kf, "\t=x", "\\09\\3Dx"); + do_test_encode_key_bijection( + kf, + "(nm-openvpn-auth-dialog:10283): GdkPixbuf-DEBUG: \tCopy pixels == false", + "(nm-openvpn-auth-dialog:10283): GdkPixbuf-DEBUG: \\09Copy pixels \\3D\\3D false"); +} + +/*****************************************************************************/ + +#define CLEAR(con, keyfile) \ + G_STMT_START \ + { \ + NMConnection **_con = (con); \ + GKeyFile ** _keyfile = (keyfile); \ + \ + g_clear_object(_con); \ + nm_clear_pointer(_keyfile, g_key_file_unref); \ + } \ + G_STMT_END + +static void +_assert_gbytes(GBytes *bytes, gconstpointer data, gssize len) +{ + g_assert((data && len > 0) || !len || (data && len == -1)); + + if (len == -1) + len = strlen(data); + + if (!len) + g_assert(!bytes); + + g_assert(nm_utils_gbytes_equal_mem(bytes, data, len)); +} + +static GKeyFile * +_keyfile_load_from_data(const char *str) +{ + GError * error = NULL; + gboolean success; + GKeyFile *keyfile; + + g_assert(str); + + keyfile = g_key_file_new(); + success = g_key_file_load_from_data(keyfile, str, strlen(str), G_KEY_FILE_NONE, &error); + g_assert_no_error(error); + g_assert(success); + + return keyfile; +} + +static GKeyFile * +_nm_keyfile_write(NMConnection *connection, NMKeyfileWriteHandler handler, void *user_data) +{ + GError * error = NULL; + GKeyFile *kf; + + g_assert(NM_IS_CONNECTION(connection)); + + kf = nm_keyfile_write(connection, NM_KEYFILE_HANDLER_FLAGS_NONE, handler, user_data, &error); + g_assert_no_error(error); + g_assert(kf); + return kf; +} + +static NMConnection * +_nm_keyfile_read(GKeyFile * keyfile, + const char * keyfile_name, + NMKeyfileReadHandler read_handler, + void * read_data, + gboolean needs_normalization) +{ + GError * error = NULL; + NMConnection *con; + gs_free char *filename = NULL; + gs_free char *base_dir = NULL; + + g_assert(keyfile); + g_assert(!keyfile_name || (keyfile_name[0] == '/')); + + base_dir = g_path_get_dirname(keyfile_name); + filename = g_path_get_basename(keyfile_name); + + con = nm_keyfile_read(keyfile, + base_dir, + NM_KEYFILE_HANDLER_FLAGS_NONE, + read_handler, + read_data, + &error); + g_assert_no_error(error); + g_assert(NM_IS_CONNECTION(con)); + + nm_keyfile_read_ensure_id(con, filename); + nm_keyfile_read_ensure_uuid(con, keyfile_name); + + if (needs_normalization) { + nmtst_assert_connection_verifies_after_normalization(con, 0, 0); + nmtst_connection_normalize(con); + } else { + { + NMSettingConnection *s_con; + + /* a non-slave connection must have a proxy setting, but + * keyfile reader does not add that (unless a [proxy] section + * is present. */ + s_con = nm_connection_get_setting_connection(con); + if (s_con && !nm_setting_connection_get_master(s_con) + && !nm_connection_get_setting_proxy(con)) + nm_connection_add_setting(con, nm_setting_proxy_new()); + } + nmtst_assert_connection_verifies_without_normalization(con); + } + return con; +} + +static void +_keyfile_convert(NMConnection ** con, + GKeyFile ** keyfile, + const char * keyfile_name, + NMKeyfileReadHandler read_handler, + void * read_data, + NMKeyfileWriteHandler write_handler, + void * write_data, + gboolean needs_normalization) +{ + NMConnection * c0; + GKeyFile * k0; + gs_unref_object NMConnection *c0_k1_c2 = NULL, *k0_c1 = NULL, *k0_c1_k2_c3 = NULL; + nm_auto_unref_keyfile GKeyFile *k0_c1_k2 = NULL, *c0_k1 = NULL, *c0_k1_c2_k3 = NULL; + + /* convert from @con to @keyfile and check that we can make + * full round trips and obtaining the same result. */ + + g_assert(con); + g_assert(keyfile); + g_assert(*con || *keyfile); + + c0 = *con; + k0 = *keyfile; + + if (c0) { + c0_k1 = _nm_keyfile_write(c0, write_handler, write_data); + c0_k1_c2 = _nm_keyfile_read(c0_k1, keyfile_name, read_handler, read_data, FALSE); + c0_k1_c2_k3 = _nm_keyfile_write(c0_k1_c2, write_handler, write_data); + + g_assert(_nm_keyfile_equals(c0_k1, c0_k1_c2_k3, TRUE)); + } + if (k0) { + NMSetting8021x *s1, *s2; + + k0_c1 = _nm_keyfile_read(k0, keyfile_name, read_handler, read_data, needs_normalization); + k0_c1_k2 = _nm_keyfile_write(k0_c1, write_handler, write_data); + k0_c1_k2_c3 = _nm_keyfile_read(k0_c1_k2, keyfile_name, read_handler, read_data, FALSE); + + /* It is a expected behavior, that if @k0 contains a relative path ca-cert, @k0_c1 will + * contain that path as relative. But @k0_c1_k2 and @k0_c1_k2_c3 will have absolute paths. + * In this case, hack up @k0_c1_k2_c3 to contain the same relative path. */ + s1 = nm_connection_get_setting_802_1x(k0_c1); + s2 = nm_connection_get_setting_802_1x(k0_c1_k2_c3); + if (s1 || s2) { + g_assert_cmpint(nm_setting_802_1x_get_ca_cert_scheme(s1), + ==, + nm_setting_802_1x_get_ca_cert_scheme(s2)); + switch (nm_setting_802_1x_get_ca_cert_scheme(s1)) { + case NM_SETTING_802_1X_CK_SCHEME_PATH: + { + const char *p1 = nm_setting_802_1x_get_ca_cert_path(s1); + const char *p2 = nm_setting_802_1x_get_ca_cert_path(s2); + + nmtst_assert_resolve_relative_path_equals(p1, p2); + if (strcmp(p1, p2) != 0) { + gs_free char * puri = NULL; + gs_unref_bytes GBytes *pfile = NULL; + + g_assert(p1[0] != '/' && p2[0] == '/'); + + /* one of the paths is a relative path and the other is absolute. This is an + * expected difference. + * Make the paths of s2 identical to s1... */ + puri = g_strconcat(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, p1, NULL); + pfile = g_bytes_new(puri, strlen(puri) + 1); + g_object_set(s2, NM_SETTING_802_1X_CA_CERT, pfile, NULL); + } + } break; + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + { + GBytes *b1, *b2; + + b1 = nm_setting_802_1x_get_ca_cert_blob(s1); + b2 = nm_setting_802_1x_get_ca_cert_blob(s2); + g_assert(b1); + g_assert(b2); + g_assert(g_bytes_equal(b1, b2)); + break; + } + default: + break; + } + } + + nmtst_assert_connection_equals(k0_c1, FALSE, k0_c1_k2_c3, FALSE); + } + + if (!k0) + *keyfile = g_key_file_ref(c0_k1); + else if (!c0) + *con = g_object_ref(k0_c1); + else { + /* finally, if both a keyfile and a connection are given, assert that they are equal + * after a round of conversion. */ + g_assert(_nm_keyfile_equals(c0_k1, k0_c1_k2, TRUE)); + nmtst_assert_connection_equals(k0_c1, FALSE, c0_k1_c2, FALSE); + } +} + +/*****************************************************************************/ + +static void +_test_8021x_cert_check(NMConnection * con, + NMSetting8021xCKScheme expected_scheme, + const void * value, + gssize val_len) +{ + GKeyFile * keyfile = NULL; + NMSetting8021x *s_8021x; + gs_free char * kval = NULL; + + _keyfile_convert(&con, &keyfile, "/_test_8021x_cert_check/foo", NULL, NULL, NULL, NULL, FALSE); + + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == expected_scheme); + + if (expected_scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + const char *path = nm_setting_802_1x_get_ca_cert_path(s_8021x); + + g_assert_cmpstr(path, ==, value); + g_assert(val_len == -1 || strlen(path) == val_len); + + kval = g_key_file_get_string(keyfile, "802-1x", "ca-cert", NULL); + g_assert(kval); + g_assert_cmpstr(kval, ==, value); + } else if (expected_scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + GBytes * blob = nm_setting_802_1x_get_ca_cert_blob(s_8021x); + gs_free char *file_blob = NULL; + + if (val_len == -1) { + gsize l; + gboolean success; + + success = g_file_get_contents(value, &file_blob, &l, NULL); + g_assert(success); + + value = file_blob; + val_len = l; + } + + g_assert(blob); + g_assert(nm_utils_gbytes_equal_mem(blob, value, val_len)); + + kval = g_key_file_get_string(keyfile, "802-1x", "ca-cert", NULL); + g_assert(kval); + g_assert(g_str_has_prefix(kval, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)); + } + + g_key_file_unref(keyfile); +} + +static void +_test_8021x_cert_check_blob_full(NMConnection *con, const void *data, gsize len) +{ + GBytes * bytes; + NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x(con); + + bytes = g_bytes_new(data, len); + g_object_set(s_8021x, NM_SETTING_802_1X_CA_CERT, bytes, NULL); + _test_8021x_cert_check(con, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + g_bytes_get_data(bytes, NULL), + g_bytes_get_size(bytes)); + g_bytes_unref(bytes); +} +#define _test_8021x_cert_check_blob(con, data) \ + _test_8021x_cert_check_blob_full(con, data, NM_STRLEN(data)) + +static void +_test_8021x_cert_from_files(const char *cert, const char *key) +{ + NMSetting8021x *s_8021x; + gs_unref_object NMConnection *con = + nmtst_create_minimal_connection("test-cert", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + GError * error = NULL; + gboolean success; + NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; + gs_free char *full_TEST_WIRED_TLS_CA_CERT = nmtst_file_resolve_relative_path(cert, NULL); + gs_free char *full_TEST_WIRED_TLS_PRIVKEY = nmtst_file_resolve_relative_path(key, NULL); + + /* test writing/reading of certificates of NMSetting8021x */ + + /* create a valid connection with NMSetting8021x */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + nm_setting_802_1x_add_eap_method(s_8021x, "tls"); + g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + success = + nm_setting_802_1x_set_ca_cert(s_8021x, full_TEST_WIRED_TLS_CA_CERT, scheme, NULL, &error); + g_assert_no_error(error); + g_assert(success); + success = nm_setting_802_1x_set_client_cert(s_8021x, + full_TEST_WIRED_TLS_CA_CERT, + scheme, + NULL, + &error); + g_assert_no_error(error); + g_assert(success); + success = nm_setting_802_1x_set_private_key(s_8021x, + full_TEST_WIRED_TLS_PRIVKEY, + "test1", + scheme, + NULL, + &error); + g_assert_no_error(error); + g_assert(success); + + /* test resetting ca-cert to different values and see whether we can write/read. */ + + nm_connection_add_setting(con, NM_SETTING(s_8021x)); + nmtst_assert_connection_verifies_and_normalizable(con); + nmtst_connection_normalize(con); + + _test_8021x_cert_check(con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1); + + scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB; + success = + nm_setting_802_1x_set_ca_cert(s_8021x, full_TEST_WIRED_TLS_CA_CERT, scheme, NULL, &error); + g_assert_no_error(error); + g_assert(success); + _test_8021x_cert_check(con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1); + + _test_8021x_cert_check_blob(con, "a"); + _test_8021x_cert_check_blob(con, "\0"); + _test_8021x_cert_check_blob(con, "10"); + _test_8021x_cert_check_blob(con, "data:;base64,a"); + _test_8021x_cert_check_blob_full(con, "data:;base64,a", NM_STRLEN("data:;base64,a") + 1); + _test_8021x_cert_check_blob(con, "data:;base64,file://a"); + _test_8021x_cert_check_blob(con, "123"); +} + +static void +test_8021x_cert(void) +{ + _test_8021x_cert_from_files(TEST_WIRED_TLS_CA_CERT, TEST_WIRED_TLS_PRIVKEY); +} + +static void +test_8021x_cert_tpm2key(void) +{ + _test_8021x_cert_from_files(TEST_WIRED_TLS_CA_CERT, TEST_WIRED_TLS_TPM2KEY); +} + +/*****************************************************************************/ + +static void +test_8021x_cert_read(void) +{ + GKeyFile * keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSetting8021x * s_8021x; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "type=ethernet", + "/test_8021x_cert_read/test0"); + CLEAR(&con, &keyfile); + + keyfile = _keyfile_load_from_data("[connection]\n" + "type=ethernet"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test1", NULL, NULL, NULL, NULL, TRUE); + CLEAR(&con, &keyfile); + + keyfile = _keyfile_load_from_data( + "[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + "ca-cert=48;130;2;52;48;130;1;161;2;16;2;173;102;126;78;69;254;94;87;111;60;152;25;94;221;" + "192;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;" + "48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;" + "73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;" + "114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;" + "121;48;30;23;13;57;52;49;49;48;57;48;48;48;48;48;48;90;23;13;49;48;48;49;48;55;50;51;53;" + "57;53;57;90;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;" + "32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;" + "11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;" + "97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;129;155;48;13;6;9;42;134;72;" + "134;247;13;1;1;1;5;0;3;129;137;0;48;129;133;2;126;0;146;206;122;193;174;131;62;90;170;137;" + "131;87;172;37;1;118;12;173;174;142;44;55;206;235;53;120;100;84;3;229;132;64;81;201;191;" + "143;8;226;138;130;8;210;22;134;55;85;233;177;33;2;173;118;104;129;154;5;162;75;201;75;37;" + "102;34;86;108;136;7;143;247;129;89;109;132;7;101;112;19;113;118;62;155;119;76;227;80;137;" + "86;152;72;185;29;167;41;26;19;46;74;17;89;156;30;21;213;73;84;44;115;58;105;130;177;151;" + "57;156;109;112;103;72;229;221;45;214;200;30;123;2;3;1;0;1;48;13;6;9;42;134;72;134;247;13;" + "1;1;2;5;0;3;126;0;101;221;126;225;178;236;176;226;58;224;236;113;70;154;25;17;184;211;199;" + "160;180;3;64;38;2;62;9;156;225;18;179;209;90;246;55;165;183;97;3;182;91;22;105;59;198;68;" + "8;12;136;83;12;107;151;73;199;62;53;220;108;185;187;170;223;92;187;58;47;147;96;182;169;" + "75;77;242;32;247;205;95;127;100;123;142;220;0;92;215;250;119;202;57;22;89;111;14;234;211;" + "181;131;127;77;77;66;86;118;180;201;95;4;248;56;248;235;210;95;117;95;205;123;252;229;142;" + "128;124;252;80;\n" + "client-cert=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;" + "107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;" + "109;0;\n" + "private-key=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;" + "107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;" + "109;0;\n" + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + CLEAR(&con, &keyfile); + + keyfile = + _keyfile_load_from_data("[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + /* unqualified strings are only recognized as path up to 500 chars*/ + "ca-cert=" + "/11111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111" + "/11111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111" + "/11111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111" + "/11111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111" + "/11111111111111111111111111111111111111111111111111111111111111111" + "111111111111111111111111111111111\n" + "client-cert=/" + "222222222222222222222222222222222222222222222222222222222222222222" + "222222222222222222222222222222221" + "/22222222222222222222222222222222222222222222222222222222222222222" + "2222222222222222222222222222222221" + "/22222222222222222222222222222222222222222222222222222222222222222" + "2222222222222222222222222222222221" + "/22222222222222222222222222222222222222222222222222222222222222222" + "2222222222222222222222222222222221" + "/22222222222222222222222222222222222222222222222222222222222222222" + "2222222222222222222222222222222222\n" + "private-key=file://" + "/33333333333333333333333333333333333333333333333333333333333333333" + "3333333333333333333333333333333331" + "/33333333333333333333333333333333333333333333333333333333333333333" + "3333333333333333333333333333333331" + "/33333333333333333333333333333333333333333333333333333333333333333" + "3333333333333333333333333333333331" + "/33333333333333333333333333333333333333333333333333333333333333333" + "3333333333333333333333333333333331" + "/33333333333333333333333333333333333333333333333333333333333333333" + "333333333333333333333333333333333111111\n" + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert(g_str_has_prefix(nm_setting_802_1x_get_ca_cert_path(s_8021x), "/111111111111")); + g_assert_cmpint(strlen(nm_setting_802_1x_get_ca_cert_path(s_8021x)), ==, 499); + + g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + g_assert( + g_str_has_prefix(g_bytes_get_data(nm_setting_802_1x_get_client_cert_blob(s_8021x), NULL), + "/2222222222")); + g_assert_cmpint(g_bytes_get_size(nm_setting_802_1x_get_client_cert_blob(s_8021x)), + ==, + 500 + 1 /* keyfile reader adds a trailing NUL */); + + g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert(g_str_has_prefix(nm_setting_802_1x_get_private_key_path(s_8021x), "/333333333")); + g_assert_cmpint(strlen(nm_setting_802_1x_get_private_key_path(s_8021x)), ==, 505); + CLEAR(&con, &keyfile); + + keyfile = _keyfile_load_from_data("[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + "ca-cert=/\n" + "client-cert=a.pem\n" + "private-key=data:;base64,aGFsbG8=\n" // hallo + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert_cmpstr(nm_setting_802_1x_get_ca_cert_path(s_8021x), ==, "/"); + + g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert_cmpstr(nm_setting_802_1x_get_client_cert_path(s_8021x), + ==, + "/test_8021x_cert_read/a.pem"); + + g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "hallo", -1); + CLEAR(&con, &keyfile); + + keyfile = _keyfile_load_from_data("[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + "ca-cert=file://data:;base64,x\n" + "client-cert=abc.der\n" + "private-key=abc.deR\n" + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert_cmpstr(nm_setting_802_1x_get_ca_cert_path(s_8021x), ==, "data:;base64,x"); + + g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert_cmpstr(nm_setting_802_1x_get_client_cert_path(s_8021x), + ==, + "/test_8021x_cert_read/abc.der"); + + g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "abc.deR\0", 8); + CLEAR(&con, &keyfile); + + keyfile = + _keyfile_load_from_data("[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + "ca-cert=104;97;108;108;111;\n" /* "hallo" without trailing NUL */ + "client-cert=104;097;108;108;111;0;\n" + "private-key=hallo\n" + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_ca_cert_blob(s_8021x), "hallo", 5); + + g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_client_cert_blob(s_8021x), "hallo\0", 6); + + g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "hallo\0", 6); + CLEAR(&con, &keyfile); +} + +static void +test_team_conf_read_valid(void) +{ + GKeyFile * keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingTeam * s_team; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "type=team\n" + "interface-name=nm-team1\n" + "[team]\n" + "config={\"foo\":\"bar\"}", + "/test_team_conf_read/valid"); + + g_assert(con); + s_team = nm_connection_get_setting_team(con); + g_assert(s_team); + g_assert_cmpstr(nm_setting_team_get_config(s_team), ==, "{\"foo\":\"bar\"}"); + + CLEAR(&con, &keyfile); +} + +static void +test_team_conf_read_invalid(void) +{ + GKeyFile * keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingTeam * s_team; + + if (!nm_json_vt()) { + g_test_skip("team test requires JSON validation"); + return; + } + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "type=team\n" + "interface-name=nm-team1\n" + "[team]\n" + "config={foobar}", + "/test_team_conf_read/invalid"); + + g_assert(con); + s_team = nm_connection_get_setting_team(con); + g_assert(s_team); + g_assert(nm_setting_team_get_config(s_team) == NULL); + + CLEAR(&con, &keyfile); +} + +/*****************************************************************************/ + +static void +test_user_1(void) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingUser * s_user; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "id=t\n" + "type=ethernet\n" + "\n" + "[user]\n" + "my-value.x=value1\n" + "", + "/test_user_1/invalid"); + g_assert(con); + s_user = NM_SETTING_USER(nm_connection_get_setting(con, NM_TYPE_SETTING_USER)); + g_assert(s_user); + g_assert_cmpstr(nm_setting_user_get_data(s_user, "my-value.x"), ==, "value1"); + + CLEAR(&con, &keyfile); + + con = nmtst_create_minimal_connection("user-2", + "8b85fb8d-3070-48ba-93d9-53eee231d9a2", + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_user = NM_SETTING_USER(nm_setting_user_new()); + +#define _USER_SET_DATA(s_user, key, val) \ + G_STMT_START \ + { \ + GError * _error = NULL; \ + gboolean _success; \ + \ + _success = nm_setting_user_set_data((s_user), (key), (val), &_error); \ + nmtst_assert_success(_success, _error); \ + } \ + G_STMT_END + +#define _USER_SET_DATA_X(s_user, key) _USER_SET_DATA(s_user, key, "val=" key "") + + _USER_SET_DATA(s_user, "my.val1", ""); + _USER_SET_DATA_X(s_user, "my.val2"); + _USER_SET_DATA_X(s_user, "my.v__al3"); + _USER_SET_DATA_X(s_user, "my._v"); + _USER_SET_DATA_X(s_user, "my.v+"); + _USER_SET_DATA_X(s_user, "my.Av"); + _USER_SET_DATA_X(s_user, "MY.AV"); + _USER_SET_DATA_X(s_user, "MY.8V"); + _USER_SET_DATA_X(s_user, "MY.8-V"); + _USER_SET_DATA_X(s_user, "MY.8_V"); + _USER_SET_DATA_X(s_user, "MY.8+V"); + _USER_SET_DATA_X(s_user, "MY.8/V"); + _USER_SET_DATA_X(s_user, "MY.8=V"); + _USER_SET_DATA_X(s_user, "MY.-"); + _USER_SET_DATA_X(s_user, "MY._"); + _USER_SET_DATA_X(s_user, "MY.+"); + _USER_SET_DATA_X(s_user, "MY./"); + _USER_SET_DATA_X(s_user, "MY.="); + _USER_SET_DATA_X(s_user, "my.keys.1"); + _USER_SET_DATA_X(s_user, "my.other.KEY.42"); + + nm_connection_add_setting(con, NM_SETTING(s_user)); + nmtst_connection_normalize(con); + + _keyfile_convert(&con, &keyfile, "/test_user_1/foo", NULL, NULL, NULL, NULL, FALSE); +} + +/*****************************************************************************/ + +static void +test_vpn_1(void) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingVpn * s_vpn; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "id=t\n" + "type=vpn\n" + "\n" + "[vpn]\n" + "service-type=a.b.c\n" + "vpn-key-1=value1\n" + "", + "/test_vpn_1/invalid"); + g_assert(con); + s_vpn = NM_SETTING_VPN(nm_connection_get_setting(con, NM_TYPE_SETTING_VPN)); + g_assert(s_vpn); + g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, "vpn-key-1"), ==, "value1"); + + CLEAR(&con, &keyfile); +} + +/*****************************************************************************/ + +static void +test_bridge_vlans(void) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingBridge * s_bridge; + NMBridgeVlan * vlan; + guint16 vid, vid_end; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "id=t\n" + "type=bridge\n" + "interface-name=br4\n" + "\n" + "[bridge]\n" + "vlans=900 , 1 pvid untagged, 100-123 untagged\n" + "", + "/test_bridge_port/vlans"); + s_bridge = NM_SETTING_BRIDGE(nm_connection_get_setting(con, NM_TYPE_SETTING_BRIDGE)); + g_assert(s_bridge); + g_assert_cmpuint(nm_setting_bridge_get_num_vlans(s_bridge), ==, 3); + + vlan = nm_setting_bridge_get_vlan(s_bridge, 0); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); + g_assert_cmpuint(vid, ==, 1); + g_assert_cmpuint(vid_end, ==, 1); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, TRUE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); + + vlan = nm_setting_bridge_get_vlan(s_bridge, 1); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); + g_assert_cmpuint(vid, ==, 100); + g_assert_cmpuint(vid_end, ==, 123); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); + + vlan = nm_setting_bridge_get_vlan(s_bridge, 2); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); + g_assert_cmpuint(vid, ==, 900); + g_assert_cmpuint(vid_end, ==, 900); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, FALSE); + + CLEAR(&con, &keyfile); +} + +static void +test_bridge_port_vlans(void) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingBridgePort * s_port; + NMBridgeVlan * vlan; + guint16 vid_start, vid_end; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "id=t\n" + "type=dummy\n" + "interface-name=dummy1\n" + "master=br0\n" + "slave-type=bridge\n" + "\n" + "[bridge-port]\n" + "vlans=4094 pvid , 10-20 untagged\n" + "", + "/test_bridge_port/vlans"); + s_port = NM_SETTING_BRIDGE_PORT(nm_connection_get_setting(con, NM_TYPE_SETTING_BRIDGE_PORT)); + g_assert(s_port); + g_assert_cmpuint(nm_setting_bridge_port_get_num_vlans(s_port), ==, 2); + + vlan = nm_setting_bridge_port_get_vlan(s_port, 0); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); + g_assert_cmpuint(vid_start, ==, 10); + g_assert_cmpuint(vid_end, ==, 20); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); + + vlan = nm_setting_bridge_port_get_vlan(s_port, 1); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); + g_assert_cmpuint(vid_start, ==, 4094); + g_assert_cmpuint(vid_end, ==, 4094); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, TRUE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, FALSE); + + CLEAR(&con, &keyfile); +} + +/*****************************************************************************/ + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init(&argc, &argv, TRUE); + + g_test_add_func("/core/keyfile/encode_key", test_encode_key); + g_test_add_func("/core/keyfile/test_8021x_cert", test_8021x_cert); + g_test_add_func("/core/keyfile/test_8021x_cert_tpm2key", test_8021x_cert_tpm2key); + g_test_add_func("/core/keyfile/test_8021x_cert_read", test_8021x_cert_read); + g_test_add_func("/core/keyfile/test_team_conf_read/valid", test_team_conf_read_valid); + g_test_add_func("/core/keyfile/test_team_conf_read/invalid", test_team_conf_read_invalid); + g_test_add_func("/core/keyfile/test_user/1", test_user_1); + g_test_add_func("/core/keyfile/test_vpn/1", test_vpn_1); + g_test_add_func("/core/keyfile/bridge/vlans", test_bridge_vlans); + g_test_add_func("/core/keyfile/bridge-port/vlans", test_bridge_port_vlans); + + return g_test_run(); +} diff --git a/src/libnm-core-impl/tests/test-secrets.c b/src/libnm-core-impl/tests/test-secrets.c new file mode 100644 index 0000000000..e2a58ded3f --- /dev/null +++ b/src/libnm-core-impl/tests/test-secrets.c @@ -0,0 +1,681 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2008 - 2011 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-8021x.h" +#include "nm-setting-cdma.h" +#include "nm-setting-connection.h" +#include "nm-setting-gsm.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-vpn.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-wireless.h" +#include "nm-simple-connection.h" +#include "nm-utils.h" +#include "libnm-core-intern/nm-core-internal.h" + +#include "nm-utils/nm-test-utils.h" + +#define TEST_CERT_DIR NM_BUILD_SRCDIR "/src/libnm-core-impl/tests/certs" +#define TEST_NEED_SECRETS_EAP_TLS_CA_CERT TEST_CERT_DIR "/test_ca_cert.pem" +#define TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT TEST_CERT_DIR "/test_key_and_cert.pem" +#define TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY TEST_CERT_DIR "/test_key_and_cert.pem" + +static void +_assert_hints_has(GPtrArray *hints, const char *item) +{ + guint i; + guint found = 0; + + g_assert(hints); + g_assert(item); + for (i = 0; i < hints->len; i++) { + g_assert(hints->pdata[i]); + if (strcmp(hints->pdata[i], item) == 0) + found++; + } + g_assert_cmpint(found, ==, 1); +} + +static NMConnection * +make_tls_connection(const char *detail, NMSetting8021xCKScheme scheme) +{ + NMConnection * connection; + NMSettingConnection *s_con; + NMSetting8021x * s_8021x; + NMSettingWired * s_wired; + NMSettingIP4Config * s_ip4; + char * uuid; + gboolean success; + GError * error = NULL; + + connection = nm_simple_connection_new(); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new(); + nm_connection_add_setting(connection, NM_SETTING(s_con)); + + uuid = nm_utils_uuid_generate(); + g_object_set(s_con, + NM_SETTING_CONNECTION_ID, + "Test Need TLS Secrets", + NM_SETTING_CONNECTION_UUID, + uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, + TRUE, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free(uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wired)); + + /* Wireless security setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + nm_connection_add_setting(connection, NM_SETTING(s_8021x)); + + g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + + nm_setting_802_1x_add_eap_method(s_8021x, "tls"); + + success = nm_setting_802_1x_set_ca_cert(s_8021x, + TEST_NEED_SECRETS_EAP_TLS_CA_CERT, + scheme, + NULL, + &error); + nmtst_assert_success(success, error); + + success = nm_setting_802_1x_set_client_cert(s_8021x, + TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, + scheme, + NULL, + &error); + nmtst_assert_success(success, error); + + success = nm_setting_802_1x_set_private_key(s_8021x, + TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, + "test", + scheme, + NULL, + &error); + nmtst_assert_success(success, error); + + success = nm_setting_set_secret_flags(NM_SETTING(s_8021x), + NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + &error); + nmtst_assert_success(success, error); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new(); + nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + nmtst_assert_connection_verifies_and_normalizable(connection); + + return connection; +} + +static void +test_need_tls_secrets_path(void) +{ + NMConnection *connection; + const char * setting_name; + GPtrArray * hints = NULL; + + connection = make_tls_connection("need-tls-secrets-path-key", NM_SETTING_802_1X_CK_SCHEME_PATH); + + /* Ensure we don't need any secrets since we just set up the connection */ + setting_name = nm_connection_need_secrets(connection, &hints); + g_assert(!setting_name); + g_assert(!hints); + + /* Connection is good; clear secrets and ensure private key password is then required */ + nm_connection_clear_secrets(connection); + + hints = NULL; + setting_name = nm_connection_need_secrets(connection, &hints); + g_assert_cmpstr(setting_name, ==, NM_SETTING_802_1X_SETTING_NAME); + _assert_hints_has(hints, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); + + g_ptr_array_free(hints, TRUE); + g_object_unref(connection); +} + +static void +test_need_tls_secrets_blob(void) +{ + NMConnection *connection; + const char * setting_name; + GPtrArray * hints = NULL; + + connection = make_tls_connection("need-tls-secrets-blob-key", NM_SETTING_802_1X_CK_SCHEME_BLOB); + + /* Ensure we don't need any secrets since we just set up the connection */ + setting_name = nm_connection_need_secrets(connection, &hints); + g_assert(!setting_name); + g_assert(!hints); + + /* Clear secrets and ensure password is again required */ + nm_connection_clear_secrets(connection); + + hints = NULL; + setting_name = nm_connection_need_secrets(connection, &hints); + g_assert_cmpstr(setting_name, ==, NM_SETTING_802_1X_SETTING_NAME); + _assert_hints_has(hints, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); + + g_ptr_array_free(hints, TRUE); + g_object_unref(connection); +} + +static NMConnection * +make_tls_phase2_connection(const char *detail, NMSetting8021xCKScheme scheme) +{ + NMConnection * connection; + NMSettingConnection *s_con; + NMSetting8021x * s_8021x; + NMSettingWired * s_wired; + NMSettingIP4Config * s_ip4; + char * uuid; + gboolean success; + GError * error = NULL; + + connection = nm_simple_connection_new(); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new(); + nm_connection_add_setting(connection, NM_SETTING(s_con)); + + uuid = nm_utils_uuid_generate(); + g_object_set(s_con, + NM_SETTING_CONNECTION_ID, + "Test Need TLS Secrets", + NM_SETTING_CONNECTION_UUID, + uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, + TRUE, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free(uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wired)); + + /* Wireless security setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + nm_connection_add_setting(connection, NM_SETTING(s_8021x)); + + g_object_set(s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "blahblah", NULL); + g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + + nm_setting_802_1x_add_eap_method(s_8021x, "ttls"); + g_object_set(s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "tls", NULL); + + success = nm_setting_802_1x_set_phase2_ca_cert(s_8021x, + TEST_NEED_SECRETS_EAP_TLS_CA_CERT, + scheme, + NULL, + &error); + nmtst_assert_success(success, error); + + success = nm_setting_802_1x_set_phase2_client_cert(s_8021x, + TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, + scheme, + NULL, + &error); + nmtst_assert_success(success, error); + + success = nm_setting_802_1x_set_phase2_private_key(s_8021x, + TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, + "test", + scheme, + NULL, + &error); + nmtst_assert_success(success, error); + + success = nm_setting_set_secret_flags(NM_SETTING(s_8021x), + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + &error); + nmtst_assert_success(success, error); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new(); + nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + nmtst_assert_connection_verifies_and_normalizable(connection); + return connection; +} + +static void +test_need_tls_phase2_secrets_path(void) +{ + NMConnection *connection; + const char * setting_name; + GPtrArray * hints = NULL; + + connection = make_tls_phase2_connection("need-tls-phase2-secrets-path-key", + NM_SETTING_802_1X_CK_SCHEME_PATH); + + /* Ensure we don't need any secrets since we just set up the connection */ + setting_name = nm_connection_need_secrets(connection, &hints); + g_assert(!setting_name); + g_assert(!hints); + + /* Connection is good; clear secrets and ensure private key password is then required */ + nm_connection_clear_secrets(connection); + + hints = NULL; + setting_name = nm_connection_need_secrets(connection, &hints); + g_assert_cmpstr(setting_name, ==, NM_SETTING_802_1X_SETTING_NAME); + _assert_hints_has(hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); + + g_ptr_array_free(hints, TRUE); + g_object_unref(connection); +} + +static void +test_need_tls_phase2_secrets_blob(void) +{ + NMConnection *connection; + const char * setting_name; + GPtrArray * hints = NULL; + + connection = make_tls_phase2_connection("need-tls-phase2-secrets-blob-key", + NM_SETTING_802_1X_CK_SCHEME_BLOB); + + /* Ensure we don't need any secrets since we just set up the connection */ + setting_name = nm_connection_need_secrets(connection, &hints); + g_assert(!setting_name); + g_assert(!hints); + + /* Connection is good; clear secrets and ensure private key password is then required */ + nm_connection_clear_secrets(connection); + + hints = NULL; + setting_name = nm_connection_need_secrets(connection, &hints); + g_assert_cmpstr(setting_name, ==, NM_SETTING_802_1X_SETTING_NAME); + _assert_hints_has(hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); + + g_ptr_array_free(hints, TRUE); + g_object_unref(connection); +} + +static NMConnection * +wifi_connection_new(void) +{ + NMConnection * connection; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + NMSettingWirelessSecurity *s_wsec; + unsigned char tmpssid[] = {0x31, 0x33, 0x33, 0x37}; + char * uuid; + GBytes * ssid; + + connection = nm_simple_connection_new(); + g_assert(connection); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new(); + g_assert(s_con); + + uuid = nm_utils_uuid_generate(); + g_object_set(s_con, + NM_SETTING_CONNECTION_ID, + "Test Wireless", + NM_SETTING_CONNECTION_UUID, + uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, + FALSE, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free(uuid); + nm_connection_add_setting(connection, NM_SETTING(s_con)); + + /* Wireless setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); + g_assert(s_wifi); + + ssid = g_bytes_new(tmpssid, sizeof(tmpssid)); + g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL); + g_bytes_unref(ssid); + nm_connection_add_setting(connection, NM_SETTING(s_wifi)); + + /* Wifi security */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); + g_assert(s_wsec); + + g_object_set(G_OBJECT(s_wsec), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NULL); + nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + + return connection; +} + +static GVariant * +build_wep_secrets(const char *wepkey) +{ + GVariantBuilder builder; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&builder, + "{sv}", + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + g_variant_new_string(wepkey)); + g_variant_builder_add(&builder, + "{sv}", + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + g_variant_new_uint32(NM_WEP_KEY_TYPE_KEY)); + + return g_variant_builder_end(&builder); +} + +static void +test_update_secrets_wifi_single_setting(void) +{ + NMConnection * connection; + NMSettingWirelessSecurity *s_wsec; + GVariant * secrets; + GError * error = NULL; + gboolean success; + const char * wepkey = "11111111111111111111111111"; + const char * tmp; + + /* Test update with a hashed setting of 802-11-wireless secrets */ + + connection = wifi_connection_new(); + + secrets = build_wep_secrets(wepkey); + success = nm_connection_update_secrets(connection, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + secrets, + &error); + g_assert_no_error(error); + g_assert(success); + + g_variant_unref(secrets); + + /* Make sure the secret is now in the connection */ + s_wsec = nm_connection_get_setting_wireless_security(connection); + g_assert(s_wsec); + tmp = nm_setting_wireless_security_get_wep_key(s_wsec, 0); + g_assert_cmpstr(tmp, ==, wepkey); + + g_object_unref(connection); +} + +static void +test_update_secrets_wifi_full_hash(void) +{ + NMConnection * connection; + NMSettingWirelessSecurity *s_wsec; + GVariantBuilder builder; + GVariant * all; + GError * error = NULL; + gboolean success; + const char * wepkey = "11111111111111111111111111"; + const char * tmp; + + /* Test update with a hashed connection containing only 802-11-wireless + * setting and secrets. + */ + + connection = wifi_connection_new(); + + g_variant_builder_init(&builder, NM_VARIANT_TYPE_CONNECTION); + g_variant_builder_add(&builder, + "{s@a{sv}}", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + build_wep_secrets(wepkey)); + all = g_variant_builder_end(&builder); + + success = nm_connection_update_secrets(connection, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + all, + &error); + g_assert_no_error(error); + g_assert(success); + + g_variant_unref(all); + + /* Make sure the secret is now in the connection */ + s_wsec = nm_connection_get_setting_wireless_security(connection); + g_assert(s_wsec); + tmp = nm_setting_wireless_security_get_wep_key(s_wsec, 0); + g_assert_cmpstr(tmp, ==, wepkey); + + g_object_unref(connection); +} + +static void +test_update_secrets_wifi_bad_setting_name(void) +{ + NMConnection *connection; + GVariant * secrets; + GError * error = NULL; + gboolean success; + const char * wepkey = "11111111111111111111111111"; + + /* Test that passing an invalid setting name to + * nm_connection_update_secrets() fails with the correct error. + */ + + connection = wifi_connection_new(); + + secrets = build_wep_secrets(wepkey); + + success = nm_connection_update_secrets(connection, "asdfasdfasdfasf", secrets, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND); + g_assert(success == FALSE); + + g_clear_error(&error); + g_variant_unref(secrets); + g_object_unref(connection); +} + +static void +test_update_secrets_whole_connection(void) +{ + NMConnection * connection; + NMSettingWirelessSecurity *s_wsec; + GVariant * secrets; + GError * error = NULL; + gboolean success; + const char * wepkey = "11111111111111111111111111"; + + /* Test calling nm_connection_update_secrets() with an entire hashed + * connection including non-secrets. + */ + + connection = wifi_connection_new(); + + /* Build up the secrets dictionary */ + secrets = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); + NMTST_VARIANT_EDITOR(secrets, + NMTST_VARIANT_ADD_PROPERTY(NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + "s", + wepkey);); + + success = nm_connection_update_secrets(connection, NULL, secrets, &error); + g_assert_no_error(error); + g_assert(success == TRUE); + + g_variant_unref(secrets); + + s_wsec = nm_connection_get_setting_wireless_security(connection); + g_assert(s_wsec); + g_assert_cmpstr(nm_setting_wireless_security_get_wep_key(s_wsec, 0), ==, wepkey); + + g_object_unref(connection); +} + +static void +test_update_secrets_whole_connection_empty_hash(void) +{ + NMConnection *connection; + GVariant * secrets; + GError * error = NULL; + gboolean success; + + /* Test that updating secrets with an empty connection hash returns success */ + + connection = wifi_connection_new(); + secrets = g_variant_new_array(G_VARIANT_TYPE("{sa{sv}}"), NULL, 0); + success = nm_connection_update_secrets(connection, NULL, secrets, &error); + g_assert_no_error(error); + g_assert(success == TRUE); + g_variant_unref(secrets); + g_object_unref(connection); +} + +static void +test_update_secrets_whole_connection_bad_setting(void) +{ + NMConnection * connection; + NMSettingWirelessSecurity *s_wsec; + GVariant * secrets, *copy, *setting_hash; + const char * setting_name; + GVariantBuilder conn_builder; + GVariantIter conn_iter; + GError * error = NULL; + gboolean success; + const char * wepkey = "11111111111111111111111111"; + + /* Test that sending a hashed connection containing an invalid setting + * name fails with the right error. + */ + + connection = wifi_connection_new(); + s_wsec = nm_connection_get_setting_wireless_security(connection); + g_assert(s_wsec != NULL); + g_object_set(G_OBJECT(s_wsec), NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, wepkey, NULL); + + /* Build up the secrets hash */ + secrets = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); + + /* Copy the dict, renaming the wireless-security setting in the process + * (so we ensure libnm is returning the right error when it finds an entry + * in the connection hash that doesn't match any setting in the connection). + */ + g_variant_builder_init(&conn_builder, NM_VARIANT_TYPE_CONNECTION); + g_variant_iter_init(&conn_iter, secrets); + while (g_variant_iter_next(&conn_iter, "{&s@a{sv}}", &setting_name, &setting_hash)) { + if (strcmp(setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0) + setting_name = "asdfasdfasdfasdf"; + + g_variant_builder_add(&conn_builder, "{s@a{sv}}", setting_name, setting_hash); + g_variant_unref(setting_hash); + } + copy = g_variant_builder_end(&conn_builder); + g_variant_unref(secrets); + + success = nm_connection_update_secrets(connection, NULL, copy, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND); + g_assert(success == FALSE); + + g_clear_error(&error); + g_variant_unref(copy); + g_object_unref(connection); +} + +static void +test_update_secrets_whole_connection_empty_base_setting(void) +{ + NMConnection *connection; + GVariant * secrets, *setting; + GError * error = NULL; + gboolean success; + + /* Test that a hashed connection which does not have any hashed secrets + * for the requested setting returns success. + */ + + connection = wifi_connection_new(); + secrets = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ONLY_SECRETS); + g_assert_cmpint(g_variant_n_children(secrets), ==, 3); + + setting = g_variant_lookup_value(secrets, NM_SETTING_WIRELESS_SETTING_NAME, NULL); + g_assert(setting != NULL); + g_variant_unref(setting); + + success = nm_connection_update_secrets(connection, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + secrets, + &error); + g_assert_no_error(error); + g_assert(success); + + g_variant_unref(secrets); + g_object_unref(connection); +} + +static void +test_update_secrets_null_setting_name_with_setting_hash(void) +{ + NMConnection *connection; + GVariant * secrets; + GError * error = NULL; + gboolean success; + const char * wepkey = "11111111111111111111111111"; + + /* Ensure that a NULL setting name and only a hashed setting fails */ + + connection = wifi_connection_new(); + + secrets = build_wep_secrets(wepkey); + + NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(setting_name || full_connection)); + success = nm_connection_update_secrets(connection, NULL, secrets, &error); + g_test_assert_expected_messages(); + g_assert_no_error(error); + g_assert(!success); + + g_variant_unref(secrets); + g_object_unref(connection); +} + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init(&argc, &argv, TRUE); + + /* The tests */ + g_test_add_func("/libnm/need_tls_secrets_path", test_need_tls_secrets_path); + g_test_add_func("/libnm/need_tls_secrets_blob", test_need_tls_secrets_blob); + g_test_add_func("/libnm/need_tls_phase2_secrets_path", test_need_tls_phase2_secrets_path); + g_test_add_func("/libnm/need_tls_phase2_secrets_blob", test_need_tls_phase2_secrets_blob); + + g_test_add_func("/libnm/update_secrets_wifi_single_setting", + test_update_secrets_wifi_single_setting); + g_test_add_func("/libnm/update_secrets_wifi_full_hash", test_update_secrets_wifi_full_hash); + g_test_add_func("/libnm/update_secrets_wifi_bad_setting_name", + test_update_secrets_wifi_bad_setting_name); + + g_test_add_func("/libnm/update_secrets_whole_connection", test_update_secrets_whole_connection); + g_test_add_func("/libnm/update_secrets_whole_connection_empty_hash", + test_update_secrets_whole_connection_empty_hash); + g_test_add_func("/libnm/update_secrets_whole_connection_bad_setting", + test_update_secrets_whole_connection_bad_setting); + g_test_add_func("/libnm/update_secrets_whole_connection_empty_base_setting", + test_update_secrets_whole_connection_empty_base_setting); + g_test_add_func("/libnm/update_secrets_null_setting_name_with_setting_hash", + test_update_secrets_null_setting_name_with_setting_hash); + + return g_test_run(); +} diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c new file mode 100644 index 0000000000..1b08413f9c --- /dev/null +++ b/src/libnm-core-impl/tests/test-setting.c @@ -0,0 +1,4356 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2008 - 2017 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include +#include + +#include "nm-glib-aux/nm-json-aux.h" +#include "nm-base/nm-ethtool-utils-base.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "nm-setting-8021x.h" +#include "nm-setting-bond.h" +#include "nm-setting-dcb.h" +#include "nm-setting-ethtool.h" +#include "nm-setting-team.h" +#include "nm-setting-team-port.h" +#include "nm-setting-tc-config.h" +#include "nm-setting-dummy.h" +#include "nm-connection.h" +#include "nm-simple-connection.h" +#include "nm-setting-connection.h" +#include "nm-errors.h" +#include "libnm-core-intern/nm-keyfile-internal.h" + +#include "nm-utils/nm-test-utils.h" + +#define TEST_CERT_DIR NM_BUILD_SRCDIR "/src/libnm-core-impl/tests/certs" + +/*****************************************************************************/ + +/* converts @dict to a connection. In this case, @dict must be good, without warnings, so that + * NM_SETTING_PARSE_FLAGS_STRICT and NM_SETTING_PARSE_FLAGS_BEST_EFFORT yield the exact same results. */ +static NMConnection * +_connection_new_from_dbus_strict(GVariant *dict, gboolean normalize) +{ + gs_unref_object NMConnection *con_x_0 = NULL; + gs_unref_object NMConnection *con_x_s = NULL; + gs_unref_object NMConnection *con_x_e = NULL; + gs_unref_object NMConnection *con_n_0 = NULL; + gs_unref_object NMConnection *con_n_s = NULL; + gs_unref_object NMConnection *con_n_e = NULL; + gs_free_error GError *error = NULL; + guint i; + + g_assert(g_variant_is_of_type(dict, NM_VARIANT_TYPE_CONNECTION)); + + con_x_0 = _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_NONE, &error); + nmtst_assert_success(NM_IS_CONNECTION(con_x_0), error); + + con_x_s = _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_STRICT, &error); + nmtst_assert_success(NM_IS_CONNECTION(con_x_s), error); + + con_x_e = _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); + nmtst_assert_success(NM_IS_CONNECTION(con_x_e), error); + + con_n_0 = _nm_simple_connection_new_from_dbus(dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, &error); + nmtst_assert_success(NM_IS_CONNECTION(con_n_0), error); + + con_n_s = _nm_simple_connection_new_from_dbus(dict, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); + nmtst_assert_success(NM_IS_CONNECTION(con_n_s), error); + + con_n_e = _nm_simple_connection_new_from_dbus(dict, + NM_SETTING_PARSE_FLAGS_BEST_EFFORT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); + nmtst_assert_success(NM_IS_CONNECTION(con_n_e), error); + + nmtst_assert_connection_verifies(con_x_0); + nmtst_assert_connection_verifies(con_x_e); + nmtst_assert_connection_verifies(con_x_s); + + nmtst_assert_connection_verifies_without_normalization(con_n_0); + nmtst_assert_connection_verifies_without_normalization(con_n_e); + nmtst_assert_connection_verifies_without_normalization(con_n_s); + + /* randomly compare some pairs that we created. They must all be equal, + * after accounting for normalization. */ + for (i = 0; i < 10; i++) { + NMConnection *cons[] = {con_x_0, con_x_s, con_x_e, con_n_0, con_n_s, con_n_e}; + guint idx_a = (nmtst_get_rand_uint32() % G_N_ELEMENTS(cons)); + guint idx_b = (nmtst_get_rand_uint32() % G_N_ELEMENTS(cons)); + gboolean normalize_a, normalize_b; + + if (idx_a <= 2 && idx_b <= 2) { + normalize_a = nmtst_get_rand_bool(); + normalize_b = normalize_a; + } else if (idx_a > 2 && idx_b > 2) { + normalize_a = nmtst_get_rand_bool(); + normalize_b = nmtst_get_rand_bool(); + } else { + normalize_a = (idx_a <= 2) ? TRUE : nmtst_get_rand_bool(); + normalize_b = (idx_b <= 2) ? TRUE : nmtst_get_rand_bool(); + } + nmtst_assert_connection_equals(cons[idx_a], normalize_a, cons[idx_b], normalize_b); + } + + return (normalize) ? g_steal_pointer(&con_x_0) : g_steal_pointer(&con_n_0); +} + +/*****************************************************************************/ + +static char * +_create_random_ipaddr(int addr_family, gboolean as_service) +{ + char delimiter = as_service ? ':' : '/'; + int num; + + if (addr_family == AF_UNSPEC) + addr_family = nmtst_rand_select(AF_INET, AF_INET6); + + g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + + if (as_service) + num = (nmtst_get_rand_uint32() % 1000) + 30000; + else + num = addr_family == AF_INET ? 32 : 128; + + if (addr_family == AF_INET) + return g_strdup_printf("192.168.%u.%u%c%d", + nmtst_get_rand_uint32() % 256, + nmtst_get_rand_uint32() % 256, + delimiter, + num); + else + return g_strdup_printf("a:b:c::%02x:%02x%c%d", + nmtst_get_rand_uint32() % 256, + nmtst_get_rand_uint32() % 256, + delimiter, + num); +} + +/*****************************************************************************/ + +static void +compare_blob_data(const char *test, const char *key_path, GBytes *key) +{ + gs_free char *contents = NULL; + gsize len = 0; + GError * error = NULL; + gboolean success; + + g_assert(key && g_bytes_get_size(key) > 0); + + success = g_file_get_contents(key_path, &contents, &len, &error); + nmtst_assert_success(success, error); + + g_assert_cmpmem(contents, len, g_bytes_get_data(key, NULL), g_bytes_get_size(key)); +} + +static void +check_scheme_path(GBytes *value, const char *path) +{ + const guint8 *p; + gsize l; + + g_assert(value); + + p = g_bytes_get_data(value, &l); + g_assert_cmpint(l, ==, strlen(path) + NM_STRLEN(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + 1); + g_assert(memcmp(p, + NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, + strlen(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) + == 0); + p += strlen(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + g_assert(memcmp(p, path, strlen(path)) == 0); + p += strlen(path); + g_assert(*p == '\0'); +} + +static void +test_private_key_import(const char *path, const char *password, NMSetting8021xCKScheme scheme) +{ + NMSetting8021x * s_8021x; + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + NMSetting8021xCKFormat tmp_fmt; + GError * error = NULL; + GBytes * tmp_key = NULL, *client_cert = NULL; + const char * pw; + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + g_assert(s_8021x); + + success = nm_setting_802_1x_set_private_key(s_8021x, path, password, scheme, &format, &error); + nmtst_assert_success(success, error); + g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + tmp_fmt = nm_setting_802_1x_get_private_key_format(s_8021x); + g_assert(tmp_fmt == format); + + /* Make sure the password is what we expect */ + pw = nm_setting_802_1x_get_private_key_password(s_8021x); + g_assert(pw != NULL); + g_assert_cmpstr(pw, ==, password); + + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + tmp_key = nm_setting_802_1x_get_private_key_blob(s_8021x); + compare_blob_data("private-key-import", path, tmp_key); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + g_object_get(s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL); + check_scheme_path(tmp_key, path); + g_bytes_unref(tmp_key); + } else + g_assert_not_reached(); + + /* If it's PKCS#12 ensure the client cert is the same value */ + if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { + g_object_get(s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL); + g_assert(tmp_key); + + g_object_get(s_8021x, NM_SETTING_802_1X_CLIENT_CERT, &client_cert, NULL); + g_assert(client_cert); + + /* make sure they are the same */ + g_assert(g_bytes_equal(tmp_key, client_cert)); + + g_bytes_unref(tmp_key); + g_bytes_unref(client_cert); + } + + g_object_unref(s_8021x); +} + +static void +test_phase2_private_key_import(const char * path, + const char * password, + NMSetting8021xCKScheme scheme) +{ + NMSetting8021x * s_8021x; + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + NMSetting8021xCKFormat tmp_fmt; + GError * error = NULL; + GBytes * tmp_key = NULL, *client_cert = NULL; + const char * pw; + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + g_assert(s_8021x); + + success = + nm_setting_802_1x_set_phase2_private_key(s_8021x, path, password, scheme, &format, &error); + nmtst_assert_success(success, error); + g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + tmp_fmt = nm_setting_802_1x_get_phase2_private_key_format(s_8021x); + g_assert(tmp_fmt == format); + + /* Make sure the password is what we expect */ + pw = nm_setting_802_1x_get_phase2_private_key_password(s_8021x); + g_assert(pw); + g_assert_cmpstr(pw, ==, password); + + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + tmp_key = nm_setting_802_1x_get_phase2_private_key_blob(s_8021x); + compare_blob_data("phase2-private-key-import", path, tmp_key); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + g_object_get(s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL); + check_scheme_path(tmp_key, path); + g_bytes_unref(tmp_key); + } else + g_assert_not_reached(); + + /* If it's PKCS#12 ensure the client cert is the same value */ + if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { + g_object_get(s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL); + g_assert(tmp_key); + + g_object_get(s_8021x, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &client_cert, NULL); + g_assert(client_cert); + + /* make sure they are the same */ + g_assert(g_bytes_equal(tmp_key, client_cert)); + + g_bytes_unref(tmp_key); + g_bytes_unref(client_cert); + } + + g_object_unref(s_8021x); +} + +static void +test_wrong_password_keeps_data(const char *path, const char *password) +{ + NMSetting8021x * s_8021x; + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + GError * error = NULL; + const char * pw; + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + g_assert(s_8021x); + + success = nm_setting_802_1x_set_private_key(s_8021x, + path, + password, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + &error); + nmtst_assert_success(success, error); + g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + + /* Now try to set it to something that's not a certificate */ + format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + success = nm_setting_802_1x_set_private_key(s_8021x, + "Makefile.am", + password, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + &error); + nmtst_assert_no_success(success, error); + g_assert(format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + g_clear_error(&error); + + /* Make sure the password hasn't changed */ + pw = nm_setting_802_1x_get_private_key_password(s_8021x); + g_assert(pw); + g_assert_cmpstr(pw, ==, password); + + g_object_unref(s_8021x); +} + +static void +test_clear_private_key(const char *path, const char *password) +{ + NMSetting8021x * s_8021x; + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + GError * error = NULL; + const char * pw; + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + g_assert(s_8021x); + + success = nm_setting_802_1x_set_private_key(s_8021x, + path, + password, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + &error); + nmtst_assert_success(success, error); + g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + + /* Make sure the password is what we expect */ + pw = nm_setting_802_1x_get_private_key_password(s_8021x); + g_assert(pw); + g_assert_cmpstr(pw, ==, password); + + /* Now clear it */ + success = nm_setting_802_1x_set_private_key(s_8021x, + NULL, + NULL, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + NULL, + &error); + nmtst_assert_success(success, error); + + /* Ensure the password is also now clear */ + g_assert(!nm_setting_802_1x_get_private_key_password(s_8021x)); + + g_object_unref(s_8021x); +} + +static void +test_wrong_phase2_password_keeps_data(const char *path, const char *password) +{ + NMSetting8021x * s_8021x; + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + GError * error = NULL; + const char * pw; + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + g_assert(s_8021x); + + success = nm_setting_802_1x_set_phase2_private_key(s_8021x, + path, + password, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + &error); + nmtst_assert_success(success, error); + g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + + /* Now try to set it to something that's not a certificate */ + format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + success = nm_setting_802_1x_set_phase2_private_key(s_8021x, + "Makefile.am", + password, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + &error); + nmtst_assert_no_success(success, error); + g_assert(format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + g_clear_error(&error); + + /* Make sure the password hasn't changed */ + pw = nm_setting_802_1x_get_phase2_private_key_password(s_8021x); + g_assert(pw); + g_assert_cmpstr(pw, ==, password); + + g_object_unref(s_8021x); +} + +static void +test_clear_phase2_private_key(const char *path, const char *password) +{ + NMSetting8021x * s_8021x; + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + GError * error = NULL; + const char * pw; + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + g_assert(s_8021x); + + success = nm_setting_802_1x_set_phase2_private_key(s_8021x, + path, + password, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + &error); + nmtst_assert_success(success, error); + g_assert(format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + + /* Make sure the password is what we expect */ + pw = nm_setting_802_1x_get_phase2_private_key_password(s_8021x); + g_assert(pw); + g_assert_cmpstr(pw, ==, password); + + /* Now clear it */ + success = nm_setting_802_1x_set_phase2_private_key(s_8021x, + NULL, + NULL, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + NULL, + &error); + nmtst_assert_success(success, error); + + /* Ensure the password is also now clear */ + g_assert(!nm_setting_802_1x_get_phase2_private_key_password(s_8021x)); + + g_object_unref(s_8021x); +} + +static void +test_8021x(gconstpointer test_data) +{ + char **parts, *path, *password; + + parts = g_strsplit((const char *) test_data, ", ", -1); + g_assert_cmpint(g_strv_length(parts), ==, 2); + + path = g_build_filename(TEST_CERT_DIR, parts[0], NULL); + password = parts[1]; + + /* Test phase1 and phase2 path scheme */ + test_private_key_import(path, password, NM_SETTING_802_1X_CK_SCHEME_PATH); + test_phase2_private_key_import(path, password, NM_SETTING_802_1X_CK_SCHEME_PATH); + + /* Test phase1 and phase2 blob scheme */ + test_private_key_import(path, password, NM_SETTING_802_1X_CK_SCHEME_BLOB); + test_phase2_private_key_import(path, password, NM_SETTING_802_1X_CK_SCHEME_BLOB); + + /* Test that using a wrong password does not change existing data */ + test_wrong_password_keeps_data(path, password); + test_wrong_phase2_password_keeps_data(path, password); + + /* Test clearing the private key */ + test_clear_private_key(path, password); + test_clear_phase2_private_key(path, password); + + g_free(path); + g_strfreev(parts); +} + +/*****************************************************************************/ + +static void +create_bond_connection(NMConnection **con, NMSettingBond **s_bond) +{ + NMSettingConnection *s_con; + + g_assert(con); + g_assert(s_bond); + + *con = nmtst_create_minimal_connection("bond", NULL, NM_SETTING_BOND_SETTING_NAME, &s_con); + + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bond0", NULL); + + *s_bond = (NMSettingBond *) nm_setting_bond_new(); + g_assert(*s_bond); + + nm_connection_add_setting(*con, NM_SETTING(*s_bond)); +} + +#define test_verify_options(exp, ...) _test_verify_options(exp, NM_MAKE_STRV(__VA_ARGS__)) + +static void +_test_verify_options(gboolean expected_result, const char *const *options) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingBond * s_bond; + const char *const * option; + + g_assert(NM_PTRARRAY_LEN(options) % 2 == 0); + + create_bond_connection(&con, &s_bond); + + for (option = options; option[0]; option += 2) + g_assert(nm_setting_bond_add_option(s_bond, option[0], option[1])); + + if (expected_result) { + nmtst_assert_connection_verifies_and_normalizable(con); + } else { + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + } +} + +static void +test_bond_verify(void) +{ + test_verify_options(TRUE, "mode", "3", "arp_interval", "0"); + test_verify_options(FALSE, + /* arp_interval not supported in balance-alb mode */ + "mode", + "balance-alb", + "arp_interval", + "1", + "arp_ip_target", + "1.2.3.4"); + test_verify_options(FALSE, + /* arp_ip_target requires arp_interval */ + "mode", + "balance-rr", + "arp_ip_target", + "1.2.3.4"); + test_verify_options(TRUE, + "mode", + "balance-rr", + "arp_interval", + "1", + "arp_ip_target", + "1.2.3.4"); + test_verify_options(FALSE, + /* num_grat_arp, num_unsol_na cannot be different */ + "mode", + "balance-rr", + "num_grat_arp", + "3", + "num_unsol_na", + "4"); + test_verify_options(TRUE, "mode", "balance-rr", "num_grat_arp", "5", "num_unsol_na", "5"); + test_verify_options(TRUE, "mode", "active-backup", "primary", "eth0"); + test_verify_options(FALSE, + /* primary requires mode=active-backup */ + "mode", + "802.3ad", + "primary", + "eth0"); + test_verify_options(TRUE, "mode", "802.3ad", "lacp_rate", "fast"); + test_verify_options(FALSE, + /* lacp_rate=fast requires mode=802.3ad */ + "mode", + "balance-rr", + "lacp_rate", + "fast"); + test_verify_options(TRUE, "mode", "802.3ad", "ad_actor_system", "ae:00:11:33:44:55"); + test_verify_options(TRUE, "mode", "0", "miimon", "0", "updelay", "0", "downdelay", "0"); + test_verify_options(TRUE, "mode", "0", "downdelay", "0", "updelay", "0"); + test_verify_options(TRUE, + "mode", + "0", + "miimon", + "100", + "arp_ip_target", + "1.1.1.1", + "arp_interval", + "200"); + test_verify_options(TRUE, + "mode", + "0", + "downdelay", + "100", + "arp_ip_target", + "1.1.1.1", + "arp_interval", + "200"); +} + +static void +test_bond_compare_options(gboolean exp_res, const char **opts1, const char **opts2) +{ + gs_unref_object NMSettingBond *s_bond1 = NULL, *s_bond2 = NULL; + const char ** p; + + s_bond1 = (NMSettingBond *) nm_setting_bond_new(); + g_assert(s_bond1); + s_bond2 = (NMSettingBond *) nm_setting_bond_new(); + g_assert(s_bond2); + + for (p = opts1; p[0] && p[1]; p += 2) + g_assert(nm_setting_bond_add_option(s_bond1, p[0], p[1])); + + for (p = opts2; p[0] && p[1]; p += 2) + g_assert(nm_setting_bond_add_option(s_bond2, p[0], p[1])); + + g_assert_cmpint(nm_setting_compare((NMSetting *) s_bond1, + (NMSetting *) s_bond2, + NM_SETTING_COMPARE_FLAG_EXACT), + ==, + exp_res); +} + +static void +test_bond_compare(void) +{ + test_bond_compare_options(TRUE, + ((const char *[]){"mode", "balance-rr", "miimon", "1", NULL}), + ((const char *[]){"mode", "balance-rr", "miimon", "1", NULL})); + test_bond_compare_options(FALSE, + ((const char *[]){"mode", "balance-rr", "miimon", "1", NULL}), + ((const char *[]){"mode", "balance-rr", "miimon", "2", NULL})); + + test_bond_compare_options(FALSE, + ((const char *[]){"miimon", "1", NULL}), + ((const char *[]){"miimon", "1", "updelay", "0", NULL})); + + test_bond_compare_options(FALSE, + ((const char *[]){"num_grat_arp", "2", NULL}), + ((const char *[]){"num_grat_arp", "1", NULL})); + test_bond_compare_options(FALSE, + ((const char *[]){"num_grat_arp", "3", NULL}), + ((const char *[]){"num_unsol_na", "3", NULL})); + test_bond_compare_options(FALSE, + ((const char *[]){"num_grat_arp", "4", NULL}), + ((const char *[]){"num_unsol_na", "4", "num_grat_arp", "4", NULL})); + + test_bond_compare_options(FALSE, + ((const char *[]){"mode", "balance-rr", "miimon", "100", NULL}), + ((const char *[]){"mode", "balance-rr", NULL})); +} + +static void +test_bond_normalize_options(const char **opts1, const char **opts2) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingBond * s_bond; + GError * error = NULL; + gboolean success; + const char ** p; + int num = 0; + + create_bond_connection(&con, &s_bond); + + for (p = opts1; p[0] && p[1]; p += 2) + g_assert(nm_setting_bond_add_option(s_bond, p[0], p[1])); + + nmtst_assert_connection_verifies_and_normalizable(con); + nmtst_connection_normalize(con); + success = nm_setting_verify((NMSetting *) s_bond, con, &error); + nmtst_assert_success(success, error); + + for (p = opts2; p[0] && p[1]; p += 2) { + g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, p[0]), ==, p[1]); + num++; + } + + g_assert_cmpint(num, ==, nm_setting_bond_get_num_options(s_bond)); +} + +static void +test_bond_normalize(void) +{ + test_bond_normalize_options( + ((const char *[]){"mode", "802.3ad", "ad_actor_system", "00:02:03:04:05:06", NULL}), + ((const char *[]){"mode", "802.3ad", "ad_actor_system", "00:02:03:04:05:06", NULL})); + test_bond_normalize_options(((const char *[]){"mode", "1", "miimon", "1", NULL}), + ((const char *[]){"mode", "active-backup", "miimon", "1", NULL})); + test_bond_normalize_options( + ((const char *[]){"mode", "balance-alb", "tlb_dynamic_lb", "1", NULL}), + ((const char *[]){"mode", "balance-alb", NULL})); + test_bond_normalize_options( + ((const char *[]){"mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL}), + ((const char *[]){"mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL})); + test_bond_normalize_options( + ((const char + *[]){"mode", "balance-rr", "ad_actor_sys_prio", "4", "packets_per_slave", "3", NULL}), + ((const char *[]){"mode", "balance-rr", "packets_per_slave", "3", NULL})); +} + +/*****************************************************************************/ + +#define DCB_FLAGS_ALL \ + (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + +static void +test_dcb_flags_valid(void) +{ + gs_unref_object NMSettingDcb *s_dcb = NULL; + GError * error = NULL; + gboolean success; + guint i; + + s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); + g_assert(s_dcb); + + g_assert_cmpint(nm_setting_dcb_get_app_fcoe_flags(s_dcb), ==, 0); + g_assert_cmpint(nm_setting_dcb_get_app_iscsi_flags(s_dcb), ==, 0); + g_assert_cmpint(nm_setting_dcb_get_app_fip_flags(s_dcb), ==, 0); + g_assert_cmpint(nm_setting_dcb_get_priority_flow_control_flags(s_dcb), ==, 0); + g_assert_cmpint(nm_setting_dcb_get_priority_group_flags(s_dcb), ==, 0); + + g_object_set(G_OBJECT(s_dcb), + NM_SETTING_DCB_APP_FCOE_FLAGS, + DCB_FLAGS_ALL, + NM_SETTING_DCB_APP_ISCSI_FLAGS, + DCB_FLAGS_ALL, + NM_SETTING_DCB_APP_FIP_FLAGS, + DCB_FLAGS_ALL, + NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, + DCB_FLAGS_ALL, + NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, + DCB_FLAGS_ALL, + NULL); + /* Priority Group Bandwidth must total 100% */ + for (i = 0; i < 7; i++) + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, i, 12); + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 7, 16); + + success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); + g_assert_no_error(error); + g_assert(success); + + g_assert_cmpint(nm_setting_dcb_get_app_fcoe_flags(s_dcb), ==, DCB_FLAGS_ALL); + g_assert_cmpint(nm_setting_dcb_get_app_iscsi_flags(s_dcb), ==, DCB_FLAGS_ALL); + g_assert_cmpint(nm_setting_dcb_get_app_fip_flags(s_dcb), ==, DCB_FLAGS_ALL); + g_assert_cmpint(nm_setting_dcb_get_priority_flow_control_flags(s_dcb), ==, DCB_FLAGS_ALL); + g_assert_cmpint(nm_setting_dcb_get_priority_group_flags(s_dcb), ==, DCB_FLAGS_ALL); +} + +#define TEST_FLAG(p, f, v) \ + { \ + /* GObject property min/max should ensure the property does not get set to \ + * the invalid value, so we ensure the value we just tried to set is 0 and \ + * that verify is successful since the property never got set. \ + */ \ + g_object_set(G_OBJECT(s_dcb), p, v, NULL); \ + g_assert_cmpint(f(s_dcb), ==, 0); \ + success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ + g_assert_no_error(error); \ + g_assert(success); \ + } + +static void +test_dcb_flags_invalid(void) +{ + gs_unref_object NMSettingDcb *s_dcb = NULL; + GError * error = NULL; + gboolean success; + + s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); + g_assert(s_dcb); + + NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + TEST_FLAG(NM_SETTING_DCB_APP_FCOE_FLAGS, nm_setting_dcb_get_app_fcoe_flags, 0x332523); + g_test_assert_expected_messages(); + + NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + TEST_FLAG(NM_SETTING_DCB_APP_ISCSI_FLAGS, nm_setting_dcb_get_app_iscsi_flags, 0xFF); + g_test_assert_expected_messages(); + + NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + TEST_FLAG(NM_SETTING_DCB_APP_FIP_FLAGS, nm_setting_dcb_get_app_fip_flags, 0x1111); + g_test_assert_expected_messages(); + + NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + TEST_FLAG(NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, + nm_setting_dcb_get_priority_flow_control_flags, + G_MAXUINT32); + g_test_assert_expected_messages(); + + NMTST_EXPECT("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*"); + TEST_FLAG( + NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, + nm_setting_dcb_get_priority_group_flags, + (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + + 1); + g_test_assert_expected_messages(); +} + +#define TEST_APP_PRIORITY(lcprop, ucprop, v) \ + { \ + g_object_set(G_OBJECT(s_dcb), \ + NM_SETTING_DCB_APP_##ucprop##_FLAGS, \ + NM_SETTING_DCB_FLAG_NONE, \ + NULL); \ + \ + g_object_set(G_OBJECT(s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, v, NULL); \ + g_assert_cmpint(nm_setting_dcb_get_app_##lcprop##_priority(s_dcb), ==, v); \ + \ + /* Assert that the setting is invalid while the app is disabled unless v is default */ \ + success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ + if (v >= 0) { \ + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); \ + g_assert(success == FALSE); \ + } else { \ + g_assert_no_error(error); \ + g_assert(success); \ + } \ + g_clear_error(&error); \ + \ + /* Set the enable flag and re-verify, this time it should be valid */ \ + g_object_set(G_OBJECT(s_dcb), \ + NM_SETTING_DCB_APP_##ucprop##_FLAGS, \ + NM_SETTING_DCB_FLAG_ENABLE, \ + NULL); \ + success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ + g_assert_no_error(error); \ + g_assert(success); \ + \ + g_object_set(G_OBJECT(s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, 0, NULL); \ + } + +static void +test_dcb_app_priorities(void) +{ + gs_unref_object NMSettingDcb *s_dcb = NULL; + GError * error = NULL; + gboolean success; + + s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); + g_assert(s_dcb); + + /* Defaults */ + g_assert_cmpint(nm_setting_dcb_get_app_fcoe_priority(s_dcb), ==, -1); + g_assert_cmpint(nm_setting_dcb_get_app_iscsi_priority(s_dcb), ==, -1); + g_assert_cmpint(nm_setting_dcb_get_app_fip_priority(s_dcb), ==, -1); + + TEST_APP_PRIORITY(fcoe, FCOE, 6); + TEST_APP_PRIORITY(iscsi, ISCSI, 5); + TEST_APP_PRIORITY(fip, FIP, 4); + + TEST_APP_PRIORITY(fcoe, FCOE, -1); + TEST_APP_PRIORITY(iscsi, ISCSI, -1); + TEST_APP_PRIORITY(fip, FIP, -1); +} + +#define TEST_PRIORITY_VALID(fn, id, val, flagsprop, verify) \ + { \ + /* Assert that setting the value gets the same value back out */ \ + nm_setting_dcb_set_priority_##fn(s_dcb, id, val); \ + g_assert_cmpint(nm_setting_dcb_get_priority_##fn(s_dcb, id), ==, val); \ + \ + if (verify) { \ + if (val != 0) { \ + /* Assert that verify fails because the flags do not include 'enabled' \ + * and a value has been set. \ + */ \ + success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); \ + g_assert(success == FALSE); \ + g_clear_error(&error); \ + } \ + \ + /* Assert that adding the 'enabled' flag verifies the setting */ \ + g_object_set(G_OBJECT(s_dcb), \ + NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, \ + NM_SETTING_DCB_FLAG_ENABLE, \ + NULL); \ + success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); \ + g_assert_no_error(error); \ + g_assert(success); \ + } \ + \ + /* Reset everything */ \ + g_object_set(G_OBJECT(s_dcb), \ + NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, \ + NM_SETTING_DCB_FLAG_NONE, \ + NULL); \ + nm_setting_dcb_set_priority_##fn(s_dcb, id, 0); \ + } + +/* If Priority Groups are enabled, PG bandwidth must equal 100% */ +#define SET_VALID_PRIORITY_GROUP_BANDWIDTH \ + { \ + guint x; \ + for (x = 0; x < 7; x++) \ + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, x, 12); \ + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 7, 16); \ + } + +static void +test_dcb_priorities_valid(void) +{ + gs_unref_object NMSettingDcb *s_dcb = NULL; + GError * error = NULL; + gboolean success; + guint i; + + s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); + g_assert(s_dcb); + + for (i = 0; i < 8; i++) + TEST_PRIORITY_VALID(flow_control, i, TRUE, FLOW_CONTROL, TRUE); + + SET_VALID_PRIORITY_GROUP_BANDWIDTH + for (i = 0; i < 8; i++) { + TEST_PRIORITY_VALID(group_id, i, i, GROUP, TRUE); + TEST_PRIORITY_VALID(group_id, i, 7 - i, GROUP, TRUE); + } + + /* Clear PG bandwidth from earlier tests */ + for (i = 0; i < 8; i++) + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, i, 0); + + /* Priority Group Bandwidth must add up to 100% if enabled, which requires + * some dancing for verifying individual values here. + */ + for (i = 0; i < 8; i++) { + guint other = 7 - (i % 8); + + /* Set another priority group to the remaining bandwidth */ + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, other, 100 - i); + TEST_PRIORITY_VALID(group_bandwidth, i, i, GROUP, TRUE); + + /* Set another priority group to the remaining bandwidth */ + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, other, 100 - (7 - i)); + TEST_PRIORITY_VALID(group_bandwidth, i, 7 - i, GROUP, TRUE); + + /* Clear remaining bandwidth */ + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, other, 0); + } + + SET_VALID_PRIORITY_GROUP_BANDWIDTH + for (i = 0; i < 8; i++) { + TEST_PRIORITY_VALID(bandwidth, i, i, GROUP, TRUE); + TEST_PRIORITY_VALID(bandwidth, i, 7 - i, GROUP, TRUE); + } + + SET_VALID_PRIORITY_GROUP_BANDWIDTH + for (i = 0; i < 8; i++) + TEST_PRIORITY_VALID(strict_bandwidth, i, TRUE, GROUP, TRUE); + + SET_VALID_PRIORITY_GROUP_BANDWIDTH + for (i = 0; i < 8; i++) { + TEST_PRIORITY_VALID(traffic_class, i, i, GROUP, TRUE); + TEST_PRIORITY_VALID(traffic_class, i, 7 - i, GROUP, TRUE); + } +} + +static void +test_dcb_bandwidth_sums(void) +{ + gs_unref_object NMSettingDcb *s_dcb = NULL; + GError * error = NULL; + gboolean success; + + s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); + g_assert(s_dcb); + + /* Assert that setting the value gets the same value back out */ + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 0, 9); + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 1, 10); + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 2, 11); + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 3, 12); + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 4, 13); + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 5, 14); + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 6, 15); + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 7, 16); + + /* Assert verify success when sums total 100% */ + g_object_set(G_OBJECT(s_dcb), + NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, + NM_SETTING_DCB_FLAG_ENABLE, + NULL); + success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); + g_assert_no_error(error); + g_assert(success); + + /* Assert verify fails when sums do not total 100% */ + nm_setting_dcb_set_priority_group_bandwidth(s_dcb, 4, 20); + success = nm_setting_verify(NM_SETTING(s_dcb), NULL, &error); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert(success == FALSE); + g_clear_error(&error); +} + +/*****************************************************************************/ + +static void +test_nm_json(void) +{ + g_assert(NM_IN_SET(WITH_JANSSON, 0, 1)); + +#if WITH_JANSSON + g_assert(nm_json_vt()); +#else + g_assert(!nm_json_vt()); +#endif + +#if WITH_JANSSON != defined(JANSSON_SONAME) + #error "WITH_JANSON and JANSSON_SONAME are defined inconsistently." +#endif +} + +/*****************************************************************************/ + +static void +_test_team_config_sync(const char *team_config, + int notify_peer_count, + int notify_peers_interval, + int mcast_rejoin_count, + int mcast_rejoin_interval, + char * runner, + char * runner_hwaddr_policy, /* activebackup */ + GPtrArray * runner_tx_hash, /* lacp, loadbalance */ + char * runner_tx_balancer, /* lacp, loadbalance */ + int runner_tx_balancer_interval, /* lacp, loadbalance */ + gboolean runner_active, /* lacp */ + gboolean runner_fast_rate, /* lacp */ + int runner_sys_prio, /* lacp */ + int runner_min_ports, /* lacp */ + char * runner_agg_select_policy, /* lacp */ + GPtrArray * link_watchers) +{ + gs_unref_object NMSettingTeam *s_team = NULL; + guint i, j; + gboolean found; + + if (!nm_json_vt()) { + g_test_skip("team test requires JSON validation"); + return; + } + + s_team = (NMSettingTeam *) nm_setting_team_new(); + g_assert(s_team); + + g_object_set(s_team, NM_SETTING_TEAM_CONFIG, team_config, NULL); + g_assert_cmpint(nm_setting_team_get_notify_peers_count(s_team), ==, notify_peer_count); + g_assert_cmpint(nm_setting_team_get_notify_peers_interval(s_team), ==, notify_peers_interval); + g_assert_cmpint(nm_setting_team_get_mcast_rejoin_count(s_team), ==, mcast_rejoin_count); + g_assert_cmpint(nm_setting_team_get_mcast_rejoin_interval(s_team), ==, mcast_rejoin_interval); + g_assert_cmpint(nm_setting_team_get_runner_tx_balancer_interval(s_team), + ==, + runner_tx_balancer_interval); + g_assert_cmpint(nm_setting_team_get_runner_active(s_team), ==, runner_active); + g_assert_cmpint(nm_setting_team_get_runner_fast_rate(s_team), ==, runner_fast_rate); + g_assert_cmpint(nm_setting_team_get_runner_sys_prio(s_team), ==, runner_sys_prio); + g_assert_cmpint(nm_setting_team_get_runner_min_ports(s_team), ==, runner_min_ports); + g_assert_cmpstr(nm_setting_team_get_runner(s_team), ==, runner); + g_assert_cmpstr(nm_setting_team_get_runner_hwaddr_policy(s_team), ==, runner_hwaddr_policy); + g_assert_cmpstr(nm_setting_team_get_runner_tx_balancer(s_team), ==, runner_tx_balancer); + g_assert_cmpstr(nm_setting_team_get_runner_agg_select_policy(s_team), + ==, + runner_agg_select_policy); + + if (runner_tx_hash) { + g_assert_cmpint(runner_tx_hash->len, ==, nm_setting_team_get_num_runner_tx_hash(s_team)); + for (i = 0; i < runner_tx_hash->len; i++) { + found = FALSE; + for (j = 0; j < nm_setting_team_get_num_runner_tx_hash(s_team); j++) { + if (nm_streq0(nm_setting_team_get_runner_tx_hash(s_team, j), + runner_tx_hash->pdata[i])) { + found = TRUE; + break; + } + } + g_assert(found); + } + } + + if (link_watchers) { + g_assert_cmpint(link_watchers->len, ==, nm_setting_team_get_num_link_watchers(s_team)); + for (i = 0; i < link_watchers->len; i++) { + found = FALSE; + for (j = 0; j < nm_setting_team_get_num_link_watchers(s_team); j++) { + if (nm_team_link_watcher_equal(link_watchers->pdata[i], + nm_setting_team_get_link_watcher(s_team, j))) { + found = TRUE; + break; + } + } + g_assert(found); + } + } + + g_assert(nm_setting_verify((NMSetting *) s_team, NULL, NULL)); +} + +static void +test_runner_roundrobin_sync_from_config(void) +{ + _test_team_config_sync("", + -1, + -1, + -1, + -1, + NULL, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + NULL); +} + +static void +test_runner_broadcast_sync_from_config(void) +{ + _test_team_config_sync("{\"runner\": {\"name\": \"broadcast\"}}", + -1, + -1, + -1, + -1, + NM_SETTING_TEAM_RUNNER_BROADCAST, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + NULL); +} + +static void +test_runner_random_sync_from_config(void) +{ + _test_team_config_sync("{\"runner\": {\"name\": \"random\"}}", + -1, + -1, + -1, + -1, + NM_SETTING_TEAM_RUNNER_RANDOM, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + NULL); +} + +static void +test_runner_activebackup_sync_from_config(void) +{ + _test_team_config_sync("{\"runner\": {\"name\": \"activebackup\"}}", + -1, + -1, + -1, + -1, + NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + NULL); +} + +static void +test_runner_loadbalance_sync_from_config(void) +{ + gs_unref_ptrarray GPtrArray *tx_hash = NULL; + + tx_hash = g_ptr_array_new_with_free_func(g_free); + g_ptr_array_add(tx_hash, g_strdup("eth")); + g_ptr_array_add(tx_hash, g_strdup("ipv4")); + g_ptr_array_add(tx_hash, g_strdup("ipv6")); + + _test_team_config_sync("{\"runner\": {\"name\": \"loadbalance\"}}", + -1, + -1, + -1, + -1, + NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + NULL); + + _test_team_config_sync("{\"runner\": {\"name\": \"loadbalance\", " + "\"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"]}}", + -1, + -1, + -1, + -1, + NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NULL, + tx_hash, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + NULL); + + _test_team_config_sync( + "{\"runner\": {\"name\": \"loadbalance\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"], " + "\"tx_balancer\": {\"name\": \"basic\", \"balancing_interval\": 30}}}", + -1, + -1, + -1, + -1, + NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NULL, + tx_hash, + "basic", + 30, + TRUE, + FALSE, + -1, + -1, + NULL, + NULL); +} + +static void +test_runner_lacp_sync_from_config(void) +{ + gs_unref_ptrarray GPtrArray *tx_hash = NULL; + + tx_hash = g_ptr_array_new_with_free_func(g_free); + g_ptr_array_add(tx_hash, g_strdup("eth")); + g_ptr_array_add(tx_hash, g_strdup("ipv4")); + g_ptr_array_add(tx_hash, g_strdup("ipv6")); + + _test_team_config_sync( + "{\"runner\": {\"name\": \"lacp\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"]}}", + -1, + -1, + -1, + -1, + NM_SETTING_TEAM_RUNNER_LACP, + NULL, + tx_hash, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + NULL); + + _test_team_config_sync( + "{\"runner\": {\"name\": \"lacp\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"], " + "\"active\": false, \"fast_rate\": true, \"sys_prio\": 10, \"min_ports\": 5, " + "\"agg_select_policy\": \"port_config\"}}", + -1, + -1, + -1, + -1, + NM_SETTING_TEAM_RUNNER_LACP, + NULL, + tx_hash, + NULL, + -1, + FALSE, + TRUE, + 10, + 5, + "port_config", + NULL); +} + +static void +test_watcher_ethtool_sync_from_config(void) +{ + gs_unref_ptrarray GPtrArray *link_watchers = NULL; + + link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); + g_ptr_array_add(link_watchers, nm_team_link_watcher_new_ethtool(0, 0, NULL)); + _test_team_config_sync("{\"link_watch\": {\"name\": \"ethtool\"}}", + -1, + -1, + -1, + -1, + NULL, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + link_watchers); +} + +static void +test_watcher_nsna_ping_sync_from_config(void) +{ + gs_unref_ptrarray GPtrArray *link_watchers = NULL; + + link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); + g_ptr_array_add(link_watchers, + nm_team_link_watcher_new_nsna_ping(0, 0, 3, "target.host", NULL)); + _test_team_config_sync( + "{\"link_watch\": {\"name\": \"nsna_ping\", \"target_host\": \"target.host\"}}", + -1, + -1, + -1, + -1, + NULL, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + link_watchers); +} + +static void +test_watcher_arp_ping_sync_from_config(void) +{ + gs_unref_ptrarray GPtrArray *link_watchers = NULL; + + link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); + g_ptr_array_add( + link_watchers, + nm_team_link_watcher_new_arp_ping(0, 0, 3, "target.host", "source.host", 0, NULL)); + _test_team_config_sync( + "{\"link_watch\": {\"name\": \"arp_ping\", \"target_host\": \"target.host\", " + "\"source_host\": \"source.host\"}}", + -1, + -1, + -1, + -1, + NULL, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + link_watchers); +} + +static void +test_multiple_watchers_sync_from_config(void) +{ + gs_unref_ptrarray GPtrArray *link_watchers = NULL; + + link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); + g_ptr_array_add(link_watchers, nm_team_link_watcher_new_ethtool(2, 4, NULL)); + g_ptr_array_add(link_watchers, + nm_team_link_watcher_new_nsna_ping(3, 6, 9, "target.host", NULL)); + g_ptr_array_add( + link_watchers, + nm_team_link_watcher_new_arp_ping(5, + 10, + 15, + "target.host", + "source.host", + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE + | NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE + | NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS, + NULL)); + _test_team_config_sync( + "{\"link_watch\": [" + "{\"name\": \"ethtool\", \"delay_up\": 2, \"delay_down\": 4}, " + "{\"name\": \"arp_ping\", \"init_wait\": 5, \"interval\": 10, \"missed_max\": 15, " + "\"target_host\": \"target.host\", \"source_host\": \"source.host\", " + "\"validate_active\": true, \"validate_inactive\": true, \"send_always\": true}, " + "{\"name\": \"nsna_ping\", \"init_wait\": 3, \"interval\": 6, \"missed_max\": 9, " + "\"target_host\": \"target.host\"}]}", + -1, + -1, + -1, + -1, + NULL, + NULL, + NULL, + NULL, + -1, + TRUE, + FALSE, + -1, + -1, + NULL, + link_watchers); +} + +/*****************************************************************************/ + +static void +_test_team_port_config_sync(const char *team_port_config, + int queue_id, + int prio, + gboolean sticky, + int lacp_prio, + int lacp_key, + GPtrArray * link_watchers) +{ + gs_unref_object NMSettingTeamPort *s_team_port = NULL; + guint i, j; + gboolean found; + + if (!nm_json_vt()) { + g_test_skip("team test requires JSON validation"); + return; + } + + s_team_port = (NMSettingTeamPort *) nm_setting_team_port_new(); + g_assert(s_team_port); + + g_object_set(s_team_port, NM_SETTING_TEAM_CONFIG, team_port_config, NULL); + g_assert(nm_setting_team_port_get_queue_id(s_team_port) == queue_id); + g_assert(nm_setting_team_port_get_prio(s_team_port) == prio); + g_assert(nm_setting_team_port_get_sticky(s_team_port) == sticky); + g_assert(nm_setting_team_port_get_lacp_prio(s_team_port) == lacp_prio); + g_assert(nm_setting_team_port_get_lacp_key(s_team_port) == lacp_key); + + if (link_watchers) { + g_assert(link_watchers->len == nm_setting_team_port_get_num_link_watchers(s_team_port)); + for (i = 0; i < link_watchers->len; i++) { + found = FALSE; + for (j = 0; j < nm_setting_team_port_get_num_link_watchers(s_team_port); j++) { + if (nm_team_link_watcher_equal( + link_watchers->pdata[i], + nm_setting_team_port_get_link_watcher(s_team_port, j))) { + found = TRUE; + break; + } + } + g_assert(found); + } + } + + g_assert(nm_setting_verify((NMSetting *) s_team_port, NULL, NULL)); +} + +static void +test_team_port_default(void) +{ + _test_team_port_config_sync("", -1, 0, FALSE, -1, -1, NULL); +} + +static void +test_team_port_queue_id(void) +{ + _test_team_port_config_sync("{\"queue_id\": 3}", 3, 0, FALSE, -1, -1, NULL); + _test_team_port_config_sync("{\"queue_id\": 0}", 0, 0, FALSE, -1, -1, NULL); +} + +static void +test_team_port_prio(void) +{ + _test_team_port_config_sync("{\"prio\": 6}", -1, 6, FALSE, -1, -1, NULL); + _test_team_port_config_sync("{\"prio\": 0}", -1, 0, FALSE, -1, -1, NULL); +} + +static void +test_team_port_sticky(void) +{ + _test_team_port_config_sync("{\"sticky\": true}", -1, 0, TRUE, -1, -1, NULL); + _test_team_port_config_sync("{\"sticky\": false}", -1, 0, FALSE, -1, -1, NULL); +} + +static void +test_team_port_lacp_prio(void) +{ + _test_team_port_config_sync("{\"lacp_prio\": 9}", -1, 0, FALSE, 9, -1, NULL); + _test_team_port_config_sync("{\"lacp_prio\": 0}", -1, 0, FALSE, 0, -1, NULL); +} + +static void +test_team_port_lacp_key(void) +{ + _test_team_port_config_sync("{\"lacp_key\": 12}", -1, 0, FALSE, -1, 12, NULL); + _test_team_port_config_sync("{\"lacp_key\": 0}", -1, 0, FALSE, -1, 0, NULL); +} + +static void +test_team_port_full_config(void) +{ + gs_unref_ptrarray GPtrArray *link_watchers = NULL; + + link_watchers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_team_link_watcher_unref); + g_ptr_array_add( + link_watchers, + nm_team_link_watcher_new_arp_ping(0, + 3, + 3, + "1.2.3.2", + "1.2.3.1", + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE, + NULL)); + g_ptr_array_add( + link_watchers, + nm_team_link_watcher_new_arp_ping(1, + 1, + 0, + "1.2.3.4", + "1.2.3.1", + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS, + NULL)); + + _test_team_port_config_sync( + "{\"queue_id\": 10, \"prio\": 20, \"sticky\": true, \"lacp_prio\": 30, " + "\"lacp_key\": 40, \"link_watch\": [" + "{\"name\": \"arp_ping\", \"interval\": 3, \"target_host\": \"1.2.3.2\", " + "\"source_host\": \"1.2.3.1\", \"validate_inactive\": true}, " + "{\"name\": \"arp_ping\", \"init_wait\": 1, \"interval\": 1, " + "\"target_host\": \"1.2.3.4\", \"source_host\": \"1.2.3.1\", " + "\"send_always\": true}]}", + 10, + 20, + true, + 30, + 40, + NULL); +} + +/*****************************************************************************/ + +static void +_check_team_setting(NMSetting *setting) +{ + gs_unref_object NMSetting *setting2 = NULL; + gs_unref_object NMSetting *setting_clone = NULL; + gboolean is_port = NM_IS_SETTING_TEAM_PORT(setting); + gs_unref_variant GVariant *variant2 = NULL; + gs_unref_variant GVariant *variant3 = NULL; + + g_assert(NM_IS_SETTING_TEAM(setting) || is_port); + + setting2 = g_object_new(G_OBJECT_TYPE(setting), + is_port ? NM_SETTING_TEAM_PORT_CONFIG : NM_SETTING_TEAM_CONFIG, + is_port ? nm_setting_team_port_get_config(NM_SETTING_TEAM_PORT(setting)) + : nm_setting_team_get_config(NM_SETTING_TEAM(setting)), + NULL); + + if (nm_json_vt()) + nmtst_assert_setting_is_equal(setting, setting2, NM_SETTING_COMPARE_FLAG_EXACT); + + g_clear_object(&setting2); + + nmtst_assert_setting_dbus_roundtrip(setting); + + /* OK, now parse the setting only from the D-Bus variant, but removing the JSON config. + * For that, we have to "drop" the JSON and we do that by resetting the property. + * This causes JSON to be regenerated and it's in a normalized form that will compare + * equal. */ + setting_clone = nm_setting_duplicate(setting); + setting = setting_clone; + if (is_port) { + g_object_set(setting, + NM_SETTING_TEAM_PORT_STICKY, + nm_setting_team_port_get_sticky(NM_SETTING_TEAM_PORT(setting)), + NULL); + } else { + g_object_set(setting, + NM_SETTING_TEAM_RUNNER_SYS_PRIO, + nm_setting_team_get_runner_sys_prio(NM_SETTING_TEAM(setting)), + NULL); + } + variant2 = _nm_setting_to_dbus(setting, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL); + variant3 = nm_utils_gvariant_vardict_filter_drop_one(variant2, "config"); + setting2 = nmtst_assert_setting_dbus_new(G_OBJECT_TYPE(setting), variant3); + nmtst_assert_setting_is_equal(setting, setting2, NM_SETTING_COMPARE_FLAG_EXACT); +} + +static void +test_team_setting(void) +{ + gs_unref_variant GVariant *variant = nmtst_variant_from_string( + G_VARIANT_TYPE_VARDICT, + "{'config': <'{\"link_watch\": {\"name\": \"ethtool\"}}'>, 'interface-name': <'nm-team'>, " + "'link-watchers': <[{'name': <'ethtool'>}]>}"); + gs_free_error GError *error = NULL; + gs_unref_object NMSetting * setting = NULL; + nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher1 = + nm_team_link_watcher_new_nsna_ping(1, 3, 4, "bbb", NULL); + nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher2 = + nm_team_link_watcher_new_arp_ping2(1, 3, 4, -1, "ccc", "ddd", 0, NULL); + + g_assert(watcher1); + g_assert(watcher2); + + setting = _nm_setting_new_from_dbus(NM_TYPE_SETTING_TEAM, + variant, + NULL, + NM_SETTING_PARSE_FLAGS_STRICT, + &error); + nmtst_assert_success(setting, error); + _check_team_setting(setting); + + g_assert_cmpstr(nm_setting_team_get_config(NM_SETTING_TEAM(setting)), + ==, + "{\"link_watch\": {\"name\": \"ethtool\"}}"); + g_assert_cmpint(nm_setting_team_get_num_link_watchers(NM_SETTING_TEAM(setting)), ==, 1); + + g_object_set(setting, NM_SETTING_TEAM_RUNNER_SYS_PRIO, (int) 10, NULL); + + _check_team_setting(setting); + g_assert_cmpint(nm_setting_team_get_num_link_watchers(NM_SETTING_TEAM(setting)), ==, 1); + g_assert_cmpstr( + nm_setting_team_get_config(NM_SETTING_TEAM(setting)), + ==, + "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"ethtool\" } }"); + + nm_setting_team_remove_link_watcher(NM_SETTING_TEAM(setting), 0); + + _check_team_setting(setting); + g_assert_cmpint(nm_setting_team_get_num_link_watchers(NM_SETTING_TEAM(setting)), ==, 0); + g_assert_cmpstr(nm_setting_team_get_config(NM_SETTING_TEAM(setting)), + ==, + "{ \"runner\": { \"sys_prio\": 10 } }"); + + nm_setting_team_add_link_watcher(NM_SETTING_TEAM(setting), watcher1); + _check_team_setting(setting); + g_assert_cmpstr( + nm_setting_team_get_config(NM_SETTING_TEAM(setting)), + ==, + "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"nsna_ping\", " + "\"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, \"target_host\": \"bbb\" } }"); + + nm_setting_team_add_link_watcher(NM_SETTING_TEAM(setting), watcher2); + _check_team_setting(setting); + g_assert_cmpstr( + nm_setting_team_get_config(NM_SETTING_TEAM(setting)), + ==, + "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": [ { \"name\": \"nsna_ping\", " + "\"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, \"target_host\": \"bbb\" }, { " + "\"name\": \"arp_ping\", \"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, " + "\"source_host\": \"ddd\", \"target_host\": \"ccc\" } ] }"); + + nm_setting_team_remove_link_watcher(NM_SETTING_TEAM(setting), 0); + nm_setting_team_remove_link_watcher(NM_SETTING_TEAM(setting), 0); + g_object_set(setting, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, (int) 5, NULL); + g_assert_cmpstr( + nm_setting_team_get_config(NM_SETTING_TEAM(setting)), + ==, + "{ \"runner\": { \"tx_balancer\": { \"balancing_interval\": 5 }, \"sys_prio\": 10 } }"); + + g_object_set(setting, NM_SETTING_TEAM_RUNNER, NULL, NULL); + _check_team_setting(setting); + g_assert_cmpstr( + nm_setting_team_get_config(NM_SETTING_TEAM(setting)), + ==, + "{ \"runner\": { \"tx_balancer\": { \"balancing_interval\": 5 }, \"sys_prio\": 10 } }"); + + g_object_set(setting, + NM_SETTING_TEAM_CONFIG, + "{ \"runner\": { \"tx_hash\": [ \"eth\", \"l3\" ] } }", + NULL); + _check_team_setting(setting); +} + +/*****************************************************************************/ + +static void +_setting_ethtool_set_feature(NMSettingEthtool *s_ethtool, const char *opt_name, NMTernary value) +{ + g_assert(NM_IS_SETTING_ETHTOOL(s_ethtool)); + + if (nmtst_get_rand_bool()) { + nm_setting_ethtool_set_feature(s_ethtool, opt_name, value); + return; + } + + if (value == NM_TERNARY_DEFAULT) { + nm_setting_option_set(NM_SETTING(s_ethtool), opt_name, NULL); + return; + } + + if (nmtst_get_rand_bool()) + nm_setting_option_set_boolean(NM_SETTING(s_ethtool), opt_name, value); + else + nm_setting_option_set(NM_SETTING(s_ethtool), opt_name, g_variant_new_boolean(value)); +} + +static NMTernary +_setting_ethtool_get_feature(NMSettingEthtool *s_ethtool, const char *opt_name) +{ + GVariant *v; + gboolean b; + + switch (nmtst_get_rand_uint32() % 3) { + case 0: + return nm_setting_ethtool_get_feature(s_ethtool, opt_name); + case 1: + if (!nm_setting_option_get_boolean(NM_SETTING(s_ethtool), opt_name, &b)) + return NM_TERNARY_DEFAULT; + return b; + default: + v = nm_setting_option_get(NM_SETTING(s_ethtool), opt_name); + if (!v || !g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) + return NM_TERNARY_DEFAULT; + return g_variant_get_boolean(v); + } +} + +static void +test_ethtool_features(void) +{ + gs_unref_object NMConnection *con = NULL; + gs_unref_object NMConnection *con2 = NULL; + gs_unref_object NMConnection *con3 = NULL; + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + NMSettingConnection * s_con; + NMSettingEthtool * s_ethtool; + NMSettingEthtool * s_ethtool2; + NMSettingEthtool * s_ethtool3; + + con = nmtst_create_minimal_connection("ethtool-1", NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con); + s_ethtool = NM_SETTING_ETHTOOL(nm_setting_ethtool_new()); + nm_connection_add_setting(con, NM_SETTING(s_ethtool)); + + _setting_ethtool_set_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX, NM_TERNARY_TRUE); + _setting_ethtool_set_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_LRO, NM_TERNARY_FALSE); + + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX), + ==, + NM_TERNARY_TRUE); + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_LRO), + ==, + NM_TERNARY_FALSE); + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_SG), + ==, + NM_TERNARY_DEFAULT); + + nmtst_connection_normalize(con); + + variant = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); + + con2 = nm_simple_connection_new_from_dbus(variant, &error); + nmtst_assert_success(con2, error); + + s_ethtool2 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con2, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_RX), + ==, + NM_TERNARY_TRUE); + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_LRO), + ==, + NM_TERNARY_FALSE); + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_SG), + ==, + NM_TERNARY_DEFAULT); + + nmtst_assert_connection_verifies_without_normalization(con2); + + nmtst_assert_connection_equals(con, FALSE, con2, FALSE); + + keyfile = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); + nmtst_assert_success(keyfile, error); + + con3 = nm_keyfile_read(keyfile, + "/ignored/current/working/directory/for/loading/relative/paths", + NM_KEYFILE_HANDLER_FLAGS_NONE, + NULL, + NULL, + &error); + nmtst_assert_success(con3, error); + + nm_keyfile_read_ensure_id(con3, "unused-because-already-has-id"); + nm_keyfile_read_ensure_uuid(con3, "unused-because-already-has-uuid"); + + nmtst_connection_normalize(con3); + + nmtst_assert_connection_equals(con, FALSE, con3, FALSE); + + s_ethtool3 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con3, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_RX), + ==, + NM_TERNARY_TRUE); + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_LRO), + ==, + NM_TERNARY_FALSE); + g_assert_cmpint(_setting_ethtool_get_feature(s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_SG), + ==, + NM_TERNARY_DEFAULT); +} + +static void +test_ethtool_coalesce(void) +{ + gs_unref_object NMConnection *con = NULL; + gs_unref_object NMConnection *con2 = NULL; + gs_unref_object NMConnection *con3 = NULL; + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + NMSettingConnection * s_con; + NMSettingEthtool * s_ethtool; + NMSettingEthtool * s_ethtool2; + NMSettingEthtool * s_ethtool3; + guint32 u32; + + con = nmtst_create_minimal_connection("ethtool-coalesce", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + &s_con); + s_ethtool = NM_SETTING_ETHTOOL(nm_setting_ethtool_new()); + nm_connection_add_setting(con, NM_SETTING(s_ethtool)); + + nm_setting_option_set_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, 4); + + g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, + &u32)); + g_assert_cmpuint(u32, ==, 4); + + nmtst_connection_normalize(con); + + variant = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); + + con2 = nm_simple_connection_new_from_dbus(variant, &error); + nmtst_assert_success(con2, error); + + s_ethtool2 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con2, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool2), + NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, + &u32)); + g_assert_cmpuint(u32, ==, 4); + + nmtst_assert_connection_verifies_without_normalization(con2); + + nmtst_assert_connection_equals(con, FALSE, con2, FALSE); + + keyfile = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); + nmtst_assert_success(keyfile, error); + + con3 = nm_keyfile_read(keyfile, + "/ignored/current/working/directory/for/loading/relative/paths", + NM_KEYFILE_HANDLER_FLAGS_NONE, + NULL, + NULL, + &error); + nmtst_assert_success(con3, error); + + nm_keyfile_read_ensure_id(con3, "unused-because-already-has-id"); + nm_keyfile_read_ensure_uuid(con3, "unused-because-already-has-uuid"); + + nmtst_connection_normalize(con3); + + nmtst_assert_connection_equals(con, FALSE, con3, FALSE); + + s_ethtool3 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con3, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool3), + NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, + &u32)); + g_assert_cmpuint(u32, ==, 4); + + nm_setting_option_set(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, NULL); + g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, + NULL)); + + nm_setting_option_set_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES, 8); + + g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES, + &u32)); + g_assert_cmpuint(u32, ==, 8); + + nm_setting_option_clear_by_name(NM_SETTING(s_ethtool), nm_ethtool_optname_is_coalesce); + g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, + NULL)); + g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES, + NULL)); + g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS, + NULL)); +} + +static void +test_ethtool_ring(void) +{ + gs_unref_object NMConnection *con = NULL; + gs_unref_object NMConnection *con2 = NULL; + gs_unref_object NMConnection *con3 = NULL; + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + NMSettingConnection * s_con; + NMSettingEthtool * s_ethtool; + NMSettingEthtool * s_ethtool2; + NMSettingEthtool * s_ethtool3; + guint32 out_value; + + con = nmtst_create_minimal_connection("ethtool-ring", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + &s_con); + s_ethtool = NM_SETTING_ETHTOOL(nm_setting_ethtool_new()); + nm_connection_add_setting(con, NM_SETTING(s_ethtool)); + + nm_setting_option_set_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, 4); + + g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, + &out_value)); + g_assert_cmpuint(out_value, ==, 4); + + nmtst_connection_normalize(con); + + variant = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); + + con2 = nm_simple_connection_new_from_dbus(variant, &error); + nmtst_assert_success(con2, error); + + s_ethtool2 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con2, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool2), + NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, + &out_value)); + g_assert_cmpuint(out_value, ==, 4); + + nmtst_assert_connection_verifies_without_normalization(con2); + + nmtst_assert_connection_equals(con, FALSE, con2, FALSE); + + keyfile = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); + nmtst_assert_success(keyfile, error); + + con3 = nm_keyfile_read(keyfile, + "/ignored/current/working/directory/for/loading/relative/paths", + NM_KEYFILE_HANDLER_FLAGS_NONE, + NULL, + NULL, + &error); + nmtst_assert_success(con3, error); + + nm_keyfile_read_ensure_id(con3, "unused-because-already-has-id"); + nm_keyfile_read_ensure_uuid(con3, "unused-because-already-has-uuid"); + + nmtst_connection_normalize(con3); + + nmtst_assert_connection_equals(con, FALSE, con3, FALSE); + + s_ethtool3 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con3, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool3), + NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, + &out_value)); + g_assert_cmpuint(out_value, ==, 4); + + nm_setting_option_set(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, NULL); + g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, + NULL)); + + nm_setting_option_set_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, 8); + + g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, + &out_value)); + g_assert_cmpuint(out_value, ==, 8); + + nm_setting_option_clear_by_name(NM_SETTING(s_ethtool), nm_ethtool_optname_is_ring); + g_assert_false(nm_setting_option_get_uint32(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, + NULL)); + g_assert_false( + nm_setting_option_get_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_RX, NULL)); + g_assert_false( + nm_setting_option_get_uint32(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_RING_TX, NULL)); +} + +/*****************************************************************************/ + +static void +test_sriov_vf(void) +{ + NMSriovVF *vf1, *vf2; + GError * error = NULL; + char * str; + + vf1 = nm_sriov_vf_new(1); + nm_sriov_vf_set_attribute(vf1, + NM_SRIOV_VF_ATTRIBUTE_MAC, + g_variant_new_string("00:11:22:33:44:55")); + nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean(TRUE)); + nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean(FALSE)); + nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32(100)); + nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32(500)); + + str = nm_utils_sriov_vf_to_str(vf1, FALSE, &error); + g_assert_no_error(error); + g_assert_cmpstr( + str, + ==, + "1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100 spoof-check=true trust=false"); + g_free(str); + + vf2 = nm_utils_sriov_vf_from_str(" 1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100", + &error); + nmtst_assert_success(vf2, error); + nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean(FALSE)); + nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean(TRUE)); + nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean(TRUE)); + nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, NULL); + nm_sriov_vf_set_attribute(vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean(FALSE)); + + g_assert(nm_sriov_vf_equal(vf1, vf2)); + + nm_sriov_vf_unref(vf1); + nm_sriov_vf_unref(vf2); +} + +static void +test_sriov_vf_dup(void) +{ + NMSriovVF *vf1, *vf2; + + vf1 = nm_sriov_vf_new(1); + nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string("foobar")); + nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean(FALSE)); + nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32(10)); + nm_sriov_vf_set_attribute(vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32(1000)); + nm_sriov_vf_add_vlan(vf1, 80); + nm_sriov_vf_set_vlan_qos(vf1, 80, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + + vf2 = nm_sriov_vf_dup(vf1); + g_assert(nm_sriov_vf_equal(vf1, vf2)); + + nm_sriov_vf_unref(vf1); + nm_sriov_vf_unref(vf2); +} + +static void +test_sriov_vf_vlan(void) +{ + NMSriovVF * vf; + const guint * vlan_ids; + guint num; + GError * error = NULL; + gs_free char *str = NULL; + + vf = nm_sriov_vf_new(19); + nm_sriov_vf_set_attribute(vf, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string("00:11:22")); + g_assert(nm_sriov_vf_add_vlan(vf, 80)); + g_assert(!nm_sriov_vf_add_vlan(vf, 80)); + g_assert(nm_sriov_vf_add_vlan(vf, 82)); + g_assert(nm_sriov_vf_add_vlan(vf, 83)); + g_assert(nm_sriov_vf_add_vlan(vf, 81)); + g_assert(!nm_sriov_vf_remove_vlan(vf, 100)); + g_assert(nm_sriov_vf_remove_vlan(vf, 82)); + nm_sriov_vf_set_vlan_qos(vf, 81, 0xabba); + nm_sriov_vf_set_vlan_protocol(vf, 81, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + + vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num); + g_assert(vlan_ids); + g_assert_cmpint(num, ==, 3); + g_assert_cmpint(vlan_ids[0], ==, 80); + g_assert_cmpint(vlan_ids[1], ==, 81); + g_assert_cmpint(vlan_ids[2], ==, 83); + g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 80), ==, 0x0); + g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 80), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 81), ==, 0xabba); + g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + + nm_sriov_vf_unref(vf); + + vf = nm_utils_sriov_vf_from_str("20 spoof-check=false vlans=85.0.q;4000.0x20.ad;81.10;83", + &error); + nmtst_assert_success(vf, error); + vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num); + g_assert(vlan_ids); + g_assert_cmpint(num, ==, 4); + g_assert_cmpint(vlan_ids[0], ==, 81); + g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 81), ==, 10); + g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_assert_cmpint(vlan_ids[1], ==, 83); + g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 83), ==, 0); + g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 83), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_assert_cmpint(vlan_ids[2], ==, 85); + g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 85), ==, 0); + g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 85), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_assert_cmpint(vlan_ids[3], ==, 4000); + g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, 4000), ==, 0x20); + g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, 4000), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + + str = nm_utils_sriov_vf_to_str(vf, FALSE, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "20 spoof-check=false vlans=81.10;83;85;4000.32.ad"); + + nm_sriov_vf_unref(vf); +} + +static void +test_sriov_setting(void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingConnection * s_con; + NMSettingSriov * s_sriov = NULL; + NMSriovVF * vf1, *vf2, *vf3; + GError * error = NULL; + gboolean success; + + con = nm_simple_connection_new(); + + s_con = (NMSettingConnection *) nm_setting_connection_new(); + nm_connection_add_setting(con, NM_SETTING(s_con)); + + g_object_set(s_con, + NM_SETTING_CONNECTION_ID, + "Test SR-IOV connection", + NM_SETTING_CONNECTION_UUID, + nm_utils_uuid_generate_a(), + NM_SETTING_CONNECTION_AUTOCONNECT, + TRUE, + NM_SETTING_CONNECTION_INTERFACE_NAME, + "eth0", + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + + nm_connection_add_setting(con, nm_setting_wired_new()); + + s_sriov = (NMSettingSriov *) nm_setting_sriov_new(); + nm_connection_add_setting(con, NM_SETTING(s_sriov)); + + g_object_set(s_sriov, NM_SETTING_SRIOV_TOTAL_VFS, 16, NULL); + nm_setting_sriov_add_vf(s_sriov, (vf1 = nm_sriov_vf_new(0))); + nm_setting_sriov_add_vf(s_sriov, (vf2 = nm_sriov_vf_new(4))); + nm_setting_sriov_add_vf(s_sriov, (vf3 = nm_sriov_vf_new(10))); + g_assert(nm_setting_sriov_remove_vf_by_index(s_sriov, 4)); + nm_sriov_vf_unref(vf2); + nm_setting_sriov_add_vf(s_sriov, (vf2 = nm_sriov_vf_new(2))); + + nmtst_assert_connection_verifies_and_normalizable(con); + nmtst_connection_normalize(con); + success = nm_setting_verify((NMSetting *) s_sriov, con, &error); + nmtst_assert_success(success, error); + + g_assert_cmpint(nm_setting_sriov_get_num_vfs(s_sriov), ==, 3); + g_assert_cmpint(nm_sriov_vf_get_index(nm_setting_sriov_get_vf(s_sriov, 0)), ==, 0); + g_assert_cmpint(nm_sriov_vf_get_index(nm_setting_sriov_get_vf(s_sriov, 1)), ==, 2); + g_assert_cmpint(nm_sriov_vf_get_index(nm_setting_sriov_get_vf(s_sriov, 2)), ==, 10); + + nm_sriov_vf_unref(vf1); + nm_sriov_vf_unref(vf2); + nm_sriov_vf_unref(vf3); +} + +typedef struct { + guint id; + guint qos; + bool proto_ad; +} VlanData; + +static void +_test_sriov_parse_vlan_one(const char *string, gboolean exp_res, VlanData *data, guint data_length) +{ + NMSriovVF * vf; + gboolean res; + guint i, num_vlans; + const guint *vlan_ids; + + vf = nm_sriov_vf_new(1); + g_assert(vf); + + res = _nm_sriov_vf_parse_vlans(vf, string, NULL); + g_assert_cmpint(res, ==, exp_res); + + if (exp_res) { + vlan_ids = nm_sriov_vf_get_vlan_ids(vf, &num_vlans); + g_assert_cmpint(num_vlans, ==, data_length); + for (i = 0; i < num_vlans; i++) { + g_assert_cmpint(vlan_ids[i], ==, data[i].id); + g_assert_cmpint(nm_sriov_vf_get_vlan_qos(vf, vlan_ids[i]), ==, data[i].qos); + g_assert_cmpint(nm_sriov_vf_get_vlan_protocol(vf, vlan_ids[i]), + ==, + data[i].proto_ad ? NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD + : NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + } + } + + nm_sriov_vf_unref(vf); +} + +#define test_sriov_parse_vlan_one(string, result, ...) \ + { \ + VlanData _data[] = {__VA_ARGS__}; \ + guint _length = G_N_ELEMENTS(_data); \ + \ + _test_sriov_parse_vlan_one(string, result, _data, _length); \ + } + +static void +test_sriov_parse_vlans(void) +{ + test_sriov_parse_vlan_one("", FALSE, {}); + test_sriov_parse_vlan_one("1", TRUE, {1, 0, 0}); + test_sriov_parse_vlan_one("1;2", TRUE, {1, 0, 0}, {2, 0, 0}); + test_sriov_parse_vlan_one("4095;;2", TRUE, {2, 0, 0}, {4095, 0, 0}); + test_sriov_parse_vlan_one("1 2", FALSE, {}); + test_sriov_parse_vlan_one("4096", FALSE, {}); + test_sriov_parse_vlan_one("1.10", TRUE, {1, 10, 0}); + test_sriov_parse_vlan_one("1.20.ad", TRUE, {1, 20, 1}); + test_sriov_parse_vlan_one("1.21.q", TRUE, {1, 21, 0}); + test_sriov_parse_vlan_one("9.20.foo", FALSE, {}); + test_sriov_parse_vlan_one("1.20.ad.12", FALSE, {}); + test_sriov_parse_vlan_one("1;1.10", FALSE, {}); + test_sriov_parse_vlan_one("1..1;2", FALSE, {}); + test_sriov_parse_vlan_one("1..ad;2", FALSE, {}); + test_sriov_parse_vlan_one("1.2.ad;2.0.q;5;3", TRUE, {1, 2, 1}, {2, 0, 0}, {3, 0, 0}, {5, 0, 0}); +} + +static void +test_bridge_vlans(void) +{ + NMBridgeVlan *v1, *v2; + GError * error = NULL; + guint16 vid_start, vid_end; + char * str; + + v1 = nm_bridge_vlan_from_str("1 foobar", &error); + nmtst_assert_no_success(v1, error); + g_clear_error(&error); + + v1 = nm_bridge_vlan_from_str("4095", &error); + nmtst_assert_no_success(v1, error); + g_clear_error(&error); + + /* test ranges */ + v1 = nm_bridge_vlan_from_str("2-1000 untagged", &error); + nmtst_assert_success(v1, error); + g_assert_cmpint(nm_bridge_vlan_get_vid_range(v1, &vid_start, &vid_end), ==, TRUE); + g_assert_cmpuint(vid_start, ==, 2); + g_assert_cmpuint(vid_end, ==, 1000); + g_assert_cmpint(nm_bridge_vlan_is_pvid(v1), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(v1), ==, TRUE); + nm_bridge_vlan_unref(v1); + + /* test comparison (1) */ + v1 = nm_bridge_vlan_from_str("10 untagged", &error); + nmtst_assert_success(v1, error); + + g_assert_cmpint(nm_bridge_vlan_get_vid_range(v1, &vid_start, &vid_end), ==, FALSE); + g_assert_cmpuint(vid_start, ==, 10); + g_assert_cmpuint(vid_end, ==, 10); + g_assert_cmpint(nm_bridge_vlan_is_sealed(v1), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_pvid(v1), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(v1), ==, TRUE); + + nm_bridge_vlan_set_pvid(v1, TRUE); + nm_bridge_vlan_set_untagged(v1, FALSE); + nm_bridge_vlan_seal(v1); + + g_assert_cmpint(nm_bridge_vlan_is_sealed(v1), ==, TRUE); + g_assert_cmpint(nm_bridge_vlan_is_pvid(v1), ==, TRUE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(v1), ==, FALSE); + + str = nm_bridge_vlan_to_str(v1, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "10 pvid"); + nm_clear_g_free(&str); + + v2 = nm_bridge_vlan_from_str(" 10 pvid ", &error); + nmtst_assert_success(v2, error); + + g_assert_cmpint(nm_bridge_vlan_cmp(v1, v2), ==, 0); + + nm_bridge_vlan_unref(v1); + nm_bridge_vlan_unref(v2); + + /* test comparison (2) */ + v1 = nm_bridge_vlan_from_str("10", &error); + nmtst_assert_success(v1, error); + v2 = nm_bridge_vlan_from_str("20", &error); + nmtst_assert_success(v2, error); + + g_assert_cmpint(nm_bridge_vlan_cmp(v1, v2), <, 0); + + nm_bridge_vlan_unref(v1); + nm_bridge_vlan_unref(v2); +} + +static void +create_bridge_connection(NMConnection **con, NMSettingBridge **s_bridge) +{ + NMSettingConnection *s_con; + + g_assert(con); + g_assert(s_bridge); + + *con = nmtst_create_minimal_connection("bridge", NULL, NM_SETTING_BOND_SETTING_NAME, &s_con); + + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bridge0", NULL); + + *s_bridge = (NMSettingBridge *) nm_setting_bridge_new(); + g_assert(*s_bridge); + + nm_connection_add_setting(*con, NM_SETTING(*s_bridge)); +} + +#define test_verify_options_bridge(exp, ...) \ + _test_verify_options_bridge(exp, NM_MAKE_STRV(__VA_ARGS__)) + +static void +_test_verify_options_bridge(gboolean expected_result, const char *const *options) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingBridge * s_bridge; + const char *const * option; + + g_assert(NM_PTRARRAY_LEN(options) % 2 == 0); + + create_bridge_connection(&con, &s_bridge); + + for (option = options; option[0]; option += 2) { + const char *option_key = option[0]; + const char *option_val = option[1]; + GParamSpec *pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(s_bridge), option_key); + + g_assert(pspec); + g_assert(option_val); + + switch (G_PARAM_SPEC_VALUE_TYPE(pspec)) { + case G_TYPE_UINT: + { + guint uvalue; + + uvalue = _nm_utils_ascii_str_to_uint64(option_val, 10, 0, G_MAXUINT, -1); + g_assert(errno == 0); + g_object_set(s_bridge, option_key, uvalue, NULL); + } break; + case G_TYPE_BOOLEAN: + { + int bvalue; + + bvalue = _nm_utils_ascii_str_to_bool(option_val, -1); + g_assert(bvalue != -1); + g_object_set(s_bridge, option_key, bvalue, NULL); + } break; + case G_TYPE_STRING: + g_object_set(s_bridge, option_key, option_val, NULL); + break; + default: + g_assert_not_reached(); + break; + } + } + + if (expected_result) + nmtst_assert_connection_verifies_and_normalizable(con); + else { + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + } +} + +static void +test_bridge_verify(void) +{ + /* group-address */ + test_verify_options_bridge(FALSE, "group-address", "nonsense"); + test_verify_options_bridge(FALSE, "group-address", "FF:FF:FF:FF:FF:FF"); + test_verify_options_bridge(FALSE, "group-address", "01:02:03:04:05:06"); + test_verify_options_bridge(TRUE, "group-address", "01:80:C2:00:00:00"); + test_verify_options_bridge(FALSE, "group-address", "01:80:C2:00:00:02"); + test_verify_options_bridge(FALSE, "group-address", "01:80:C2:00:00:03"); + test_verify_options_bridge(TRUE, "group-address", "01:80:C2:00:00:00"); + test_verify_options_bridge(TRUE, "group-address", "01:80:C2:00:00:0A"); + /* vlan-protocol */ + test_verify_options_bridge(FALSE, "vlan-protocol", "nonsense124"); + test_verify_options_bridge(FALSE, "vlan-protocol", "802.11"); + test_verify_options_bridge(FALSE, "vlan-protocol", "802.1Q1"); + test_verify_options_bridge(TRUE, "vlan-protocol", "802.1Q"); + test_verify_options_bridge(TRUE, "vlan-protocol", "802.1ad"); + /* multicast-router */ + test_verify_options_bridge(FALSE, "multicast-router", "nonsense"); + test_verify_options_bridge(TRUE, "multicast-snooping", "no", "multicast-router", "auto"); + test_verify_options_bridge(TRUE, "multicast-snooping", "no", "multicast-router", "enabled"); + test_verify_options_bridge(TRUE, "multicast-snooping", "no", "multicast-router", "disabled"); + test_verify_options_bridge(TRUE, "multicast-snooping", "yes", "multicast-router", "enabled"); + test_verify_options_bridge(TRUE, "multicast-snooping", "yes", "multicast-router", "auto"); + test_verify_options_bridge(TRUE, "multicast-snooping", "yes", "multicast-router", "disabled"); + /* multicast-hash-max */ + test_verify_options_bridge(TRUE, "multicast-hash-max", "1024"); + test_verify_options_bridge(TRUE, "multicast-hash-max", "8192"); + test_verify_options_bridge(FALSE, "multicast-hash-max", "3"); +} + +/*****************************************************************************/ + +static void +test_tc_config_qdisc(void) +{ + NMTCQdisc *qdisc1, *qdisc2; + char * str; + GError * error = NULL; + GVariant * variant; + + qdisc1 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error); + nmtst_assert_success(qdisc1, error); + + qdisc2 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error); + nmtst_assert_success(qdisc2, error); + + g_assert(nm_tc_qdisc_equal(qdisc1, qdisc2)); + + nm_tc_qdisc_unref(qdisc2); + qdisc2 = nm_tc_qdisc_dup(qdisc1); + + g_assert(nm_tc_qdisc_equal(qdisc1, qdisc2)); + + g_assert_cmpstr(nm_tc_qdisc_get_kind(qdisc1), ==, "fq_codel"); + g_assert(nm_tc_qdisc_get_handle(qdisc1) == TC_H_UNSPEC); + g_assert(nm_tc_qdisc_get_parent(qdisc1) == TC_H_ROOT); + + str = nm_utils_tc_qdisc_to_str(qdisc1, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "root fq_codel"); + g_free(str); + + nm_tc_qdisc_unref(qdisc1); + qdisc1 = nm_tc_qdisc_new("ingress", TC_H_INGRESS, &error); + nmtst_assert_success(qdisc1, error); + + g_assert(!nm_tc_qdisc_equal(qdisc1, qdisc2)); + + str = nm_utils_tc_qdisc_to_str(qdisc1, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "ingress"); + g_free(str); + + nm_tc_qdisc_unref(qdisc1); + qdisc1 = nm_utils_tc_qdisc_from_str("narodil sa kristus pan", &error); + nmtst_assert_no_success(qdisc1, error); + g_clear_error(&error); + + qdisc1 = nm_utils_tc_qdisc_from_str("handle 1234 parent fff1:1 pfifo_fast", &error); + nmtst_assert_success(qdisc1, error); + + g_assert_cmpstr(nm_tc_qdisc_get_kind(qdisc1), ==, "pfifo_fast"); + g_assert(nm_tc_qdisc_get_handle(qdisc1) == TC_H_MAKE(0x1234u << 16, 0x0000u)); + g_assert(nm_tc_qdisc_get_parent(qdisc1) == TC_H_MAKE(0xfff1u << 16, 0x0001u)); + + str = nm_utils_tc_qdisc_to_str(qdisc1, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "parent fff1:1 handle 1234: pfifo_fast"); + g_free(str); + + nm_tc_qdisc_unref(qdisc2); + str = nm_utils_tc_qdisc_to_str(qdisc1, &error); + nmtst_assert_success(str, error); + qdisc2 = nm_utils_tc_qdisc_from_str(str, &error); + nmtst_assert_success(qdisc2, error); + g_free(str); + + g_assert(nm_tc_qdisc_equal(qdisc1, qdisc2)); + + nm_tc_qdisc_unref(qdisc1); + nm_tc_qdisc_unref(qdisc2); + + qdisc1 = nm_utils_tc_qdisc_from_str("clsact", &error); + nmtst_assert_success(qdisc1, error); + str = nm_utils_tc_qdisc_to_str(qdisc1, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "clsact"); + nm_tc_qdisc_unref(qdisc1); + g_free(str); + +#define CHECK_ATTRIBUTE(qdisc, name, vtype, type, value) \ + variant = nm_tc_qdisc_get_attribute(qdisc, name); \ + g_assert(variant); \ + g_assert(g_variant_is_of_type(variant, vtype)); \ + g_assert_cmpint(g_variant_get_##type(variant), ==, value); + + qdisc1 = nm_utils_tc_qdisc_from_str("handle 1235 root sfq perturb 10 quantum 1480 " + "limit 9000 flows 1024 divisor 500 depth 12", + &error); + nmtst_assert_success(qdisc1, error); + + g_assert_cmpstr(nm_tc_qdisc_get_kind(qdisc1), ==, "sfq"); + g_assert(nm_tc_qdisc_get_handle(qdisc1) == TC_H_MAKE(0x1235u << 16, 0x0000u)); + g_assert(nm_tc_qdisc_get_parent(qdisc1) == TC_H_ROOT); + CHECK_ATTRIBUTE(qdisc1, "perturb", G_VARIANT_TYPE_INT32, int32, 10); + CHECK_ATTRIBUTE(qdisc1, "quantum", G_VARIANT_TYPE_UINT32, uint32, 1480); + CHECK_ATTRIBUTE(qdisc1, "limit", G_VARIANT_TYPE_UINT32, uint32, 9000); + CHECK_ATTRIBUTE(qdisc1, "flows", G_VARIANT_TYPE_UINT32, uint32, 1024); + CHECK_ATTRIBUTE(qdisc1, "divisor", G_VARIANT_TYPE_UINT32, uint32, 500); + CHECK_ATTRIBUTE(qdisc1, "depth", G_VARIANT_TYPE_UINT32, uint32, 12); + nm_tc_qdisc_unref(qdisc1); + + qdisc1 = nm_utils_tc_qdisc_from_str("handle 1235 root tbf rate 1000000 burst 5000 limit 10000", + &error); + nmtst_assert_success(qdisc1, error); + + g_assert_cmpstr(nm_tc_qdisc_get_kind(qdisc1), ==, "tbf"); + g_assert(nm_tc_qdisc_get_handle(qdisc1) == TC_H_MAKE(0x1235u << 16, 0x0000u)); + g_assert(nm_tc_qdisc_get_parent(qdisc1) == TC_H_ROOT); + CHECK_ATTRIBUTE(qdisc1, "rate", G_VARIANT_TYPE_UINT64, uint64, 1000000); + CHECK_ATTRIBUTE(qdisc1, "burst", G_VARIANT_TYPE_UINT32, uint32, 5000); + CHECK_ATTRIBUTE(qdisc1, "limit", G_VARIANT_TYPE_UINT32, uint32, 10000); + nm_tc_qdisc_unref(qdisc1); + +#undef CHECK_ATTRIBUTE +} + +static void +test_tc_config_action(void) +{ + NMTCAction *action1, *action2; + char * str; + GError * error = NULL; + + action1 = nm_tc_action_new("drop", &error); + nmtst_assert_success(action1, error); + action2 = nm_tc_action_new("drop", &error); + nmtst_assert_success(action2, error); + + g_assert(nm_tc_action_equal(action1, action2)); + g_assert_cmpstr(nm_tc_action_get_kind(action1), ==, "drop"); + + nm_tc_action_unref(action1); + action1 = nm_tc_action_new("simple", &error); + nmtst_assert_success(action1, error); + nm_tc_action_set_attribute(action1, "sdata", g_variant_new_bytestring("Hello")); + + g_assert(!nm_tc_action_equal(action1, action2)); + + str = nm_utils_tc_action_to_str(action1, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "simple sdata Hello"); + g_free(str); + + str = nm_utils_tc_action_to_str(action2, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "drop"); + g_free(str); + + nm_tc_action_unref(action2); + action2 = nm_tc_action_dup(action1); + + g_assert(nm_tc_action_equal(action1, action2)); + + nm_tc_action_unref(action1); + action1 = nm_utils_tc_action_from_str("narodil sa kristus pan", &error); + nmtst_assert_no_success(action1, error); + g_clear_error(&error); + + action1 = nm_utils_tc_action_from_str("simple sdata Hello", &error); + nmtst_assert_success(action1, error); + + g_assert_cmpstr(nm_tc_action_get_kind(action1), ==, "simple"); + g_assert_cmpstr(g_variant_get_bytestring(nm_tc_action_get_attribute(action1, "sdata")), + ==, + "Hello"); + + nm_tc_action_unref(action1); + nm_tc_action_unref(action2); +} + +static void +test_tc_config_tfilter_matchall_sdata(void) +{ + NMTCAction * action1; + NMTCTfilter *tfilter1, *tfilter2; + char * str; + GError * error = NULL; + + tfilter1 = nm_tc_tfilter_new("matchall", TC_H_MAKE(0x1234u << 16, 0x0000u), &error); + nmtst_assert_success(tfilter1, error); + + tfilter2 = nm_tc_tfilter_new("matchall", TC_H_MAKE(0x1234u << 16, 0x0000u), &error); + nmtst_assert_success(tfilter2, error); + + g_assert(nm_tc_tfilter_equal(tfilter1, tfilter2)); + + action1 = nm_tc_action_new("simple", &error); + nmtst_assert_success(action1, error); + nm_tc_action_set_attribute(action1, "sdata", g_variant_new_bytestring("Hello")); + nm_tc_tfilter_set_action(tfilter1, action1); + nm_tc_action_unref(action1); + + g_assert(!nm_tc_tfilter_equal(tfilter1, tfilter2)); + + str = nm_utils_tc_tfilter_to_str(tfilter1, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "parent 1234: matchall action simple sdata Hello"); + g_free(str); + + nm_tc_tfilter_unref(tfilter2); + tfilter2 = nm_tc_tfilter_dup(tfilter1); + + g_assert(nm_tc_tfilter_equal(tfilter1, tfilter2)); + + nm_tc_tfilter_unref(tfilter1); + tfilter1 = nm_utils_tc_tfilter_from_str("narodil sa kristus pan", &error); + nmtst_assert_no_success(tfilter1, error); + g_clear_error(&error); + + str = nm_utils_tc_tfilter_to_str(tfilter2, &error); + nmtst_assert_success(str, error); + tfilter1 = nm_utils_tc_tfilter_from_str(str, &error); + nmtst_assert_success(tfilter1, error); + g_free(str); + + g_assert(nm_tc_tfilter_equal(tfilter1, tfilter2)); + + nm_tc_tfilter_unref(tfilter1); + nm_tc_tfilter_unref(tfilter2); +} + +static void +test_tc_config_tfilter_matchall_mirred(void) +{ + NMTCAction * action; + NMTCTfilter * tfilter1; + GError * error = NULL; + gs_strfreev char **attr_names = NULL; + gs_free char * str; + GVariant * variant; + + tfilter1 = + nm_utils_tc_tfilter_from_str("parent ffff: matchall action mirred ingress mirror dev eth0", + &error); + nmtst_assert_success(tfilter1, error); + g_assert_cmpint(nm_tc_tfilter_get_parent(tfilter1), ==, TC_H_MAKE(0xffff << 16, 0)); + g_assert_cmpstr(nm_tc_tfilter_get_kind(tfilter1), ==, "matchall"); + + action = nm_tc_tfilter_get_action(tfilter1); + nm_assert(action); + g_assert_cmpstr(nm_tc_action_get_kind(action), ==, "mirred"); + attr_names = nm_tc_action_get_attribute_names(action); + g_assert(attr_names); + g_assert_cmpint(g_strv_length(attr_names), ==, 3); + + variant = nm_tc_action_get_attribute(action, "ingress"); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); + g_assert(g_variant_get_boolean(variant)); + + variant = nm_tc_action_get_attribute(action, "mirror"); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); + g_assert(g_variant_get_boolean(variant)); + + variant = nm_tc_action_get_attribute(action, "dev"); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr(g_variant_get_string(variant, NULL), ==, "eth0"); + + str = nm_utils_tc_tfilter_to_str(tfilter1, &error); + nmtst_assert_success(str, error); + g_assert_cmpstr(str, ==, "parent ffff: matchall action mirred dev eth0 ingress mirror"); + + nm_tc_tfilter_unref(tfilter1); +} + +static void +test_tc_config_setting_valid(void) +{ + gs_unref_object NMSettingTCConfig *s_tc = NULL; + NMTCQdisc * qdisc1, *qdisc2; + GError * error = NULL; + + s_tc = (NMSettingTCConfig *) nm_setting_tc_config_new(); + + qdisc1 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error); + nmtst_assert_success(qdisc1, error); + + qdisc2 = nm_tc_qdisc_new("pfifo_fast", TC_H_MAKE(0xfff1u << 16, 0x0001u), &error); + nmtst_assert_success(qdisc2, error); + nm_tc_qdisc_set_handle(qdisc2, TC_H_MAKE(0x1234u << 16, 0x0000u)); + + g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 0); + g_assert(nm_setting_tc_config_add_qdisc(s_tc, qdisc1) == TRUE); + g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 1); + g_assert(nm_setting_tc_config_get_qdisc(s_tc, 0) != NULL); + g_assert(nm_setting_tc_config_remove_qdisc_by_value(s_tc, qdisc2) == FALSE); + g_assert(nm_setting_tc_config_add_qdisc(s_tc, qdisc2) == TRUE); + g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 2); + g_assert(nm_setting_tc_config_remove_qdisc_by_value(s_tc, qdisc1) == TRUE); + g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 1); + nm_setting_tc_config_clear_qdiscs(s_tc); + g_assert(nm_setting_tc_config_get_num_qdiscs(s_tc) == 0); + + nm_tc_qdisc_unref(qdisc1); + nm_tc_qdisc_unref(qdisc2); +} + +static void +test_tc_config_setting_duplicates(void) +{ + gs_unref_ptrarray GPtrArray *qdiscs = NULL; + gs_unref_ptrarray GPtrArray *tfilters = NULL; + NMSettingConnection * s_con; + NMConnection * con; + NMSetting * s_tc; + NMTCQdisc * qdisc; + NMTCTfilter * tfilter; + GError * error = NULL; + + con = nmtst_create_minimal_connection("dummy", NULL, NM_SETTING_DUMMY_SETTING_NAME, &s_con); + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "dummy1", NULL); + + s_tc = nm_setting_tc_config_new(); + nm_connection_add_setting(con, s_tc); + qdiscs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_qdisc_unref); + tfilters = g_ptr_array_new_with_free_func((GDestroyNotify) nm_tc_tfilter_unref); + + /* 1. add duplicate qdiscs */ + qdisc = nm_utils_tc_qdisc_from_str("handle 1234 parent fff1:1 pfifo_fast", &error); + nmtst_assert_success(qdisc, error); + g_ptr_array_add(qdiscs, qdisc); + + qdisc = nm_utils_tc_qdisc_from_str("handle 1234 parent fff1:1 pfifo_fast", &error); + nmtst_assert_success(qdisc, error); + g_ptr_array_add(qdiscs, qdisc); + + g_object_set(s_tc, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + /* 2. make qdiscs unique */ + g_ptr_array_remove_index(qdiscs, 0); + g_object_set(s_tc, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL); + nmtst_assert_connection_verifies_and_normalizable(con); + + /* 3. add duplicate filters */ + tfilter = + nm_utils_tc_tfilter_from_str("parent 1234: matchall action simple sdata Hello", &error); + nmtst_assert_success(tfilter, error); + g_ptr_array_add(tfilters, tfilter); + + tfilter = + nm_utils_tc_tfilter_from_str("parent 1234: matchall action simple sdata Hello", &error); + nmtst_assert_success(tfilter, error); + g_ptr_array_add(tfilters, tfilter); + + g_object_set(s_tc, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL); + nmtst_assert_connection_unnormalizable(con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + + /* 4. make filters unique */ + g_ptr_array_remove_index(tfilters, 0); + g_object_set(s_tc, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL); + nmtst_assert_connection_verifies_and_normalizable(con); +} + +static void +test_tc_config_dbus(void) +{ + NMConnection *connection1, *connection2; + NMSetting * s_tc; + NMTCQdisc * qdisc1, *qdisc2; + NMTCTfilter * tfilter1, *tfilter2; + NMTCAction * action; + GVariant * dbus, *tc_dbus, *var1, *var2; + GError * error = NULL; + gboolean success; + + connection1 = + nmtst_create_minimal_connection("dummy", NULL, NM_SETTING_DUMMY_SETTING_NAME, NULL); + + s_tc = nm_setting_tc_config_new(); + + qdisc1 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error); + nmtst_assert_success(qdisc1, error); + nm_tc_qdisc_set_handle(qdisc1, TC_H_MAKE(0x1234u << 16, 0x0000u)); + nm_setting_tc_config_add_qdisc(NM_SETTING_TC_CONFIG(s_tc), qdisc1); + + qdisc2 = nm_tc_qdisc_new("ingress", TC_H_INGRESS, &error); + nmtst_assert_success(qdisc2, error); + nm_tc_qdisc_set_handle(qdisc2, TC_H_MAKE(TC_H_INGRESS, 0u)); + nm_setting_tc_config_add_qdisc(NM_SETTING_TC_CONFIG(s_tc), qdisc2); + + tfilter1 = nm_tc_tfilter_new("matchall", TC_H_MAKE(0x1234u << 16, 0x0000u), &error); + nmtst_assert_success(tfilter1, error); + action = nm_tc_action_new("drop", &error); + nmtst_assert_success(action, error); + nm_tc_tfilter_set_action(tfilter1, action); + nm_tc_action_unref(action); + nm_setting_tc_config_add_tfilter(NM_SETTING_TC_CONFIG(s_tc), tfilter1); + nm_tc_tfilter_unref(tfilter1); + + tfilter2 = nm_tc_tfilter_new("matchall", TC_H_MAKE(TC_H_INGRESS, 0u), &error); + nmtst_assert_success(tfilter2, error); + action = nm_tc_action_new("simple", &error); + nmtst_assert_success(action, error); + nm_tc_action_set_attribute(action, "sdata", g_variant_new_bytestring("Hello")); + nm_tc_tfilter_set_action(tfilter2, action); + nm_tc_action_unref(action); + nm_setting_tc_config_add_tfilter(NM_SETTING_TC_CONFIG(s_tc), tfilter2); + nm_tc_tfilter_unref(tfilter2); + + nm_connection_add_setting(connection1, s_tc); + + dbus = nm_connection_to_dbus(connection1, NM_CONNECTION_SERIALIZE_ALL); + + tc_dbus = g_variant_lookup_value(dbus, "tc", G_VARIANT_TYPE_VARDICT); + g_assert(tc_dbus); + + var1 = g_variant_lookup_value(tc_dbus, "qdiscs", G_VARIANT_TYPE("aa{sv}")); + var2 = g_variant_new_parsed("[{'kind': <'fq_codel'>," + " 'handle': ," + " 'parent': }," + " {'kind': <'ingress'>," + " 'handle': ," + " 'parent': }]"); + g_assert(g_variant_equal(var1, var2)); + g_variant_unref(var1); + g_variant_unref(var2); + + var1 = g_variant_lookup_value(tc_dbus, "tfilters", G_VARIANT_TYPE("aa{sv}")); + var2 = g_variant_new_parsed("[{'kind': <'matchall'>," + " 'handle': ," + " 'parent': ," + " 'action': <{'kind': <'drop'>}>}," + " {'kind': <'matchall'>," + " 'handle': ," + " 'parent': ," + " 'action': <{'kind': <'simple'>," + " 'sdata': }>}]"); + g_variant_unref(var1); + g_variant_unref(var2); + + g_variant_unref(tc_dbus); + + connection2 = nm_simple_connection_new(); + success = nm_connection_replace_settings(connection2, dbus, &error); + nmtst_assert_success(success, error); + + g_assert(nm_connection_diff(connection1, connection2, NM_SETTING_COMPARE_FLAG_EXACT, NULL)); + + g_variant_unref(dbus); + + nm_tc_qdisc_unref(qdisc1); + nm_tc_qdisc_unref(qdisc2); + + g_object_unref(connection1); + g_object_unref(connection2); +} + +/*****************************************************************************/ + +static void +_rndt_wired_add_s390_options(NMSettingWired *s_wired, char **out_keyfile_entries) +{ + gsize n_opts; + gsize i, j; + const char *const * option_names; + gs_free const char **opt_keys = NULL; + gs_strfreev char ** opt_vals = NULL; + gs_free bool * opt_found = NULL; + GString * keyfile_entries; + nm_auto_free_gstring GString *str_tmp = NULL; + + option_names = nm_setting_wired_get_valid_s390_options(nmtst_get_rand_bool() ? NULL : s_wired); + + n_opts = NM_PTRARRAY_LEN(option_names); + opt_keys = g_new(const char *, (n_opts + 1)); + nmtst_rand_perm(NULL, opt_keys, option_names, sizeof(const char *), n_opts); + n_opts = nmtst_get_rand_uint32() % (n_opts + 1); + opt_keys[n_opts] = NULL; + + opt_vals = g_new0(char *, n_opts + 1); + opt_found = g_new0(bool, n_opts + 1); + for (i = 0; i < n_opts; i++) { + guint p = nmtst_get_rand_uint32() % 1000; + + if (p < 200) + opt_vals[i] = nm_strdup_int(i); + else { + opt_vals[i] = g_strdup_printf("%s%s%s%s-%zu", + ((p % 5) % 2) ? "\n" : "", + ((p % 7) % 2) ? "\t" : "", + ((p % 11) % 2) ? "x" : "", + ((p % 13) % 2) ? "=" : "", + i); + } + } + + if (nmtst_get_rand_bool()) { + gs_unref_hashtable GHashTable *hash = NULL; + + hash = g_hash_table_new(nm_str_hash, g_str_equal); + for (i = 0; i < n_opts; i++) + g_hash_table_insert(hash, (char *) opt_keys[i], opt_vals[i]); + g_object_set(s_wired, NM_SETTING_WIRED_S390_OPTIONS, hash, NULL); + } else { + _nm_setting_wired_clear_s390_options(s_wired); + for (i = 0; i < n_opts; i++) { + if (!nm_setting_wired_add_s390_option(s_wired, opt_keys[i], opt_vals[i])) + g_assert_not_reached(); + } + } + + g_assert_cmpint(nm_setting_wired_get_num_s390_options(s_wired), ==, n_opts); + + keyfile_entries = g_string_new(NULL); + str_tmp = g_string_new(NULL); + if (n_opts > 0) + g_string_append_printf(keyfile_entries, "[ethernet-s390-options]\n"); + for (i = 0; i < n_opts; i++) { + gssize idx; + const char *k, *v; + + nm_setting_wired_get_s390_option(s_wired, i, &k, &v); + g_assert(k); + g_assert(v); + + idx = nm_utils_strv_find_first((char **) opt_keys, n_opts, k); + g_assert(idx >= 0); + g_assert(!opt_found[idx]); + opt_found[idx] = TRUE; + g_assert_cmpstr(opt_keys[idx], ==, k); + g_assert_cmpstr(opt_vals[idx], ==, v); + + g_string_truncate(str_tmp, 0); + for (j = 0; v[j] != '\0'; j++) { + if (v[j] == '\n') + g_string_append(str_tmp, "\\n"); + else if (v[j] == '\t') + g_string_append(str_tmp, "\\t"); + else + g_string_append_c(str_tmp, v[j]); + } + + g_string_append_printf(keyfile_entries, "%s=%s\n", k, str_tmp->str); + } + for (i = 0; i < n_opts; i++) + g_assert(opt_found[i]); + if (n_opts > 0) + g_string_append_printf(keyfile_entries, "\n"); + *out_keyfile_entries = g_string_free(keyfile_entries, FALSE); +} + +static GPtrArray * +_rndt_wg_peers_create(void) +{ + GPtrArray *wg_peers; + guint i, n; + + wg_peers = g_ptr_array_new_with_free_func((GDestroyNotify) nm_wireguard_peer_unref); + + n = nmtst_get_rand_uint32() % 10; + for (i = 0; i < n; i++) { + NMWireGuardPeer *peer; + guint8 public_key_buf[NM_WIREGUARD_PUBLIC_KEY_LEN]; + guint8 preshared_key_buf[NM_WIREGUARD_SYMMETRIC_KEY_LEN]; + gs_free char * public_key = NULL; + gs_free char * preshared_key = NULL; + gs_free char * s_endpoint = NULL; + guint i_aip, n_aip; + + /* we don't bother to create a valid curve25519 public key. Of course, libnm cannot + * check whether the public key is bogus or not. Hence, for our purpose a random + * bogus key is good enough. */ + public_key = g_base64_encode(nmtst_rand_buf(NULL, public_key_buf, sizeof(public_key_buf)), + sizeof(public_key_buf)); + + preshared_key = + g_base64_encode(nmtst_rand_buf(NULL, preshared_key_buf, sizeof(preshared_key_buf)), + sizeof(preshared_key_buf)); + + s_endpoint = _create_random_ipaddr(AF_UNSPEC, TRUE); + + peer = nm_wireguard_peer_new(); + if (!nm_wireguard_peer_set_public_key(peer, public_key, TRUE)) + g_assert_not_reached(); + + if (!nm_wireguard_peer_set_preshared_key(peer, + nmtst_rand_select(NULL, preshared_key), + TRUE)) + g_assert_not_reached(); + + nm_wireguard_peer_set_preshared_key_flags( + peer, + nmtst_rand_select(NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_SECRET_FLAG_AGENT_OWNED)); + + nm_wireguard_peer_set_persistent_keepalive( + peer, + nmtst_rand_select((guint32) 0, nmtst_get_rand_uint32())); + + if (!nm_wireguard_peer_set_endpoint(peer, nmtst_rand_select(s_endpoint, NULL), TRUE)) + g_assert_not_reached(); + + n_aip = nmtst_rand_select(0, nmtst_get_rand_uint32() % 10); + for (i_aip = 0; i_aip < n_aip; i_aip++) { + gs_free char *aip = NULL; + + aip = _create_random_ipaddr(AF_UNSPEC, FALSE); + if (!nm_wireguard_peer_append_allowed_ip(peer, aip, FALSE)) + g_assert_not_reached(); + } + + g_assert(nm_wireguard_peer_is_valid(peer, TRUE, TRUE, NULL)); + + nm_wireguard_peer_seal(peer); + g_ptr_array_add(wg_peers, peer); + } + + return wg_peers; +} + +static const char * +_rndt_wg_peers_to_keyfile(GPtrArray *wg_peers, gboolean strict, char **out_str) +{ + nm_auto_free_gstring GString *gstr = NULL; + nm_auto_free_gstring GString *gstr_aip = NULL; + guint i, j; + + g_assert(wg_peers); + g_assert(out_str && !*out_str); + + nm_gstring_prepare(&gstr); + for (i = 0; i < wg_peers->len; i++) { + const NMWireGuardPeer *peer = wg_peers->pdata[i]; + gs_free char * s_endpoint = NULL; + gs_free char * s_preshared_key = NULL; + gs_free char * s_preshared_key_flags = NULL; + gs_free char * s_persistent_keepalive = NULL; + gs_free char * s_allowed_ips = NULL; + + if (nm_wireguard_peer_get_endpoint(peer)) + s_endpoint = g_strdup_printf("endpoint=%s\n", nm_wireguard_peer_get_endpoint(peer)); + else if (!strict) + s_endpoint = g_strdup_printf("endpoint=\n"); + + if (nm_wireguard_peer_get_preshared_key(peer) || !strict) { + if (nm_wireguard_peer_get_preshared_key_flags(peer) == NM_SETTING_SECRET_FLAG_NONE) + s_preshared_key = g_strdup_printf("preshared-key=%s\n", + nm_wireguard_peer_get_preshared_key(peer) ?: ""); + } + + if (nm_wireguard_peer_get_preshared_key_flags(peer) != NM_SETTING_SECRET_FLAG_NOT_REQUIRED + || !strict) + s_preshared_key_flags = + g_strdup_printf("preshared-key-flags=%d\n", + (int) nm_wireguard_peer_get_preshared_key_flags(peer)); + + if (nm_wireguard_peer_get_persistent_keepalive(peer) != 0 || !strict) + s_persistent_keepalive = + g_strdup_printf("persistent-keepalive=%u\n", + nm_wireguard_peer_get_persistent_keepalive(peer)); + + if (nm_wireguard_peer_get_allowed_ips_len(peer) > 0 || !strict) { + nm_gstring_prepare(&gstr_aip); + for (j = 0; j < nm_wireguard_peer_get_allowed_ips_len(peer); j++) + g_string_append_printf(gstr_aip, + "%s;", + nm_wireguard_peer_get_allowed_ip(peer, j, NULL)); + s_allowed_ips = g_strdup_printf("allowed-ips=%s\n", gstr_aip->str); + } + + if (!s_endpoint && !s_preshared_key && !s_preshared_key_flags && !s_persistent_keepalive + && !s_allowed_ips) + s_endpoint = g_strdup_printf("endpoint=\n"); + + g_string_append_printf(gstr, + "\n" + "[wireguard-peer.%s]\n" + "%s" /* endpoint */ + "%s" /* preshared-key */ + "%s" /* preshared-key-flags */ + "%s" /* persistent-keepalive */ + "%s" /* allowed-ips */ + "", + nm_wireguard_peer_get_public_key(peer), + s_endpoint ?: "", + s_preshared_key ?: "", + s_preshared_key_flags ?: "", + s_persistent_keepalive ?: "", + s_allowed_ips ?: ""); + } + + return (*out_str = g_string_free(g_steal_pointer(&gstr), FALSE)); +} + +static void +_rndt_wg_peers_assert_equal(NMSettingWireGuard *s_wg, + GPtrArray * peers, + gboolean consider_persistent_secrets, + gboolean consider_all_secrets, + gboolean expect_no_secrets) +{ + guint i; + + g_assert(NM_IS_SETTING_WIREGUARD(s_wg)); + g_assert(peers); + + g_assert_cmpint(peers->len, ==, nm_setting_wireguard_get_peers_len(s_wg)); + + for (i = 0; i < peers->len; i++) { + const NMWireGuardPeer *a = peers->pdata[i]; + const NMWireGuardPeer *b = nm_setting_wireguard_get_peer(s_wg, i); + gboolean consider_secrets; + + g_assert(a); + g_assert(b); + + g_assert_cmpint(nm_wireguard_peer_cmp(a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS), ==, 0); + + if (consider_all_secrets || !nm_wireguard_peer_get_preshared_key(a)) + consider_secrets = TRUE; + else if (nm_wireguard_peer_get_preshared_key(b)) + consider_secrets = TRUE; + else if (consider_persistent_secrets + && nm_wireguard_peer_get_preshared_key_flags(b) == NM_SETTING_SECRET_FLAG_NONE) + consider_secrets = TRUE; + else + consider_secrets = FALSE; + + if (consider_secrets) { + g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(a), + ==, + nm_wireguard_peer_get_preshared_key(b)); + g_assert_cmpint(nm_wireguard_peer_cmp(a, b, NM_SETTING_COMPARE_FLAG_EXACT), ==, 0); + } + + if (expect_no_secrets) + g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(b), ==, NULL); + } +} + +static void +_rndt_wg_peers_fix_secrets(NMSettingWireGuard *s_wg, GPtrArray *peers) +{ + guint i; + + g_assert(NM_IS_SETTING_WIREGUARD(s_wg)); + g_assert(peers); + + g_assert_cmpint(peers->len, ==, nm_setting_wireguard_get_peers_len(s_wg)); + + for (i = 0; i < peers->len; i++) { + const NMWireGuardPeer *a = peers->pdata[i]; + const NMWireGuardPeer *b = nm_setting_wireguard_get_peer(s_wg, i); + nm_auto_unref_wgpeer NMWireGuardPeer *b_clone = NULL; + + g_assert(a); + g_assert(b); + + g_assert_cmpint(nm_wireguard_peer_get_preshared_key_flags(a), + ==, + nm_wireguard_peer_get_preshared_key_flags(b)); + g_assert_cmpint(nm_wireguard_peer_cmp(a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS), ==, 0); + + if (!nm_streq0(nm_wireguard_peer_get_preshared_key(a), + nm_wireguard_peer_get_preshared_key(b))) { + g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(a), !=, NULL); + g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(b), ==, NULL); + g_assert(NM_IN_SET(nm_wireguard_peer_get_preshared_key_flags(a), + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NM_SETTING_SECRET_FLAG_NOT_SAVED)); + b_clone = nm_wireguard_peer_new_clone(b, TRUE); + if (!nm_wireguard_peer_set_preshared_key(b_clone, + nm_wireguard_peer_get_preshared_key(a), + TRUE)) + g_assert_not_reached(); + nm_setting_wireguard_set_peer(s_wg, b_clone, i); + b = nm_setting_wireguard_get_peer(s_wg, i); + g_assert(b == b_clone); + } else { + if (nm_wireguard_peer_get_preshared_key(a)) { + g_assert(NM_IN_SET(nm_wireguard_peer_get_preshared_key_flags(a), + NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_SECRET_FLAG_NOT_REQUIRED)); + } else { + g_assert(NM_IN_SET(nm_wireguard_peer_get_preshared_key_flags(a), + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_SECRET_FLAG_NOT_REQUIRED)); + } + } + + g_assert_cmpstr(nm_wireguard_peer_get_preshared_key(a), + ==, + nm_wireguard_peer_get_preshared_key(b)); + g_assert_cmpint(nm_wireguard_peer_cmp(a, b, NM_SETTING_COMPARE_FLAG_EXACT), ==, 0); + } +} + +static void +test_roundtrip_conversion(gconstpointer test_data) +{ + const int MODE = GPOINTER_TO_INT(test_data); + const char *ID = nm_sprintf_bufa(100, "roundtrip-conversion-%d", MODE); + const char *UUID = "63376701-b61e-4318-bf7e-664a1c1eeaab"; + const char *INTERFACE_NAME = nm_sprintf_bufa(100, "ifname%d", MODE); + guint32 ETH_MTU = nmtst_rand_select((guint32) 0u, nmtst_get_rand_uint32()); + const char *WG_PRIVATE_KEY = + nmtst_get_rand_bool() ? "yGXGK+5bVnxSJUejH4vbpXbq+ZtaG4NB8IHRK/aVtE0=" : NULL; + const NMSettingSecretFlags WG_PRIVATE_KEY_FLAGS = + nmtst_rand_select(NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_SECRET_FLAG_AGENT_OWNED); + const guint WG_LISTEN_PORT = nmtst_rand_select(0u, nmtst_get_rand_uint32() % 0x10000); + const guint WG_FWMARK = nmtst_rand_select(0u, nmtst_get_rand_uint32()); + gs_unref_ptrarray GPtrArray *kf_data_arr = g_ptr_array_new_with_free_func(g_free); + gs_unref_ptrarray GPtrArray * wg_peers = NULL; + const NMConnectionSerializationFlags dbus_serialization_flags[] = { + NM_CONNECTION_SERIALIZE_ALL, + NM_CONNECTION_SERIALIZE_NO_SECRETS, + NM_CONNECTION_SERIALIZE_ONLY_SECRETS, + }; + guint dbus_serialization_flags_idx; + gs_unref_object NMConnection *con = NULL; + gs_free_error GError *error = NULL; + gs_free char * tmp_str = NULL; + guint kf_data_idx; + NMSettingConnection * s_con = NULL; + NMSettingWired * s_eth = NULL; + NMSettingWireGuard * s_wg = NULL; + union { + struct { + NMSettingIPConfig *s_6; + NMSettingIPConfig *s_4; + }; + NMSettingIPConfig *s_x[2]; + } s_ip; + int is_ipv4; + guint i; + gboolean success; + gs_free char *s390_keyfile_entries = NULL; + + switch (MODE) { + case 0: + con = nmtst_create_minimal_connection(ID, UUID, NM_SETTING_WIRED_SETTING_NAME, &s_con); + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, INTERFACE_NAME, NULL); + nmtst_connection_normalize(con); + + s_eth = NM_SETTING_WIRED(nm_connection_get_setting(con, NM_TYPE_SETTING_WIRED)); + g_assert(NM_IS_SETTING_WIRED(s_eth)); + + g_object_set(s_eth, NM_SETTING_WIRED_MTU, ETH_MTU, NULL); + + _rndt_wired_add_s390_options(s_eth, &s390_keyfile_entries); + + g_ptr_array_add( + kf_data_arr, + g_strdup_printf("[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=ethernet\n" + "interface-name=%s\n" + "permissions=\n" + "\n" + "[ethernet]\n" + "mac-address-blacklist=\n" + "%s" /* mtu */ + "\n" + "%s" /* [ethernet-s390-options] */ + "[ipv4]\n" + "dns-search=\n" + "method=auto\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=auto\n" + "\n" + "[proxy]\n" + "", + ID, + UUID, + INTERFACE_NAME, + (ETH_MTU != 0) ? nm_sprintf_bufa(100, "mtu=%u\n", ETH_MTU) : "", + s390_keyfile_entries)); + + g_ptr_array_add( + kf_data_arr, + g_strdup_printf("[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=ethernet\n" + "interface-name=%s\n" + "permissions=\n" + "\n" + "[ethernet]\n" + "mac-address-blacklist=\n" + "%s" /* mtu */ + "\n" + "%s" /* [ethernet-s390-options] */ + "[ipv4]\n" + "dns-search=\n" + "method=auto\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=auto\n" + "", + ID, + UUID, + INTERFACE_NAME, + (ETH_MTU != 0) ? nm_sprintf_bufa(100, "mtu=%d\n", (int) ETH_MTU) : "", + s390_keyfile_entries)); + + break; + + case 1: + con = nmtst_create_minimal_connection(ID, UUID, "wireguard", &s_con); + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, INTERFACE_NAME, NULL); + nmtst_connection_normalize(con); + + s_wg = NM_SETTING_WIREGUARD(nm_connection_get_setting(con, NM_TYPE_SETTING_WIREGUARD)); + + g_ptr_array_add(kf_data_arr, + g_strdup_printf("[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=wireguard\n" + "interface-name=%s\n" + "permissions=\n" + "\n" + "[wireguard]\n" + "\n" + "[ipv4]\n" + "dns-search=\n" + "method=disabled\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=ignore\n" + "\n" + "[proxy]\n" + "", + ID, + UUID, + INTERFACE_NAME)); + break; + + case 2: + con = nmtst_create_minimal_connection(ID, UUID, "wireguard", &s_con); + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, INTERFACE_NAME, NULL); + nmtst_connection_normalize(con); + + s_wg = NM_SETTING_WIREGUARD(nm_connection_get_setting(con, NM_TYPE_SETTING_WIREGUARD)); + g_object_set(s_wg, + NM_SETTING_WIREGUARD_PRIVATE_KEY, + WG_PRIVATE_KEY, + NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, + WG_PRIVATE_KEY_FLAGS, + NM_SETTING_WIREGUARD_LISTEN_PORT, + WG_LISTEN_PORT, + NM_SETTING_WIREGUARD_FWMARK, + WG_FWMARK, + NULL); + + wg_peers = _rndt_wg_peers_create(); + + for (i = 0; i < wg_peers->len; i++) + nm_setting_wireguard_append_peer(s_wg, wg_peers->pdata[i]); + + nm_clear_g_free(&tmp_str); + + g_ptr_array_add( + kf_data_arr, + g_strdup_printf( + "[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=wireguard\n" + "interface-name=%s\n" + "permissions=\n" + "\n" + "[wireguard]\n" + "%s" /* fwmark */ + "%s" /* listen-port */ + "%s" /* private-key-flags */ + "%s" /* private-key */ + "%s" /* [wireguard-peers*] */ + "\n" + "[ipv4]\n" + "dns-search=\n" + "method=disabled\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=ignore\n" + "\n" + "[proxy]\n" + "", + ID, + UUID, + INTERFACE_NAME, + ((WG_FWMARK != 0) ? nm_sprintf_bufa(100, "fwmark=%u\n", WG_FWMARK) : ""), + ((WG_LISTEN_PORT != 0) ? nm_sprintf_bufa(100, "listen-port=%u\n", WG_LISTEN_PORT) + : ""), + ((WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) + ? nm_sprintf_bufa(100, "private-key-flags=%u\n", (guint) WG_PRIVATE_KEY_FLAGS) + : ""), + ((WG_PRIVATE_KEY && WG_PRIVATE_KEY_FLAGS == NM_SETTING_SECRET_FLAG_NONE) + ? nm_sprintf_bufa(100, "private-key=%s\n", WG_PRIVATE_KEY) + : ""), + _rndt_wg_peers_to_keyfile(wg_peers, TRUE, &tmp_str))); + + _rndt_wg_peers_assert_equal(s_wg, wg_peers, TRUE, TRUE, FALSE); + break; + + case 3: + con = nmtst_create_minimal_connection(ID, UUID, NM_SETTING_WIRED_SETTING_NAME, &s_con); + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, INTERFACE_NAME, NULL); + nmtst_connection_normalize(con); + + s_eth = NM_SETTING_WIRED(nm_connection_get_setting(con, NM_TYPE_SETTING_WIRED)); + g_assert(NM_IS_SETTING_WIRED(s_eth)); + + g_object_set(s_eth, NM_SETTING_WIRED_MTU, ETH_MTU, NULL); + + s_ip.s_4 = NM_SETTING_IP_CONFIG(nm_connection_get_setting(con, NM_TYPE_SETTING_IP4_CONFIG)); + g_assert(NM_IS_SETTING_IP4_CONFIG(s_ip.s_4)); + + s_ip.s_6 = NM_SETTING_IP_CONFIG(nm_connection_get_setting(con, NM_TYPE_SETTING_IP6_CONFIG)); + g_assert(NM_IS_SETTING_IP6_CONFIG(s_ip.s_6)); + + for (is_ipv4 = 0; is_ipv4 < 2; is_ipv4++) { + g_assert(NM_IS_SETTING_IP_CONFIG(s_ip.s_x[is_ipv4])); + for (i = 0; i < 3; i++) { + char addrstr[NM_UTILS_INET_ADDRSTRLEN]; + + nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr = NULL; + + rr = nm_ip_routing_rule_new(is_ipv4 ? AF_INET : AF_INET6); + nm_ip_routing_rule_set_priority(rr, i + 1); + if (i > 0) { + if (is_ipv4) + nm_sprintf_buf(addrstr, "192.168.%u.0", i); + else + nm_sprintf_buf(addrstr, "1:2:3:%x::", 10 + i); + nm_ip_routing_rule_set_from(rr, addrstr, is_ipv4 ? 24 + i : 64 + i); + } + nm_ip_routing_rule_set_table(rr, 1000 + i); + + success = nm_ip_routing_rule_validate(rr, &error); + nmtst_assert_success(success, error); + + nm_setting_ip_config_add_routing_rule(s_ip.s_x[is_ipv4], rr); + } + } + + g_ptr_array_add( + kf_data_arr, + g_strdup_printf("[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=ethernet\n" + "interface-name=%s\n" + "permissions=\n" + "\n" + "[ethernet]\n" + "mac-address-blacklist=\n" + "%s" /* mtu */ + "\n" + "[ipv4]\n" + "dns-search=\n" + "method=auto\n" + "routing-rule1=priority 1 from 0.0.0.0/0 table 1000\n" + "routing-rule2=priority 2 from 192.168.1.0/25 table 1001\n" + "routing-rule3=priority 3 from 192.168.2.0/26 table 1002\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=auto\n" + "routing-rule1=priority 1 from ::/0 table 1000\n" + "routing-rule2=priority 2 from 1:2:3:b::/65 table 1001\n" + "routing-rule3=priority 3 from 1:2:3:c::/66 table 1002\n" + "\n" + "[proxy]\n" + "", + ID, + UUID, + INTERFACE_NAME, + (ETH_MTU != 0) ? nm_sprintf_bufa(100, "mtu=%u\n", ETH_MTU) : "")); + + break; + + default: + g_assert_not_reached(); + } + + /* the first kf_data_arr entry is special: it is the exact result of what we expect + * when converting @con to keyfile. Write @con to keyfile and compare the expected result + * literally. */ + { + nm_auto_unref_keyfile GKeyFile *kf = NULL; + + kf = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); + nmtst_assert_success(kf, error); + + /* the first kf_data_arr entry is special: it must be what the writer would + * produce again. */ + nmtst_keyfile_assert_data(kf, kf_data_arr->pdata[0], -1); + } + + /* check that reading any of kf_data_arr yields the same result that we expect. */ + for (kf_data_idx = 0; kf_data_idx < kf_data_arr->len; kf_data_idx++) { + gs_unref_object NMConnection *con2 = NULL; + NMSettingWireGuard * s_wg2 = NULL; + NMSettingWired * s_eth2 = NULL; + + con2 = nmtst_create_connection_from_keyfile(kf_data_arr->pdata[kf_data_idx], + "/no/where/file.nmconnection"); + + switch (MODE) { + case 0: + s_eth2 = NM_SETTING_WIRED(nm_connection_get_setting(con2, NM_TYPE_SETTING_WIRED)); + g_assert(NM_IS_SETTING_WIRED(s_eth2)); + + if (ETH_MTU > (guint32) G_MAXINT && kf_data_idx == 1) { + /* older versions wrote values > 2^21 as signed integers, but the reader would + * always reject such negative values for G_TYPE_UINT. + * + * The test case kf_data_idx #1 still writes the values in the old style. + * The behavior was fixed, but such values are still rejected as invalid. + * + * Patch the setting so that the comparison below succeeds are usual. */ + g_assert_cmpint(nm_setting_wired_get_mtu(s_eth2), ==, 0); + g_object_set(s_eth2, NM_SETTING_WIRED_MTU, ETH_MTU, NULL); + } + + g_assert_cmpint(nm_setting_wired_get_mtu(s_eth), ==, ETH_MTU); + g_assert_cmpint(nm_setting_wired_get_mtu(s_eth2), ==, ETH_MTU); + + g_assert_cmpint(nm_setting_wired_get_num_s390_options(s_eth2), + ==, + nm_setting_wired_get_num_s390_options(s_eth)); + + break; + + case 1: + s_wg2 = + NM_SETTING_WIREGUARD(nm_connection_get_setting(con2, NM_TYPE_SETTING_WIREGUARD)); + g_assert(NM_IS_SETTING_WIREGUARD(s_wg2)); + + g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg), ==, NULL); + g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg2), ==, NULL); + break; + + case 2: + s_wg2 = + NM_SETTING_WIREGUARD(nm_connection_get_setting(con2, NM_TYPE_SETTING_WIREGUARD)); + g_assert(NM_IS_SETTING_WIREGUARD(s_wg2)); + + /* the private key was lost due to the secret-flags. Patch it. */ + if (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) { + g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg2), ==, NULL); + g_object_set(s_wg2, NM_SETTING_WIREGUARD_PRIVATE_KEY, WG_PRIVATE_KEY, NULL); + } + + g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg), ==, WG_PRIVATE_KEY); + g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg2), ==, WG_PRIVATE_KEY); + + _rndt_wg_peers_assert_equal(s_wg2, wg_peers, TRUE, FALSE, FALSE); + _rndt_wg_peers_fix_secrets(s_wg2, wg_peers); + _rndt_wg_peers_assert_equal(s_wg2, wg_peers, TRUE, TRUE, FALSE); + break; + } + + nmtst_assert_connection_equals(con, nmtst_get_rand_bool(), con2, nmtst_get_rand_bool()); + } + + for (dbus_serialization_flags_idx = 0; + dbus_serialization_flags_idx < G_N_ELEMENTS(dbus_serialization_flags); + dbus_serialization_flags_idx++) { + NMConnectionSerializationFlags flag = + dbus_serialization_flags[dbus_serialization_flags_idx]; + gs_unref_variant GVariant *con_var = NULL; + gs_unref_object NMConnection *con2 = NULL; + NMSettingWireGuard * s_wg2 = NULL; + + con_var = nm_connection_to_dbus(con, flag); + g_assert(g_variant_is_of_type(con_var, NM_VARIANT_TYPE_CONNECTION)); + g_assert(g_variant_is_floating(con_var)); + g_variant_ref_sink(con_var); + + if (flag == NM_CONNECTION_SERIALIZE_ALL) { + con2 = _connection_new_from_dbus_strict(con_var, TRUE); + nmtst_assert_connection_equals(con, nmtst_get_rand_bool(), con2, nmtst_get_rand_bool()); + + { + nm_auto_unref_keyfile GKeyFile *kf = NULL; + + kf = nm_keyfile_write(con2, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); + nmtst_assert_success(kf, error); + nmtst_keyfile_assert_data(kf, kf_data_arr->pdata[0], -1); + } + } + + switch (MODE) { + case 2: + if (flag == NM_CONNECTION_SERIALIZE_ALL) { + s_wg2 = NM_SETTING_WIREGUARD( + nm_connection_get_setting(con2, NM_TYPE_SETTING_WIREGUARD)); + + if (flag == NM_CONNECTION_SERIALIZE_ALL) + _rndt_wg_peers_assert_equal(s_wg2, wg_peers, TRUE, TRUE, FALSE); + else if (flag == NM_CONNECTION_SERIALIZE_NO_SECRETS) + _rndt_wg_peers_assert_equal(s_wg2, wg_peers, FALSE, FALSE, TRUE); + else + g_assert_not_reached(); + } + break; + } + } +} + +/*****************************************************************************/ + +static NMIPRoutingRule * +_rr_from_str_get_impl(const char *str, const char *const *aliases) +{ + nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr = NULL; + gs_free_error GError * error = NULL; + gboolean vbool; + int addr_family; + int i; + NMIPRoutingRuleAsStringFlags to_string_flags; + + rr = nm_ip_routing_rule_from_string(str, + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE, + NULL, + &error); + nmtst_assert_success(rr, error); + + addr_family = nm_ip_routing_rule_get_addr_family(rr); + g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + + if (addr_family == AF_INET) + to_string_flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET; + else + to_string_flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6; + + for (i = 0; TRUE; i++) { + nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr2 = NULL; + gs_free char * str1 = NULL; + gs_unref_variant GVariant *variant1 = NULL; + const char * cstr1; + + switch (i) { + case 0: + rr2 = nm_ip_routing_rule_ref(rr); + break; + + case 1: + rr2 = nm_ip_routing_rule_from_string( + str, + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE + | (nmtst_get_rand_bool() ? to_string_flags + : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE), + NULL, + &error); + nmtst_assert_success(rr, error); + break; + + case 2: + str1 = nm_ip_routing_rule_to_string( + rr, + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE + | (nmtst_get_rand_bool() ? to_string_flags + : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE), + NULL, + &error); + nmtst_assert_success(str1 && str1[0], error); + + g_assert_cmpstr(str, ==, str1); + + rr2 = nm_ip_routing_rule_from_string( + str1, + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE + | (nmtst_get_rand_bool() ? to_string_flags + : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE), + NULL, + &error); + nmtst_assert_success(rr, error); + break; + + case 3: + variant1 = nm_ip_routing_rule_to_dbus(rr); + g_assert(variant1); + g_assert(g_variant_is_floating(variant1)); + g_assert(g_variant_is_of_type(variant1, G_VARIANT_TYPE_VARDICT)); + + rr2 = nm_ip_routing_rule_from_dbus(variant1, TRUE, &error); + nmtst_assert_success(rr, error); + break; + + default: + if (!aliases || !aliases[0]) + goto done; + cstr1 = (aliases++)[0]; + rr2 = nm_ip_routing_rule_from_string( + cstr1, + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE + | (nmtst_get_rand_bool() ? to_string_flags + : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE), + NULL, + &error); + nmtst_assert_success(rr, error); + break; + } + + g_assert(rr2); + vbool = nm_ip_routing_rule_validate(rr, &error); + nmtst_assert_success(vbool, error); + vbool = nm_ip_routing_rule_validate(rr2, &error); + nmtst_assert_success(vbool, error); + + g_assert_cmpint(nm_ip_routing_rule_cmp(rr, rr2), ==, 0); + g_assert_cmpint(nm_ip_routing_rule_cmp(rr2, rr), ==, 0); + } + +done: + return g_steal_pointer(&rr); +} +#define _rr_from_str_get(a, ...) _rr_from_str_get_impl(a, &(NM_MAKE_STRV(NULL, ##__VA_ARGS__))[1]) + +#define _rr_from_str(...) \ + G_STMT_START \ + { \ + nm_auto_unref_ip_routing_rule NMIPRoutingRule *_rr = NULL; \ + \ + _rr = _rr_from_str_get(__VA_ARGS__); \ + g_assert(_rr); \ + } \ + G_STMT_END + +static void +test_routing_rule(gconstpointer test_data) +{ + nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr1 = NULL; + gboolean success; + char ifname_buf[16]; + + _rr_from_str("priority 5 from 0.0.0.0 table 1", " from 0.0.0.0 priority 5 lookup 1 "); + _rr_from_str("priority 5 from 0.0.0.0/0 table 4"); + _rr_from_str("priority 5 to 0.0.0.0 table 6"); + _rr_from_str("priority 5 to 0.0.0.0 table 254", "priority 5 to 0.0.0.0/32"); + _rr_from_str("priority 5 from 1.2.3.4 table 15", + "priority 5 from 1.2.3.4/32 table 0xF ", + "priority 5 from 1.2.3.4/32 to 0.0.0.0/0 lookup 15 "); + _rr_from_str("priority 5 from 1.2.3.4 to 0.0.0.0 table 8"); + _rr_from_str("priority 5 to a:b:c:: tos 0x16 table 25", + "priority 5 to a:b:c::/128 table 0x19 tos 16", + "priority 5 to a:b:c::/128 lookup 0x19 dsfield 16", + "priority 5 to a:b:c::/128 lookup 0x19 dsfield 16 fwmark 0/0x00", + "priority 5 to a:b:c:: from all lookup 0x19 dsfield 16 fwmark 0x0/0"); + _rr_from_str("priority 5 from :: fwmark 0 table 25", + "priority 5 from ::/128 to all table 0x19 fwmark 0/0xFFFFFFFF", + "priority 5 from :: to ::/0 table 0x19 fwmark 0x00/4294967295"); + _rr_from_str("priority 5 from :: iif aab table 25"); + _rr_from_str("priority 5 from :: iif aab oif er table 25", + "priority 5 from :: table 0x19 dev aab oif er"); + _rr_from_str("priority 5 from :: iif a\\\\303b table 25"); + _rr_from_str("priority 5 to 0.0.0.0 sport 10 table 6", + "priority 5 to 0.0.0.0 sport 10-10 table 6"); + _rr_from_str("priority 5 not to 0.0.0.0 dport 10-133 table 6", + "not priority 5 to 0.0.0.0 dport 10-133 table 6", + "not priority 5 not to 0.0.0.0 dport 10-133 table 6", + "priority 5 to 0.0.0.0 not dport 10-133 not table 6", + "priority 5 to 0.0.0.0 not dport 10-\\ 133 not table 6"); + _rr_from_str("priority 5 to 0.0.0.0 ipproto 10 sport 10 table 6"); + + rr1 = _rr_from_str_get("priority 5 from :: iif aab table 25"); + g_assert_cmpstr(nm_ip_routing_rule_get_iifname(rr1), ==, "aab"); + success = nm_ip_routing_rule_get_xifname_bin(rr1, FALSE, ifname_buf); + g_assert(!success); + success = nm_ip_routing_rule_get_xifname_bin(rr1, TRUE, ifname_buf); + g_assert_cmpstr(ifname_buf, ==, "aab"); + g_assert(success); + nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); + + rr1 = _rr_from_str_get("priority 5 from :: iif a\\\\303\\\\261xb table 254"); + g_assert_cmpstr(nm_ip_routing_rule_get_iifname(rr1), ==, "a\\303\\261xb"); + success = nm_ip_routing_rule_get_xifname_bin(rr1, FALSE, ifname_buf); + g_assert(!success); + success = nm_ip_routing_rule_get_xifname_bin(rr1, TRUE, ifname_buf); + g_assert_cmpstr(ifname_buf, ==, "a\303\261xb"); + g_assert(success); + nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); + + rr1 = _rr_from_str_get("priority 5 from :: oif \\\\101=\\\\303\\\\261xb table 7"); + g_assert_cmpstr(nm_ip_routing_rule_get_oifname(rr1), ==, "\\101=\\303\\261xb"); + success = nm_ip_routing_rule_get_xifname_bin(rr1, FALSE, ifname_buf); + g_assert_cmpstr(ifname_buf, ==, "A=\303\261xb"); + g_assert(success); + success = nm_ip_routing_rule_get_xifname_bin(rr1, TRUE, ifname_buf); + g_assert(!success); + nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); + + rr1 = _rr_from_str_get("priority 5 to 0.0.0.0 tos 0x10 table 7"); + g_assert_cmpstr(NULL, ==, nm_ip_routing_rule_get_from(rr1)); + g_assert(!nm_ip_routing_rule_get_from_bin(rr1)); + g_assert_cmpint(0, ==, nm_ip_routing_rule_get_from_len(rr1)); + g_assert_cmpstr("0.0.0.0", ==, nm_ip_routing_rule_get_to(rr1)); + g_assert(nm_ip_addr_is_null(AF_INET, nm_ip_routing_rule_get_to_bin(rr1))); + g_assert_cmpint(32, ==, nm_ip_routing_rule_get_to_len(rr1)); + g_assert_cmpint(7, ==, nm_ip_routing_rule_get_table(rr1)); + g_assert_cmpint(0x10, ==, nm_ip_routing_rule_get_tos(rr1)); + nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); + + rr1 = _rr_from_str_get("priority 5 from :: iif a\\\\303\\\\261,x;b table 254", + "priority 5 from :: iif a\\\\303\\\\261,x;b table 254"); + g_assert_cmpstr(nm_ip_routing_rule_get_iifname(rr1), ==, "a\\303\\261,x;b"); + success = nm_ip_routing_rule_get_xifname_bin(rr1, FALSE, ifname_buf); + g_assert(!success); + success = nm_ip_routing_rule_get_xifname_bin(rr1, TRUE, ifname_buf); + g_assert_cmpstr(ifname_buf, ==, "a\303\261,x;b"); + g_assert(success); + nm_clear_pointer(&rr1, nm_ip_routing_rule_unref); +} + +/*****************************************************************************/ + +static void +test_parse_tc_handle(void) +{ +#define _parse_tc_handle(str, exp) \ + G_STMT_START \ + { \ + gs_free_error GError *_error = NULL; \ + GError ** _perror = nmtst_get_rand_bool() ? &_error : NULL; \ + guint32 _v; \ + const guint32 _v_exp = (exp); \ + \ + _v = _nm_utils_parse_tc_handle("" str "", _perror); \ + \ + if (_v != _v_exp) \ + g_error("%s:%d: \"%s\" gave %08x but %08x expected.", \ + __FILE__, \ + __LINE__, \ + "" str "", \ + _v, \ + _v_exp); \ + \ + if (_v == TC_H_UNSPEC) \ + g_assert(!_perror || *_perror); \ + else \ + g_assert(!_perror || !*_perror); \ + } \ + G_STMT_END + +#define _parse_tc_handle_inval(str) _parse_tc_handle(str, TC_H_UNSPEC) +#define _parse_tc_handle_valid(str, maj, min) \ + _parse_tc_handle(str, TC_H_MAKE(((guint32)(maj)) << 16, ((guint16)(min)))) + + _parse_tc_handle_inval(""); + _parse_tc_handle_inval(" "); + _parse_tc_handle_inval(" \n"); + _parse_tc_handle_valid("1", 1, 0); + _parse_tc_handle_valid(" 1 ", 1, 0); + _parse_tc_handle_valid("1:", 1, 0); + _parse_tc_handle_valid("1: ", 1, 0); + _parse_tc_handle_valid("1:0", 1, 0); + _parse_tc_handle_valid("1 :0", 1, 0); + _parse_tc_handle_valid("1 \t\n\f\r:0", 1, 0); + _parse_tc_handle_inval("1 \t\n\f\r\v:0"); + _parse_tc_handle_valid(" 1 : 0 ", 1, 0); + _parse_tc_handle_inval(" \t\v\n1: 0"); + _parse_tc_handle_valid("1:2", 1, 2); + _parse_tc_handle_valid("01:02", 1, 2); + _parse_tc_handle_inval("0x01:0x02"); + _parse_tc_handle_valid(" 01: 02", 1, 2); + _parse_tc_handle_valid("019: 020", 0x19, 0x20); + _parse_tc_handle_valid("FFFF: 020", 0xFFFF, 0x20); + _parse_tc_handle_valid("FfFF: ffff", 0xFFFF, 0xFFFF); + _parse_tc_handle_valid("FFFF", 0xFFFF, 0); + _parse_tc_handle_inval("0xFFFF"); + _parse_tc_handle_inval("10000"); + _parse_tc_handle_valid("\t\n\f\r FFFF", 0xFFFF, 0); + _parse_tc_handle_inval("\t\n\f\r \vFFFF"); +} + +/*****************************************************************************/ + +static void +test_empty_setting(void) +{ + gs_unref_object NMConnection *con = NULL; + gs_unref_object NMConnection *con2 = NULL; + NMSettingBluetooth * s_bt; + NMSettingGsm * s_gsm; + nm_auto_unref_keyfile GKeyFile *kf = NULL; + gs_free_error GError *error = NULL; + + con = nmtst_create_minimal_connection("bt-empty-gsm", + "dca3192a-f2dc-48eb-b806-d0ff788f122c", + NM_SETTING_BLUETOOTH_SETTING_NAME, + NULL); + + s_bt = _nm_connection_get_setting(con, NM_TYPE_SETTING_BLUETOOTH); + g_object_set(s_bt, + NM_SETTING_BLUETOOTH_TYPE, + "dun", + NM_SETTING_BLUETOOTH_BDADDR, + "aa:bb:cc:dd:ee:ff", + NULL); + + s_gsm = NM_SETTING_GSM(nm_setting_gsm_new()); + nm_connection_add_setting(con, NM_SETTING(s_gsm)); + + nmtst_connection_normalize(con); + + nmtst_assert_connection_verifies_without_normalization(con); + + kf = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); + nmtst_assert_success(kf, error); + + g_assert(g_key_file_has_group(kf, "gsm")); + g_assert_cmpint(nmtst_keyfile_get_num_keys(kf, "gsm"), ==, 0); + + con2 = nm_keyfile_read(kf, + "/ignored/current/working/directory/for/loading/relative/paths", + NM_KEYFILE_HANDLER_FLAGS_NONE, + NULL, + NULL, + &error); + nmtst_assert_success(con2, error); + + g_assert(nm_connection_get_setting(con2, NM_TYPE_SETTING_GSM)); + + nmtst_assert_connection_verifies_without_normalization(con2); +} + +/*****************************************************************************/ + +static guint +_PROP_IDX_PACK(NMMetaSettingType meta_type, guint idx) +{ + return (((guint) meta_type) & 0xFFu) | (idx << 8); +} + +static const char * +_PROP_IDX_OWNER(GHashTable *h_property_types, const NMSettInfoPropertType *property_type) +{ + const NMSettInfoSetting *sett_info_settings = nmtst_sett_info_settings(); + const NMSettInfoSetting *sis; + const NMMetaSettingInfo *msi; + GArray * arr; + guint idx; + NMMetaSettingType meta_type; + guint prop_idx; + char sbuf[300]; + + g_assert(h_property_types); + g_assert(property_type); + + arr = g_hash_table_lookup(h_property_types, property_type); + + g_assert(arr); + g_assert(arr->len > 0); + + idx = g_array_index(arr, guint, 0); + + meta_type = (idx & 0xFFu); + prop_idx = idx >> 8; + + g_assert(meta_type < _NM_META_SETTING_TYPE_NUM); + + sis = &sett_info_settings[meta_type]; + msi = &nm_meta_setting_infos[meta_type]; + + g_assert(prop_idx < sis->property_infos_len); + + nm_sprintf_buf(sbuf, "%s.%s", msi->setting_name, sis->property_infos[prop_idx].name); + + return g_intern_string(sbuf); +} + +static void +test_setting_metadata(void) +{ + const NMSettInfoSetting *sett_info_settings = nmtst_sett_info_settings(); + NMMetaSettingType meta_type; + gs_unref_hashtable GHashTable *h_property_types = NULL; + + G_STATIC_ASSERT(_NM_META_SETTING_TYPE_NUM == NM_META_SETTING_TYPE_UNKNOWN); + + h_property_types = + g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) g_array_unref); + + for (meta_type = 0; meta_type < _NM_META_SETTING_TYPE_NUM; meta_type++) { + const NMMetaSettingInfo *msi = &nm_meta_setting_infos[meta_type]; + nm_auto_unref_gtypeclass NMSettingClass *klass = NULL; + GType gtype; + + g_assert(msi->setting_name); + g_assert(msi->get_setting_gtype); + g_assert(msi->meta_type == meta_type); + g_assert(msi->setting_priority >= NM_SETTING_PRIORITY_CONNECTION); + g_assert(msi->setting_priority <= NM_SETTING_PRIORITY_USER); + + if (meta_type > 0) + g_assert_cmpint( + strcmp(nm_meta_setting_infos[meta_type - 1].setting_name, msi->setting_name), + <, + 0); + + gtype = msi->get_setting_gtype(); + + g_assert(g_type_is_a(gtype, NM_TYPE_SETTING)); + g_assert(gtype != NM_TYPE_SETTING); + + klass = g_type_class_ref(gtype); + g_assert(klass); + g_assert(NM_IS_SETTING_CLASS(klass)); + + g_assert(msi == klass->setting_info); + } + + g_assert(sett_info_settings); + + for (meta_type = 0; meta_type < _NM_META_SETTING_TYPE_NUM; meta_type++) { + const NMSettInfoSetting *sis = &sett_info_settings[meta_type]; + const NMMetaSettingInfo *msi = &nm_meta_setting_infos[meta_type]; + gs_unref_hashtable GHashTable *h_properties = NULL; + GType gtype; + gs_unref_object NMSetting *setting = NULL; + guint prop_idx; + gs_free GParamSpec **property_specs = NULL; + guint n_property_specs; + + g_assert(sis); + + g_assert(NM_IS_SETTING_CLASS(sis->setting_class)); + + gtype = msi->get_setting_gtype(); + + g_assert(G_TYPE_FROM_CLASS(sis->setting_class) == gtype); + + setting = g_object_new(gtype, NULL); + + g_assert(NM_IS_SETTING(setting)); + + g_assert_cmpint(sis->property_infos_len, >, 0); + g_assert(sis->property_infos); + + h_properties = g_hash_table_new(nm_str_hash, g_str_equal); + + for (prop_idx = 0; prop_idx < sis->property_infos_len; prop_idx++) { + const NMSettInfoProperty *sip = &sis->property_infos[prop_idx]; + GArray * property_types_data; + guint prop_idx_val; + + g_assert(sip->name); + + if (prop_idx > 0) + g_assert_cmpint(strcmp(sis->property_infos[prop_idx - 1].name, sip->name), <, 0); + + g_assert(sip->property_type); + g_assert(sip->property_type->dbus_type); + g_assert(g_variant_type_string_is_valid((const char *) sip->property_type->dbus_type)); + + g_assert(!sip->property_type->to_dbus_fcn || !sip->property_type->gprop_to_dbus_fcn); + g_assert(!sip->property_type->from_dbus_fcn + || !sip->property_type->gprop_from_dbus_fcn); + + if (!g_hash_table_insert(h_properties, (char *) sip->name, sip->param_spec)) + g_assert_not_reached(); + + property_types_data = g_hash_table_lookup(h_property_types, sip->property_type); + if (!property_types_data) { + property_types_data = g_array_new(FALSE, FALSE, sizeof(guint)); + if (!g_hash_table_insert(h_property_types, + (gpointer) sip->property_type, + property_types_data)) + g_assert_not_reached(); + } + prop_idx_val = _PROP_IDX_PACK(meta_type, prop_idx); + g_array_append_val(property_types_data, prop_idx_val); + + if (sip->param_spec) { + nm_auto_unset_gvalue GValue val = G_VALUE_INIT; + + g_assert_cmpstr(sip->name, ==, sip->param_spec->name); + + g_value_init(&val, sip->param_spec->value_type); + g_object_get_property(G_OBJECT(setting), sip->name, &val); + + if (sip->param_spec->value_type == G_TYPE_STRING) { + const char *default_value; + + default_value = ((const GParamSpecString *) sip->param_spec)->default_value; + if (default_value) { + /* having a string property with a default != NULL is really ugly. They + * should be best avoided... */ + if (meta_type == NM_META_SETTING_TYPE_DCB + && nm_streq(sip->name, NM_SETTING_DCB_APP_FCOE_MODE)) { + /* Whitelist the properties that have a non-NULL default value. */ + g_assert_cmpstr(default_value, ==, NM_SETTING_DCB_FCOE_MODE_FABRIC); + } else + g_assert_not_reached(); + } + + if (nm_streq(sip->name, NM_SETTING_NAME)) + g_assert_cmpstr(g_value_get_string(&val), ==, msi->setting_name); + else + g_assert_cmpstr(g_value_get_string(&val), ==, default_value); + } + + if (NM_FLAGS_HAS(sip->param_spec->flags, NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS)) + g_assert(sip->property_type->to_dbus_fcn); + } + } + + /* check that all GObject based properties are tracked by the settings. */ + property_specs = + g_object_class_list_properties(G_OBJECT_CLASS(sis->setting_class), &n_property_specs); + g_assert(property_specs); + g_assert_cmpint(n_property_specs, >, 0); + for (prop_idx = 0; prop_idx < n_property_specs; prop_idx++) { + const GParamSpec *pip = property_specs[prop_idx]; + + g_assert(g_hash_table_lookup(h_properties, pip->name) == pip); + } + + /* check that property_infos_sorted is as expected. */ + if (sis->property_infos_sorted) { + gs_unref_hashtable GHashTable *h = g_hash_table_new(nm_direct_hash, NULL); + + /* property_infos_sorted is only implemented for [connection] type */ + g_assert_cmpint(meta_type, ==, NM_META_SETTING_TYPE_CONNECTION); + + /* ensure that there are no duplicates, and that all properties are also + * tracked by sis->property_infos. */ + for (prop_idx = 0; prop_idx < sis->property_infos_len; prop_idx++) { + const NMSettInfoProperty *sip = sis->property_infos_sorted[prop_idx]; + + if (!g_hash_table_add(h, (gpointer) sip)) + g_assert_not_reached(); + } + for (prop_idx = 0; prop_idx < sis->property_infos_len; prop_idx++) { + const NMSettInfoProperty *sip = &sis->property_infos[prop_idx]; + + g_assert(g_hash_table_contains(h, sip)); + } + } else + g_assert_cmpint(meta_type, !=, NM_META_SETTING_TYPE_CONNECTION); + + /* consistency check for gendata-info. */ + if (sis->detail.gendata_info) { + g_assert_cmpint(meta_type, ==, NM_META_SETTING_TYPE_ETHTOOL); + g_assert(sis->detail.gendata_info->get_variant_type); + + /* the gendata info based setting has only one regular property: the "name". */ + g_assert_cmpint(sis->property_infos_len, ==, 1); + g_assert_cmpstr(sis->property_infos[0].name, ==, NM_SETTING_NAME); + } else + g_assert_cmpint(meta_type, !=, NM_META_SETTING_TYPE_ETHTOOL); + } + + { + gs_free NMSettInfoPropertType **a_property_types = NULL; + guint a_property_types_len; + guint prop_idx; + guint prop_idx_2; + + a_property_types = + (NMSettInfoPropertType **) g_hash_table_get_keys_as_array(h_property_types, + &a_property_types_len); + + for (prop_idx = 0; prop_idx < a_property_types_len; prop_idx++) { + const NMSettInfoPropertType *pt = a_property_types[prop_idx]; + + for (prop_idx_2 = prop_idx + 1; prop_idx_2 < a_property_types_len; prop_idx_2++) { + const NMSettInfoPropertType *pt_2 = a_property_types[prop_idx_2]; + + if (!g_variant_type_equal(pt->dbus_type, pt_2->dbus_type) + || pt->to_dbus_fcn != pt_2->to_dbus_fcn + || pt->from_dbus_fcn != pt_2->from_dbus_fcn + || pt->missing_from_dbus_fcn != pt_2->missing_from_dbus_fcn + || pt->gprop_to_dbus_fcn != pt_2->gprop_to_dbus_fcn + || pt->gprop_from_dbus_fcn != pt_2->gprop_from_dbus_fcn) + continue; + + if ((pt == &nm_sett_info_propert_type_plain_i + && pt_2 == &nm_sett_info_propert_type_deprecated_ignore_i) + || (pt_2 == &nm_sett_info_propert_type_plain_i + && pt == &nm_sett_info_propert_type_deprecated_ignore_i) + || (pt == &nm_sett_info_propert_type_plain_u + && pt_2 == &nm_sett_info_propert_type_deprecated_ignore_u) + || (pt_2 == &nm_sett_info_propert_type_plain_u + && pt == &nm_sett_info_propert_type_deprecated_ignore_u)) { + /* These are known to be duplicated. This is the case for + * "gsm.network-type" and plain properties like "802-11-wireless-security.fils" ("i" D-Bus type) + * "gsm.allowed-bands" and plain properties like "802-11-olpc-mesh.channel" ("u" D-Bus type) + * While the content/behaviour of the property types are identical, their purpose + * is different. So allow them. + */ + continue; + } + + /* the property-types with same content should all be shared. Here we have two that + * are the same content, but different instances. Bug. */ + g_error("The identical property type for D-Bus type \"%s\" is used by: %s and %s", + (const char *) pt->dbus_type, + _PROP_IDX_OWNER(h_property_types, pt), + _PROP_IDX_OWNER(h_property_types, pt_2)); + } + } + } +} + +/*****************************************************************************/ + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init(&argc, &argv, TRUE); + + g_test_add_data_func("/libnm/setting-8021x/key-and-cert", + "test_key_and_cert.pem, test", + test_8021x); + g_test_add_data_func("/libnm/setting-8021x/key-only", "test-key-only.pem, test", test_8021x); + g_test_add_data_func("/libnm/setting-8021x/pkcs8-enc-key", + "pkcs8-enc-key.pem, 1234567890", + test_8021x); + g_test_add_data_func("/libnm/setting-8021x/pkcs12", "test-cert.p12, test", test_8021x); + + g_test_add_func("/libnm/settings/bond/verify", test_bond_verify); + g_test_add_func("/libnm/settings/bond/compare", test_bond_compare); + g_test_add_func("/libnm/settings/bond/normalize", test_bond_normalize); + + g_test_add_func("/libnm/settings/dcb/flags-valid", test_dcb_flags_valid); + g_test_add_func("/libnm/settings/dcb/flags-invalid", test_dcb_flags_invalid); + g_test_add_func("/libnm/settings/dcb/app-priorities", test_dcb_app_priorities); + g_test_add_func("/libnm/settings/dcb/priorities", test_dcb_priorities_valid); + g_test_add_func("/libnm/settings/dcb/bandwidth-sums", test_dcb_bandwidth_sums); + + g_test_add_func("/libnm/settings/ethtool/features", test_ethtool_features); + g_test_add_func("/libnm/settings/ethtool/coalesce", test_ethtool_coalesce); + g_test_add_func("/libnm/settings/ethtool/ring", test_ethtool_ring); + + g_test_add_func("/libnm/settings/sriov/vf", test_sriov_vf); + g_test_add_func("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup); + g_test_add_func("/libnm/settings/sriov/vf-vlan", test_sriov_vf_vlan); + g_test_add_func("/libnm/settings/sriov/setting", test_sriov_setting); + g_test_add_func("/libnm/settings/sriov/vlans", test_sriov_parse_vlans); + + g_test_add_func("/libnm/settings/tc_config/qdisc", test_tc_config_qdisc); + g_test_add_func("/libnm/settings/tc_config/action", test_tc_config_action); + g_test_add_func("/libnm/settings/tc_config/tfilter/matchall_sdata", + test_tc_config_tfilter_matchall_sdata); + g_test_add_func("/libnm/settings/tc_config/tfilter/matchall_mirred", + test_tc_config_tfilter_matchall_mirred); + g_test_add_func("/libnm/settings/tc_config/setting/valid", test_tc_config_setting_valid); + g_test_add_func("/libnm/settings/tc_config/setting/duplicates", + test_tc_config_setting_duplicates); + g_test_add_func("/libnm/settings/tc_config/dbus", test_tc_config_dbus); + + g_test_add_func("/libnm/settings/bridge/vlans", test_bridge_vlans); + g_test_add_func("/libnm/settings/bridge/verify", test_bridge_verify); + + g_test_add_func("/libnm/test_nm_json", test_nm_json); + g_test_add_func("/libnm/settings/team/sync_runner_from_config_roundrobin", + test_runner_roundrobin_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_runner_from_config_broadcast", + test_runner_broadcast_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_runner_from_config_random", + test_runner_random_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_runner_from_config_activebackup", + test_runner_activebackup_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_runner_from_config_loadbalance", + test_runner_loadbalance_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_runner_from_config_lacp", + test_runner_lacp_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_watcher_from_config_ethtool", + test_watcher_ethtool_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_watcher_from_config_nsna_ping", + test_watcher_nsna_ping_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_watcher_from_config_arp_ping", + test_watcher_arp_ping_sync_from_config); + g_test_add_func("/libnm/settings/team/sync_watcher_from_config_all", + test_multiple_watchers_sync_from_config); + + g_test_add_func("/libnm/settings/team-port/sync_from_config_defaults", test_team_port_default); + g_test_add_func("/libnm/settings/team-port/sync_from_config_queue_id", test_team_port_queue_id); + g_test_add_func("/libnm/settings/team-port/sync_from_config_prio", test_team_port_prio); + g_test_add_func("/libnm/settings/team-port/sync_from_config_sticky", test_team_port_sticky); + g_test_add_func("/libnm/settings/team-port/sync_from_config_lacp_prio", + test_team_port_lacp_prio); + g_test_add_func("/libnm/settings/team-port/sync_from_config_lacp_key", test_team_port_lacp_key); + g_test_add_func("/libnm/settings/team-port/sycn_from_config_full", test_team_port_full_config); + + g_test_add_data_func("/libnm/settings/roundtrip-conversion/general/0", + GINT_TO_POINTER(0), + test_roundtrip_conversion); + g_test_add_data_func("/libnm/settings/roundtrip-conversion/wireguard/1", + GINT_TO_POINTER(1), + test_roundtrip_conversion); + g_test_add_data_func("/libnm/settings/roundtrip-conversion/wireguard/2", + GINT_TO_POINTER(2), + test_roundtrip_conversion); + g_test_add_data_func("/libnm/settings/roundtrip-conversion/general/3", + GINT_TO_POINTER(3), + test_roundtrip_conversion); + + g_test_add_data_func("/libnm/settings/routing-rule/1", GINT_TO_POINTER(0), test_routing_rule); + + g_test_add_func("/libnm/parse-tc-handle", test_parse_tc_handle); + + g_test_add_func("/libnm/test_team_setting", test_team_setting); + + g_test_add_func("/libnm/test_empty_setting", test_empty_setting); + + g_test_add_func("/libnm/test_setting_metadata", test_setting_metadata); + + return g_test_run(); +} diff --git a/src/libnm-core-impl/tests/test-settings-defaults.c b/src/libnm-core-impl/tests/test-settings-defaults.c new file mode 100644 index 0000000000..e04a55ec7a --- /dev/null +++ b/src/libnm-core-impl/tests/test-settings-defaults.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2008 - 2011 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-utils.h" +#include "nm-setting-8021x.h" +#include "nm-setting-cdma.h" +#include "nm-setting-connection.h" +#include "nm-setting-gsm.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-serial.h" +#include "nm-setting-vpn.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wireless-security.h" + +#include "nm-utils/nm-test-utils.h" + +static void +test_defaults(GType type, const char *name) +{ + GParamSpec **property_specs; + guint n_property_specs; + GObject * setting; + int i; + + setting = g_object_new(type, NULL); + + property_specs = g_object_class_list_properties(G_OBJECT_GET_CLASS(setting), &n_property_specs); + g_assert(property_specs); + + for (i = 0; i < n_property_specs; i++) { + GParamSpec *prop_spec = property_specs[i]; + GValue value = G_VALUE_INIT; + GValue defvalue = G_VALUE_INIT; + char * actual, *expected; + gboolean ok = FALSE; + + /* Ignore non-fundamental types since they won't really have + * defaults. + */ + if (!G_TYPE_IS_FUNDAMENTAL(prop_spec->value_type)) + continue; + + g_value_init(&value, prop_spec->value_type); + g_object_get_property(G_OBJECT(setting), prop_spec->name, &value); + + g_value_init(&defvalue, prop_spec->value_type); + g_param_value_set_default(prop_spec, &defvalue); + + actual = g_strdup_value_contents(&value); + expected = g_strdup_value_contents(&defvalue); + + if (!strcmp(prop_spec->name, NM_SETTING_NAME)) { + /* 'name' is always the setting name, not the default value */ + ok = !strcmp(nm_setting_get_name(NM_SETTING(setting)), name); + g_free(expected); + expected = g_strdup(name); + } else + ok = g_param_value_defaults(prop_spec, &value); + + g_assert(ok); + + g_free(actual); + g_free(expected); + g_value_unset(&value); + g_value_unset(&defvalue); + } + + g_free(property_specs); + g_object_unref(setting); +} + +static void +defaults(void) +{ + /* The tests */ + test_defaults(NM_TYPE_SETTING_CONNECTION, NM_SETTING_CONNECTION_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_802_1X, NM_SETTING_802_1X_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_CDMA, NM_SETTING_CDMA_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_GSM, NM_SETTING_GSM_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_IP4_CONFIG, NM_SETTING_IP4_CONFIG_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_IP6_CONFIG, NM_SETTING_IP6_CONFIG_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_PPP, NM_SETTING_PPP_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_PPPOE, NM_SETTING_PPPOE_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_SERIAL, NM_SETTING_SERIAL_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_VPN, NM_SETTING_VPN_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_WIRED, NM_SETTING_WIRED_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_WIRELESS, NM_SETTING_WIRELESS_SETTING_NAME); + test_defaults(NM_TYPE_SETTING_WIRELESS_SECURITY, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); +} + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init(&argc, &argv, TRUE); + + g_test_add_func("/libnm/defaults", defaults); + + return g_test_run(); +} diff --git a/src/libnm-core-intern/README.md b/src/libnm-core-intern/README.md new file mode 100644 index 0000000000..f17cf4daf2 --- /dev/null +++ b/src/libnm-core-intern/README.md @@ -0,0 +1,19 @@ +libnm-core-intern +================= + +This contains header files only, which are also part of +the internal API of [`libnm-core-impl`](../libnm-core-impl). + +[`libnm-core-impl`](../libnm-core-impl) is a static library that (among others) implements +[`libnm-core-public`](../libnm-core-public) (which is a part of the public API of [`libnm`](../../libnm)). +This library gets statically linked into [`libnm`](../../libnm) and `NetworkManager`. +Hence, those components can also access internal (but not private) API of +[`libnm-core-impl`](../libnm-core-impl), and this API is in [`libnm-core-intern`](../libnm-core-intern). + +These headers can thus be included by anybody who statically links with +[`libnm-core-impl`](../libnm-core-impl) (including [`libnm-core-impl`](../libnm-core-impl) itself). + +The directory should not be added to the include search path, instead +users should explicitly `#include "libnm-core-intern/nm-core-internal.h"`) + +There is no source code here and no static library to link against. diff --git a/src/libnm-core-intern/meson.build b/src/libnm-core-intern/meson.build new file mode 100644 index 0000000000..0373452c20 --- /dev/null +++ b/src/libnm-core-intern/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnm_core_intern_inc = include_directories('.') + +libnm_core_intern_dep = declare_dependency( + dependencies: [ + libnm_core_public_dep, + glib_dep, + ], +) diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h new file mode 100644 index 0000000000..4687e710cb --- /dev/null +++ b/src/libnm-core-intern/nm-core-internal.h @@ -0,0 +1,930 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2014 - 2018 Red Hat, Inc. + */ + +#ifndef NM_CORE_NM_INTERNAL_H +#define NM_CORE_NM_INTERNAL_H + +/* This header file contain functions that are provided as private API + * by libnm-core. It will contain functions to give privileged access to + * libnm-core. This can be useful for NetworkManager and libnm.so + * which both are special users of libnm-core. + * It also exposes some utility functions for reuse. + * + * These functions are not exported and are only available to components that link + * statically against libnm-core. This basically means libnm-core, libnm, NetworkManager + * and some test programs. + **/ +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) + #error Cannot use this header. +#endif + +#include "nm-base/nm-base.h" +#include "nm-connection.h" +#include "nm-core-enum-types.h" +#include "nm-core-types-internal.h" +#include "nm-meta-setting-base.h" +#include "nm-setting-6lowpan.h" +#include "nm-setting-8021x.h" +#include "nm-setting-adsl.h" +#include "nm-setting-bluetooth.h" +#include "nm-setting-bond.h" +#include "nm-setting-bridge-port.h" +#include "nm-setting-bridge.h" +#include "nm-setting-cdma.h" +#include "nm-setting-connection.h" +#include "nm-setting-dcb.h" +#include "nm-setting-dummy.h" +#include "nm-setting-generic.h" +#include "nm-setting-gsm.h" +#include "nm-setting-hostname.h" +#include "nm-setting-infiniband.h" +#include "nm-setting-ip-tunnel.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-macsec.h" +#include "nm-setting-macvlan.h" +#include "nm-setting-match.h" +#include "nm-setting-olpc-mesh.h" +#include "nm-setting-ovs-bridge.h" +#include "nm-setting-ovs-interface.h" +#include "nm-setting-ovs-dpdk.h" +#include "nm-setting-ovs-patch.h" +#include "nm-setting-ovs-port.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-proxy.h" +#include "nm-setting-serial.h" +#include "nm-setting-sriov.h" +#include "nm-setting-tc-config.h" +#include "nm-setting-team-port.h" +#include "nm-setting-team.h" +#include "nm-setting-tun.h" +#include "nm-setting-veth.h" +#include "nm-setting-vlan.h" +#include "nm-setting-vpn.h" +#include "nm-setting-vrf.h" +#include "nm-setting-vxlan.h" +#include "nm-setting-wifi-p2p.h" +#include "nm-setting-wimax.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireguard.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wpan.h" +#include "nm-setting.h" +#include "nm-simple-connection.h" +#include "nm-utils.h" +#include "nm-vpn-dbus-interface.h" +#include "nm-vpn-editor-plugin.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" + +/* IEEE 802.1D-1998 timer values */ +#define NM_BRIDGE_HELLO_TIME_MIN 1u +#define NM_BRIDGE_HELLO_TIME_DEF 2u +#define NM_BRIDGE_HELLO_TIME_DEF_SYS (NM_BRIDGE_HELLO_TIME_DEF * 100u) +#define NM_BRIDGE_HELLO_TIME_MAX 10u + +#define NM_BRIDGE_FORWARD_DELAY_MIN 2u +#define NM_BRIDGE_FORWARD_DELAY_DEF 15u +#define NM_BRIDGE_FORWARD_DELAY_DEF_SYS (NM_BRIDGE_FORWARD_DELAY_DEF * 100u) +#define NM_BRIDGE_FORWARD_DELAY_MAX 30u + +#define NM_BRIDGE_MAX_AGE_MIN 6u +#define NM_BRIDGE_MAX_AGE_DEF 20u +#define NM_BRIDGE_MAX_AGE_DEF_SYS (NM_BRIDGE_MAX_AGE_DEF * 100u) +#define NM_BRIDGE_MAX_AGE_MAX 40u + +/* IEEE 802.1D-1998 Table 7.4 */ +#define NM_BRIDGE_AGEING_TIME_MIN 0u +#define NM_BRIDGE_AGEING_TIME_DEF 300u +#define NM_BRIDGE_AGEING_TIME_DEF_SYS (NM_BRIDGE_AGEING_TIME_DEF * 100u) +#define NM_BRIDGE_AGEING_TIME_MAX 1000000u + +#define NM_BRIDGE_PORT_PRIORITY_MIN 0u +#define NM_BRIDGE_PORT_PRIORITY_DEF 32u +#define NM_BRIDGE_PORT_PRIORITY_MAX 63u + +#define NM_BRIDGE_PORT_PATH_COST_MIN 0u +#define NM_BRIDGE_PORT_PATH_COST_DEF 100u +#define NM_BRIDGE_PORT_PATH_COST_MAX 65535u + +#define NM_BRIDGE_MULTICAST_HASH_MAX_MIN 1u +#define NM_BRIDGE_MULTICAST_HASH_MAX_DEF 4096u +#define NM_BRIDGE_MULTICAST_HASH_MAX_MAX ((guint) G_MAXUINT32) + +#define NM_BRIDGE_STP_DEF TRUE + +#define NM_BRIDGE_GROUP_ADDRESS_DEF_BIN 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 +#define NM_BRIDGE_GROUP_ADDRESS_DEF_STR "01:80:C2:00:00:00" + +#define NM_BRIDGE_PRIORITY_MIN 0u +#define NM_BRIDGE_PRIORITY_DEF 0x8000u +#define NM_BRIDGE_PRIORITY_MAX ((guint) G_MAXUINT16) + +#define NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MIN 0u +#define NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF 2u +#define NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MAX ((guint) G_MAXUINT32) + +#define NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MIN ((guint64) 0) +#define NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF ((guint64) 100) +#define NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MAX G_MAXUINT64 + +#define NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MIN ((guint64) 0) +#define NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF ((guint64) 26000) +#define NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MAX G_MAXUINT64 + +#define NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MIN ((guint64) 0) +#define NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF ((guint64) 25500) +#define NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MAX G_MAXUINT64 + +#define NM_BRIDGE_MULTICAST_QUERIER_DEF FALSE + +#define NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MIN ((guint64) 0) +#define NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF ((guint64) 12500) +#define NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MAX G_MAXUINT64 + +#define NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MIN ((guint64) 0) +#define NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF ((guint64) 1000) +#define NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MAX G_MAXUINT64 + +#define NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF FALSE + +#define NM_BRIDGE_MULTICAST_SNOOPING_DEF TRUE + +#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MIN 0u +#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF 2u +#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MAX ((guint) G_MAXUINT32) + +#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MIN ((guint64) 0) +#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF ((guint64) 3125) +#define NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MAX G_MAXUINT64 + +#define NM_BRIDGE_VLAN_STATS_ENABLED_DEF FALSE + +#define NM_BRIDGE_VLAN_DEFAULT_PVID_DEF 1u + +/* NM_SETTING_COMPARE_FLAG_INFERRABLE: check whether a device-generated + * connection can be replaced by a already-defined connection. This flag only + * takes into account properties marked with the %NM_SETTING_PARAM_INFERRABLE + * flag. + */ +#define NM_SETTING_COMPARE_FLAG_INFERRABLE ((NMSettingCompareFlags) 0x80000000) + +/* NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY: this flag is used for properties + * that automatically get re-applied on an active connection when the settings + * connection is modified. For most properties, the applied-connection is distinct + * from the setting-connection and changes don't propagate. Exceptions are the + * firewall-zone and the metered property. + */ +#define NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY ((NMSettingCompareFlags) 0x40000000) + +/* NM_SETTING_COMPARE_FLAG_NONE: for convenience, define a special flag NONE -- which + * equals to numeric zero (NM_SETTING_COMPARE_FLAG_EXACT). + */ +#define NM_SETTING_COMPARE_FLAG_NONE ((NMSettingCompareFlags) 0) + +/*****************************************************************************/ + +#define NM_SETTING_SECRET_FLAG_ALL \ + ((NMSettingSecretFlags)(NM_SETTING_SECRET_FLAG_NONE | NM_SETTING_SECRET_FLAG_AGENT_OWNED \ + | NM_SETTING_SECRET_FLAG_NOT_SAVED \ + | NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) + +static inline gboolean +_nm_setting_secret_flags_valid(NMSettingSecretFlags flags) +{ + return !NM_FLAGS_ANY(flags, ~NM_SETTING_SECRET_FLAG_ALL); +} + +/*****************************************************************************/ + +const char * +nm_bluetooth_capability_to_string(NMBluetoothCapabilities capabilities, char *buf, gsize len); + +/*****************************************************************************/ + +#define NM_DHCP_HOSTNAME_FLAGS_FQDN_MASK \ + (NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE \ + | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE | NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS) + +#define NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP4 \ + (NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) + +#define NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP6 NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE + +/*****************************************************************************/ + +static inline _NMSettingWiredWakeOnLan +_NM_SETTING_WIRED_WAKE_ON_LAN_CAST(NMSettingWiredWakeOnLan v) +{ + /* _NMSettingWiredWakeOnLan and NMSettingWiredWakeOnLan enums are really + * the same. + * + * The former is used by nm-platform (which should have no libnm-core dependency), + * the latter is used by libnm-core. A unit test ensures they are exactly the same, + * so we can just cast them. */ + return (_NMSettingWiredWakeOnLan) v; +} + +/*****************************************************************************/ + +static inline NMTernary +NM_TERNARY_FROM_OPTION_BOOL(NMOptionBool v) +{ + nm_assert(NM_IN_SET(v, NM_OPTION_BOOL_DEFAULT, NM_OPTION_BOOL_TRUE, NM_OPTION_BOOL_FALSE)); + + return (NMTernary) v; +} + +static inline NMOptionBool +NM_TERNARY_TO_OPTION_BOOL(NMTernary v) +{ + nm_assert(NM_IN_SET(v, NM_TERNARY_DEFAULT, NM_TERNARY_TRUE, NM_TERNARY_FALSE)); + + return (NMOptionBool) v; +} + +/*****************************************************************************/ + +typedef enum { /*< skip >*/ + NM_SETTING_PARSE_FLAGS_NONE = 0, + NM_SETTING_PARSE_FLAGS_STRICT = 1LL << 0, + NM_SETTING_PARSE_FLAGS_BEST_EFFORT = 1LL << 1, + NM_SETTING_PARSE_FLAGS_NORMALIZE = 1LL << 2, + + _NM_SETTING_PARSE_FLAGS_LAST, + NM_SETTING_PARSE_FLAGS_ALL = ((_NM_SETTING_PARSE_FLAGS_LAST - 1) << 1) - 1, +} NMSettingParseFlags; + +gboolean _nm_connection_replace_settings(NMConnection * connection, + GVariant * new_settings, + NMSettingParseFlags parse_flags, + GError ** error); + +gpointer _nm_connection_check_main_setting(NMConnection *connection, + const char * setting_name, + GError ** error); + +typedef struct { + struct { + guint64 val; + bool has; + } timestamp; + + const char **seen_bssids; + +} NMConnectionSerializationOptions; + +GVariant *nm_connection_to_dbus_full(NMConnection * connection, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options); + +typedef enum { + /* whether the connection has any secrets. + * + * @arg may be %NULL or a pointer to a gboolean for the result. The return + * value of _nm_connection_aggregate() is likewise the boolean result. */ + NM_CONNECTION_AGGREGATE_ANY_SECRETS, + + /* whether the connection has any secret with flags NM_SETTING_SECRET_FLAG_NONE. + * Note that this only cares about the flags, not whether the secret is actually + * present. + * + * @arg may be %NULL or a pointer to a gboolean for the result. The return + * value of _nm_connection_aggregate() is likewise the boolean result. */ + NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, +} NMConnectionAggregateType; + +gboolean +_nm_connection_aggregate(NMConnection *connection, NMConnectionAggregateType type, gpointer arg); + +/** + * NMSettingVerifyResult: + * @NM_SETTING_VERIFY_SUCCESS: the setting verifies successfully + * @NM_SETTING_VERIFY_ERROR: the setting has a serious misconfiguration + * @NM_SETTING_VERIFY_NORMALIZABLE: the setting is valid but has properties + * that should be normalized + * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR: the setting is invalid but the + * errors can be fixed by nm_connection_normalize(). + */ +typedef enum { + NM_SETTING_VERIFY_SUCCESS = TRUE, + NM_SETTING_VERIFY_ERROR = FALSE, + NM_SETTING_VERIFY_NORMALIZABLE = 2, + NM_SETTING_VERIFY_NORMALIZABLE_ERROR = 3, +} NMSettingVerifyResult; + +NMSettingVerifyResult _nm_connection_verify(NMConnection *connection, GError **error); + +gboolean _nm_connection_ensure_normalized(NMConnection * connection, + gboolean allow_modify, + const char * expected_uuid, + gboolean coerce_uuid, + NMConnection **out_connection_clone, + GError ** error); + +gboolean _nm_connection_remove_setting(NMConnection *connection, GType setting_type); + +#if NM_MORE_ASSERTS +extern const char _nmtst_connection_unchanging_user_data; +void nmtst_connection_assert_unchanging(NMConnection *connection); +#else +static inline void +nmtst_connection_assert_unchanging(NMConnection *connection) +{} +#endif + +NMConnection *_nm_simple_connection_new_from_dbus(GVariant * dict, + NMSettingParseFlags parse_flags, + GError ** error); + +NMSettingPriority _nm_setting_get_setting_priority(NMSetting *setting); + +gboolean _nm_setting_get_property(NMSetting *setting, const char *name, GValue *value); + +/*****************************************************************************/ + +GHashTable *_nm_setting_option_hash(NMSetting *setting, gboolean create_if_necessary); + +void _nm_setting_option_notify(NMSetting *setting, gboolean keys_changed); + +guint _nm_setting_option_get_all(NMSetting * setting, + const char *const **out_names, + GVariant *const ** out_values); + +gboolean _nm_setting_option_clear(NMSetting *setting, const char *optname); + +/*****************************************************************************/ + +guint nm_setting_ethtool_init_features( + NMSettingEthtool *setting, + NMOptionBool * requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */); + +/*****************************************************************************/ + +#define NM_UTILS_HWADDR_LEN_MAX_STR (NM_UTILS_HWADDR_LEN_MAX * 3) + +gboolean nm_utils_is_valid_iface_name_utf8safe(const char *utf8safe_name); + +GSList *_nm_utils_hash_values_to_slist(GHashTable *hash); + +GHashTable *_nm_utils_copy_strdict(GHashTable *strdict); + +typedef gpointer (*NMUtilsCopyFunc)(gpointer); + +const char ** +_nm_ip_address_get_attribute_names(const NMIPAddress *addr, gboolean sorted, guint *out_length); + +void _nm_setting_wired_clear_s390_options(NMSettingWired *setting); + +gboolean _nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error); +const char ** +_nm_ip_route_get_attribute_names(const NMIPRoute *route, gboolean sorted, guint *out_length); +GHashTable *_nm_ip_route_get_attributes(NMIPRoute *route); + +NMSriovVF *_nm_utils_sriov_vf_from_strparts(const char *index, + const char *detail, + gboolean ignore_unknown, + GError ** error); +gboolean _nm_sriov_vf_attribute_validate_all(const NMSriovVF *vf, GError **error); + +GPtrArray * +_nm_utils_copy_array(const GPtrArray *array, NMUtilsCopyFunc copy_func, GDestroyNotify free_func); +GPtrArray *_nm_utils_copy_object_array(const GPtrArray *array); + +gssize _nm_utils_ptrarray_find_first(gconstpointer *list, gssize len, gconstpointer needle); + +GSList *_nm_utils_strv_to_slist(char **strv, gboolean deep_copy); +char ** _nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy); + +GPtrArray *_nm_utils_strv_to_ptrarray(char **strv); +char ** _nm_utils_ptrarray_to_strv(const GPtrArray *ptrarray); + +gboolean _nm_utils_check_file(const char * filename, + gint64 check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + struct stat * out_st, + GError ** error); + +gboolean _nm_utils_check_module_file(const char * name, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError ** error); + +/*****************************************************************************/ + +typedef struct _NMUuid { + guchar uuid[16]; +} NMUuid; + +NMUuid *_nm_utils_uuid_parse(const char *str, NMUuid *uuid); +char * _nm_utils_uuid_unparse(const NMUuid *uuid, char *out_str /*[37]*/); +NMUuid *_nm_utils_uuid_generate_random(NMUuid *out_uuid); + +gboolean nm_utils_uuid_is_null(const NMUuid *uuid); + +#define NM_UTILS_UUID_TYPE_LEGACY 0 +#define NM_UTILS_UUID_TYPE_VERSION3 3 +#define NM_UTILS_UUID_TYPE_VERSION5 5 + +NMUuid *nm_utils_uuid_generate_from_string_bin(NMUuid * uuid, + const char *s, + gssize slen, + int uuid_type, + gpointer type_args); + +char * +nm_utils_uuid_generate_from_string(const char *s, gssize slen, int uuid_type, gpointer type_args); + +/* arbitrarily chosen namespace UUID for _nm_utils_uuid_generate_from_strings() */ +#define NM_UTILS_UUID_NS "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905" + +char *_nm_utils_uuid_generate_from_strings(const char *string1, ...) G_GNUC_NULL_TERMINATED; + +char *nm_utils_uuid_generate_buf_(char *buf); +#define nm_utils_uuid_generate_buf(buf) \ + ({ \ + G_STATIC_ASSERT(sizeof(buf) == G_N_ELEMENTS(buf) && sizeof(buf) >= 37); \ + nm_utils_uuid_generate_buf_(buf); \ + }) +#define nm_utils_uuid_generate_a() (nm_utils_uuid_generate_buf_(g_alloca(37))) + +void _nm_dbus_errors_init(void); + +extern gboolean _nm_utils_is_manager_process; + +gboolean +_nm_dbus_typecheck_response(GVariant *response, const GVariantType *reply_type, GError **error); + +gulong _nm_dbus_signal_connect_data(GDBusProxy * proxy, + const char * signal_name, + const GVariantType *signature, + GCallback c_handler, + gpointer data, + GClosureNotify destroy_data, + GConnectFlags connect_flags); +#define _nm_dbus_signal_connect(proxy, name, signature, handler, data) \ + _nm_dbus_signal_connect_data(proxy, name, signature, handler, data, NULL, (GConnectFlags) 0) + +GVariant *_nm_dbus_proxy_call_finish(GDBusProxy * proxy, + GAsyncResult * res, + const GVariantType *reply_type, + GError ** error); + +GVariant *_nm_dbus_connection_call_finish(GDBusConnection * dbus_connection, + GAsyncResult * result, + const GVariantType *reply_type, + GError ** error); + +gboolean _nm_dbus_error_has_name(GError *error, const char *dbus_error_name); + +/*****************************************************************************/ + +char * _nm_utils_ssid_to_string_arr(const guint8 *ssid, gsize len); +char * _nm_utils_ssid_to_string(GBytes *ssid); +char * _nm_utils_ssid_to_utf8(GBytes *ssid); +gboolean _nm_utils_is_empty_ssid(GBytes *ssid); + +/*****************************************************************************/ + +gboolean _nm_vpn_plugin_info_check_file(const char * filename, + gboolean check_absolute, + gboolean do_validate_filename, + gint64 check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError ** error); + +const char *_nm_vpn_plugin_info_get_default_dir_etc(void); +const char *_nm_vpn_plugin_info_get_default_dir_lib(void); +const char *_nm_vpn_plugin_info_get_default_dir_user(void); + +GSList *_nm_vpn_plugin_info_list_load_dir(const char * dirname, + gboolean do_validate_filename, + gint64 check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data); + +/*****************************************************************************/ + +GHashTable *_nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *self); + +/*****************************************************************************/ + +typedef struct { + const char *name; + gboolean numeric; + gboolean ipv6_only; +} NMUtilsDNSOptionDesc; + +extern const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[]; + +gboolean _nm_utils_dns_option_validate(const char * option, + char ** out_name, + long * out_value, + gboolean ipv6, + const NMUtilsDNSOptionDesc *option_descs); +gssize _nm_utils_dns_option_find_idx(GPtrArray *array, const char *option); + +int nm_setting_ip_config_next_valid_dns_option(NMSettingIPConfig *setting, guint idx); + +/*****************************************************************************/ + +typedef struct _NMUtilsStrStrDictKey NMUtilsStrStrDictKey; +guint _nm_utils_strstrdictkey_hash(gconstpointer a); +gboolean _nm_utils_strstrdictkey_equal(gconstpointer a, gconstpointer b); +NMUtilsStrStrDictKey *_nm_utils_strstrdictkey_create(const char *v1, const char *v2); + +#define _nm_utils_strstrdictkey_static(v1, v2) ((NMUtilsStrStrDictKey *) ("\03" v1 "\0" v2 "")) + +/*****************************************************************************/ + +gboolean _nm_setting_vlan_set_priorities(NMSettingVlan * setting, + NMVlanPriorityMap map, + const NMVlanQosMapping *qos_map, + guint n_qos_map); +void _nm_setting_vlan_get_priorities(NMSettingVlan * setting, + NMVlanPriorityMap map, + NMVlanQosMapping **out_qos_map, + guint * out_n_qos_map); + +/*****************************************************************************/ + +struct ether_addr; + +gboolean _nm_utils_generate_mac_address_mask_parse(const char * value, + struct ether_addr * out_mask, + struct ether_addr **out_ouis, + gsize * out_ouis_len, + GError ** error); + +/*****************************************************************************/ + +static inline gpointer +_nm_connection_get_setting(NMConnection *connection, GType type) +{ + return (gpointer) nm_connection_get_setting(connection, type); +} + +NMSettingIPConfig *nm_connection_get_setting_ip_config(NMConnection *connection, int addr_family); + +/*****************************************************************************/ + +typedef enum { + NM_BOND_OPTION_TYPE_INT, + NM_BOND_OPTION_TYPE_BOTH, + NM_BOND_OPTION_TYPE_IP, + NM_BOND_OPTION_TYPE_MAC, + NM_BOND_OPTION_TYPE_IFNAME, +} NMBondOptionType; + +NMBondOptionType _nm_setting_bond_get_option_type(NMSettingBond *setting, const char *name); + +const char *nm_setting_bond_get_option_or_default(NMSettingBond *self, const char *option); + +/*****************************************************************************/ + +/* nm_connection_get_uuid() asserts against NULL, which is the right thing to + * do in order to catch bugs. However, sometimes that behavior is inconvenient. + * Just try or return NULL. */ + +static inline const char * +_nm_connection_get_id(NMConnection *connection) +{ + return connection ? nm_connection_get_id(connection) : NULL; +} + +static inline const char * +_nm_connection_get_uuid(NMConnection *connection) +{ + return connection ? nm_connection_get_uuid(connection) : NULL; +} + +NMConnectionMultiConnect _nm_connection_get_multi_connect(NMConnection *connection); + +/*****************************************************************************/ + +gboolean _nm_setting_bond_option_supported(const char *option, NMBondMode mode); + +/*****************************************************************************/ + +NMSettingBluetooth *_nm_connection_get_setting_bluetooth_for_nap(NMConnection *connection); + +gboolean _nm_utils_inet6_is_token(const struct in6_addr *in6addr); + +/*****************************************************************************/ + +NMTeamLinkWatcher *_nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher); + +int nm_team_link_watcher_cmp(const NMTeamLinkWatcher *watcher, const NMTeamLinkWatcher *other); + +int nm_team_link_watchers_cmp(const NMTeamLinkWatcher *const *a, + const NMTeamLinkWatcher *const *b, + gsize len, + gboolean ignore_order); + +gboolean nm_team_link_watchers_equal(const GPtrArray *a, const GPtrArray *b, gboolean ignore_order); + +/*****************************************************************************/ + +guint32 _nm_utils_parse_tc_handle(const char *str, GError **error); +void _nm_utils_string_append_tc_parent(GString *string, const char *prefix, guint32 parent); +void _nm_utils_string_append_tc_qdisc_rest(GString *string, NMTCQdisc *qdisc); +gboolean +_nm_utils_string_append_tc_tfilter_rest(GString *string, NMTCTfilter *tfilter, GError **error); + +GHashTable *_nm_tc_qdisc_get_attributes(NMTCQdisc *qdisc); +GHashTable *_nm_tc_action_get_attributes(NMTCAction *action); + +/*****************************************************************************/ + +static inline gboolean +_nm_connection_type_is_master(const char *type) +{ + return (NM_IN_STRSET(type, + NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_TEAM_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME)); +} + +/*****************************************************************************/ + +gboolean _nm_utils_dhcp_duid_valid(const char *duid, GBytes **out_duid_bin); + +/*****************************************************************************/ + +gboolean _nm_setting_sriov_sort_vfs(NMSettingSriov *setting); +gboolean _nm_setting_bridge_port_sort_vlans(NMSettingBridgePort *setting); +gboolean _nm_setting_bridge_sort_vlans(NMSettingBridge *setting); + +/*****************************************************************************/ + +typedef struct _NMSockAddrEndpoint NMSockAddrEndpoint; + +NMSockAddrEndpoint *nm_sock_addr_endpoint_new(const char *endpoint); + +NMSockAddrEndpoint *nm_sock_addr_endpoint_ref(NMSockAddrEndpoint *self); +void nm_sock_addr_endpoint_unref(NMSockAddrEndpoint *self); + +const char *nm_sock_addr_endpoint_get_endpoint(NMSockAddrEndpoint *self); +const char *nm_sock_addr_endpoint_get_host(NMSockAddrEndpoint *self); +gint32 nm_sock_addr_endpoint_get_port(NMSockAddrEndpoint *self); + +gboolean nm_sock_addr_endpoint_get_fixed_sockaddr(NMSockAddrEndpoint *self, gpointer sockaddr); + +#define nm_auto_unref_sockaddrendpoint nm_auto(_nm_auto_unref_sockaddrendpoint) +NM_AUTO_DEFINE_FCN0(NMSockAddrEndpoint *, + _nm_auto_unref_sockaddrendpoint, + nm_sock_addr_endpoint_unref); + +/*****************************************************************************/ + +NMSockAddrEndpoint *_nm_wireguard_peer_get_endpoint(const NMWireGuardPeer *self); +void _nm_wireguard_peer_set_endpoint(NMWireGuardPeer *self, NMSockAddrEndpoint *endpoint); + +void +_nm_wireguard_peer_set_public_key_bin(NMWireGuardPeer *self, + const guint8 public_key[static NM_WIREGUARD_PUBLIC_KEY_LEN]); + +/*****************************************************************************/ + +const NMIPAddr *nm_ip_routing_rule_get_from_bin(const NMIPRoutingRule *self); +void nm_ip_routing_rule_set_from_bin(NMIPRoutingRule *self, gconstpointer from, guint8 len); + +const NMIPAddr *nm_ip_routing_rule_get_to_bin(const NMIPRoutingRule *self); +void nm_ip_routing_rule_set_to_bin(NMIPRoutingRule *self, gconstpointer to, guint8 len); + +gboolean nm_ip_routing_rule_get_xifname_bin(const NMIPRoutingRule *self, + gboolean iif /* or else oif */, + char out_xifname[static 16]); + +#define NM_IP_ROUTING_RULE_ATTR_ACTION "action" +#define NM_IP_ROUTING_RULE_ATTR_DPORT_END "dport-end" +#define NM_IP_ROUTING_RULE_ATTR_DPORT_START "dport-start" +#define NM_IP_ROUTING_RULE_ATTR_FAMILY "family" +#define NM_IP_ROUTING_RULE_ATTR_FROM "from" +#define NM_IP_ROUTING_RULE_ATTR_FROM_LEN "from-len" +#define NM_IP_ROUTING_RULE_ATTR_FWMARK "fwmark" +#define NM_IP_ROUTING_RULE_ATTR_FWMASK "fwmask" +#define NM_IP_ROUTING_RULE_ATTR_IIFNAME "iifname" +#define NM_IP_ROUTING_RULE_ATTR_INVERT "invert" +#define NM_IP_ROUTING_RULE_ATTR_IPPROTO "ipproto" +#define NM_IP_ROUTING_RULE_ATTR_OIFNAME "oifname" +#define NM_IP_ROUTING_RULE_ATTR_PRIORITY "priority" +#define NM_IP_ROUTING_RULE_ATTR_SPORT_END "sport-end" +#define NM_IP_ROUTING_RULE_ATTR_SPORT_START "sport-start" +#define NM_IP_ROUTING_RULE_ATTR_SUPPRESS_PREFIXLENGTH "suppress-prefixlength" +#define NM_IP_ROUTING_RULE_ATTR_TABLE "table" +#define NM_IP_ROUTING_RULE_ATTR_TO "to" +#define NM_IP_ROUTING_RULE_ATTR_TOS "tos" +#define NM_IP_ROUTING_RULE_ATTR_TO_LEN "to-len" + +NMIPRoutingRule *nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error); +GVariant * nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self); + +/*****************************************************************************/ + +typedef struct _NMSettInfoSetting NMSettInfoSetting; +typedef struct _NMSettInfoProperty NMSettInfoProperty; + +typedef GVariant *(*NMSettInfoPropToDBusFcn)(const NMSettInfoSetting * sett_info, + guint property_idx, + NMConnection * connection, + NMSetting * setting, + NMConnectionSerializationFlags flags, + const NMConnectionSerializationOptions *options); +typedef gboolean (*NMSettInfoPropFromDBusFcn)(NMSetting * setting, + GVariant * connection_dict, + const char * property, + GVariant * value, + NMSettingParseFlags parse_flags, + GError ** error); +typedef gboolean (*NMSettInfoPropMissingFromDBusFcn)(NMSetting * setting, + GVariant * connection_dict, + const char * property, + NMSettingParseFlags parse_flags, + GError ** error); +typedef GVariant *(*NMSettInfoPropGPropToDBusFcn)(const GValue *from); +typedef void (*NMSettInfoPropGPropFromDBusFcn)(GVariant *from, GValue *to); + +const NMSettInfoSetting *nmtst_sett_info_settings(void); + +typedef struct { + const GVariantType *dbus_type; + + NMSettInfoPropToDBusFcn to_dbus_fcn; + NMSettInfoPropFromDBusFcn from_dbus_fcn; + NMSettInfoPropMissingFromDBusFcn missing_from_dbus_fcn; + + /* Simpler variants of @to_dbus_fcn/@from_dbus_fcn that operate solely + * on the GValue value of the GObject property. */ + NMSettInfoPropGPropToDBusFcn gprop_to_dbus_fcn; + NMSettInfoPropGPropFromDBusFcn gprop_from_dbus_fcn; +} NMSettInfoPropertType; + +struct _NMSettInfoProperty { + const char *name; + + GParamSpec *param_spec; + + const NMSettInfoPropertType *property_type; +}; + +typedef struct { + const GVariantType *(*get_variant_type)(const struct _NMSettInfoSetting *sett_info, + const char * name, + GError ** error); +} NMSettInfoSettGendata; + +typedef struct { + /* if set, then this setting class has no own fields. Instead, its + * data is entirely based on gendata. Meaning: it tracks all data + * as native GVariants. + * It might have some GObject properties, but these are merely accessors + * to the underlying gendata. + * + * Note, that at the moment there are few hooks, to customize the behavior + * of the setting further. They are currently unneeded. This is desired, + * but could be added when there is a good reason. + * + * However, a few hooks there are... see NMSettInfoSettGendata. */ + const NMSettInfoSettGendata *gendata_info; +} NMSettInfoSettDetail; + +struct _NMSettInfoSetting { + NMSettingClass *setting_class; + + /* the properties, sorted by property name. */ + const NMSettInfoProperty *property_infos; + + /* the @property_infos list is sorted by property name. For some uses we need + * a different sort order. If @property_infos_sorted is set, this is the order + * instead. It is used for: + * + * - nm_setting_enumerate_values() + * - keyfile writer adding keys to the group. + * + * Note that currently only NMSettingConnection implements here a sort order + * that differs from alphabetical sort of the property names. + */ + const NMSettInfoProperty *const *property_infos_sorted; + + guint property_infos_len; + NMSettInfoSettDetail detail; +}; + +static inline const NMSettInfoProperty * +_nm_sett_info_property_info_get_sorted(const NMSettInfoSetting *sett_info, guint idx) +{ + nm_assert(sett_info); + nm_assert(idx < sett_info->property_infos_len); + nm_assert(!sett_info->property_infos_sorted || sett_info->property_infos_sorted[idx]); + + return sett_info->property_infos_sorted ? sett_info->property_infos_sorted[idx] + : &sett_info->property_infos[idx]; +} + +const NMSettInfoProperty * +_nm_sett_info_setting_get_property_info(const NMSettInfoSetting *sett_info, + const char * property_name); + +const NMSettInfoSetting *_nm_setting_class_get_sett_info(NMSettingClass *setting_class); + +static inline const NMSettInfoProperty * +_nm_setting_class_get_property_info(NMSettingClass *setting_class, const char *property_name) +{ + return _nm_sett_info_setting_get_property_info(_nm_setting_class_get_sett_info(setting_class), + property_name); +} + +/*****************************************************************************/ + +gboolean _nm_setting_compare(NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags); + +gboolean _nm_setting_diff(NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags, + gboolean invert_results, + GHashTable ** results); + +NMSetting8021xCKScheme _nm_setting_802_1x_cert_get_scheme(GBytes *bytes, GError **error); + +GBytes *_nm_setting_802_1x_cert_value_to_bytes(NMSetting8021xCKScheme scheme, + const guint8 * val_bin, + gssize val_len, + GError ** error); + +/*****************************************************************************/ + +static inline gboolean +_nm_connection_serialize_secrets(NMConnectionSerializationFlags flags, + NMSettingSecretFlags secret_flags) +{ + if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_NO_SECRETS)) + return FALSE; + if (NM_FLAGS_HAS(flags, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED) + && !NM_FLAGS_HAS(secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) + return FALSE; + return TRUE; +} + +void _nm_connection_clear_secrets_by_secret_flags(NMConnection * self, + NMSettingSecretFlags filter_flags); + +GVariant *_nm_connection_for_each_secret(NMConnection * self, + GVariant * secrets, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data); + +typedef gboolean (*NMConnectionFindSecretFunc)(NMSettingSecretFlags flags, gpointer user_data); + +gboolean _nm_connection_find_secret(NMConnection * self, + GVariant * secrets, + NMConnectionFindSecretFunc callback, + gpointer callback_data); + +/*****************************************************************************/ + +gboolean nm_utils_base64secret_normalize(const char *base64_key, + gsize required_key_len, + char ** out_base64_key_norm); + +/*****************************************************************************/ + +gboolean nm_utils_connection_is_adhoc_wpa(NMConnection *connection); + +const char *nm_utils_wifi_freq_to_band(guint32 freq); + +gboolean _nm_utils_iaid_verify(const char *str, gint64 *out_value); + +gboolean +_nm_utils_validate_dhcp_hostname_flags(NMDhcpHostnameFlags flags, int addr_family, GError **error); + +/*****************************************************************************/ + +gboolean _nmtst_variant_attribute_spec_assert_sorted(const NMVariantAttributeSpec *const *array, + gsize len); + +const NMVariantAttributeSpec * +_nm_variant_attribute_spec_find_binary_search(const NMVariantAttributeSpec *const *array, + gsize len, + const char * name); + +/*****************************************************************************/ + +gboolean _nm_ip_tunnel_mode_is_layer2(NMIPTunnelMode mode); + +#endif diff --git a/src/libnm-core-intern/nm-core-types-internal.h b/src/libnm-core-intern/nm-core-types-internal.h new file mode 100644 index 0000000000..346458d359 --- /dev/null +++ b/src/libnm-core-intern/nm-core-types-internal.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef NM_CORE_TYPES_INTERNAL_H +#define NM_CORE_TYPES_INTERNAL_H + +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) + #error Cannot use this header. +#endif + +typedef struct { + guint32 from; + guint32 to; +} NMVlanQosMapping; + +#define _NM_IP_TUNNEL_FLAG_ALL_IP6TNL \ + (NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \ + | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL | NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV \ + | NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK) + +#endif /* NM_CORE_TYPES_INTERNAL_H */ diff --git a/src/libnm-core-intern/nm-keyfile-internal.h b/src/libnm-core-intern/nm-keyfile-internal.h new file mode 100644 index 0000000000..5140d8eb7c --- /dev/null +++ b/src/libnm-core-intern/nm-keyfile-internal.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2008 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_KEYFILE_INTERNAL_H__ +#define __NM_KEYFILE_INTERNAL_H__ + +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) + #error Cannot use this header. +#endif + +#include + +#include "nm-keyfile.h" + +#include "nm-connection.h" +#include "nm-setting-8021x.h" + +#include "libnm-core-intern/nm-core-internal.h" + +/*****************************************************************************/ + +#define NM_KEYFILE_CERT_SCHEME_PREFIX_PATH "file://" +#define NM_KEYFILE_CERT_SCHEME_PREFIX_PKCS11 "pkcs11:" +#define NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB "data:;base64," + +char *nm_keyfile_detect_unqualified_path_scheme(const char * base_dir, + gconstpointer pdata, + gsize data_len, + gboolean consider_exists, + gboolean * out_exists); + +gboolean nm_keyfile_read_ensure_id(NMConnection *connection, const char *fallback_id); + +gboolean nm_keyfile_read_ensure_uuid(NMConnection *connection, const char *fallback_uuid_seed); + +/*****************************************************************************/ + +/** + * NMKeyfileHandlerDataWarn: + * + * this struct is passed as @handler_data for the @NMKeyfileReadHandler of + * type %NM_KEYFILE_HANDLER_TYPE_WARN. + */ +typedef struct { + NMKeyfileWarnSeverity severity; + char * message; + const char * fmt; + va_list ap; +} NMKeyfileHandlerDataWarn; + +/** + * NMKeyfileHandlerDataWriteCert: + * + * this struct is passed as @handler_data for the @NMKeyfileWriteHandler of + * type %NM_KEYFILE_HANDLER_TYPE_WRITE_CERT. + */ +typedef struct { + const NMSetting8021xSchemeVtable *vtable; +} NMKeyfileHandlerDataWriteCert; + +struct _NMKeyfileHandlerData { + NMKeyfileHandlerType type; + + GError **p_error; + + const char *kf_group_name; + const char *kf_key; + + NMSetting * cur_setting; + const char *cur_property; + + union { + NMKeyfileHandlerDataWarn warn; + NMKeyfileHandlerDataWriteCert write_cert; + }; +}; + +/*****************************************************************************/ + +const char *_nm_keyfile_handler_data_warn_get_message(const NMKeyfileHandlerData *handler_data); + +/*****************************************************************************/ + +char * +nm_keyfile_plugin_kf_get_string(GKeyFile *kf, const char *group, const char *key, GError **error); +void nm_keyfile_plugin_kf_set_string(GKeyFile * kf, + const char *group, + const char *key, + const char *value); + +int nm_key_file_get_boolean(GKeyFile *kf, const char *group, const char *key, int default_value); + +void _nm_keyfile_copy(GKeyFile *dst, GKeyFile *src); +gboolean _nm_keyfile_a_contains_all_in_b(GKeyFile *kf_a, GKeyFile *kf_b); +gboolean _nm_keyfile_equals(GKeyFile *kf_a, GKeyFile *kf_b, gboolean consider_order); +gboolean _nm_keyfile_has_values(GKeyFile *keyfile); + +/*****************************************************************************/ + +#define NM_KEYFILE_GROUP_NMMETA ".nmmeta" +#define NM_KEYFILE_KEY_NMMETA_NM_GENERATED "nm-generated" +#define NM_KEYFILE_KEY_NMMETA_VOLATILE "volatile" +#define NM_KEYFILE_KEY_NMMETA_EXTERNAL "external" +#define NM_KEYFILE_KEY_NMMETA_SHADOWED_STORAGE "shadowed-storage" +#define NM_KEYFILE_KEY_NMMETA_SHADOWED_OWNED "shadowed-owned" + +#define NM_KEYFILE_PATH_NAME_LIB NMLIBDIR "/system-connections" +#define NM_KEYFILE_PATH_NAME_ETC_DEFAULT NMCONFDIR "/system-connections" +#define NM_KEYFILE_PATH_NAME_RUN NMRUNDIR "/system-connections" + +#define NM_KEYFILE_PATH_SUFFIX_NMCONNECTION ".nmconnection" + +#define NM_KEYFILE_PATH_SUFFIX_NMMETA ".nmmeta" + +#define NM_KEYFILE_PATH_NMMETA_SYMLINK_NULL "/dev/null" + +gboolean nm_keyfile_utils_ignore_filename(const char *filename, gboolean require_extension); + +char *nm_keyfile_utils_create_filename(const char *filename, gboolean with_extension); + +#endif /* __NM_KEYFILE_INTERNAL_H__ */ diff --git a/src/libnm-core-intern/nm-keyfile-utils.h b/src/libnm-core-intern/nm-keyfile-utils.h new file mode 100644 index 0000000000..1555c11244 --- /dev/null +++ b/src/libnm-core-intern/nm-keyfile-utils.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2010 - 2015 Red Hat, Inc. + */ + +#ifndef __NM_KEYFILE_UTILS_H__ +#define __NM_KEYFILE_UTILS_H__ + +#if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) + #error Cannot use this header. +#endif + +/*****************************************************************************/ + +#include "nm-glib-aux/nm-shared-utils.h" + +/*****************************************************************************/ + +#define NM_KEYFILE_GROUP_VPN_SECRETS "vpn-secrets" +#define NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER "wireguard-peer." + +#define nm_keyfile_error_is_not_found(error) \ + nm_g_error_matches(error, \ + G_KEY_FILE_ERROR, \ + G_KEY_FILE_ERROR_GROUP_NOT_FOUND, \ + G_KEY_FILE_ERROR_KEY_NOT_FOUND) + +const char *nm_keyfile_plugin_get_alias_for_setting_name(const char *setting_name); + +const char *nm_keyfile_plugin_get_setting_name_for_alias(const char *alias); + +/*****************************************************************************/ + +guint *nm_keyfile_plugin_kf_get_integer_list_uint(GKeyFile * kf, + const char *group, + const char *key, + gsize * out_length, + GError ** error); +char **nm_keyfile_plugin_kf_get_string_list(GKeyFile * kf, + const char *group, + const char *key, + gsize * out_length, + GError ** error); +char * +nm_keyfile_plugin_kf_get_string(GKeyFile *kf, const char *group, const char *key, GError **error); +gboolean +nm_keyfile_plugin_kf_get_boolean(GKeyFile *kf, const char *group, const char *key, GError **error); +char * +nm_keyfile_plugin_kf_get_value(GKeyFile *kf, const char *group, const char *key, GError **error); + +void nm_keyfile_plugin_kf_set_integer_list_uint8(GKeyFile * kf, + const char * group, + const char * key, + const guint8 *list, + gsize length); +void nm_keyfile_plugin_kf_set_integer_list_uint(GKeyFile * kf, + const char * group, + const char * key, + const guint *list, + gsize length); +void nm_keyfile_plugin_kf_set_string_list(GKeyFile * kf, + const char * group, + const char * key, + const char *const *list, + gsize length); + +void nm_keyfile_plugin_kf_set_string(GKeyFile * kf, + const char *group, + const char *key, + const char *value); +void +nm_keyfile_plugin_kf_set_boolean(GKeyFile *kf, const char *group, const char *key, gboolean value); +void +nm_keyfile_plugin_kf_set_value(GKeyFile *kf, const char *group, const char *key, const char *value); + +gint64 nm_keyfile_plugin_kf_get_int64(GKeyFile * kf, + const char *group, + const char *key, + guint base, + gint64 min, + gint64 max, + gint64 fallback, + GError ** error); + +char ** +nm_keyfile_plugin_kf_get_keys(GKeyFile *kf, const char *group, gsize *out_length, GError **error); + +gboolean +nm_keyfile_plugin_kf_has_key(GKeyFile *kf, const char *group, const char *key, GError **error); + +const char *nm_keyfile_key_encode(const char *name, char **out_to_free); + +const char *nm_keyfile_key_decode(const char *key, char **out_to_free); + +#endif /* __NM_KEYFILE_UTILS_H__ */ diff --git a/src/libnm-core-intern/nm-meta-setting-base-impl.h b/src/libnm-core-intern/nm-meta-setting-base-impl.h new file mode 100644 index 0000000000..94b14e844f --- /dev/null +++ b/src/libnm-core-intern/nm-meta-setting-base-impl.h @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 - 2018 Red Hat, Inc. + */ + +#ifndef __NM_META_SETTING_BASE_IMPL_H__ +#define __NM_META_SETTING_BASE_IMPL_H__ + +#include "nm-setting-8021x.h" + +/*****************************************************************************/ + +/* + * A setting's priority should roughly follow the OSI layer model, but it also + * controls which settings get asked for secrets first. Thus settings which + * relate to things that must be working first, like hardware, should get a + * higher priority than things which layer on top of the hardware. For example, + * the GSM/CDMA settings should provide secrets before the PPP setting does, + * because a PIN is required to unlock the device before PPP can even start. + * Even settings without secrets should be assigned the right priority. + * + * 0: reserved for invalid + * + * 1: reserved for the Connection setting + * + * 2,3: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc. + * These priority 1 settings are also "base types", which means that at least + * one of them is required for the connection to be valid, and their name is + * valid in the 'type' property of the Connection setting. + * + * 4: hardware-related auxiliary settings that require a base setting to be + * successful first, like Wi-Fi security, 802.1x, etc. + * + * 5: hardware-independent settings that are required before IP connectivity + * can be established, like PPP, PPPoE, etc. + * + * 6: IP-level stuff + * + * 10: NMSettingUser + */ +typedef enum { /*< skip >*/ + NM_SETTING_PRIORITY_INVALID = 0, + NM_SETTING_PRIORITY_CONNECTION = 1, + NM_SETTING_PRIORITY_HW_BASE = 2, + NM_SETTING_PRIORITY_HW_NON_BASE = 3, + NM_SETTING_PRIORITY_HW_AUX = 4, + NM_SETTING_PRIORITY_AUX = 5, + NM_SETTING_PRIORITY_IP = 6, + NM_SETTING_PRIORITY_USER = 10, +} NMSettingPriority; + +/*****************************************************************************/ + +typedef enum { + NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT, + NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT, + NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT, + NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT, + NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY, + NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY, + + NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN, + + _NM_SETTING_802_1X_SCHEME_TYPE_NUM = NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN, +} NMSetting8021xSchemeType; + +typedef struct { + const char *setting_key; + NMSetting8021xCKScheme (*scheme_func)(NMSetting8021x *setting); + NMSetting8021xCKFormat (*format_func)(NMSetting8021x *setting); + const char *(*path_func)(NMSetting8021x *setting); + GBytes *(*blob_func)(NMSetting8021x *setting); + const char *(*uri_func)(NMSetting8021x *setting); + const char *(*passwd_func)(NMSetting8021x *setting); + NMSettingSecretFlags (*pwflag_func)(NMSetting8021x *setting); + gboolean (*set_cert_func)(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error); + gboolean (*set_private_key_func)(NMSetting8021x * setting, + const char * value, + const char * password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error); + const char * file_suffix; + NMSetting8021xSchemeType scheme_type; + bool is_secret : 1; +} NMSetting8021xSchemeVtable; + +extern const NMSetting8021xSchemeVtable + nm_setting_8021x_scheme_vtable[_NM_SETTING_802_1X_SCHEME_TYPE_NUM + 1]; + +/*****************************************************************************/ + +typedef enum { + /* the enum (and their numeric values) are internal API. Do not assign + * any meaning the numeric values, because they already have one: + * + * they are sorted in a way, that corresponds to the asciibetical sort + * order of the corresponding setting-name. */ + + NM_META_SETTING_TYPE_6LOWPAN, + NM_META_SETTING_TYPE_OLPC_MESH, + NM_META_SETTING_TYPE_WIRELESS, + NM_META_SETTING_TYPE_WIRELESS_SECURITY, + NM_META_SETTING_TYPE_802_1X, + NM_META_SETTING_TYPE_WIRED, + NM_META_SETTING_TYPE_ADSL, + NM_META_SETTING_TYPE_BLUETOOTH, + NM_META_SETTING_TYPE_BOND, + NM_META_SETTING_TYPE_BRIDGE, + NM_META_SETTING_TYPE_BRIDGE_PORT, + NM_META_SETTING_TYPE_CDMA, + NM_META_SETTING_TYPE_CONNECTION, + NM_META_SETTING_TYPE_DCB, + NM_META_SETTING_TYPE_DUMMY, + NM_META_SETTING_TYPE_ETHTOOL, + NM_META_SETTING_TYPE_GENERIC, + NM_META_SETTING_TYPE_GSM, + NM_META_SETTING_TYPE_HOSTNAME, + NM_META_SETTING_TYPE_INFINIBAND, + NM_META_SETTING_TYPE_IP_TUNNEL, + NM_META_SETTING_TYPE_IP4_CONFIG, + NM_META_SETTING_TYPE_IP6_CONFIG, + NM_META_SETTING_TYPE_MACSEC, + NM_META_SETTING_TYPE_MACVLAN, + NM_META_SETTING_TYPE_MATCH, + NM_META_SETTING_TYPE_OVS_BRIDGE, + NM_META_SETTING_TYPE_OVS_DPDK, + NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, + NM_META_SETTING_TYPE_OVS_INTERFACE, + NM_META_SETTING_TYPE_OVS_PATCH, + NM_META_SETTING_TYPE_OVS_PORT, + NM_META_SETTING_TYPE_PPP, + NM_META_SETTING_TYPE_PPPOE, + NM_META_SETTING_TYPE_PROXY, + NM_META_SETTING_TYPE_SERIAL, + NM_META_SETTING_TYPE_SRIOV, + NM_META_SETTING_TYPE_TC_CONFIG, + NM_META_SETTING_TYPE_TEAM, + NM_META_SETTING_TYPE_TEAM_PORT, + NM_META_SETTING_TYPE_TUN, + NM_META_SETTING_TYPE_USER, + NM_META_SETTING_TYPE_VETH, + NM_META_SETTING_TYPE_VLAN, + NM_META_SETTING_TYPE_VPN, + NM_META_SETTING_TYPE_VRF, + NM_META_SETTING_TYPE_VXLAN, + NM_META_SETTING_TYPE_WIFI_P2P, + NM_META_SETTING_TYPE_WIMAX, + NM_META_SETTING_TYPE_WIREGUARD, + NM_META_SETTING_TYPE_WPAN, + + NM_META_SETTING_TYPE_UNKNOWN, + + _NM_META_SETTING_TYPE_NUM = NM_META_SETTING_TYPE_UNKNOWN, +} NMMetaSettingType; + +#if _NM_META_SETTING_BASE_IMPL_LIBNM + #define _NMMetaSettingInfo_Alias _NMMetaSettingInfo +#else + #define _NMMetaSettingInfo_Alias _NMMetaSettingInfoCli +#endif + +struct _NMMetaSettingInfo_Alias { + const char *setting_name; + GType (*get_setting_gtype)(void); + NMMetaSettingType meta_type; + NMSettingPriority setting_priority; +}; + +typedef struct _NMMetaSettingInfo_Alias NMMetaSettingInfo; + +extern const NMMetaSettingInfo nm_meta_setting_infos[_NM_META_SETTING_TYPE_NUM + 1]; + +const NMMetaSettingInfo *nm_meta_setting_infos_by_name(const char *name); +const NMMetaSettingInfo *nm_meta_setting_infos_by_gtype(GType gtype); + +/*****************************************************************************/ + +NMSettingPriority nm_meta_setting_info_get_base_type_priority(const NMMetaSettingInfo *setting_info, + GType gtype); +NMSettingPriority _nm_setting_type_get_base_type_priority(GType type); + +#endif /* __NM_META_SETTING_BASE_IMPL_H__ */ diff --git a/src/libnm-core-intern/nm-meta-setting-base.h b/src/libnm-core-intern/nm-meta-setting-base.h new file mode 100644 index 0000000000..72fa8e6602 --- /dev/null +++ b/src/libnm-core-intern/nm-meta-setting-base.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#ifndef __NM_META_SETTING_BASE_H__ +#define __NM_META_SETTING_BASE_H__ + +#define _NM_META_SETTING_BASE_IMPL_LIBNM 1 + +#include "nm-meta-setting-base-impl.h" + +#endif /* __NM_META_SETTING_BASE_H__ */ diff --git a/src/libnm-core-public/README.md b/src/libnm-core-public/README.md new file mode 100644 index 0000000000..0737269d1c --- /dev/null +++ b/src/libnm-core-public/README.md @@ -0,0 +1,24 @@ +libnm-core-public +================= + +This contains (mostly) header files only, which are also part of +the public API of [`libnm`](../../libnm). + +Also, this API is implemented by the static library [`libnm-core-impl`](../libnm-core-impl), +which in turn is statically linked into NetworkManager core and [`libnm`](../../libnm). + +These headers can be used by anybody who either: + +- links (statically) against [`libnm-core-impl`](../libnm-core-impl). +- links dynamically against [`libnm`](../../libnm). + +Note that there is also one source file: `nm-core-enum-types.c`. +This source file really belongs to [`libnm-core-impl`](../libnm-core-impl) but it is here +because it's a generated file and so far I couldn't figure out how +to generate `nm-core-enum-types.h` here while moving `nm-core-enum-types.c` +to [`libnm-core-impl`](../libnm-core-impl). + +Aside `nm-core-enum-types.c`, this directory only provides header files. +Users should add this directory (both srcdir and builddir) to the include +search path, because libnm users are used to include these headers unqualified +(like `#include "nm-setting.h`). diff --git a/src/libnm-core-public/meson.build b/src/libnm-core-public/meson.build new file mode 100644 index 0000000000..6b8dad0f28 --- /dev/null +++ b/src/libnm-core-public/meson.build @@ -0,0 +1,128 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnm_core_public_inc = include_directories('.') + +libnm_core_headers = files( + 'nm-connection.h', + 'nm-core-types.h', + 'nm-dbus-interface.h', + 'nm-errors.h', + 'nm-keyfile.h', + 'nm-setting-6lowpan.h', + 'nm-setting-8021x.h', + 'nm-setting-adsl.h', + 'nm-setting-bluetooth.h', + 'nm-setting-bond.h', + 'nm-setting-bridge-port.h', + 'nm-setting-bridge.h', + 'nm-setting-cdma.h', + 'nm-setting-connection.h', + 'nm-setting-dcb.h', + 'nm-setting-dummy.h', + 'nm-setting-ethtool.h', + 'nm-setting-generic.h', + 'nm-setting-gsm.h', + 'nm-setting-hostname.h', + 'nm-setting-infiniband.h', + 'nm-setting-ip-config.h', + 'nm-setting-ip-tunnel.h', + 'nm-setting-ip4-config.h', + 'nm-setting-ip6-config.h', + 'nm-setting-macsec.h', + 'nm-setting-macvlan.h', + 'nm-setting-match.h', + 'nm-setting-olpc-mesh.h', + 'nm-setting-ovs-bridge.h', + 'nm-setting-ovs-dpdk.h', + 'nm-setting-ovs-external-ids.h', + 'nm-setting-ovs-interface.h', + 'nm-setting-ovs-patch.h', + 'nm-setting-ovs-port.h', + 'nm-setting-ppp.h', + 'nm-setting-pppoe.h', + 'nm-setting-proxy.h', + 'nm-setting-serial.h', + 'nm-setting-sriov.h', + 'nm-setting-tc-config.h', + 'nm-setting-team-port.h', + 'nm-setting-team.h', + 'nm-setting-tun.h', + 'nm-setting-user.h', + 'nm-setting-veth.h', + 'nm-setting-vlan.h', + 'nm-setting-vpn.h', + 'nm-setting-vrf.h', + 'nm-setting-vxlan.h', + 'nm-setting-wifi-p2p.h', + 'nm-setting-wimax.h', + 'nm-setting-wired.h', + 'nm-setting-wireguard.h', + 'nm-setting-wireless-security.h', + 'nm-setting-wireless.h', + 'nm-setting-wpan.h', + 'nm-setting.h', + 'nm-simple-connection.h', + 'nm-utils.h', + 'nm-version.h', + 'nm-vpn-dbus-interface.h', + 'nm-vpn-editor-plugin.h', + 'nm-vpn-plugin-info.h', +) + +nm_version_macro_header = configure_file( + input: 'nm-version-macros.h.in', + output: '@BASENAME@', + configuration: data_conf, +) + +libnm_core_public_enum_sources = gnome.mkenums_simple( + 'nm-core-enum-types', + sources: libnm_core_headers + [nm_version_macro_header], + identifier_prefix: nm_id_prefix, + body_prefix: '#include "libnm-core-impl/nm-default-libnm-core.h"', + install_header: true, + install_dir: libnm_pkgincludedir, +) + +libnm_core_public_dep = declare_dependency( + sources: libnm_core_headers + [ + libnm_core_public_enum_sources[1], + nm_version_macro_header, + ], + include_directories: [ + libnm_core_public_inc, + src_inc, + top_inc, + ], + dependencies: [ + glib_dep, + ], +) + +docbooks = [ + ['nm-dbus-types', 'nm-dbus-interface.h', 'NetworkManager D-Bus API Types'], + ['nm-vpn-dbus-types', 'nm-vpn-dbus-interface.h', 'VPN Plugin D-Bus API Types'], +] + +foreach docbook: docbooks + output = docbook[0] + '.xml' + + xml = custom_target( + output, + input: docbook[1], + output: output, + capture: true, + command: [ + perl, + join_paths(source_root, 'tools', 'enums-to-docbook.pl'), + docbook[0], + docbook[2], + '@INPUT@', + ], + # FIXME: gtkdoc does not depend directly on this. + # https://github.com/mesonbuild/meson/pull/2806 + build_by_default: true, + ) + + content_files += xml.full_path() +endforeach diff --git a/src/libnm-core-public/nm-connection.h b/src/libnm-core-public/nm-connection.h new file mode 100644 index 0000000000..19034e790a --- /dev/null +++ b/src/libnm-core-public/nm-connection.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2018 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_CONNECTION_H__ +#define __NM_CONNECTION_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-core-types.h" +#include "nm-setting.h" +#include "nm-errors.h" + +G_BEGIN_DECLS + +#define NM_TYPE_CONNECTION (nm_connection_get_type()) +#define NM_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_CONNECTION, NMConnection)) +#define NM_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_CONNECTION)) +#define NM_CONNECTION_GET_INTERFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE((obj), NM_TYPE_CONNECTION, NMConnectionClass)) + +/* Signals */ +#define NM_CONNECTION_SECRETS_UPDATED "secrets-updated" +#define NM_CONNECTION_SECRETS_CLEARED "secrets-cleared" +#define NM_CONNECTION_CHANGED "changed" + +/* + * NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD: overwrite the ip6 method + * when normalizing ip6 configuration. If omitted, this defaults to + * @NM_SETTING_IP6_CONFIG_METHOD_AUTO. + */ +#define NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD "ip6-config-method" + +/** + * NMConnection: + * + * NMConnection is the interface implemented by #NMRemoteConnection on the + * client side, and #NMSettingsConnection on the daemon side. + */ + +/** + * NMConnectionInterface: + * @parent: the parent interface struct + * @secrets_updated: emitted when the connection's secrets are updated + * @secrets_cleared: emitted when the connection's secrets are cleared + * @changed: emitted when any change to the connection's settings occurs + */ +typedef struct { + GTypeInterface parent; + + /* Signals */ + void (*secrets_updated)(NMConnection *connection, const char *setting); + void (*secrets_cleared)(NMConnection *connection); + void (*changed)(NMConnection *connection); + +} NMConnectionInterface; + +GType nm_connection_get_type(void); + +void nm_connection_add_setting(NMConnection *connection, NMSetting *setting); + +void nm_connection_remove_setting(NMConnection *connection, GType setting_type); + +NMSetting *nm_connection_get_setting(NMConnection *connection, GType setting_type); + +NMSetting *nm_connection_get_setting_by_name(NMConnection *connection, const char *name); + +/** + * NM_VARIANT_TYPE_CONNECTION: + * + * #GVariantType for a dictionary mapping from setting names to + * %NM_VARIANT_TYPE_SETTING variants. This is used to represent an + * #NMConnection, and is the type taken by nm_simple_connection_new_from_dbus() + * and returned from nm_connection_to_dbus(). + */ +#define NM_VARIANT_TYPE_CONNECTION (G_VARIANT_TYPE("a{sa{sv}}")) + +/** + * NM_VARIANT_TYPE_SETTING: + * + * #GVariantType for a dictionary mapping from property names to values. This is + * an alias for %G_VARIANT_TYPE_VARDICT, and is the type of each element of + * an %NM_VARIANT_TYPE_CONNECTION dictionary. + */ +#define NM_VARIANT_TYPE_SETTING G_VARIANT_TYPE_VARDICT + +/** + * NMConnectionSerializationFlags: + * @NM_CONNECTION_SERIALIZE_ALL: serialize all properties (including secrets) + * @NM_CONNECTION_SERIALIZE_NO_SECRETS: do not include secrets + * @NM_CONNECTION_SERIALIZE_ONLY_SECRETS: only serialize secrets + * @NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED: if set, only secrets that + * are agent owned will be serialized. Since: 1.20. + * + * These flags determine which properties are serialized when calling when + * calling nm_connection_to_dbus(). + **/ +typedef enum { /*< flags >*/ + NM_CONNECTION_SERIALIZE_ALL = 0x00000000, + NM_CONNECTION_SERIALIZE_NO_SECRETS = 0x00000001, + NM_CONNECTION_SERIALIZE_ONLY_SECRETS = 0x00000002, + NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED = 0x00000004, +} NMConnectionSerializationFlags; + +GVariant *nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags); + +gboolean +nm_connection_replace_settings(NMConnection *connection, GVariant *new_settings, GError **error); + +void nm_connection_replace_settings_from_connection(NMConnection *connection, + NMConnection *new_connection); + +void nm_connection_clear_settings(NMConnection *connection); + +gboolean nm_connection_compare(NMConnection *a, NMConnection *b, NMSettingCompareFlags flags); + +gboolean nm_connection_diff(NMConnection * a, + NMConnection * b, + NMSettingCompareFlags flags, + GHashTable ** out_settings); + +gboolean nm_connection_verify(NMConnection *connection, GError **error); +NM_AVAILABLE_IN_1_2 +gboolean nm_connection_verify_secrets(NMConnection *connection, GError **error); +gboolean nm_connection_normalize(NMConnection *connection, + GHashTable * parameters, + gboolean * modified, + GError ** error); + +const char *nm_connection_need_secrets(NMConnection *connection, GPtrArray **hints); + +void nm_connection_clear_secrets(NMConnection *connection); + +void nm_connection_clear_secrets_with_flags(NMConnection * connection, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data); + +gboolean nm_connection_update_secrets(NMConnection *connection, + const char * setting_name, + GVariant * secrets, + GError ** error); + +void nm_connection_set_path(NMConnection *connection, const char *path); + +const char *nm_connection_get_path(NMConnection *connection); + +const char *nm_connection_get_interface_name(NMConnection *connection); + +gboolean nm_connection_is_type(NMConnection *connection, const char *type); + +void nm_connection_for_each_setting_value(NMConnection * connection, + NMSettingValueIterFn func, + gpointer user_data); + +NM_AVAILABLE_IN_1_10 +NMSetting **nm_connection_get_settings(NMConnection *connection, guint *out_length); + +void nm_connection_dump(NMConnection *connection); + +/* Helpers */ +const char *nm_connection_get_uuid(NMConnection *connection); +const char *nm_connection_get_id(NMConnection *connection); +const char *nm_connection_get_connection_type(NMConnection *connection); + +gboolean nm_connection_is_virtual(NMConnection *connection); +char * nm_connection_get_virtual_device_description(NMConnection *connection); + +NMSetting8021x * nm_connection_get_setting_802_1x(NMConnection *connection); +NMSettingBluetooth * nm_connection_get_setting_bluetooth(NMConnection *connection); +NMSettingBond * nm_connection_get_setting_bond(NMConnection *connection); +NMSettingTeam * nm_connection_get_setting_team(NMConnection *connection); +NMSettingTeamPort * nm_connection_get_setting_team_port(NMConnection *connection); +NMSettingBridge * nm_connection_get_setting_bridge(NMConnection *connection); +NMSettingBridgePort *nm_connection_get_setting_bridge_port(NMConnection *connection); +NMSettingCdma * nm_connection_get_setting_cdma(NMConnection *connection); +NMSettingConnection *nm_connection_get_setting_connection(NMConnection *connection); +NMSettingDcb * nm_connection_get_setting_dcb(NMConnection *connection); +NM_AVAILABLE_IN_1_8 +NMSettingDummy * nm_connection_get_setting_dummy(NMConnection *connection); +NMSettingGeneric * nm_connection_get_setting_generic(NMConnection *connection); +NMSettingGsm * nm_connection_get_setting_gsm(NMConnection *connection); +NMSettingInfiniband *nm_connection_get_setting_infiniband(NMConnection *connection); +NM_AVAILABLE_IN_1_2 +NMSettingIPTunnel *nm_connection_get_setting_ip_tunnel(NMConnection *connection); +NMSettingIPConfig *nm_connection_get_setting_ip4_config(NMConnection *connection); +NMSettingIPConfig *nm_connection_get_setting_ip6_config(NMConnection *connection); +NM_AVAILABLE_IN_1_6 +NMSettingMacsec *nm_connection_get_setting_macsec(NMConnection *connection); +NM_AVAILABLE_IN_1_2 +NMSettingMacvlan * nm_connection_get_setting_macvlan(NMConnection *connection); +NMSettingOlpcMesh *nm_connection_get_setting_olpc_mesh(NMConnection *connection); +NM_AVAILABLE_IN_1_10 +NMSettingOvsBridge *nm_connection_get_setting_ovs_bridge(NMConnection *connection); +NM_AVAILABLE_IN_1_10 +NMSettingOvsInterface *nm_connection_get_setting_ovs_interface(NMConnection *connection); +NMSettingOvsPatch * nm_connection_get_setting_ovs_patch(NMConnection *connection); +NM_AVAILABLE_IN_1_10 +NMSettingOvsPort *nm_connection_get_setting_ovs_port(NMConnection *connection); +NMSettingPpp * nm_connection_get_setting_ppp(NMConnection *connection); +NMSettingPppoe * nm_connection_get_setting_pppoe(NMConnection *connection); +NM_AVAILABLE_IN_1_6 +NMSettingProxy * nm_connection_get_setting_proxy(NMConnection *connection); +NMSettingSerial *nm_connection_get_setting_serial(NMConnection *connection); +NM_AVAILABLE_IN_1_12 +NMSettingTCConfig *nm_connection_get_setting_tc_config(NMConnection *connection); +NM_AVAILABLE_IN_1_2 +NMSettingTun * nm_connection_get_setting_tun(NMConnection *connection); +NMSettingVpn * nm_connection_get_setting_vpn(NMConnection *connection); +NMSettingWimax * nm_connection_get_setting_wimax(NMConnection *connection); +NMSettingAdsl * nm_connection_get_setting_adsl(NMConnection *connection); +NMSettingWired * nm_connection_get_setting_wired(NMConnection *connection); +NMSettingWireless * nm_connection_get_setting_wireless(NMConnection *connection); +NMSettingWirelessSecurity *nm_connection_get_setting_wireless_security(NMConnection *connection); +NMSettingVlan * nm_connection_get_setting_vlan(NMConnection *connection); +NM_AVAILABLE_IN_1_2 +NMSettingVxlan *nm_connection_get_setting_vxlan(NMConnection *connection); + +G_END_DECLS + +#endif /* __NM_CONNECTION_H__ */ diff --git a/src/libnm-core-public/nm-core-types.h b/src/libnm-core-public/nm-core-types.h new file mode 100644 index 0000000000..bf0c2a9966 --- /dev/null +++ b/src/libnm-core-public/nm-core-types.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2014 - 2018 Red Hat, Inc. + */ + +#ifndef __NM_CORE_TYPES_H__ +#define __NM_CORE_TYPES_H__ + +#include + +#include "nm-version.h" +#include "nm-dbus-interface.h" +#include "nm-core-enum-types.h" + +typedef struct _NMConnection NMConnection; +typedef struct _NMSetting NMSetting; +typedef struct _NMSetting6Lowpan NMSetting6Lowpan; +typedef struct _NMSetting8021x NMSetting8021x; +typedef struct _NMSettingAdsl NMSettingAdsl; +typedef struct _NMSettingBluetooth NMSettingBluetooth; +typedef struct _NMSettingBond NMSettingBond; +typedef struct _NMSettingBridge NMSettingBridge; +typedef struct _NMSettingBridgePort NMSettingBridgePort; +typedef struct _NMSettingCdma NMSettingCdma; +typedef struct _NMSettingConnection NMSettingConnection; +typedef struct _NMSettingDcb NMSettingDcb; +typedef struct _NMSettingDummy NMSettingDummy; +typedef struct _NMSettingEthtool NMSettingEthtool; +typedef struct _NMSettingGeneric NMSettingGeneric; +typedef struct _NMSettingGsm NMSettingGsm; +typedef struct _NMSettingHostname NMSettingHostname; +typedef struct _NMSettingIP4Config NMSettingIP4Config; +typedef struct _NMSettingIP6Config NMSettingIP6Config; +typedef struct _NMSettingIPConfig NMSettingIPConfig; +typedef struct _NMSettingIPTunnel NMSettingIPTunnel; +typedef struct _NMSettingInfiniband NMSettingInfiniband; +typedef struct _NMSettingMacsec NMSettingMacsec; +typedef struct _NMSettingMacvlan NMSettingMacvlan; +typedef struct _NMSettingMatch NMSettingMatch; +typedef struct _NMSettingOlpcMesh NMSettingOlpcMesh; +typedef struct _NMSettingOvsBridge NMSettingOvsBridge; +typedef struct _NMSettingOvsDpdk NMSettingOvsDpdk; +typedef struct _NMSettingOvsExternalIDs NMSettingOvsExternalIDs; +typedef struct _NMSettingOvsInterface NMSettingOvsInterface; +typedef struct _NMSettingOvsPatch NMSettingOvsPatch; +typedef struct _NMSettingOvsPort NMSettingOvsPort; +typedef struct _NMSettingPpp NMSettingPpp; +typedef struct _NMSettingPppoe NMSettingPppoe; +typedef struct _NMSettingProxy NMSettingProxy; +typedef struct _NMSettingSerial NMSettingSerial; +typedef struct _NMSettingSriov NMSettingSriov; +typedef struct _NMSettingTCConfig NMSettingTCConfig; +typedef struct _NMSettingTeam NMSettingTeam; +typedef struct _NMSettingTeamPort NMSettingTeamPort; +typedef struct _NMSettingTun NMSettingTun; +typedef struct _NMSettingUser NMSettingUser; +typedef struct _NMSettingVeth NMSettingVeth; +typedef struct _NMSettingVlan NMSettingVlan; +typedef struct _NMSettingVpn NMSettingVpn; +typedef struct _NMSettingVrf NMSettingVrf; +typedef struct _NMSettingVxlan NMSettingVxlan; +typedef struct _NMSettingWifiP2P NMSettingWifiP2P; +typedef struct _NMSettingWimax NMSettingWimax; +typedef struct _NMSettingWired NMSettingWired; +typedef struct _NMSettingWireGuard NMSettingWireGuard; +typedef struct _NMSettingWireless NMSettingWireless; +typedef struct _NMSettingWirelessSecurity NMSettingWirelessSecurity; +typedef struct _NMSettingWpan NMSettingWpan; +typedef struct _NMSimpleConnection NMSimpleConnection; + +typedef gboolean (*NMUtilsPredicateStr)(const char *str); + +#endif /* __NM_CORE_TYPES_H__ */ diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h new file mode 100644 index 0000000000..295a22a177 --- /dev/null +++ b/src/libnm-core-public/nm-dbus-interface.h @@ -0,0 +1,1284 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2004 - 2018 Red Hat, Inc. + */ + +/* Definitions related to NetworkManager's D-Bus interfaces. + * + * Note that although this header is installed as part of libnm, it is also + * used by some external code that does not link to libnm. + */ + +#ifndef __NM_DBUS_INTERFACE_H__ +#define __NM_DBUS_INTERFACE_H__ + +/* This header must not include glib or libnm. */ + +#ifndef NM_VERSION_H + #define NM_AVAILABLE_IN_1_2 + #define NM_AVAILABLE_IN_1_8 +#endif + +/* + * dbus services details + */ +#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager" + +#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" +#define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint" +#define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active" +#define NM_DBUS_INTERFACE_CHECKPOINT NM_DBUS_INTERFACE ".Checkpoint" +#define NM_DBUS_INTERFACE_DEVICE NM_DBUS_INTERFACE ".Device" +#define NM_DBUS_INTERFACE_DEVICE_6LOWPAN NM_DBUS_INTERFACE_DEVICE ".Lowpan" +#define NM_DBUS_INTERFACE_DEVICE_ADSL NM_DBUS_INTERFACE_DEVICE ".Adsl" +#define NM_DBUS_INTERFACE_DEVICE_BLUETOOTH NM_DBUS_INTERFACE_DEVICE ".Bluetooth" +#define NM_DBUS_INTERFACE_DEVICE_BOND NM_DBUS_INTERFACE_DEVICE ".Bond" +#define NM_DBUS_INTERFACE_DEVICE_BRIDGE NM_DBUS_INTERFACE_DEVICE ".Bridge" +#define NM_DBUS_INTERFACE_DEVICE_DUMMY NM_DBUS_INTERFACE_DEVICE ".Dummy" +#define NM_DBUS_INTERFACE_DEVICE_GENERIC NM_DBUS_INTERFACE_DEVICE ".Generic" +#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre" +#define NM_DBUS_INTERFACE_DEVICE_INFINIBAND NM_DBUS_INTERFACE_DEVICE ".Infiniband" +#define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel" +#define NM_DBUS_INTERFACE_DEVICE_MACSEC NM_DBUS_INTERFACE_DEVICE ".Macsec" +#define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan" +#define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem" +#define NM_DBUS_INTERFACE_DEVICE_OLPC_MESH NM_DBUS_INTERFACE_DEVICE ".OlpcMesh" +#define NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE NM_DBUS_INTERFACE_DEVICE ".OvsBridge" +#define NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE NM_DBUS_INTERFACE_DEVICE ".OvsInterface" +#define NM_DBUS_INTERFACE_DEVICE_OVS_PORT NM_DBUS_INTERFACE_DEVICE ".OvsPort" +#define NM_DBUS_INTERFACE_DEVICE_PPP NM_DBUS_INTERFACE_DEVICE ".Ppp" +#define NM_DBUS_INTERFACE_DEVICE_STATISTICS NM_DBUS_INTERFACE_DEVICE ".Statistics" +#define NM_DBUS_INTERFACE_DEVICE_TEAM NM_DBUS_INTERFACE_DEVICE ".Team" +#define NM_DBUS_INTERFACE_DEVICE_TUN NM_DBUS_INTERFACE_DEVICE ".Tun" +#define NM_DBUS_INTERFACE_DEVICE_VETH NM_DBUS_INTERFACE_DEVICE ".Veth" +#define NM_DBUS_INTERFACE_DEVICE_VLAN NM_DBUS_INTERFACE_DEVICE ".Vlan" +#define NM_DBUS_INTERFACE_DEVICE_VRF NM_DBUS_INTERFACE_DEVICE ".Vrf" +#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan" +#define NM_DBUS_INTERFACE_DEVICE_WIFI_P2P NM_DBUS_INTERFACE_DEVICE ".WifiP2P" +#define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax" +#define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired" +#define NM_DBUS_INTERFACE_DEVICE_WIREGUARD NM_DBUS_INTERFACE_DEVICE ".WireGuard" +#define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless" +#define NM_DBUS_INTERFACE_DEVICE_WPAN NM_DBUS_INTERFACE_DEVICE ".Wpan" +#define NM_DBUS_INTERFACE_DHCP4_CONFIG NM_DBUS_INTERFACE ".DHCP4Config" +#define NM_DBUS_INTERFACE_DHCP6_CONFIG NM_DBUS_INTERFACE ".DHCP6Config" +#define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config" +#define NM_DBUS_INTERFACE_IP6_CONFIG NM_DBUS_INTERFACE ".IP6Config" +#define NM_DBUS_INTERFACE_WIFI_P2P_PEER NM_DBUS_INTERFACE ".WifiP2PPeer" +#define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp" + +#define NM_DBUS_PATH "/org/freedesktop/NetworkManager" +#define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint" +#define NM_DBUS_PATH_WIFI_P2P_PEER NM_DBUS_PATH "/WifiP2PPeer" +#define NM_DBUS_PATH_WIMAX_NSP NM_DBUS_PATH "/Nsp" + +#define NM_DBUS_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings" +#define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings" + +#define NM_DBUS_INTERFACE_SETTINGS_CONNECTION "org.freedesktop.NetworkManager.Settings.Connection" +#define NM_DBUS_PATH_SETTINGS_CONNECTION "/org/freedesktop/NetworkManager/Settings/Connection" +#define NM_DBUS_INTERFACE_SETTINGS_CONNECTION_SECRETS \ + "org.freedesktop.NetworkManager.Settings.Connection.Secrets" + +#define NM_DBUS_INTERFACE_AGENT_MANAGER NM_DBUS_INTERFACE ".AgentManager" +#define NM_DBUS_PATH_AGENT_MANAGER "/org/freedesktop/NetworkManager/AgentManager" + +#define NM_DBUS_INTERFACE_SECRET_AGENT NM_DBUS_INTERFACE ".SecretAgent" +#define NM_DBUS_PATH_SECRET_AGENT "/org/freedesktop/NetworkManager/SecretAgent" + +#define NM_DBUS_INTERFACE_DNS_MANAGER "org.freedesktop.NetworkManager.DnsManager" +#define NM_DBUS_PATH_DNS_MANAGER "/org/freedesktop/NetworkManager/DnsManager" + +/** + * NMCapability: + * @NM_CAPABILITY_TEAM: Teams can be managed. This means the team device plugin + * is loaded. + * @NM_CAPABILITY_OVS: OpenVSwitch can be managed. This means the OVS device plugin + * is loaded. Since: 1.24. + * + * #NMCapability names the numbers in the Capabilities property. + * Capabilities are positive numbers. They are part of stable API + * and a certain capability number is guaranteed not to change. + * + * The range 0x7000 - 0x7FFF of capabilities is guaranteed not to be + * used by upstream NetworkManager. It could thus be used for downstream + * extensions. + */ +typedef enum { + NM_CAPABILITY_TEAM = 1, + NM_CAPABILITY_OVS = 2, +} NMCapability; + +/** + * NMState: + * @NM_STATE_UNKNOWN: Networking state is unknown. This indicates a daemon error + * that makes it unable to reasonably assess the state. In such event the + * applications are expected to assume Internet connectivity might be present + * and not disable controls that require network access. + * The graphical shells may hide the network accessibility indicator altogether + * since no meaningful status indication can be provided. + * @NM_STATE_ASLEEP: Networking is not enabled, the system is being suspended or + * resumed from suspend. + * @NM_STATE_DISCONNECTED: There is no active network connection. + * The graphical shell should indicate no network connectivity and the + * applications should not attempt to access the network. + * @NM_STATE_DISCONNECTING: Network connections are being cleaned up. + * The applications should tear down their network sessions. + * @NM_STATE_CONNECTING: A network connection is being started + * The graphical shell should indicate the network is being connected while + * the applications should still make no attempts to connect the network. + * @NM_STATE_CONNECTED_LOCAL: There is only local IPv4 and/or IPv6 connectivity, + * but no default route to access the Internet. The graphical shell should + * indicate no network connectivity. + * @NM_STATE_CONNECTED_SITE: There is only site-wide IPv4 and/or IPv6 connectivity. + * This means a default route is available, but the Internet connectivity check + * (see "Connectivity" property) did not succeed. The graphical shell should + * indicate limited network connectivity. + * @NM_STATE_CONNECTED_GLOBAL: There is global IPv4 and/or IPv6 Internet connectivity + * This means the Internet connectivity check succeeded, the graphical shell should + * indicate full network connectivity. + * + * #NMState values indicate the current overall networking state. + **/ +typedef enum { + NM_STATE_UNKNOWN = 0, + NM_STATE_ASLEEP = 10, + NM_STATE_DISCONNECTED = 20, + NM_STATE_DISCONNECTING = 30, + NM_STATE_CONNECTING = 40, + NM_STATE_CONNECTED_LOCAL = 50, + NM_STATE_CONNECTED_SITE = 60, + NM_STATE_CONNECTED_GLOBAL = 70, +} NMState; + +/** + * NMConnectivityState: + * @NM_CONNECTIVITY_UNKNOWN: Network connectivity is unknown. This means the + * connectivity checks are disabled (e.g. on server installations) or has + * not run yet. The graphical shell should assume the Internet connection + * might be available and not present a captive portal window. + * @NM_CONNECTIVITY_NONE: The host is not connected to any network. There's + * no active connection that contains a default route to the internet and + * thus it makes no sense to even attempt a connectivity check. The graphical + * shell should use this state to indicate the network connection is unavailable. + * @NM_CONNECTIVITY_PORTAL: The Internet connection is hijacked by a captive + * portal gateway. The graphical shell may open a sandboxed web browser window + * (because the captive portals typically attempt a man-in-the-middle attacks + * against the https connections) for the purpose of authenticating to a gateway + * and retrigger the connectivity check with CheckConnectivity() when the + * browser window is dismissed. + * @NM_CONNECTIVITY_LIMITED: The host is connected to a network, does not appear + * to be able to reach the full Internet, but a captive portal has not been + * detected. + * @NM_CONNECTIVITY_FULL: The host is connected to a network, and + * appears to be able to reach the full Internet. + */ +typedef enum { + NM_CONNECTIVITY_UNKNOWN = 0, + NM_CONNECTIVITY_NONE = 1, + NM_CONNECTIVITY_PORTAL = 2, + NM_CONNECTIVITY_LIMITED = 3, + NM_CONNECTIVITY_FULL = 4, +} NMConnectivityState; + +/** + * NMDeviceType: + * @NM_DEVICE_TYPE_UNKNOWN: unknown device + * @NM_DEVICE_TYPE_GENERIC: generic support for unrecognized device types + * @NM_DEVICE_TYPE_ETHERNET: a wired ethernet device + * @NM_DEVICE_TYPE_WIFI: an 802.11 Wi-Fi device + * @NM_DEVICE_TYPE_UNUSED1: not used + * @NM_DEVICE_TYPE_UNUSED2: not used + * @NM_DEVICE_TYPE_BT: a Bluetooth device supporting PAN or DUN access protocols + * @NM_DEVICE_TYPE_OLPC_MESH: an OLPC XO mesh networking device + * @NM_DEVICE_TYPE_WIMAX: an 802.16e Mobile WiMAX broadband device + * @NM_DEVICE_TYPE_MODEM: a modem supporting analog telephone, CDMA/EVDO, + * GSM/UMTS, or LTE network access protocols + * @NM_DEVICE_TYPE_INFINIBAND: an IP-over-InfiniBand device + * @NM_DEVICE_TYPE_BOND: a bond master interface + * @NM_DEVICE_TYPE_VLAN: an 802.1Q VLAN interface + * @NM_DEVICE_TYPE_ADSL: ADSL modem + * @NM_DEVICE_TYPE_BRIDGE: a bridge master interface + * @NM_DEVICE_TYPE_TEAM: a team master interface + * @NM_DEVICE_TYPE_TUN: a TUN or TAP interface + * @NM_DEVICE_TYPE_IP_TUNNEL: a IP tunnel interface + * @NM_DEVICE_TYPE_MACVLAN: a MACVLAN interface + * @NM_DEVICE_TYPE_VXLAN: a VXLAN interface + * @NM_DEVICE_TYPE_VETH: a VETH interface + * @NM_DEVICE_TYPE_MACSEC: a MACsec interface + * @NM_DEVICE_TYPE_DUMMY: a dummy interface + * @NM_DEVICE_TYPE_PPP: a PPP interface + * @NM_DEVICE_TYPE_OVS_INTERFACE: a Open vSwitch interface + * @NM_DEVICE_TYPE_OVS_PORT: a Open vSwitch port + * @NM_DEVICE_TYPE_OVS_BRIDGE: a Open vSwitch bridge + * @NM_DEVICE_TYPE_WPAN: a IEEE 802.15.4 (WPAN) MAC Layer Device + * @NM_DEVICE_TYPE_6LOWPAN: 6LoWPAN interface + * @NM_DEVICE_TYPE_WIREGUARD: a WireGuard interface + * @NM_DEVICE_TYPE_WIFI_P2P: an 802.11 Wi-Fi P2P device. Since: 1.16. + * @NM_DEVICE_TYPE_VRF: A VRF (Virtual Routing and Forwarding) interface. Since: 1.24. + * + * #NMDeviceType values indicate the type of hardware represented by a + * device object. + **/ +typedef enum { + NM_DEVICE_TYPE_UNKNOWN = 0, + NM_DEVICE_TYPE_ETHERNET = 1, + NM_DEVICE_TYPE_WIFI = 2, + NM_DEVICE_TYPE_UNUSED1 = 3, + NM_DEVICE_TYPE_UNUSED2 = 4, + NM_DEVICE_TYPE_BT = 5, /* Bluetooth */ + NM_DEVICE_TYPE_OLPC_MESH = 6, + NM_DEVICE_TYPE_WIMAX = 7, + NM_DEVICE_TYPE_MODEM = 8, + NM_DEVICE_TYPE_INFINIBAND = 9, + NM_DEVICE_TYPE_BOND = 10, + NM_DEVICE_TYPE_VLAN = 11, + NM_DEVICE_TYPE_ADSL = 12, + NM_DEVICE_TYPE_BRIDGE = 13, + NM_DEVICE_TYPE_GENERIC = 14, + NM_DEVICE_TYPE_TEAM = 15, + NM_DEVICE_TYPE_TUN = 16, + NM_DEVICE_TYPE_IP_TUNNEL = 17, + NM_DEVICE_TYPE_MACVLAN = 18, + NM_DEVICE_TYPE_VXLAN = 19, + NM_DEVICE_TYPE_VETH = 20, + NM_DEVICE_TYPE_MACSEC = 21, + NM_DEVICE_TYPE_DUMMY = 22, + NM_DEVICE_TYPE_PPP = 23, + NM_DEVICE_TYPE_OVS_INTERFACE = 24, + NM_DEVICE_TYPE_OVS_PORT = 25, + NM_DEVICE_TYPE_OVS_BRIDGE = 26, + NM_DEVICE_TYPE_WPAN = 27, + NM_DEVICE_TYPE_6LOWPAN = 28, + NM_DEVICE_TYPE_WIREGUARD = 29, + NM_DEVICE_TYPE_WIFI_P2P = 30, + NM_DEVICE_TYPE_VRF = 31, +} NMDeviceType; + +/** + * NMDeviceCapabilities: + * @NM_DEVICE_CAP_NONE: device has no special capabilities + * @NM_DEVICE_CAP_NM_SUPPORTED: NetworkManager supports this device + * @NM_DEVICE_CAP_CARRIER_DETECT: this device can indicate carrier status + * @NM_DEVICE_CAP_IS_SOFTWARE: this device is a software device + * @NM_DEVICE_CAP_SRIOV: this device supports single-root I/O virtualization + * + * General device capability flags. + **/ +typedef enum { /*< flags >*/ + NM_DEVICE_CAP_NONE = 0x00000000, + NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001, + NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002, + NM_DEVICE_CAP_IS_SOFTWARE = 0x00000004, + NM_DEVICE_CAP_SRIOV = 0x00000008, +} NMDeviceCapabilities; + +/** + * NMDeviceWifiCapabilities: + * @NM_WIFI_DEVICE_CAP_NONE: device has no encryption/authentication capabilities + * @NM_WIFI_DEVICE_CAP_CIPHER_WEP40: device supports 40/64-bit WEP encryption + * @NM_WIFI_DEVICE_CAP_CIPHER_WEP104: device supports 104/128-bit WEP encryption + * @NM_WIFI_DEVICE_CAP_CIPHER_TKIP: device supports TKIP encryption + * @NM_WIFI_DEVICE_CAP_CIPHER_CCMP: device supports AES/CCMP encryption + * @NM_WIFI_DEVICE_CAP_WPA: device supports WPA1 authentication + * @NM_WIFI_DEVICE_CAP_RSN: device supports WPA2/RSN authentication + * @NM_WIFI_DEVICE_CAP_AP: device supports Access Point mode + * @NM_WIFI_DEVICE_CAP_ADHOC: device supports Ad-Hoc mode + * @NM_WIFI_DEVICE_CAP_FREQ_VALID: device reports frequency capabilities + * @NM_WIFI_DEVICE_CAP_FREQ_2GHZ: device supports 2.4GHz frequencies + * @NM_WIFI_DEVICE_CAP_FREQ_5GHZ: device supports 5GHz frequencies + * @NM_WIFI_DEVICE_CAP_MESH: device supports acting as a mesh point. Since: 1.20. + * @NM_WIFI_DEVICE_CAP_IBSS_RSN: device supports WPA2/RSN in an IBSS network. Since: 1.22. + * + * 802.11 specific device encryption and authentication capabilities. + **/ +typedef enum { /*< flags >*/ + NM_WIFI_DEVICE_CAP_NONE = 0x00000000, + NM_WIFI_DEVICE_CAP_CIPHER_WEP40 = 0x00000001, + NM_WIFI_DEVICE_CAP_CIPHER_WEP104 = 0x00000002, + NM_WIFI_DEVICE_CAP_CIPHER_TKIP = 0x00000004, + NM_WIFI_DEVICE_CAP_CIPHER_CCMP = 0x00000008, + NM_WIFI_DEVICE_CAP_WPA = 0x00000010, + NM_WIFI_DEVICE_CAP_RSN = 0x00000020, + NM_WIFI_DEVICE_CAP_AP = 0x00000040, + NM_WIFI_DEVICE_CAP_ADHOC = 0x00000080, + NM_WIFI_DEVICE_CAP_FREQ_VALID = 0x00000100, + NM_WIFI_DEVICE_CAP_FREQ_2GHZ = 0x00000200, + NM_WIFI_DEVICE_CAP_FREQ_5GHZ = 0x00000400, + NM_WIFI_DEVICE_CAP_MESH = 0x00001000, + NM_WIFI_DEVICE_CAP_IBSS_RSN = 0x00002000, +} NMDeviceWifiCapabilities; + +/** + * NM80211ApFlags: + * @NM_802_11_AP_FLAGS_NONE: access point has no special capabilities + * @NM_802_11_AP_FLAGS_PRIVACY: access point requires authentication and + * encryption (usually means WEP) + * @NM_802_11_AP_FLAGS_WPS: access point supports some WPS method + * @NM_802_11_AP_FLAGS_WPS_PBC: access point supports push-button WPS + * @NM_802_11_AP_FLAGS_WPS_PIN: access point supports PIN-based WPS + * + * 802.11 access point flags. + **/ +typedef enum { /*< underscore_name=nm_802_11_ap_flags, flags >*/ + NM_802_11_AP_FLAGS_NONE = 0x00000000, + NM_802_11_AP_FLAGS_PRIVACY = 0x00000001, + NM_802_11_AP_FLAGS_WPS = 0x00000002, + NM_802_11_AP_FLAGS_WPS_PBC = 0x00000004, + NM_802_11_AP_FLAGS_WPS_PIN = 0x00000008, +} NM80211ApFlags; + +/** + * NM80211ApSecurityFlags: + * @NM_802_11_AP_SEC_NONE: the access point has no special security requirements + * @NM_802_11_AP_SEC_PAIR_WEP40: 40/64-bit WEP is supported for + * pairwise/unicast encryption + * @NM_802_11_AP_SEC_PAIR_WEP104: 104/128-bit WEP is supported for + * pairwise/unicast encryption + * @NM_802_11_AP_SEC_PAIR_TKIP: TKIP is supported for pairwise/unicast encryption + * @NM_802_11_AP_SEC_PAIR_CCMP: AES/CCMP is supported for pairwise/unicast encryption + * @NM_802_11_AP_SEC_GROUP_WEP40: 40/64-bit WEP is supported for group/broadcast + * encryption + * @NM_802_11_AP_SEC_GROUP_WEP104: 104/128-bit WEP is supported for + * group/broadcast encryption + * @NM_802_11_AP_SEC_GROUP_TKIP: TKIP is supported for group/broadcast encryption + * @NM_802_11_AP_SEC_GROUP_CCMP: AES/CCMP is supported for group/broadcast + * encryption + * @NM_802_11_AP_SEC_KEY_MGMT_PSK: WPA/RSN Pre-Shared Key encryption is + * supported + * @NM_802_11_AP_SEC_KEY_MGMT_802_1X: 802.1x authentication and key management + * is supported + * @NM_802_11_AP_SEC_KEY_MGMT_SAE: WPA/RSN Simultaneous Authentication of Equals is + * supported + * @NM_802_11_AP_SEC_KEY_MGMT_OWE: WPA/RSN Opportunistic Wireless Encryption is + * supported + * @NM_802_11_AP_SEC_KEY_MGMT_OWE_TM: WPA/RSN Opportunistic Wireless Encryption + * transition mode is supported. Since: 1.26. + * @NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192: WPA3 Enterprise Suite-B 192 bit mode + * is supported. Since: 1.30. + * + * 802.11 access point security and authentication flags. These flags describe + * the current security requirements of an access point as determined from the + * access point's beacon. + **/ +typedef enum { /*< underscore_name=nm_802_11_ap_security_flags, flags >*/ + NM_802_11_AP_SEC_NONE = 0x00000000, + NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001, + NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002, + NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004, + NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008, + NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010, + NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020, + NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040, + NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080, + NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100, + NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200, + NM_802_11_AP_SEC_KEY_MGMT_SAE = 0x00000400, + NM_802_11_AP_SEC_KEY_MGMT_OWE = 0x00000800, + NM_802_11_AP_SEC_KEY_MGMT_OWE_TM = 0x00001000, + NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 = 0x00002000, +} NM80211ApSecurityFlags; + +/** + * NM80211Mode: + * @NM_802_11_MODE_UNKNOWN: the device or access point mode is unknown + * @NM_802_11_MODE_ADHOC: for both devices and access point objects, indicates + * the object is part of an Ad-Hoc 802.11 network without a central + * coordinating access point. + * @NM_802_11_MODE_INFRA: the device or access point is in infrastructure mode. + * For devices, this indicates the device is an 802.11 client/station. For + * access point objects, this indicates the object is an access point that + * provides connectivity to clients. + * @NM_802_11_MODE_AP: the device is an access point/hotspot. Not valid for + * access point objects; used only for hotspot mode on the local machine. + * @NM_802_11_MODE_MESH: the device is a 802.11s mesh point. Since: 1.20. + * + * Indicates the 802.11 mode an access point or device is currently in. + **/ +typedef enum { /*< underscore_name=nm_802_11_mode >*/ + NM_802_11_MODE_UNKNOWN = 0, + NM_802_11_MODE_ADHOC = 1, + NM_802_11_MODE_INFRA = 2, + NM_802_11_MODE_AP = 3, + NM_802_11_MODE_MESH = 4, +} NM80211Mode; + +/** + * NMBluetoothCapabilities: + * @NM_BT_CAPABILITY_NONE: device has no usable capabilities + * @NM_BT_CAPABILITY_DUN: device provides Dial-Up Networking capability + * @NM_BT_CAPABILITY_NAP: device provides Network Access Point capability + * + * #NMBluetoothCapabilities values indicate the usable capabilities of a + * Bluetooth device. + **/ +typedef enum { /*< flags >*/ + NM_BT_CAPABILITY_NONE = 0x00000000, + NM_BT_CAPABILITY_DUN = 0x00000001, + NM_BT_CAPABILITY_NAP = 0x00000002, +} NMBluetoothCapabilities; + +/** + * NMDeviceModemCapabilities: + * @NM_DEVICE_MODEM_CAPABILITY_NONE: modem has no usable capabilities + * @NM_DEVICE_MODEM_CAPABILITY_POTS: modem uses the analog wired telephone + * network and is not a wireless/cellular device + * @NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO: modem supports at least one of CDMA + * 1xRTT, EVDO revision 0, EVDO revision A, or EVDO revision B + * @NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS: modem supports at least one of GSM, + * GPRS, EDGE, UMTS, HSDPA, HSUPA, or HSPA+ packet switched data capability + * @NM_DEVICE_MODEM_CAPABILITY_LTE: modem has LTE data capability + * + * #NMDeviceModemCapabilities values indicate the generic radio access + * technology families a modem device supports. For more information on the + * specific access technologies the device supports use the ModemManager D-Bus + * API. + **/ +typedef enum { /*< flags >*/ + NM_DEVICE_MODEM_CAPABILITY_NONE = 0x00000000, + NM_DEVICE_MODEM_CAPABILITY_POTS = 0x00000001, + NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO = 0x00000002, + NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS = 0x00000004, + NM_DEVICE_MODEM_CAPABILITY_LTE = 0x00000008, +} NMDeviceModemCapabilities; + +/** + * NMWimaxNspNetworkType: + * @NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN: unknown network type + * @NM_WIMAX_NSP_NETWORK_TYPE_HOME: home network + * @NM_WIMAX_NSP_NETWORK_TYPE_PARTNER: partner network + * @NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER: roaming partner network + * + * WiMAX network type. + */ +typedef enum { + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN = 0, + NM_WIMAX_NSP_NETWORK_TYPE_HOME = 1, + NM_WIMAX_NSP_NETWORK_TYPE_PARTNER = 2, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER = 3, +} NMWimaxNspNetworkType; + +/** + * NMDeviceState: + * @NM_DEVICE_STATE_UNKNOWN: the device's state is unknown + * @NM_DEVICE_STATE_UNMANAGED: the device is recognized, but not managed by + * NetworkManager + * @NM_DEVICE_STATE_UNAVAILABLE: the device is managed by NetworkManager, but + * is not available for use. Reasons may include the wireless switched off, + * missing firmware, no ethernet carrier, missing supplicant or modem manager, + * etc. + * @NM_DEVICE_STATE_DISCONNECTED: the device can be activated, but is currently + * idle and not connected to a network. + * @NM_DEVICE_STATE_PREPARE: the device is preparing the connection to the + * network. This may include operations like changing the MAC address, + * setting physical link properties, and anything else required to connect + * to the requested network. + * @NM_DEVICE_STATE_CONFIG: the device is connecting to the requested network. + * This may include operations like associating with the Wi-Fi AP, dialing + * the modem, connecting to the remote Bluetooth device, etc. + * @NM_DEVICE_STATE_NEED_AUTH: the device requires more information to continue + * connecting to the requested network. This includes secrets like WiFi + * passphrases, login passwords, PIN codes, etc. + * @NM_DEVICE_STATE_IP_CONFIG: the device is requesting IPv4 and/or IPv6 + * addresses and routing information from the network. + * @NM_DEVICE_STATE_IP_CHECK: the device is checking whether further action is + * required for the requested network connection. This may include checking + * whether only local network access is available, whether a captive portal + * is blocking access to the Internet, etc. + * @NM_DEVICE_STATE_SECONDARIES: the device is waiting for a secondary + * connection (like a VPN) which must activated before the device can be + * activated + * @NM_DEVICE_STATE_ACTIVATED: the device has a network connection, either local + * or global. + * @NM_DEVICE_STATE_DEACTIVATING: a disconnection from the current network + * connection was requested, and the device is cleaning up resources used for + * that connection. The network connection may still be valid. + * @NM_DEVICE_STATE_FAILED: the device failed to connect to the requested + * network and is cleaning up the connection request + **/ +typedef enum { + NM_DEVICE_STATE_UNKNOWN = 0, + NM_DEVICE_STATE_UNMANAGED = 10, + NM_DEVICE_STATE_UNAVAILABLE = 20, + NM_DEVICE_STATE_DISCONNECTED = 30, + NM_DEVICE_STATE_PREPARE = 40, + NM_DEVICE_STATE_CONFIG = 50, + NM_DEVICE_STATE_NEED_AUTH = 60, + NM_DEVICE_STATE_IP_CONFIG = 70, + NM_DEVICE_STATE_IP_CHECK = 80, + NM_DEVICE_STATE_SECONDARIES = 90, + NM_DEVICE_STATE_ACTIVATED = 100, + NM_DEVICE_STATE_DEACTIVATING = 110, + NM_DEVICE_STATE_FAILED = 120, +} NMDeviceState; + +/** + * NMDeviceStateReason: + * @NM_DEVICE_STATE_REASON_NONE: No reason given + * @NM_DEVICE_STATE_REASON_UNKNOWN: Unknown error + * @NM_DEVICE_STATE_REASON_NOW_MANAGED: Device is now managed + * @NM_DEVICE_STATE_REASON_NOW_UNMANAGED: Device is now unmanaged + * @NM_DEVICE_STATE_REASON_CONFIG_FAILED: The device could not be readied for configuration + * @NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE: IP configuration could not be reserved (no available address, timeout, etc) + * @NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED: The IP config is no longer valid + * @NM_DEVICE_STATE_REASON_NO_SECRETS: Secrets were required, but not provided + * @NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT: 802.1x supplicant disconnected + * @NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED: 802.1x supplicant configuration failed + * @NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED: 802.1x supplicant failed + * @NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT: 802.1x supplicant took too long to authenticate + * @NM_DEVICE_STATE_REASON_PPP_START_FAILED: PPP service failed to start + * @NM_DEVICE_STATE_REASON_PPP_DISCONNECT: PPP service disconnected + * @NM_DEVICE_STATE_REASON_PPP_FAILED: PPP failed + * @NM_DEVICE_STATE_REASON_DHCP_START_FAILED: DHCP client failed to start + * @NM_DEVICE_STATE_REASON_DHCP_ERROR: DHCP client error + * @NM_DEVICE_STATE_REASON_DHCP_FAILED: DHCP client failed + * @NM_DEVICE_STATE_REASON_SHARED_START_FAILED: Shared connection service failed to start + * @NM_DEVICE_STATE_REASON_SHARED_FAILED: Shared connection service failed + * @NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED: AutoIP service failed to start + * @NM_DEVICE_STATE_REASON_AUTOIP_ERROR: AutoIP service error + * @NM_DEVICE_STATE_REASON_AUTOIP_FAILED: AutoIP service failed + * @NM_DEVICE_STATE_REASON_MODEM_BUSY: The line is busy + * @NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE: No dial tone + * @NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER: No carrier could be established + * @NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT: The dialing request timed out + * @NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED: The dialing attempt failed + * @NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: Modem initialization failed + * @NM_DEVICE_STATE_REASON_GSM_APN_FAILED: Failed to select the specified APN + * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: Not searching for networks + * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: Network registration denied + * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT: Network registration timed out + * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED: Failed to register with the requested network + * @NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED: PIN check failed + * @NM_DEVICE_STATE_REASON_FIRMWARE_MISSING: Necessary firmware for the device may be missing + * @NM_DEVICE_STATE_REASON_REMOVED: The device was removed + * @NM_DEVICE_STATE_REASON_SLEEPING: NetworkManager went to sleep + * @NM_DEVICE_STATE_REASON_CONNECTION_REMOVED: The device's active connection disappeared + * @NM_DEVICE_STATE_REASON_USER_REQUESTED: Device disconnected by user or client + * @NM_DEVICE_STATE_REASON_CARRIER: Carrier/link changed + * @NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED: The device's existing connection was assumed + * @NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: The supplicant is now available + * @NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND: The modem could not be found + * @NM_DEVICE_STATE_REASON_BT_FAILED: The Bluetooth connection failed or timed out + * @NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: GSM Modem's SIM Card not inserted + * @NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: GSM Modem's SIM Pin required + * @NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED: GSM Modem's SIM Puk required + * @NM_DEVICE_STATE_REASON_GSM_SIM_WRONG: GSM Modem's SIM wrong + * @NM_DEVICE_STATE_REASON_INFINIBAND_MODE: InfiniBand device does not support connected mode + * @NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: A dependency of the connection failed + * @NM_DEVICE_STATE_REASON_BR2684_FAILED: Problem with the RFC 2684 Ethernet over ADSL bridge + * @NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE: ModemManager not running + * @NM_DEVICE_STATE_REASON_SSID_NOT_FOUND: The Wi-Fi network could not be found + * @NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED: A secondary connection of the base connection failed + * @NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED: DCB or FCoE setup failed + * @NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED: teamd control failed + * @NM_DEVICE_STATE_REASON_MODEM_FAILED: Modem failed or no longer available + * @NM_DEVICE_STATE_REASON_MODEM_AVAILABLE: Modem now ready and available + * @NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT: SIM PIN was incorrect + * @NM_DEVICE_STATE_REASON_NEW_ACTIVATION: New connection activation was enqueued + * @NM_DEVICE_STATE_REASON_PARENT_CHANGED: the device's parent changed + * @NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED: the device parent's management changed + * @NM_DEVICE_STATE_REASON_OVSDB_FAILED: problem communicating with Open vSwitch database + * @NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE: a duplicate IP address was detected + * @NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED: The selected IP method is not supported + * @NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED: configuration of SR-IOV parameters failed + * @NM_DEVICE_STATE_REASON_PEER_NOT_FOUND: The Wi-Fi P2P peer could not be found + * + * Device state change reason codes + */ +typedef enum { + NM_DEVICE_STATE_REASON_NONE = 0, + NM_DEVICE_STATE_REASON_UNKNOWN = 1, + NM_DEVICE_STATE_REASON_NOW_MANAGED = 2, + NM_DEVICE_STATE_REASON_NOW_UNMANAGED = 3, + NM_DEVICE_STATE_REASON_CONFIG_FAILED = 4, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE = 5, + NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED = 6, + NM_DEVICE_STATE_REASON_NO_SECRETS = 7, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8, + NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED = 9, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED = 10, + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT = 11, + NM_DEVICE_STATE_REASON_PPP_START_FAILED = 12, + NM_DEVICE_STATE_REASON_PPP_DISCONNECT = 13, + NM_DEVICE_STATE_REASON_PPP_FAILED = 14, + NM_DEVICE_STATE_REASON_DHCP_START_FAILED = 15, + NM_DEVICE_STATE_REASON_DHCP_ERROR = 16, + NM_DEVICE_STATE_REASON_DHCP_FAILED = 17, + NM_DEVICE_STATE_REASON_SHARED_START_FAILED = 18, + NM_DEVICE_STATE_REASON_SHARED_FAILED = 19, + NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED = 20, + NM_DEVICE_STATE_REASON_AUTOIP_ERROR = 21, + NM_DEVICE_STATE_REASON_AUTOIP_FAILED = 22, + NM_DEVICE_STATE_REASON_MODEM_BUSY = 23, + NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE = 24, + NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER = 25, + NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT = 26, + NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED = 27, + NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED = 28, + NM_DEVICE_STATE_REASON_GSM_APN_FAILED = 29, + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING = 30, + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED = 31, + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT = 32, + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED = 33, + NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED = 34, + NM_DEVICE_STATE_REASON_FIRMWARE_MISSING = 35, + NM_DEVICE_STATE_REASON_REMOVED = 36, + NM_DEVICE_STATE_REASON_SLEEPING = 37, + NM_DEVICE_STATE_REASON_CONNECTION_REMOVED = 38, + NM_DEVICE_STATE_REASON_USER_REQUESTED = 39, + NM_DEVICE_STATE_REASON_CARRIER = 40, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED = 41, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE = 42, + NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND = 43, + NM_DEVICE_STATE_REASON_BT_FAILED = 44, + NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED = 45, + NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED = 46, + NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED = 47, + NM_DEVICE_STATE_REASON_GSM_SIM_WRONG = 48, + NM_DEVICE_STATE_REASON_INFINIBAND_MODE = 49, + NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED = 50, + NM_DEVICE_STATE_REASON_BR2684_FAILED = 51, + NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE = 52, + NM_DEVICE_STATE_REASON_SSID_NOT_FOUND = 53, + NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED = 54, + NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED = 55, + NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED = 56, + NM_DEVICE_STATE_REASON_MODEM_FAILED = 57, + NM_DEVICE_STATE_REASON_MODEM_AVAILABLE = 58, + NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT = 59, + NM_DEVICE_STATE_REASON_NEW_ACTIVATION = 60, + NM_DEVICE_STATE_REASON_PARENT_CHANGED = 61, + NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED = 62, + NM_DEVICE_STATE_REASON_OVSDB_FAILED = 63, + NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE = 64, + NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED = 65, + NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED = 66, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND = 67, +} NMDeviceStateReason; + +/** + * NMMetered: + * @NM_METERED_UNKNOWN: The metered status is unknown + * @NM_METERED_YES: Metered, the value was explicitly configured + * @NM_METERED_NO: Not metered, the value was explicitly configured + * @NM_METERED_GUESS_YES: Metered, the value was guessed + * @NM_METERED_GUESS_NO: Not metered, the value was guessed + * + * The NMMetered enum has two different purposes: one is to configure + * "connection.metered" setting of a connection profile in #NMSettingConnection, and + * the other is to express the actual metered state of the #NMDevice at a given moment. + * + * For the connection profile only #NM_METERED_UNKNOWN, #NM_METERED_NO + * and #NM_METERED_YES are allowed. + * + * The device's metered state at runtime is determined by the profile + * which is currently active. If the profile explicitly specifies #NM_METERED_NO + * or #NM_METERED_YES, then the device's metered state is as such. + * If the connection profile leaves it undecided at #NM_METERED_UNKNOWN (the default), + * then NetworkManager tries to guess the metered state, for example based on the + * device type or on DHCP options (like Android devices exposing a "ANDROID_METERED" + * DHCP vendor option). This then leads to either #NM_METERED_GUESS_NO or #NM_METERED_GUESS_YES. + * + * Most applications probably should treat the runtime state #NM_METERED_GUESS_YES + * like #NM_METERED_YES, and all other states as not metered. + * + * Note that the per-device metered states are then combined to a global metered + * state. This is basically the metered state of the device with the best default + * route. However, that generalization of a global metered state may not be correct + * if the default routes for IPv4 and IPv6 are on different devices, or if policy + * routing is configured. In general, the global metered state tries to express whether + * the traffic is likely metered, but since that depends on the traffic itself, + * there is not one answer in all cases. Hence, an application may want to consider + * the per-device's metered states. + * + * Since: 1.2 + **/ +NM_AVAILABLE_IN_1_2 +typedef enum { + NM_METERED_UNKNOWN = 0, + NM_METERED_YES = 1, + NM_METERED_NO = 2, + NM_METERED_GUESS_YES = 3, + NM_METERED_GUESS_NO = 4, +} NMMetered; + +/** + * NMConnectionMultiConnect: + * @NM_CONNECTION_MULTI_CONNECT_DEFAULT: indicates that the per-connection + * setting is unspecified. In this case, it will fallback to the default + * value, which is %NM_CONNECTION_MULTI_CONNECT_SINGLE. + * @NM_CONNECTION_MULTI_CONNECT_SINGLE: the connection profile can only + * be active once at each moment. Activating a profile that is already active, + * will first deactivate it. + * @NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE: the profile can + * be manually activated multiple times on different devices. However, + * regarding autoconnect, the profile will autoconnect only if it is + * currently not connected otherwise. + * @NM_CONNECTION_MULTI_CONNECT_MULTIPLE: the profile can autoactivate + * and be manually activated multiple times together. + * + * Since: 1.14 + */ +typedef enum { + NM_CONNECTION_MULTI_CONNECT_DEFAULT = 0, + NM_CONNECTION_MULTI_CONNECT_SINGLE = 1, + NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE = 2, + NM_CONNECTION_MULTI_CONNECT_MULTIPLE = 3, +} NMConnectionMultiConnect; + +/** + * NMActiveConnectionState: + * @NM_ACTIVE_CONNECTION_STATE_UNKNOWN: the state of the connection is unknown + * @NM_ACTIVE_CONNECTION_STATE_ACTIVATING: a network connection is being prepared + * @NM_ACTIVE_CONNECTION_STATE_ACTIVATED: there is a connection to the network + * @NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: the network connection is being + * torn down and cleaned up + * @NM_ACTIVE_CONNECTION_STATE_DEACTIVATED: the network connection is disconnected + * and will be removed + * + * #NMActiveConnectionState values indicate the state of a connection to a + * specific network while it is starting, connected, or disconnecting from that + * network. + **/ +typedef enum { + NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0, + NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING = 3, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED = 4, +} NMActiveConnectionState; + +/** + * NMActiveConnectionStateReason: + * @NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN: The reason for the active connection + * state change is unknown. + * @NM_ACTIVE_CONNECTION_STATE_REASON_NONE: No reason was given for the active + * connection state change. + * @NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED: The active connection changed + * state because the user disconnected it. + * @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED: The active connection + * changed state because the device it was using was disconnected. + * @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED: The service providing the + * VPN connection was stopped. + * @NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID: The IP config of the active + * connection was invalid. + * @NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT: The connection attempt to + * the VPN service timed out. + * @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT: A timeout occurred + * while starting the service providing the VPN connection. + * @NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED: Starting the service + * providing the VPN connection failed. + * @NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS: Necessary secrets for the + * connection were not provided. + * @NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED: Authentication to the + * server failed. + * @NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED: The connection was + * deleted from settings. + * @NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED: Master connection of this + * connection failed to activate. + * @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED: Could not create the + * software device link. + * @NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED: The device this connection + * depended on disappeared. + * + * Active connection state reasons. + * + * Since: 1.8 + */ +NM_AVAILABLE_IN_1_8 +typedef enum { + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN = 0, + NM_ACTIVE_CONNECTION_STATE_REASON_NONE = 1, + NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED = 2, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED = 3, + NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED = 4, + NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID = 5, + NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT = 6, + NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT = 7, + NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED = 8, + NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS = 9, + NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED = 10, + NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED = 11, + NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED = 12, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED = 13, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED = 14, +} NMActiveConnectionStateReason; + +/** + * NMSecretAgentGetSecretsFlags: + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE: no special behavior; by default no + * user interaction is allowed and requests for secrets are fulfilled from + * persistent storage, or if no secrets are available an error is returned. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION: allows the request to + * interact with the user, possibly prompting via UI for secrets if any are + * required, or if none are found in persistent storage. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW: explicitly prompt for new + * secrets from the user. This flag signals that NetworkManager thinks any + * existing secrets are invalid or wrong. This flag implies that interaction + * is allowed. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED: set if the request was + * initiated by user-requested action via the D-Bus interface, as opposed to + * automatically initiated by NetworkManager in response to (for example) scan + * results or carrier changes. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE: indicates that WPS enrollment + * is active with PBC method. The agent may suggest that the user pushes a button + * on the router instead of supplying a PSK. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM: Internal flag, not part of + * the D-Bus API. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS: Internal flag, not part of + * the D-Bus API. + * + * #NMSecretAgentGetSecretsFlags values modify the behavior of a GetSecrets request. + */ +typedef enum { /*< flags >*/ + NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE = 0x0, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1, + NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2, + NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4, + NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE = 0x8, + + /* Internal to NM; not part of the D-Bus API */ + NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM = 0x80000000, + NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS = 0x40000000, +} NMSecretAgentGetSecretsFlags; + +/** + * NMSecretAgentCapabilities: + * @NM_SECRET_AGENT_CAPABILITY_NONE: the agent supports no special capabilities + * @NM_SECRET_AGENT_CAPABILITY_VPN_HINTS: the agent supports passing hints to + * VPN plugin authentication dialogs. + * @NM_SECRET_AGENT_CAPABILITY_LAST: bounds checking value; should not be used. + * + * #NMSecretAgentCapabilities indicate various capabilities of the agent. + */ +typedef enum /*< flags >*/ { + NM_SECRET_AGENT_CAPABILITY_NONE = 0x0, + NM_SECRET_AGENT_CAPABILITY_VPN_HINTS = 0x1, + + /* boundary value */ + NM_SECRET_AGENT_CAPABILITY_LAST = NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, +} NMSecretAgentCapabilities; + +#ifndef NM_VERSION_H + #undef NM_AVAILABLE_IN_1_2 + #undef NM_AVAILABLE_IN_1_8 +#endif + +#define NM_LLDP_ATTR_RAW "raw" +#define NM_LLDP_ATTR_DESTINATION "destination" +#define NM_LLDP_ATTR_CHASSIS_ID_TYPE "chassis-id-type" +#define NM_LLDP_ATTR_CHASSIS_ID "chassis-id" +#define NM_LLDP_ATTR_PORT_ID_TYPE "port-id-type" +#define NM_LLDP_ATTR_PORT_ID "port-id" +#define NM_LLDP_ATTR_PORT_DESCRIPTION "port-description" +#define NM_LLDP_ATTR_SYSTEM_NAME "system-name" +#define NM_LLDP_ATTR_SYSTEM_DESCRIPTION "system-description" +#define NM_LLDP_ATTR_SYSTEM_CAPABILITIES "system-capabilities" +#define NM_LLDP_ATTR_MANAGEMENT_ADDRESSES "management-addresses" + +#define NM_LLDP_ATTR_IEEE_802_1_PVID "ieee-802-1-pvid" +#define NM_LLDP_ATTR_IEEE_802_1_VLANS "ieee-802-1-vlans" +#define NM_LLDP_ATTR_IEEE_802_1_PPVIDS "ieee-802-1-ppvids" + +#define NM_LLDP_ATTR_IEEE_802_3_MAC_PHY_CONF "ieee-802-3-mac-phy-conf" +#define NM_LLDP_ATTR_IEEE_802_3_POWER_VIA_MDI "ieee-802-3-power-via-mdi" +#define NM_LLDP_ATTR_IEEE_802_3_MAX_FRAME_SIZE "ieee-802-3-max-frame-size" + +#define NM_LLDP_ATTR_MUD_URL "mud-url" + +/* These are deprecated in favor of NM_LLDP_ATTR_IEEE_802_1_VLANS, + * which can report multiple VLANs */ +#define NM_LLDP_ATTR_IEEE_802_1_VID "ieee-802-1-vid" +#define NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME "ieee-802-1-vlan-name" + +/* These are deprecated in favor of NM_LLDP_ATTR_IEEE_802_1_PPVIDS, + * which can report multiple PPVIDs */ +#define NM_LLDP_ATTR_IEEE_802_1_PPVID "ieee-802-1-ppvid" +#define NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS "ieee-802-1-ppvid-flags" + +#define NM_LLDP_DEST_NEAREST_BRIDGE "nearest-bridge" +#define NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE "nearest-non-tpmr-bridge" +#define NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE "nearest-customer-bridge" + +/** + * NMIPTunnelMode: + * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode + * @NM_IP_TUNNEL_MODE_IPIP: IP in IP tunnel + * @NM_IP_TUNNEL_MODE_GRE: GRE tunnel + * @NM_IP_TUNNEL_MODE_SIT: SIT tunnel + * @NM_IP_TUNNEL_MODE_ISATAP: ISATAP tunnel + * @NM_IP_TUNNEL_MODE_VTI: VTI tunnel + * @NM_IP_TUNNEL_MODE_IP6IP6: IPv6 in IPv6 tunnel + * @NM_IP_TUNNEL_MODE_IPIP6: IPv4 in IPv6 tunnel + * @NM_IP_TUNNEL_MODE_IP6GRE: IPv6 GRE tunnel + * @NM_IP_TUNNEL_MODE_VTI6: IPv6 VTI tunnel + * @NM_IP_TUNNEL_MODE_GRETAP: GRETAP tunnel + * @NM_IP_TUNNEL_MODE_IP6GRETAP: IPv6 GRETAP tunnel + * + * The tunneling mode. + * + * Since: 1.2 + */ +typedef enum { + NM_IP_TUNNEL_MODE_UNKNOWN = 0, + NM_IP_TUNNEL_MODE_IPIP = 1, + NM_IP_TUNNEL_MODE_GRE = 2, + NM_IP_TUNNEL_MODE_SIT = 3, + NM_IP_TUNNEL_MODE_ISATAP = 4, + NM_IP_TUNNEL_MODE_VTI = 5, + NM_IP_TUNNEL_MODE_IP6IP6 = 6, + NM_IP_TUNNEL_MODE_IPIP6 = 7, + NM_IP_TUNNEL_MODE_IP6GRE = 8, + NM_IP_TUNNEL_MODE_VTI6 = 9, + NM_IP_TUNNEL_MODE_GRETAP = 10, + NM_IP_TUNNEL_MODE_IP6GRETAP = 11, +} NMIPTunnelMode; + +/** + * NMCheckpointCreateFlags: + * @NM_CHECKPOINT_CREATE_FLAG_NONE: no flags + * @NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL: when creating + * a new checkpoint, destroy all existing ones. + * @NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS: upon rollback, + * delete any new connection added after the checkpoint. Since: 1.6. + * @NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES: upon rollback, + * disconnect any new device appeared after the checkpoint. Since: 1.6. + * @NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING: by default, creating + * a checkpoint fails if there are already existing checkoints that + * reference the same devices. With this flag, creation of such + * checkpoints is allowed, however, if an older checkpoint + * that references overlapping devices gets rolled back, it will + * automatically destroy this checkpoint during rollback. This + * allows to create several overlapping checkpoints in parallel, + * and rollback to them at will. With the special case that + * rolling back to an older checkpoint will invalidate all + * overlapping younger checkpoints. This opts-in that the + * checkpoint can be automatically destroyed by the rollback + * of an older checkpoint. Since: 1.12. + * + * The flags for CheckpointCreate call + * + * Since: 1.4 (gi flags generated since 1.12) + */ +typedef enum { /*< flags >*/ + NM_CHECKPOINT_CREATE_FLAG_NONE = 0, + NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL = 0x01, + NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS = 0x02, + NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES = 0x04, + NM_CHECKPOINT_CREATE_FLAG_ALLOW_OVERLAPPING = 0x08, +} NMCheckpointCreateFlags; + +/** + * NMRollbackResult: + * @NM_ROLLBACK_RESULT_OK: the rollback succeeded. + * @NM_ROLLBACK_RESULT_ERR_NO_DEVICE: the device no longer exists. + * @NM_ROLLBACK_RESULT_ERR_DEVICE_UNMANAGED: the device is now unmanaged. + * @NM_ROLLBACK_RESULT_ERR_FAILED: other errors during rollback. + * + * The result of a checkpoint Rollback() operation for a specific device. + * + * Since: 1.4 + **/ +typedef enum { /*< skip >*/ + NM_ROLLBACK_RESULT_OK = 0, + NM_ROLLBACK_RESULT_ERR_NO_DEVICE = 1, + NM_ROLLBACK_RESULT_ERR_DEVICE_UNMANAGED = 2, + NM_ROLLBACK_RESULT_ERR_FAILED = 3, +} NMRollbackResult; + +/** + * NMSettingsConnectionFlags: + * @NM_SETTINGS_CONNECTION_FLAG_NONE: an alias for numeric zero, no flags set. + * @NM_SETTINGS_CONNECTION_FLAG_UNSAVED: the connection is not saved to disk. + * That either means, that the connection is in-memory only and currently + * is not backed by a file. Or, that the connection is backed by a file, + * but has modifications in-memory that were not persisted to disk. + * @NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED: A connection is "nm-generated" if + * it was generated by NetworkManger. If the connection gets modified or saved + * by the user, the flag gets cleared. A nm-generated is also unsaved + * and has no backing file as it is in-memory only. + * @NM_SETTINGS_CONNECTION_FLAG_VOLATILE: The connection will be deleted + * when it disconnects. That is for in-memory connections (unsaved), which are + * currently active but deleted on disconnect. Volatile connections are + * always unsaved, but they are also no backing file on disk and are entirely + * in-memory only. + * @NM_SETTINGS_CONNECTION_FLAG_EXTERNAL: the profile was generated to represent + * an external configuration of a networking device. Since: 1.26. + * + * Flags describing the current activation state. + * + * Since: 1.12 + **/ +typedef enum { /*< flags >*/ + NM_SETTINGS_CONNECTION_FLAG_NONE = 0, + NM_SETTINGS_CONNECTION_FLAG_UNSAVED = 0x01, + NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED = 0x02, + NM_SETTINGS_CONNECTION_FLAG_VOLATILE = 0x04, + NM_SETTINGS_CONNECTION_FLAG_EXTERNAL = 0x08, +} NMSettingsConnectionFlags; + +/** + * NMActivationStateFlags: + * @NM_ACTIVATION_STATE_FLAG_NONE: an alias for numeric zero, no flags set. + * @NM_ACTIVATION_STATE_FLAG_IS_MASTER: the device is a master. + * @NM_ACTIVATION_STATE_FLAG_IS_SLAVE: the device is a slave. + * @NM_ACTIVATION_STATE_FLAG_LAYER2_READY: layer2 is activated and ready. + * @NM_ACTIVATION_STATE_FLAG_IP4_READY: IPv4 setting is completed. + * @NM_ACTIVATION_STATE_FLAG_IP6_READY: IPv6 setting is completed. + * @NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES: The master has any slave devices attached. + * This only makes sense if the device is a master. + * @NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY: the lifetime + * of the activation is bound to the visibility of the connection profile, + * which in turn depends on "connection.permissions" and whether a session + * for the user exists. Since: 1.16. + * @NM_ACTIVATION_STATE_FLAG_EXTERNAL: the active connection was generated to + * represent an external configuration of a networking device. Since: 1.26. + * + * Flags describing the current activation state. + * + * Since: 1.10 + **/ +typedef enum { /*< flags >*/ + NM_ACTIVATION_STATE_FLAG_NONE = 0, + + NM_ACTIVATION_STATE_FLAG_IS_MASTER = 0x1, + NM_ACTIVATION_STATE_FLAG_IS_SLAVE = 0x2, + NM_ACTIVATION_STATE_FLAG_LAYER2_READY = 0x4, + NM_ACTIVATION_STATE_FLAG_IP4_READY = 0x8, + NM_ACTIVATION_STATE_FLAG_IP6_READY = 0x10, + NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES = 0x20, + NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY = 0x40, + NM_ACTIVATION_STATE_FLAG_EXTERNAL = 0x80, +} NMActivationStateFlags; + +/** + * NMSettingsAddConnection2Flags: + * @NM_SETTINGS_ADD_CONNECTION2_FLAG_NONE: an alias for numeric zero, no flags set. + * @NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK: to persist the connection to disk. + * @NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY: to make the connection in-memory only. + * @NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT: usually, when the connection + * has autoconnect enabled and gets added, it becomes eligible to autoconnect + * right away. Setting this flag, disables autoconnect until the connection + * is manually activated. + * + * Numeric flags for the "flags" argument of AddConnection2() D-Bus API. + * + * Since: 1.20 + */ +typedef enum { /*< flags >*/ + NM_SETTINGS_ADD_CONNECTION2_FLAG_NONE = 0, + NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK = 0x1, + NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY = 0x2, + NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT = 0x20, +} NMSettingsAddConnection2Flags; + +/** + * NMSettingsUpdate2Flags: + * @NM_SETTINGS_UPDATE2_FLAG_NONE: an alias for numeric zero, no flags set. + * @NM_SETTINGS_UPDATE2_FLAG_TO_DISK: to persist the connection to disk. + * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY: makes the profile in-memory. + * Note that such profiles are stored in keyfile format under /run. + * If the file is already in-memory, the file in /run is updated in-place. + * Otherwise, the previous storage for the profile is left unchanged + * on disk, and the in-memory copy shadows it. + * Note that the original filename of the previous persistent storage (if any) + * is remembered. That means, when later persisting the profile again to disk, + * the file on disk will be overwritten again. + * Likewise, when finally deleting the profile, both the storage from /run + * and persistent storage are deleted (or if the persistent storage does not + * allow deletion, and nmmeta file is written to mark the UUID as deleted). + * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED: this is almost the same + * as %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, with one difference: when later deleting + * the profile, the original profile will not be deleted. Instead a nmmeta + * file is written to /run to indicate that the profile is gone. + * Note that if such a nmmeta tombstone file exists and hides a file in persistent + * storage, then when re-adding the profile with the same UUID, then the original + * storage is taken over again. + * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY: this is like %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, + * but if the connection has a corresponding file on persistent storage, the file + * will be deleted right away. If the profile is later again persisted to disk, + * a new, unused filename will be chosen. + * @NM_SETTINGS_UPDATE2_FLAG_VOLATILE: This can be specified with either + * %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED + * or %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY. + * After making the connection in-memory only, the connection is marked + * as volatile. That means, if the connection is currently not active + * it will be deleted right away. Otherwise, it is marked to for deletion + * once the connection deactivates. A volatile connection cannot autoactivate + * again (because it's about to be deleted), but a manual activation will + * clear the volatile flag. + * @NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT: usually, when the connection + * has autoconnect enabled and is modified, it becomes eligible to autoconnect + * right away. Setting this flag, disables autoconnect until the connection + * is manually activated. + * @NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY: when a profile gets modified that is + * currently active, then these changes don't take effect for the active + * device unless the profile gets reactivated or the configuration reapplied. + * There are two exceptions: by default "connection.zone" and "connection.metered" + * properties take effect immediately. Specify this flag to prevent these + * properties to take effect, so that the change is restricted to modify + * the profile. Since: 1.20. + * + * Since: 1.12 + */ +typedef enum { /*< flags >*/ + NM_SETTINGS_UPDATE2_FLAG_NONE = 0, + NM_SETTINGS_UPDATE2_FLAG_TO_DISK = 0x1, + NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY = 0x2, + NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED = 0x4, + NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY = 0x8, + NM_SETTINGS_UPDATE2_FLAG_VOLATILE = 0x10, + NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT = 0x20, + NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY = 0x40, +} NMSettingsUpdate2Flags; + +/** + * NMTernary: + * @NM_TERNARY_DEFAULT: use the globally-configured default value. + * @NM_TERNARY_FALSE: the option is disabled. + * @NM_TERNARY_TRUE: the option is enabled. + * + * An boolean value that can be overridden by a default. + * + * Since: 1.14 + **/ +typedef enum { + NM_TERNARY_DEFAULT = -1, + NM_TERNARY_FALSE = 0, + NM_TERNARY_TRUE = 1, +} NMTernary; + +/** + * NMManagerReloadFlags: + * @NM_MANAGER_RELOAD_FLAG_NONE: an alias for numeric zero, no flags set. This + * reloads everything that is supported and is identical to a SIGHUP. + * @NM_MANAGER_RELOAD_FLAG_CONF: reload the NetworkManager.conf configuration + * from disk. Note that this does not include connections, which can be + * reloaded via Setting's ReloadConnections(). + * @NM_MANAGER_RELOAD_FLAG_DNS_RC: update DNS configuration, which usually + * involves writing /etc/resolv.conf anew. + * @NM_MANAGER_RELOAD_FLAG_DNS_FULL: means to restart the DNS plugin. This + * is for example useful when using dnsmasq plugin, which uses additional + * configuration in /etc/NetworkManager/dnsmasq.d. If you edit those files, + * you can restart the DNS plugin. This action shortly interrupts name + * resolution. + * @NM_MANAGER_RELOAD_FLAG_ALL: all flags. + * + * Flags for the manager Reload() call. + * + * Since: 1.22 + */ +typedef enum { /*< flags >*/ + NM_MANAGER_RELOAD_FLAG_NONE = 0, /*< skip >*/ + NM_MANAGER_RELOAD_FLAG_CONF = 0x1, + NM_MANAGER_RELOAD_FLAG_DNS_RC = 0x2, + NM_MANAGER_RELOAD_FLAG_DNS_FULL = 0x4, + NM_MANAGER_RELOAD_FLAG_ALL = 0x7, /*< skip >*/ +} NMManagerReloadFlags; + +/** + * NMDeviceInterfaceFlags: + * @NM_DEVICE_INTERFACE_FLAG_NONE: an alias for numeric zero, no flags set. + * @NM_DEVICE_INTERFACE_FLAG_UP: the interface is enabled from the + * administrative point of view. Corresponds to kernel IFF_UP. + * @NM_DEVICE_INTERFACE_FLAG_LOWER_UP: the physical link is up. Corresponds + * to kernel IFF_LOWER_UP. + * @NM_DEVICE_INTERFACE_FLAG_CARRIER: the interface has carrier. In most + * cases this is equal to the value of @NM_DEVICE_INTERFACE_FLAG_LOWER_UP. + * However some devices have a non-standard carrier detection mechanism. + * + * Flags for a network interface. + * + * Since: 1.22 + */ +typedef enum { /*< flags >*/ + /* kernel flags */ + NM_DEVICE_INTERFACE_FLAG_NONE = 0, /*< skip >*/ + NM_DEVICE_INTERFACE_FLAG_UP = 0x1, + NM_DEVICE_INTERFACE_FLAG_LOWER_UP = 0x2, + /* NM-specific flags */ + NM_DEVICE_INTERFACE_FLAG_CARRIER = 0x10000, +} NMDeviceInterfaceFlags; + +/** + * NMClientPermission: + * @NM_CLIENT_PERMISSION_NONE: unknown or no permission + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK: controls whether networking + * can be globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI: controls whether Wi-Fi can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN: controls whether WWAN (3G) can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX: controls whether WiMAX can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_SLEEP_WAKE: controls whether the client can ask + * NetworkManager to sleep and wake + * @NM_CLIENT_PERMISSION_NETWORK_CONTROL: controls whether networking connections + * can be started, stopped, and changed + * @NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED: controls whether a password + * protected Wi-Fi hotspot can be created + * @NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN: controls whether an open Wi-Fi hotspot + * can be created + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM: controls whether connections + * that are available to all users can be modified + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN: controls whether connections + * owned by the current user can be modified + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME: controls whether the + * persistent hostname can be changed + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS: modify persistent global + * DNS configuration + * @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload. + * @NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK: permission to create checkpoints. + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS: controls whether device + * statistics can be globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK: controls whether + * connectivity check can be enabled or disabled + * @NM_CLIENT_PERMISSION_WIFI_SCAN: controls whether wifi scans can be performed + * @NM_CLIENT_PERMISSION_LAST: a reserved boundary value + * + * #NMClientPermission values indicate various permissions that NetworkManager + * clients can obtain to perform certain tasks on behalf of the current user. + **/ +typedef enum { + NM_CLIENT_PERMISSION_NONE = 0, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 4, + NM_CLIENT_PERMISSION_SLEEP_WAKE = 5, + NM_CLIENT_PERMISSION_NETWORK_CONTROL = 6, + NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED = 7, + NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 8, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM = 9, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12, + NM_CLIENT_PERMISSION_RELOAD = 13, + NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK = 16, + NM_CLIENT_PERMISSION_WIFI_SCAN = 17, + + NM_CLIENT_PERMISSION_LAST = 17, +} NMClientPermission; + +/** + * NMClientPermissionResult: + * @NM_CLIENT_PERMISSION_RESULT_UNKNOWN: unknown or no authorization + * @NM_CLIENT_PERMISSION_RESULT_YES: the permission is available + * @NM_CLIENT_PERMISSION_RESULT_AUTH: authorization is necessary before the + * permission is available + * @NM_CLIENT_PERMISSION_RESULT_NO: permission to perform the operation is + * denied by system policy + * + * #NMClientPermissionResult values indicate what authorizations and permissions + * the user requires to obtain a given #NMClientPermission + **/ +typedef enum { + NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0, + NM_CLIENT_PERMISSION_RESULT_YES, + NM_CLIENT_PERMISSION_RESULT_AUTH, + NM_CLIENT_PERMISSION_RESULT_NO +} NMClientPermissionResult; + +#endif /* __NM_DBUS_INTERFACE_H__ */ diff --git a/src/libnm-core-public/nm-errors.h b/src/libnm-core-public/nm-errors.h new file mode 100644 index 0000000000..639c508e3e --- /dev/null +++ b/src/libnm-core-public/nm-errors.h @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2004 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_ERRORS_H__ +#define __NM_ERRORS_H__ + +/** + * NMAgentManagerError: + * @NM_AGENT_MANAGER_ERROR_FAILED: unknown or unspecified error + * @NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED: The caller does not have permission + * to register a secret agent, or is trying to register the same secret agent + * twice. + * @NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER: The identifier is not a valid + * secret agent identifier. + * @NM_AGENT_MANAGER_ERROR_NOT_REGISTERED: The caller tried to unregister an agent + * that was not registered. + * @NM_AGENT_MANAGER_ERROR_NO_SECRETS: No secret agent returned secrets for this + * request + * @NM_AGENT_MANAGER_ERROR_USER_CANCELED: The user canceled the secrets request. + * + * Errors returned from the secret-agent manager. + * + * These errors may be returned from operations that could cause secrets to be + * requested (such as nm_client_activate_connection()), and correspond to D-Bus + * errors in the "org.freedesktop.NetworkManager.AgentManager" namespace. + */ +typedef enum { + NM_AGENT_MANAGER_ERROR_FAILED = 0, /*< nick=Failed >*/ + NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/ + NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER, /*< nick=InvalidIdentifier >*/ + NM_AGENT_MANAGER_ERROR_NOT_REGISTERED, /*< nick=NotRegistered >*/ + NM_AGENT_MANAGER_ERROR_NO_SECRETS, /*< nick=NoSecrets >*/ + NM_AGENT_MANAGER_ERROR_USER_CANCELED, /*< nick=UserCanceled >*/ +} NMAgentManagerError; + +GQuark nm_agent_manager_error_quark(void); +#define NM_AGENT_MANAGER_ERROR (nm_agent_manager_error_quark()) + +/** + * NMConnectionError: + * @NM_CONNECTION_ERROR_FAILED: unknown or unclassified error + * @NM_CONNECTION_ERROR_SETTING_NOT_FOUND: the #NMConnection object + * did not contain the specified #NMSetting object + * @NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND: the #NMConnection did not contain the + * requested #NMSetting property + * @NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET: an operation which requires a secret + * was attempted on a non-secret property + * @NM_CONNECTION_ERROR_MISSING_SETTING: the #NMConnection object is missing an + * #NMSetting which is required for its configuration. The error message will + * always be prefixed with "<setting-name>: ", where "<setting-name>" is the + * name of the setting that is missing. + * @NM_CONNECTION_ERROR_INVALID_SETTING: the #NMConnection object contains an + * invalid or inappropriate #NMSetting. The error message will always be + * prefixed with "<setting-name>: ", where "<setting-name>" is the name of the + * setting that is invalid. + * @NM_CONNECTION_ERROR_MISSING_PROPERTY: the #NMConnection object is invalid + * because it is missing a required property. The error message will always be + * prefixed with "<setting-name>.<property-name>: ", where "<setting-name>" is + * the name of the setting with the missing property, and "<property-name>" is + * the property that is missing. + * @NM_CONNECTION_ERROR_INVALID_PROPERTY: the #NMConnection object is invalid + * because a property has an invalid value. The error message will always be + * prefixed with "<setting-name>.<property-name>: ", where "<setting-name>" is + * the name of the setting with the invalid property, and "<property-name>" is + * the property that is invalid. + * + * Describes errors that may result from operations involving a #NMConnection + * or its #NMSettings. + * + * These errors may be returned directly from #NMConnection and #NMSetting + * methods, or may be returned from D-Bus operations (eg on #NMClient or + * #NMDevice), where they correspond to errors in the + * "org.freedesktop.NetworkManager.Settings.Connection" namespace. + */ +typedef enum { + NM_CONNECTION_ERROR_FAILED = 0, /*< nick=Failed >*/ + NM_CONNECTION_ERROR_SETTING_NOT_FOUND, /*< nick=SettingNotFound >*/ + NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND, /*< nick=PropertyNotFound >*/ + NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, /*< nick=PropertyNotSecret >*/ + NM_CONNECTION_ERROR_MISSING_SETTING, /*< nick=MissingSetting >*/ + NM_CONNECTION_ERROR_INVALID_SETTING, /*< nick=InvalidSetting >*/ + NM_CONNECTION_ERROR_MISSING_PROPERTY, /*< nick=MissingProperty >*/ + NM_CONNECTION_ERROR_INVALID_PROPERTY, /*< nick=InvalidProperty >*/ +} NMConnectionError; + +#define NM_CONNECTION_ERROR nm_connection_error_quark() +GQuark nm_connection_error_quark(void); + +/** + * NMCryptoError: + * @NM_CRYPTO_ERROR_FAILED: generic failure + * @NM_CRYPTO_ERROR_INVALID_DATA: the certificate or key data provided + * was invalid + * @NM_CRYPTO_ERROR_INVALID_PASSWORD: the password was invalid + * @NM_CRYPTO_ERROR_UNKNOWN_CIPHER: the data uses an unknown cipher + * @NM_CRYPTO_ERROR_DECRYPTION_FAILED: decryption failed + * @NM_CRYPTO_ERROR_ENCRYPTION_FAILED: encryption failed + * + * Cryptography-related errors that can be returned from some nm-utils methods, + * and some #NMSetting8021x operations. + */ +typedef enum { + NM_CRYPTO_ERROR_FAILED = 0, + NM_CRYPTO_ERROR_INVALID_DATA, + NM_CRYPTO_ERROR_INVALID_PASSWORD, + NM_CRYPTO_ERROR_UNKNOWN_CIPHER, + NM_CRYPTO_ERROR_DECRYPTION_FAILED, + NM_CRYPTO_ERROR_ENCRYPTION_FAILED, +} NMCryptoError; + +#define NM_CRYPTO_ERROR nm_crypto_error_quark() +GQuark nm_crypto_error_quark(void); + +/** + * NMDeviceError: + * @NM_DEVICE_ERROR_FAILED: unknown or unclassified error + * @NM_DEVICE_ERROR_CREATION_FAILED: NetworkManager failed to create the device + * @NM_DEVICE_ERROR_INVALID_CONNECTION: the specified connection is not valid + * @NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION: the specified connection is not + * compatible with this device. + * @NM_DEVICE_ERROR_NOT_ACTIVE: the device does not have an active connection + * @NM_DEVICE_ERROR_NOT_SOFTWARE: the requested operation is only valid on + * software devices. + * @NM_DEVICE_ERROR_NOT_ALLOWED: the requested operation is not allowed at + * this time. + * @NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND: the "specific object" in the + * activation request (eg, the #NMAccessPoint or #NMWimaxNsp) was not + * found. + * @NM_DEVICE_ERROR_VERSION_ID_MISMATCH: the version id did not match. + * @NM_DEVICE_ERROR_MISSING_DEPENDENCIES: the requested operation could not + * be completed due to missing dependencies. + * @NM_DEVICE_ERROR_INVALID_ARGUMENT: invalid argument. Since: 1.16. + * + * Device-related errors. + * + * These errors may be returned directly from #NMDevice methods, or may be + * returned from D-Bus operations (where they correspond to errors in the + * "org.freedesktop.NetworkManager.Device" namespace). + */ +typedef enum { + NM_DEVICE_ERROR_FAILED = 0, /*< nick=Failed >*/ + NM_DEVICE_ERROR_CREATION_FAILED, /*< nick=CreationFailed >*/ + NM_DEVICE_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/ + NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, /*< nick=IncompatibleConnection >*/ + NM_DEVICE_ERROR_NOT_ACTIVE, /*< nick=NotActive >*/ + NM_DEVICE_ERROR_NOT_SOFTWARE, /*< nick=NotSoftware >*/ + NM_DEVICE_ERROR_NOT_ALLOWED, /*< nick=NotAllowed >*/ + NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, /*< nick=SpecificObjectNotFound >*/ + NM_DEVICE_ERROR_VERSION_ID_MISMATCH, /*< nick=VersionIdMismatch >*/ + NM_DEVICE_ERROR_MISSING_DEPENDENCIES, /*< nick=MissingDependencies >*/ + NM_DEVICE_ERROR_INVALID_ARGUMENT, /*< nick=InvalidArgument >*/ +} NMDeviceError; + +#define NM_DEVICE_ERROR nm_device_error_quark() +GQuark nm_device_error_quark(void); + +/** + * NMManagerError: + * @NM_MANAGER_ERROR_FAILED: unknown or unclassified error + * @NM_MANAGER_ERROR_PERMISSION_DENIED: Permission denied. + * @NM_MANAGER_ERROR_UNKNOWN_CONNECTION: The requested connection is not known. + * @NM_MANAGER_ERROR_UNKNOWN_DEVICE: The requested device is not known. + * @NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE: The requested connection cannot be + * activated at this time. + * @NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE: The request could not be completed + * because a required connection is not active. + * @NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE: The connection to be activated was + * already active on another device. + * @NM_MANAGER_ERROR_DEPENDENCY_FAILED: An activation request failed due to a + * dependency being unavailable. + * @NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE: The manager is already in the requested + * sleep/wake state. + * @NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED: The network is already + * enabled/disabled. + * @NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL: Unknown log level in SetLogging + * @NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN: Unknown log domain in SetLogging + * @NM_MANAGER_ERROR_INVALID_ARGUMENTS: Invalid arguments for D-Bus request + * @NM_MANAGER_ERROR_MISSING_PLUGIN: A plug-in was needed to complete the + * activation but is not available. + * + * Errors related to the main "network management" interface of NetworkManager. + * These may be returned from #NMClient methods that invoke D-Bus operations on + * the "org.freedesktop.NetworkManager" interface, and correspond to D-Bus + * errors in that namespace. + */ +typedef enum { + NM_MANAGER_ERROR_FAILED = 0, /*< nick=Failed >*/ + NM_MANAGER_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/ + NM_MANAGER_ERROR_UNKNOWN_CONNECTION, /*< nick=UnknownConnection >*/ + NM_MANAGER_ERROR_UNKNOWN_DEVICE, /*< nick=UnknownDevice >*/ + NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE, /*< nick=ConnectionNotAvailable >*/ + NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, /*< nick=ConnectionNotActive >*/ + NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, /*< nick=ConnectionAlreadyActive >*/ + NM_MANAGER_ERROR_DEPENDENCY_FAILED, /*< nick=DependencyFailed >*/ + NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE, /*< nick=AlreadyAsleepOrAwake >*/ + NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, /*< nick=AlreadyEnabledOrDisabled >*/ + NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL, /*< nick=UnknownLogLevel >*/ + NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN, /*< nick=UnknownLogDomain >*/ + NM_MANAGER_ERROR_INVALID_ARGUMENTS, /*< nick=InvalidArguments >*/ + NM_MANAGER_ERROR_MISSING_PLUGIN, /*< nick=MissingPlugin >*/ +} NMManagerError; + +GQuark nm_manager_error_quark(void); +#define NM_MANAGER_ERROR (nm_manager_error_quark()) + +/** + * NMSecretAgentError: + * @NM_SECRET_AGENT_ERROR_FAILED: unknown or unclassified error + * @NM_SECRET_AGENT_ERROR_PERMISSION_DENIED: the caller (ie, NetworkManager) is + * not authorized to make this request + * @NM_SECRET_AGENT_ERROR_INVALID_CONNECTION: the connection for which secrets + * were requested is invalid + * @NM_SECRET_AGENT_ERROR_USER_CANCELED: the request was canceled by the user + * @NM_SECRET_AGENT_ERROR_AGENT_CANCELED: the agent canceled the request + * because it was requested to do so by NetworkManager + * @NM_SECRET_AGENT_ERROR_NO_SECRETS: the agent cannot find any secrets for this + * connection + * + * #NMSecretAgentError values are passed by secret agents back to NetworkManager + * when they encounter problems retrieving secrets on behalf of NM. They + * correspond to errors in the "org.freedesktop.NetworkManager.SecretManager" + * namespace. + * + * Client APIs such as nm_client_activate_connection() will not see these error + * codes; instead, the secret agent manager will translate them to the + * corresponding #NMAgentManagerError codes. + */ +typedef enum { + NM_SECRET_AGENT_ERROR_FAILED = 0, /*< nick=Failed >*/ + NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/ + NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/ + NM_SECRET_AGENT_ERROR_USER_CANCELED, /*< nick=UserCanceled >*/ + NM_SECRET_AGENT_ERROR_AGENT_CANCELED, /*< nick=AgentCanceled >*/ + NM_SECRET_AGENT_ERROR_NO_SECRETS, /*< nick=NoSecrets >*/ +} NMSecretAgentError; + +GQuark nm_secret_agent_error_quark(void); +#define NM_SECRET_AGENT_ERROR (nm_secret_agent_error_quark()) + +/** + * NMSettingsError: + * @NM_SETTINGS_ERROR_FAILED: unknown or unclassified error + * @NM_SETTINGS_ERROR_PERMISSION_DENIED: permission denied + * @NM_SETTINGS_ERROR_NOT_SUPPORTED: the requested operation is not supported by any + * active settings backend + * @NM_SETTINGS_ERROR_INVALID_CONNECTION: the connection was invalid + * @NM_SETTINGS_ERROR_READ_ONLY_CONNECTION: attempted to modify a read-only connection + * @NM_SETTINGS_ERROR_UUID_EXISTS: a connection with that UUID already exists + * @NM_SETTINGS_ERROR_INVALID_HOSTNAME: attempted to set an invalid hostname + * @NM_SETTINGS_ERROR_INVALID_ARGUMENTS: invalid arguments + * + * Errors related to the settings/persistent configuration interface of + * NetworkManager. + * + * These may be returned from #NMClient methods that invoke D-Bus operations on + * the "org.freedesktop.NetworkManager.Settings" interface, and correspond to + * D-Bus errors in that namespace. + */ +typedef enum { + NM_SETTINGS_ERROR_FAILED = 0, /*< nick=Failed >*/ + NM_SETTINGS_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/ + NM_SETTINGS_ERROR_NOT_SUPPORTED, /*< nick=NotSupported >*/ + NM_SETTINGS_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/ + NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, /*< nick=ReadOnlyConnection >*/ + NM_SETTINGS_ERROR_UUID_EXISTS, /*< nick=UuidExists >*/ + NM_SETTINGS_ERROR_INVALID_HOSTNAME, /*< nick=InvalidHostname >*/ + NM_SETTINGS_ERROR_INVALID_ARGUMENTS, /*< nick=InvalidArguments >*/ +} NMSettingsError; + +GQuark nm_settings_error_quark(void); +#define NM_SETTINGS_ERROR (nm_settings_error_quark()) + +/** + * NMVpnPluginError: + * @NM_VPN_PLUGIN_ERROR_FAILED: unknown or unclassified error + * @NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS: the plugin is already starting, + * and another connect request was received + * @NM_VPN_PLUGIN_ERROR_ALREADY_STARTED: the plugin is already connected, and + * another connect request was received + * @NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS: the plugin is already stopping, + * and another stop request was received + * @NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED: the plugin is already stopped, and + * another disconnect request was received + * @NM_VPN_PLUGIN_ERROR_WRONG_STATE: the operation could not be performed in + * this state + * @NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS: the operation could not be performed as + * the request contained malformed arguments, or arguments of unexpected type. + * Usually means that one of the VPN setting data items or secrets was not of + * the expected type (ie int, string, bool, etc). + * @NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED: a child process failed to launch + * @NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION: the operation could not be performed + * because the connection was invalid. Usually means that the connection's + * VPN setting was missing some required data item or secret. + * @NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED: the operation could not be + * performed as the plugin does not support interactive operations, such as + * ConnectInteractive() or NewSecrets() + * + * Returned by the VPN service plugin to indicate errors. These codes correspond + * to errors in the "org.freedesktop.NetworkManager.VPN.Error" namespace. + **/ +typedef enum { + NM_VPN_PLUGIN_ERROR_FAILED, /*< nick=Failed >*/ + NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, /*< nick=StartingInProgress >*/ + NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, /*< nick=AlreadyStarted >*/ + NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, /*< nick=StoppingInProgress >*/ + NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, /*< nick=AlreadyStopped >*/ + NM_VPN_PLUGIN_ERROR_WRONG_STATE, /*< nick=WrongState >*/ + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, /*< nick=BadArguments >*/ + NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, /*< nick=LaunchFailed >*/ + NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/ + NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, /*< nick=InteractiveNotSupported >*/ +} NMVpnPluginError; + +#define NM_VPN_PLUGIN_ERROR (nm_vpn_plugin_error_quark()) +GQuark nm_vpn_plugin_error_quark(void); + +#endif /* __NM_ERRORS_H__ */ diff --git a/src/libnm-core-public/nm-keyfile.h b/src/libnm-core-public/nm-keyfile.h new file mode 100644 index 0000000000..28c052f999 --- /dev/null +++ b/src/libnm-core-public/nm-keyfile.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#ifndef __NM_KEYFILE_H__ +#define __NM_KEYFILE_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-core-types.h" + +G_BEGIN_DECLS + +/** + * NMKeyfileHandlerFlags: + * @NM_KEYFILE_HANDLER_FLAGS_NONE: no flags set. + * + * Flags for customizing nm_keyfile_read() and nm_keyfile_write(). + * + * Currently no flags are implemented. + * + * Since: 1.30 + */ +typedef enum { /*< flags >*/ + NM_KEYFILE_HANDLER_FLAGS_NONE = 0, +} NMKeyfileHandlerFlags; + +/** + * NMKeyfileHandlerType: + * @NM_KEYFILE_HANDLER_TYPE_WARN: a warning. + * @NM_KEYFILE_HANDLER_TYPE_WRITE_CERT: for handling certificates while writing + * a connection to keyfile. + * + * The type of the callback for %NMKeyfileReadHandler and %NMKeyfileWriteHandler. + * Depending on the type, you can interpret %NMKeyfileHandlerData. + * + * Since: 1.30 + */ +typedef enum { + NM_KEYFILE_HANDLER_TYPE_WARN = 1, + NM_KEYFILE_HANDLER_TYPE_WRITE_CERT = 2, +} NMKeyfileHandlerType; + +/** + * NMKeyfileHandlerData: + * + * Opaque type with parameters for the callback. The actual content + * depends on the %NMKeyfileHandlerType. + * + * Since: 1.30 + */ +typedef struct _NMKeyfileHandlerData NMKeyfileHandlerData; + +/** + * NMKeyfileReadHandler: + * @keyfile: the #GKeyFile that is currently read + * @connection: the #NMConnection that is being constructed. + * @handler_type: the %NMKeyfileHandlerType that indicates which type + * the request is. + * @handler_data: the #NMKeyfileHandlerData. What you can do with it + * depends on the @handler_type. + * @user_data: the user-data argument to nm_keyfile_read(). + * + * Hook to nm_keyfile_read(). + * + * The callee may abort the reading by setting an error via nm_keyfile_handler_data_fail_with_error(). + * + * Returns: the callee should return TRUE, if the event was handled and/or recognized. + * Otherwise, a default action will be performed that depends on the @type. + * For %NM_KEYFILE_HANDLER_TYPE_WARN type, the default action is doing nothing. + * + * Since: 1.30 + */ +typedef gboolean (*NMKeyfileReadHandler)(GKeyFile * keyfile, + NMConnection * connection, + NMKeyfileHandlerType handler_type, + NMKeyfileHandlerData *handler_data, + void * user_data); + +NM_AVAILABLE_IN_1_30 +NMConnection *nm_keyfile_read(GKeyFile * keyfile, + const char * base_dir, + NMKeyfileHandlerFlags handler_flags, + NMKeyfileReadHandler handler, + void * user_data, + GError ** error); + +/** + * NMKeyfileWriteHandler: + * @connection: the #NMConnection that is currently written. + * @keyfile: the #GKeyFile that is currently constructed. + * @handler_type: the %NMKeyfileHandlerType that indicates which type + * the request is. + * @handler_data: the #NMKeyfileHandlerData. What you can do with it + * depends on the @handler_type. + * @user_data: the user-data argument to nm_keyfile_read(). + * + * This is a hook to tweak the serialization. + * + * Handler for certain properties or events that are not entirely contained + * within the keyfile or that might be serialized differently. The @type and + * @handler_data arguments tell which kind of argument we have at hand. + * + * Currently only the type %NM_KEYFILE_HANDLER_TYPE_WRITE_CERT is supported. + * + * The callee may call nm_keyfile_handler_data_fail_with_error() to abort + * the writing with error. + * + * Returns: the callee should return %TRUE if the event was handled. If the + * event was unhandled, a default action will be performed that depends on + * the @handler_type. + * + * Since: 1.30 + */ +typedef gboolean (*NMKeyfileWriteHandler)(NMConnection * connection, + GKeyFile * keyfile, + NMKeyfileHandlerType handler_type, + NMKeyfileHandlerData *handler_data, + void * user_data); + +NM_AVAILABLE_IN_1_30 +GKeyFile *nm_keyfile_write(NMConnection * connection, + NMKeyfileHandlerFlags handler_flags, + NMKeyfileWriteHandler handler, + void * user_data, + GError ** error); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_30 +void nm_keyfile_handler_data_fail_with_error(NMKeyfileHandlerData *handler_data, GError *src); + +NM_AVAILABLE_IN_1_30 +void nm_keyfile_handler_data_get_context(const NMKeyfileHandlerData *handler_data, + const char ** out_kf_group_name, + const char ** out_kf_key_name, + NMSetting ** out_cur_setting, + const char ** out_cur_property_name); + +/** + * NMKeyfileWarnSeverity: + * @NM_KEYFILE_WARN_SEVERITY_DEBUG: debug message + * @NM_KEYFILE_WARN_SEVERITY_INFO: info message + * @NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE: info message about a missing file + * @NM_KEYFILE_WARN_SEVERITY_WARN: a warning message + * + * The severity level of %NM_KEYFILE_HANDLER_TYPE_WARN events. + * + * Since: 1.30 + */ +typedef enum { + NM_KEYFILE_WARN_SEVERITY_DEBUG = 1000, + NM_KEYFILE_WARN_SEVERITY_INFO = 2000, + NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE = 2901, + NM_KEYFILE_WARN_SEVERITY_WARN = 3000, +} NMKeyfileWarnSeverity; + +NM_AVAILABLE_IN_1_30 +void nm_keyfile_handler_data_warn_get(const NMKeyfileHandlerData *handler_data, + const char ** out_message, + NMKeyfileWarnSeverity * out_severity); + +G_END_DECLS + +#endif /* __NM_KEYFILE_H__ */ diff --git a/src/libnm-core-public/nm-setting-6lowpan.h b/src/libnm-core-public/nm-setting-6lowpan.h new file mode 100644 index 0000000000..5a7c39866b --- /dev/null +++ b/src/libnm-core-public/nm-setting-6lowpan.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_6LOWPAN_H__ +#define __NM_SETTING_6LOWPAN_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_6LOWPAN (nm_setting_6lowpan_get_type()) +#define NM_SETTING_6LOWPAN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_6LOWPAN, NMSetting6Lowpan)) +#define NM_SETTING_6LOWPAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_6LOWPANCONFIG, NMSetting6LowpanClass)) +#define NM_IS_SETTING_6LOWPAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_6LOWPAN)) +#define NM_IS_SETTING_6LOWPAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_6LOWPAN)) +#define NM_SETTING_6LOWPAN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanClass)) + +#define NM_SETTING_6LOWPAN_SETTING_NAME "6lowpan" + +#define NM_SETTING_6LOWPAN_PARENT "parent" + +typedef struct _NMSetting6LowpanClass NMSetting6LowpanClass; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_6lowpan_get_type(void); +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_6lowpan_new(void); + +NM_AVAILABLE_IN_1_14 +const char *nm_setting_6lowpan_get_parent(NMSetting6Lowpan *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_6LOWPAN_H__ */ diff --git a/src/libnm-core-public/nm-setting-8021x.h b/src/libnm-core-public/nm-setting-8021x.h new file mode 100644 index 0000000000..30b725be59 --- /dev/null +++ b/src/libnm-core-public/nm-setting-8021x.h @@ -0,0 +1,366 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_8021X_H__ +#define __NM_SETTING_8021X_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH "file://" +#define NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11 "pkcs11:" + +/** + * NMSetting8021xCKFormat: + * @NM_SETTING_802_1X_CK_FORMAT_UNKNOWN: unknown file format + * @NM_SETTING_802_1X_CK_FORMAT_X509: file contains an X.509 format certificate + * @NM_SETTING_802_1X_CK_FORMAT_RAW_KEY: file contains an old-style OpenSSL PEM + * or DER private key + * @NM_SETTING_802_1X_CK_FORMAT_PKCS12: file contains a PKCS#12 certificate + * and private key + * + * #NMSetting8021xCKFormat values indicate the general type of a certificate + * or private key + */ +typedef enum { /*< underscore_name=nm_setting_802_1x_ck_format >*/ + NM_SETTING_802_1X_CK_FORMAT_UNKNOWN = 0, + NM_SETTING_802_1X_CK_FORMAT_X509, + NM_SETTING_802_1X_CK_FORMAT_RAW_KEY, + NM_SETTING_802_1X_CK_FORMAT_PKCS12 +} NMSetting8021xCKFormat; + +/** + * NMSetting8021xCKScheme: + * @NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: unknown certificate or private key + * scheme + * @NM_SETTING_802_1X_CK_SCHEME_BLOB: certificate or key is stored as the raw + * item data + * @NM_SETTING_802_1X_CK_SCHEME_PATH: certificate or key is stored as a path + * to a file containing the certificate or key data + * @NM_SETTING_802_1X_CK_SCHEME_PKCS11: certificate or key is stored as a + * URI of an object on a PKCS#11 token + * + * #NMSetting8021xCKScheme values indicate how a certificate or private key is + * stored in the setting properties, either as a blob of the item's data, or as + * a path to a certificate or private key file on the filesystem + */ +typedef enum { /*< underscore_name=nm_setting_802_1x_ck_scheme >*/ + NM_SETTING_802_1X_CK_SCHEME_UNKNOWN = 0, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + NM_SETTING_802_1X_CK_SCHEME_PATH, + NM_SETTING_802_1X_CK_SCHEME_PKCS11, +} NMSetting8021xCKScheme; + +/** + * NMSetting8021xAuthFlags: + * @NM_SETTING_802_1X_AUTH_FLAGS_NONE: No flags + * @NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE: Disable TLSv1.0 + * @NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE: Disable TLSv1.1 + * @NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_2_DISABLE: Disable TLSv1.2 + * @NM_SETTING_802_1X_AUTH_FLAGS_ALL: All supported flags + * + * #NMSetting8021xAuthFlags values indicate which authentication settings + * should be used. + * + * Before 1.22, this was wrongly marked as a enum and not as a flags + * type. + * + * Since: 1.8 + */ +typedef enum { /*< flags, underscore_name=nm_setting_802_1x_auth_flags >*/ + NM_SETTING_802_1X_AUTH_FLAGS_NONE = 0, + NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE = 0x1, + NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE = 0x2, + NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_2_DISABLE = 0x4, + + NM_SETTING_802_1X_AUTH_FLAGS_ALL = 0x7, +} NMSetting8021xAuthFlags; + +#define NM_TYPE_SETTING_802_1X (nm_setting_802_1x_get_type()) +#define NM_SETTING_802_1X(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_802_1X, NMSetting8021x)) +#define NM_SETTING_802_1X_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_802_1X, NMSetting8021xClass)) +#define NM_IS_SETTING_802_1X(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_802_1X)) +#define NM_IS_SETTING_802_1X_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_802_1X)) +#define NM_SETTING_802_1X_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_802_1X, NMSetting8021xClass)) + +#define NM_SETTING_802_1X_SETTING_NAME "802-1x" + +#define NM_SETTING_802_1X_EAP "eap" +#define NM_SETTING_802_1X_IDENTITY "identity" +#define NM_SETTING_802_1X_ANONYMOUS_IDENTITY "anonymous-identity" +#define NM_SETTING_802_1X_PAC_FILE "pac-file" +#define NM_SETTING_802_1X_CA_CERT "ca-cert" +#define NM_SETTING_802_1X_CA_CERT_PASSWORD "ca-cert-password" +#define NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS "ca-cert-password-flags" +#define NM_SETTING_802_1X_CA_PATH "ca-path" +#define NM_SETTING_802_1X_SUBJECT_MATCH "subject-match" +#define NM_SETTING_802_1X_ALTSUBJECT_MATCHES "altsubject-matches" +#define NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH "domain-suffix-match" +#define NM_SETTING_802_1X_DOMAIN_MATCH "domain-match" +#define NM_SETTING_802_1X_CLIENT_CERT "client-cert" +#define NM_SETTING_802_1X_CLIENT_CERT_PASSWORD "client-cert-password" +#define NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS "client-cert-password-flags" +#define NM_SETTING_802_1X_PHASE1_PEAPVER "phase1-peapver" +#define NM_SETTING_802_1X_PHASE1_PEAPLABEL "phase1-peaplabel" +#define NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING "phase1-fast-provisioning" +#define NM_SETTING_802_1X_PHASE1_AUTH_FLAGS "phase1-auth-flags" +#define NM_SETTING_802_1X_PHASE2_AUTH "phase2-auth" +#define NM_SETTING_802_1X_PHASE2_AUTHEAP "phase2-autheap" +#define NM_SETTING_802_1X_PHASE2_CA_CERT "phase2-ca-cert" +#define NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD "phase2-ca-cert-password" +#define NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS "phase2-ca-cert-password-flags" +#define NM_SETTING_802_1X_PHASE2_CA_PATH "phase2-ca-path" +#define NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH "phase2-subject-match" +#define NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES "phase2-altsubject-matches" +#define NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH "phase2-domain-suffix-match" +#define NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH "phase2-domain-match" +#define NM_SETTING_802_1X_PHASE2_CLIENT_CERT "phase2-client-cert" +#define NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD "phase2-client-cert-password" +#define NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS "phase2-client-cert-password-flags" +#define NM_SETTING_802_1X_PASSWORD "password" +#define NM_SETTING_802_1X_PASSWORD_FLAGS "password-flags" +#define NM_SETTING_802_1X_PASSWORD_RAW "password-raw" +#define NM_SETTING_802_1X_PASSWORD_RAW_FLAGS "password-raw-flags" +#define NM_SETTING_802_1X_PRIVATE_KEY "private-key" +#define NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD "private-key-password" +#define NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS "private-key-password-flags" +#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY "phase2-private-key" +#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD "phase2-private-key-password" +#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS "phase2-private-key-password-flags" +#define NM_SETTING_802_1X_PIN "pin" +#define NM_SETTING_802_1X_PIN_FLAGS "pin-flags" +#define NM_SETTING_802_1X_SYSTEM_CA_CERTS "system-ca-certs" +#define NM_SETTING_802_1X_AUTH_TIMEOUT "auth-timeout" +#define NM_SETTING_802_1X_OPTIONAL "optional" + +/* PRIVATE KEY NOTE: when setting PKCS#12 private keys directly via properties + * using the "blob" scheme, the data must be passed in PKCS#12 binary format. + * In this case, the appropriate "client-cert" (or "phase2-client-cert") + * property of the NMSetting8021x object must also contain the exact same + * PKCS#12 binary data that the private key does. This is because the + * PKCS#12 file contains both the private key and client certificate, so both + * properties need to be set to the same thing. When using the "path" scheme, + * just set both the private-key and client-cert properties to the same path. + * + * When setting OpenSSL-derived "traditional" format (ie S/MIME style, not + * PKCS#8) RSA and DSA keys directly via properties with the "blob" scheme, they + * should be passed to NetworkManager in PEM format with the "DEK-Info" and + * "Proc-Type" tags intact. Decrypted private keys should not be used as this + * is insecure and could allow unprivileged users to access the decrypted + * private key data. + * + * When using the "path" scheme, just set the private-key and client-cert + * properties to the paths to their respective objects. + */ + +/** + * NMSetting8021x: + * + * IEEE 802.1x Authentication Settings + */ +struct _NMSetting8021x { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSetting8021xClass; + +GType nm_setting_802_1x_get_type(void); + +NMSetting *nm_setting_802_1x_new(void); + +NM_AVAILABLE_IN_1_2 +NMSetting8021xCKScheme +nm_setting_802_1x_check_cert_scheme(gconstpointer pdata, gsize length, GError **error); + +guint32 nm_setting_802_1x_get_num_eap_methods(NMSetting8021x *setting); +const char *nm_setting_802_1x_get_eap_method(NMSetting8021x *setting, guint32 i); +gboolean nm_setting_802_1x_add_eap_method(NMSetting8021x *setting, const char *eap); +void nm_setting_802_1x_remove_eap_method(NMSetting8021x *setting, guint32 i); +gboolean nm_setting_802_1x_remove_eap_method_by_value(NMSetting8021x *setting, const char *eap); +void nm_setting_802_1x_clear_eap_methods(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_identity(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_anonymous_identity(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_pac_file(NMSetting8021x *setting); + +gboolean nm_setting_802_1x_get_system_ca_certs(NMSetting8021x *setting); +const char *nm_setting_802_1x_get_ca_path(NMSetting8021x *setting); +const char *nm_setting_802_1x_get_phase2_ca_path(NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_ca_cert_scheme(NMSetting8021x *setting); +GBytes * nm_setting_802_1x_get_ca_cert_blob(NMSetting8021x *setting); +const char * nm_setting_802_1x_get_ca_cert_path(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_802_1x_get_ca_cert_uri(NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_ca_cert(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error); + +NM_AVAILABLE_IN_1_8 +const char *nm_setting_802_1x_get_ca_cert_password(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_8 +NMSettingSecretFlags nm_setting_802_1x_get_ca_cert_password_flags(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_subject_match(NMSetting8021x *setting); + +guint32 nm_setting_802_1x_get_num_altsubject_matches(NMSetting8021x *setting); +const char *nm_setting_802_1x_get_altsubject_match(NMSetting8021x *setting, guint32 i); +gboolean nm_setting_802_1x_add_altsubject_match(NMSetting8021x *setting, + const char * altsubject_match); +void nm_setting_802_1x_remove_altsubject_match(NMSetting8021x *setting, guint32 i); +gboolean nm_setting_802_1x_remove_altsubject_match_by_value(NMSetting8021x *setting, + const char * altsubject_match); +void nm_setting_802_1x_clear_altsubject_matches(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_802_1x_get_domain_suffix_match(NMSetting8021x *setting); + +NM_AVAILABLE_IN_1_24 +const char *nm_setting_802_1x_get_domain_match(NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme(NMSetting8021x *setting); +GBytes * nm_setting_802_1x_get_client_cert_blob(NMSetting8021x *setting); +const char * nm_setting_802_1x_get_client_cert_path(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_802_1x_get_client_cert_uri(NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_client_cert(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error); + +NM_AVAILABLE_IN_1_8 +const char *nm_setting_802_1x_get_client_cert_password(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_8 +NMSettingSecretFlags nm_setting_802_1x_get_client_cert_password_flags(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_phase1_peapver(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_phase1_peaplabel(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_phase1_fast_provisioning(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_phase2_auth(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_phase2_autheap(NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_ca_cert_scheme(NMSetting8021x *setting); +GBytes * nm_setting_802_1x_get_phase2_ca_cert_blob(NMSetting8021x *setting); +const char * nm_setting_802_1x_get_phase2_ca_cert_path(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_802_1x_get_phase2_ca_cert_uri(NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_ca_cert(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error); + +NM_AVAILABLE_IN_1_8 +const char *nm_setting_802_1x_get_phase2_ca_cert_password(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_8 +NMSettingSecretFlags nm_setting_802_1x_get_phase2_ca_cert_password_flags(NMSetting8021x *setting); + +const char *nm_setting_802_1x_get_phase2_subject_match(NMSetting8021x *setting); + +guint32 nm_setting_802_1x_get_num_phase2_altsubject_matches(NMSetting8021x *setting); +const char *nm_setting_802_1x_get_phase2_altsubject_match(NMSetting8021x *setting, guint32 i); +gboolean nm_setting_802_1x_add_phase2_altsubject_match(NMSetting8021x *setting, + const char * phase2_altsubject_match); +void nm_setting_802_1x_remove_phase2_altsubject_match(NMSetting8021x *setting, guint32 i); +gboolean + nm_setting_802_1x_remove_phase2_altsubject_match_by_value(NMSetting8021x *setting, + const char * phase2_altsubject_match); +void nm_setting_802_1x_clear_phase2_altsubject_matches(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_802_1x_get_phase2_domain_suffix_match(NMSetting8021x *setting); + +NM_AVAILABLE_IN_1_24 +const char *nm_setting_802_1x_get_phase2_domain_match(NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme(NMSetting8021x *setting); +GBytes * nm_setting_802_1x_get_phase2_client_cert_blob(NMSetting8021x *setting); +const char * nm_setting_802_1x_get_phase2_client_cert_path(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_802_1x_get_phase2_client_cert_uri(NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_client_cert(NMSetting8021x * setting, + const char * value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error); + +NM_AVAILABLE_IN_1_8 +const char *nm_setting_802_1x_get_phase2_client_cert_password(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_8 +NMSettingSecretFlags +nm_setting_802_1x_get_phase2_client_cert_password_flags(NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_password(NMSetting8021x *setting); +NMSettingSecretFlags nm_setting_802_1x_get_password_flags(NMSetting8021x *setting); +GBytes * nm_setting_802_1x_get_password_raw(NMSetting8021x *setting); +NMSettingSecretFlags nm_setting_802_1x_get_password_raw_flags(NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_pin(NMSetting8021x *setting); +NMSettingSecretFlags nm_setting_802_1x_get_pin_flags(NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_private_key_scheme(NMSetting8021x *setting); +GBytes * nm_setting_802_1x_get_private_key_blob(NMSetting8021x *setting); +const char * nm_setting_802_1x_get_private_key_path(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_6 +const char * nm_setting_802_1x_get_private_key_uri(NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_private_key(NMSetting8021x * setting, + const char * value, + const char * password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error); +const char * nm_setting_802_1x_get_private_key_password(NMSetting8021x *setting); +NMSettingSecretFlags nm_setting_802_1x_get_private_key_password_flags(NMSetting8021x *setting); + +NMSetting8021xCKFormat nm_setting_802_1x_get_private_key_format(NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_private_key_scheme(NMSetting8021x *setting); +GBytes * nm_setting_802_1x_get_phase2_private_key_blob(NMSetting8021x *setting); +const char * nm_setting_802_1x_get_phase2_private_key_path(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_802_1x_get_phase2_private_key_uri(NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_private_key(NMSetting8021x * setting, + const char * value, + const char * password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError ** error); +const char *nm_setting_802_1x_get_phase2_private_key_password(NMSetting8021x *setting); +NMSettingSecretFlags +nm_setting_802_1x_get_phase2_private_key_password_flags(NMSetting8021x *setting); + +NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format(NMSetting8021x *setting); + +NM_AVAILABLE_IN_1_8 +NMSetting8021xAuthFlags nm_setting_802_1x_get_phase1_auth_flags(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_8 +int nm_setting_802_1x_get_auth_timeout(NMSetting8021x *setting); +NM_AVAILABLE_IN_1_22 +gboolean nm_setting_802_1x_get_optional(NMSetting8021x *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_8021X_H__ */ diff --git a/src/libnm-core-public/nm-setting-adsl.h b/src/libnm-core-public/nm-setting-adsl.h new file mode 100644 index 0000000000..3d8e99c9f1 --- /dev/null +++ b/src/libnm-core-public/nm-setting-adsl.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2008 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_ADSL_H__ +#define __NM_SETTING_ADSL_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_ADSL (nm_setting_adsl_get_type()) +#define NM_SETTING_ADSL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_ADSL, NMSettingAdsl)) +#define NM_SETTING_ADSL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_ADSL, NMSettingAdslClass)) +#define NM_IS_SETTING_ADSL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_ADSL)) +#define NM_IS_SETTING_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_ADSL)) +#define NM_SETTING_ADSL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_ADSL, NMSettingAdslClass)) + +#define NM_SETTING_ADSL_SETTING_NAME "adsl" + +#define NM_SETTING_ADSL_USERNAME "username" +#define NM_SETTING_ADSL_PASSWORD "password" +#define NM_SETTING_ADSL_PASSWORD_FLAGS "password-flags" +#define NM_SETTING_ADSL_PROTOCOL "protocol" +#define NM_SETTING_ADSL_ENCAPSULATION "encapsulation" +#define NM_SETTING_ADSL_VPI "vpi" +#define NM_SETTING_ADSL_VCI "vci" + +#define NM_SETTING_ADSL_PROTOCOL_PPPOA "pppoa" +#define NM_SETTING_ADSL_PROTOCOL_PPPOE "pppoe" +#define NM_SETTING_ADSL_PROTOCOL_IPOATM "ipoatm" + +#define NM_SETTING_ADSL_ENCAPSULATION_VCMUX "vcmux" +#define NM_SETTING_ADSL_ENCAPSULATION_LLC "llc" + +/** + * NMSettingAdsl: + * + * ADSL Settings + */ +struct _NMSettingAdsl { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingAdslClass; + +GType nm_setting_adsl_get_type(void); + +NMSetting * nm_setting_adsl_new(void); +const char * nm_setting_adsl_get_username(NMSettingAdsl *setting); +const char * nm_setting_adsl_get_password(NMSettingAdsl *setting); +const char * nm_setting_adsl_get_protocol(NMSettingAdsl *setting); +const char * nm_setting_adsl_get_encapsulation(NMSettingAdsl *setting); +guint32 nm_setting_adsl_get_vpi(NMSettingAdsl *setting); +guint32 nm_setting_adsl_get_vci(NMSettingAdsl *setting); +NMSettingSecretFlags nm_setting_adsl_get_password_flags(NMSettingAdsl *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_ADSL_H__ */ diff --git a/src/libnm-core-public/nm-setting-bluetooth.h b/src/libnm-core-public/nm-setting-bluetooth.h new file mode 100644 index 0000000000..4f001ef7fe --- /dev/null +++ b/src/libnm-core-public/nm-setting-bluetooth.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2009 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_BLUETOOTH_H__ +#define __NM_SETTING_BLUETOOTH_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_BLUETOOTH (nm_setting_bluetooth_get_type()) +#define NM_SETTING_BLUETOOTH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetooth)) +#define NM_SETTING_BLUETOOTH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothClass)) +#define NM_IS_SETTING_BLUETOOTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_BLUETOOTH)) +#define NM_IS_SETTING_BLUETOOTH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_BLUETOOTH)) +#define NM_SETTING_BLUETOOTH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothClass)) + +#define NM_SETTING_BLUETOOTH_SETTING_NAME "bluetooth" + +#define NM_SETTING_BLUETOOTH_BDADDR "bdaddr" +#define NM_SETTING_BLUETOOTH_TYPE "type" + +/** + * NM_SETTING_BLUETOOTH_TYPE_DUN: + * + * Connection type describing a connection to devices that support the Bluetooth + * DUN profile. + */ +#define NM_SETTING_BLUETOOTH_TYPE_DUN "dun" + +/** + * NM_SETTING_BLUETOOTH_TYPE_PANU: + * + * Connection type describing PANU connection to a Bluetooth NAP (Network + * Access Point). + */ +#define NM_SETTING_BLUETOOTH_TYPE_PANU "panu" + +/** + * NM_SETTING_BLUETOOTH_TYPE_NAP: + * + * Connection type describing a Bluetooth NAP (Network Access Point), + * which accepts PANU clients. + */ +#define NM_SETTING_BLUETOOTH_TYPE_NAP "nap" + +/** + * NMSettingBluetooth: + * + * Bluetooth Settings + */ +struct _NMSettingBluetooth { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingBluetoothClass; + +GType nm_setting_bluetooth_get_type(void); + +NMSetting * nm_setting_bluetooth_new(void); +const char *nm_setting_bluetooth_get_bdaddr(NMSettingBluetooth *setting); +const char *nm_setting_bluetooth_get_connection_type(NMSettingBluetooth *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_BLUETOOTH_H__ */ diff --git a/src/libnm-core-public/nm-setting-bond.h b/src/libnm-core-public/nm-setting-bond.h new file mode 100644 index 0000000000..25ae8c36e7 --- /dev/null +++ b/src/libnm-core-public/nm-setting-bond.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2013 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_BOND_H__ +#define __NM_SETTING_BOND_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_BOND (nm_setting_bond_get_type()) +#define NM_SETTING_BOND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_BOND, NMSettingBond)) +#define NM_SETTING_BOND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_BOND, NMSettingBondClass)) +#define NM_IS_SETTING_BOND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_BOND)) +#define NM_IS_SETTING_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_BOND)) +#define NM_SETTING_BOND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_BOND, NMSettingBondClass)) + +#define NM_SETTING_BOND_SETTING_NAME "bond" + +#define NM_SETTING_BOND_OPTIONS "options" + +/* Valid options for the 'options' property */ +#define NM_SETTING_BOND_OPTION_MODE "mode" +#define NM_SETTING_BOND_OPTION_MIIMON "miimon" +#define NM_SETTING_BOND_OPTION_DOWNDELAY "downdelay" +#define NM_SETTING_BOND_OPTION_UPDELAY "updelay" +#define NM_SETTING_BOND_OPTION_ARP_INTERVAL "arp_interval" +#define NM_SETTING_BOND_OPTION_ARP_IP_TARGET "arp_ip_target" +#define NM_SETTING_BOND_OPTION_ARP_VALIDATE "arp_validate" +#define NM_SETTING_BOND_OPTION_PRIMARY "primary" +#define NM_SETTING_BOND_OPTION_PRIMARY_RESELECT "primary_reselect" +#define NM_SETTING_BOND_OPTION_FAIL_OVER_MAC "fail_over_mac" +#define NM_SETTING_BOND_OPTION_USE_CARRIER "use_carrier" +#define NM_SETTING_BOND_OPTION_AD_SELECT "ad_select" +#define NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY "xmit_hash_policy" +#define NM_SETTING_BOND_OPTION_RESEND_IGMP "resend_igmp" +#define NM_SETTING_BOND_OPTION_LACP_RATE "lacp_rate" +#define NM_SETTING_BOND_OPTION_ACTIVE_SLAVE "active_slave" +#define NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO "ad_actor_sys_prio" +#define NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM "ad_actor_system" +#define NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY "ad_user_port_key" +#define NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE "all_slaves_active" +#define NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS "arp_all_targets" +#define NM_SETTING_BOND_OPTION_MIN_LINKS "min_links" +#define NM_SETTING_BOND_OPTION_NUM_GRAT_ARP "num_grat_arp" +#define NM_SETTING_BOND_OPTION_NUM_UNSOL_NA "num_unsol_na" +#define NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE "packets_per_slave" +#define NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB "tlb_dynamic_lb" +#define NM_SETTING_BOND_OPTION_LP_INTERVAL "lp_interval" + +/** + * NMSettingBond: + * + * Bonding Settings + */ +struct _NMSettingBond { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingBondClass; + +GType nm_setting_bond_get_type(void); + +NMSetting * nm_setting_bond_new(void); +guint32 nm_setting_bond_get_num_options(NMSettingBond *setting); +gboolean nm_setting_bond_get_option(NMSettingBond *setting, + guint32 idx, + const char ** out_name, + const char ** out_value); +const char *nm_setting_bond_get_option_by_name(NMSettingBond *setting, const char *name); +gboolean nm_setting_bond_add_option(NMSettingBond *setting, const char *name, const char *value); +gboolean nm_setting_bond_remove_option(NMSettingBond *setting, const char *name); + +gboolean nm_setting_bond_validate_option(const char *name, const char *value); + +const char **nm_setting_bond_get_valid_options(NMSettingBond *setting); + +const char *nm_setting_bond_get_option_default(NMSettingBond *setting, const char *name); + +NM_AVAILABLE_IN_1_24 +const char *nm_setting_bond_get_option_normalized(NMSettingBond *setting, const char *name); + +G_END_DECLS + +#endif /* __NM_SETTING_BOND_H__ */ diff --git a/src/libnm-core-public/nm-setting-bridge-port.h b/src/libnm-core-public/nm-setting-bridge-port.h new file mode 100644 index 0000000000..679131d287 --- /dev/null +++ b/src/libnm-core-public/nm-setting-bridge-port.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2012 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_BRIDGE_PORT_H__ +#define __NM_SETTING_BRIDGE_PORT_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" +#include "nm-setting-bridge.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_BRIDGE_PORT (nm_setting_bridge_port_get_type()) +#define NM_SETTING_BRIDGE_PORT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePort)) +#define NM_SETTING_BRIDGE_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortClass)) +#define NM_IS_SETTING_BRIDGE_PORT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_BRIDGE_PORT)) +#define NM_IS_SETTING_BRIDGE_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_BRIDGE_PORT)) +#define NM_SETTING_BRIDGE_PORT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortClass)) + +#define NM_SETTING_BRIDGE_PORT_SETTING_NAME "bridge-port" + +#define NM_SETTING_BRIDGE_PORT_PRIORITY "priority" +#define NM_SETTING_BRIDGE_PORT_PATH_COST "path-cost" +#define NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE "hairpin-mode" +#define NM_SETTING_BRIDGE_PORT_VLANS "vlans" + +/** + * NMSettingBridgePort: + * + * Bridge Port Settings + */ +struct _NMSettingBridgePort { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingBridgePortClass; + +GType nm_setting_bridge_port_get_type(void); + +NMSetting *nm_setting_bridge_port_new(void); + +guint16 nm_setting_bridge_port_get_priority(NMSettingBridgePort *setting); + +guint16 nm_setting_bridge_port_get_path_cost(NMSettingBridgePort *setting); + +gboolean nm_setting_bridge_port_get_hairpin_mode(NMSettingBridgePort *setting); + +NM_AVAILABLE_IN_1_18 +void nm_setting_bridge_port_add_vlan(NMSettingBridgePort *setting, NMBridgeVlan *vlan); +NM_AVAILABLE_IN_1_18 +guint nm_setting_bridge_port_get_num_vlans(NMSettingBridgePort *setting); +NM_AVAILABLE_IN_1_18 +NMBridgeVlan *nm_setting_bridge_port_get_vlan(NMSettingBridgePort *setting, guint idx); +NM_AVAILABLE_IN_1_18 +void nm_setting_bridge_port_remove_vlan(NMSettingBridgePort *setting, guint idx); +NM_AVAILABLE_IN_1_18 +gboolean nm_setting_bridge_port_remove_vlan_by_vid(NMSettingBridgePort *setting, + guint16 vid_start, + guint16 vid_end); +NM_AVAILABLE_IN_1_18 +void nm_setting_bridge_port_clear_vlans(NMSettingBridgePort *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_BRIDGE_PORT_H__ */ diff --git a/src/libnm-core-public/nm-setting-bridge.h b/src/libnm-core-public/nm-setting-bridge.h new file mode 100644 index 0000000000..cda1861294 --- /dev/null +++ b/src/libnm-core-public/nm-setting-bridge.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2015 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_BRIDGE_H__ +#define __NM_SETTING_BRIDGE_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_BRIDGE (nm_setting_bridge_get_type()) +#define NM_SETTING_BRIDGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_BRIDGE, NMSettingBridge)) +#define NM_SETTING_BRIDGE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_BRIDGE, NMSettingBridgeClass)) +#define NM_IS_SETTING_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_BRIDGE)) +#define NM_IS_SETTING_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_BRIDGE)) +#define NM_SETTING_BRIDGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_BRIDGE, NMSettingBridgeClass)) + +#define NM_SETTING_BRIDGE_SETTING_NAME "bridge" + +#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address" +#define NM_SETTING_BRIDGE_STP "stp" +#define NM_SETTING_BRIDGE_PRIORITY "priority" +#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay" +#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" +#define NM_SETTING_BRIDGE_MAX_AGE "max-age" +#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" +#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" +#define NM_SETTING_BRIDGE_MULTICAST_HASH_MAX "multicast-hash-max" +#define NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_COUNT "multicast-last-member-count" +#define NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL "multicast-last-member-interval" +#define NM_SETTING_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL "multicast-membership-interval" +#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" +#define NM_SETTING_BRIDGE_MULTICAST_ROUTER "multicast-router" +#define NM_SETTING_BRIDGE_MULTICAST_QUERIER "multicast-querier" +#define NM_SETTING_BRIDGE_MULTICAST_QUERIER_INTERVAL "multicast-querier-interval" +#define NM_SETTING_BRIDGE_MULTICAST_QUERY_INTERVAL "multicast-query-interval" +#define NM_SETTING_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL "multicast-query-response-interval" +#define NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR "multicast-query-use-ifaddr" +#define NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT "multicast-startup-query-count" +#define NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL "multicast-startup-query-interval" +#define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" +#define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" +#define NM_SETTING_BRIDGE_VLANS "vlans" +#define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" +#define NM_SETTING_BRIDGE_VLAN_PROTOCOL "vlan-protocol" +#define NM_SETTING_BRIDGE_VLAN_STATS_ENABLED "vlan-stats-enabled" + +#define NM_BRIDGE_VLAN_VID_MIN 1 +#define NM_BRIDGE_VLAN_VID_MAX 4094 + +typedef struct _NMSettingBridgeClass NMSettingBridgeClass; + +typedef struct _NMBridgeVlan NMBridgeVlan; + +GType nm_setting_bridge_get_type(void); + +NMSetting *nm_setting_bridge_new(void); + +const char *nm_setting_bridge_get_mac_address(NMSettingBridge *setting); + +gboolean nm_setting_bridge_get_stp(NMSettingBridge *setting); + +guint16 nm_setting_bridge_get_priority(NMSettingBridge *setting); + +guint16 nm_setting_bridge_get_forward_delay(NMSettingBridge *setting); + +guint16 nm_setting_bridge_get_hello_time(NMSettingBridge *setting); + +guint16 nm_setting_bridge_get_max_age(NMSettingBridge *setting); + +guint32 nm_setting_bridge_get_ageing_time(NMSettingBridge *setting); +NM_AVAILABLE_IN_1_10 +guint16 nm_setting_bridge_get_group_forward_mask(NMSettingBridge *setting); + +gboolean nm_setting_bridge_get_multicast_snooping(NMSettingBridge *setting); +NM_AVAILABLE_IN_1_18 +gboolean nm_setting_bridge_get_vlan_filtering(NMSettingBridge *setting); +NM_AVAILABLE_IN_1_18 +guint16 nm_setting_bridge_get_vlan_default_pvid(NMSettingBridge *setting); +NM_AVAILABLE_IN_1_18 +void nm_setting_bridge_add_vlan(NMSettingBridge *setting, NMBridgeVlan *vlan); +NM_AVAILABLE_IN_1_18 +guint nm_setting_bridge_get_num_vlans(NMSettingBridge *setting); +NM_AVAILABLE_IN_1_18 +NMBridgeVlan *nm_setting_bridge_get_vlan(NMSettingBridge *setting, guint idx); +NM_AVAILABLE_IN_1_18 +void nm_setting_bridge_remove_vlan(NMSettingBridge *setting, guint idx); +NM_AVAILABLE_IN_1_18 +gboolean +nm_setting_bridge_remove_vlan_by_vid(NMSettingBridge *setting, guint16 vid_start, guint16 vid_end); +NM_AVAILABLE_IN_1_18 +void nm_setting_bridge_clear_vlans(NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_18 +GType nm_bridge_vlan_get_type(void); +NM_AVAILABLE_IN_1_18 +NMBridgeVlan *nm_bridge_vlan_new(guint16 vid_start, guint16 vid_end); +NM_AVAILABLE_IN_1_18 +NMBridgeVlan *nm_bridge_vlan_ref(NMBridgeVlan *vlan); +NM_AVAILABLE_IN_1_18 +void nm_bridge_vlan_unref(NMBridgeVlan *vlan); +NM_AVAILABLE_IN_1_18 +NMBridgeVlan *nm_bridge_vlan_new_clone(const NMBridgeVlan *vlan); +NM_AVAILABLE_IN_1_18 +int nm_bridge_vlan_cmp(const NMBridgeVlan *a, const NMBridgeVlan *b); +NM_AVAILABLE_IN_1_18 +void nm_bridge_vlan_seal(NMBridgeVlan *vlan); +NM_AVAILABLE_IN_1_18 +gboolean nm_bridge_vlan_is_sealed(const NMBridgeVlan *vlan); +NM_AVAILABLE_IN_1_18 +void nm_bridge_vlan_set_untagged(NMBridgeVlan *vlan, gboolean value); +NM_AVAILABLE_IN_1_18 +void nm_bridge_vlan_set_pvid(NMBridgeVlan *vlan, gboolean value); +NM_AVAILABLE_IN_1_18 +gboolean +nm_bridge_vlan_get_vid_range(const NMBridgeVlan *vlan, guint16 *vid_start, guint16 *vid_end); +NM_AVAILABLE_IN_1_18 +gboolean nm_bridge_vlan_is_untagged(const NMBridgeVlan *vlan); +NM_AVAILABLE_IN_1_18 +gboolean nm_bridge_vlan_is_pvid(const NMBridgeVlan *vlan); + +NM_AVAILABLE_IN_1_18 +char *nm_bridge_vlan_to_str(const NMBridgeVlan *vlan, GError **error); +NM_AVAILABLE_IN_1_18 +NMBridgeVlan *nm_bridge_vlan_from_str(const char *str, GError **error); + +NM_AVAILABLE_IN_1_24 +const char *nm_setting_bridge_get_group_address(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +const char *nm_setting_bridge_get_vlan_protocol(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_vlan_stats_enabled(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +const char *nm_setting_bridge_get_multicast_router(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_multicast_query_use_ifaddr(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_multicast_querier(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint32 nm_setting_bridge_get_multicast_hash_max(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint32 nm_setting_bridge_get_multicast_last_member_count(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint64 nm_setting_bridge_get_multicast_last_member_interval(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint64 nm_setting_bridge_get_multicast_membership_interval(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint64 nm_setting_bridge_get_multicast_querier_interval(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint64 nm_setting_bridge_get_multicast_query_interval(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint64 nm_setting_bridge_get_multicast_query_response_interval(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint32 nm_setting_bridge_get_multicast_startup_query_count(const NMSettingBridge *setting); + +NM_AVAILABLE_IN_1_26 +guint64 nm_setting_bridge_get_multicast_startup_query_interval(const NMSettingBridge *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/src/libnm-core-public/nm-setting-cdma.h b/src/libnm-core-public/nm-setting-cdma.h new file mode 100644 index 0000000000..67784e8963 --- /dev/null +++ b/src/libnm-core-public/nm-setting-cdma.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2011 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_CDMA_H__ +#define __NM_SETTING_CDMA_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_CDMA (nm_setting_cdma_get_type()) +#define NM_SETTING_CDMA(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_CDMA, NMSettingCdma)) +#define NM_SETTING_CDMA_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_CDMA, NMSettingCdmaClass)) +#define NM_IS_SETTING_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_CDMA)) +#define NM_IS_SETTING_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_CDMA)) +#define NM_SETTING_CDMA_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_CDMA, NMSettingCdmaClass)) + +#define NM_SETTING_CDMA_SETTING_NAME "cdma" + +#define NM_SETTING_CDMA_NUMBER "number" +#define NM_SETTING_CDMA_USERNAME "username" +#define NM_SETTING_CDMA_PASSWORD "password" +#define NM_SETTING_CDMA_PASSWORD_FLAGS "password-flags" +#define NM_SETTING_CDMA_MTU "mtu" + +/** + * NMSettingCdma: + * + * CDMA-based Mobile Broadband Settings + */ +struct _NMSettingCdma { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingCdmaClass; + +GType nm_setting_cdma_get_type(void); + +NMSetting * nm_setting_cdma_new(void); +const char * nm_setting_cdma_get_number(NMSettingCdma *setting); +const char * nm_setting_cdma_get_username(NMSettingCdma *setting); +const char * nm_setting_cdma_get_password(NMSettingCdma *setting); +NMSettingSecretFlags nm_setting_cdma_get_password_flags(NMSettingCdma *setting); + +NM_AVAILABLE_IN_1_8 +guint32 nm_setting_cdma_get_mtu(NMSettingCdma *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_CDMA_H__ */ diff --git a/src/libnm-core-public/nm-setting-connection.h b/src/libnm-core-public/nm-setting-connection.h new file mode 100644 index 0000000000..34b40a4ff0 --- /dev/null +++ b/src/libnm-core-public/nm-setting-connection.h @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_CONNECTION_H__ +#define __NM_SETTING_CONNECTION_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_CONNECTION (nm_setting_connection_get_type()) +#define NM_SETTING_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_CONNECTION, NMSettingConnection)) +#define NM_SETTING_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionClass)) +#define NM_IS_SETTING_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_CONNECTION)) +#define NM_IS_SETTING_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_CONNECTION)) +#define NM_SETTING_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionClass)) + +#define NM_SETTING_CONNECTION_SETTING_NAME "connection" + +#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN -999 +#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX 999 +#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT 0 + +#define NM_SETTING_CONNECTION_ID "id" +#define NM_SETTING_CONNECTION_UUID "uuid" +#define NM_SETTING_CONNECTION_STABLE_ID "stable-id" +#define NM_SETTING_CONNECTION_INTERFACE_NAME "interface-name" +#define NM_SETTING_CONNECTION_TYPE "type" +#define NM_SETTING_CONNECTION_AUTOCONNECT "autoconnect" +#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY "autoconnect-priority" +#define NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES "autoconnect-retries" +#define NM_SETTING_CONNECTION_MULTI_CONNECT "multi-connect" +#define NM_SETTING_CONNECTION_TIMESTAMP "timestamp" +#define NM_SETTING_CONNECTION_READ_ONLY "read-only" +#define NM_SETTING_CONNECTION_PERMISSIONS "permissions" +#define NM_SETTING_CONNECTION_ZONE "zone" +#define NM_SETTING_CONNECTION_MASTER "master" +#define NM_SETTING_CONNECTION_SLAVE_TYPE "slave-type" +#define NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES "autoconnect-slaves" +#define NM_SETTING_CONNECTION_SECONDARIES "secondaries" +#define NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT "gateway-ping-timeout" +#define NM_SETTING_CONNECTION_METERED "metered" +#define NM_SETTING_CONNECTION_LLDP "lldp" +#define NM_SETTING_CONNECTION_AUTH_RETRIES "auth-retries" +#define NM_SETTING_CONNECTION_MDNS "mdns" +#define NM_SETTING_CONNECTION_LLMNR "llmnr" +#define NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT "wait-device-timeout" +#define NM_SETTING_CONNECTION_MUD_URL "mud-url" + +/* Types for property values */ +/** + * NMSettingConnectionAutoconnectSlaves: + * @NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT: default value + * @NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO: slaves are not brought up when + * master is activated + * @NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES: slaves are brought up when + * master is activated + * + * #NMSettingConnectionAutoconnectSlaves values indicate whether slave connections + * should be activated when master is activated. + */ +typedef enum { + NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT = -1, + NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO = 0, + NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES = 1, +} NMSettingConnectionAutoconnectSlaves; + +/** + * NMSettingConnectionLldp: + * @NM_SETTING_CONNECTION_LLDP_DEFAULT: default value + * @NM_SETTING_CONNECTION_LLDP_DISABLE: disable LLDP + * @NM_SETTING_CONNECTION_LLDP_ENABLE_RX: enable reception of LLDP frames + * + * #NMSettingConnectionLldp values indicate whether LLDP should be enabled. + */ +typedef enum { + NM_SETTING_CONNECTION_LLDP_DEFAULT = -1, + NM_SETTING_CONNECTION_LLDP_DISABLE = 0, + NM_SETTING_CONNECTION_LLDP_ENABLE_RX = 1, +} NMSettingConnectionLldp; + +/** + * NMSettingConnectionMdns: + * @NM_SETTING_CONNECTION_MDNS_DEFAULT: default value + * @NM_SETTING_CONNECTION_MDNS_NO: disable mDNS + * @NM_SETTING_CONNECTION_MDNS_RESOLVE: support only resolving, do not register hostname + * @NM_SETTING_CONNECTION_MDNS_YES: enable mDNS + * + * #NMSettingConnectionMdns values indicate whether mDNS should be enabled. + * + * Since: 1.12 + */ +typedef enum { + NM_SETTING_CONNECTION_MDNS_DEFAULT = -1, + NM_SETTING_CONNECTION_MDNS_NO = 0, + NM_SETTING_CONNECTION_MDNS_RESOLVE = 1, + NM_SETTING_CONNECTION_MDNS_YES = 2, +} NMSettingConnectionMdns; + +/** + * NMSettingConnectionLlmnr: + * @NM_SETTING_CONNECTION_LLMNR_DEFAULT: default value + * @NM_SETTING_CONNECTION_LLMNR_NO: disable LLMNR + * @NM_SETTING_CONNECTION_LLMNR_RESOLVE: support only resolving, do not register hostname + * @NM_SETTING_CONNECTION_LLMNR_YES: enable LLMNR + * + * #NMSettingConnectionLlmnr values indicate whether LLMNR should be enabled. + * + * Since: 1.14 + */ +typedef enum { + NM_SETTING_CONNECTION_LLMNR_DEFAULT = -1, + NM_SETTING_CONNECTION_LLMNR_NO = 0, + NM_SETTING_CONNECTION_LLMNR_RESOLVE = 1, + NM_SETTING_CONNECTION_LLMNR_YES = 2, +} NMSettingConnectionLlmnr; + +/** + * NMSettingConnection: + * + * General Connection Profile Settings + */ +struct _NMSettingConnection { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingConnectionClass; + +GType nm_setting_connection_get_type(void); + +NMSetting * nm_setting_connection_new(void); +const char *nm_setting_connection_get_id(NMSettingConnection *setting); +const char *nm_setting_connection_get_uuid(NMSettingConnection *setting); +NM_AVAILABLE_IN_1_4 +const char *nm_setting_connection_get_stable_id(NMSettingConnection *setting); +const char *nm_setting_connection_get_interface_name(NMSettingConnection *setting); +const char *nm_setting_connection_get_connection_type(NMSettingConnection *setting); +gboolean nm_setting_connection_get_autoconnect(NMSettingConnection *setting); +int nm_setting_connection_get_autoconnect_priority(NMSettingConnection *setting); +NM_AVAILABLE_IN_1_6 +int nm_setting_connection_get_autoconnect_retries(NMSettingConnection *setting); +NM_AVAILABLE_IN_1_14 +NMConnectionMultiConnect nm_setting_connection_get_multi_connect(NMSettingConnection *setting); +guint64 nm_setting_connection_get_timestamp(NMSettingConnection *setting); +gboolean nm_setting_connection_get_read_only(NMSettingConnection *setting); + +guint32 nm_setting_connection_get_num_permissions(NMSettingConnection *setting); +gboolean nm_setting_connection_get_permission(NMSettingConnection *setting, + guint32 idx, + const char ** out_ptype, + const char ** out_pitem, + const char ** out_detail); +const char *nm_setting_connection_get_zone(NMSettingConnection *setting); +gboolean nm_setting_connection_permissions_user_allowed(NMSettingConnection *setting, + const char * uname); +gboolean nm_setting_connection_add_permission(NMSettingConnection *setting, + const char * ptype, + const char * pitem, + const char * detail); +void nm_setting_connection_remove_permission(NMSettingConnection *setting, guint32 idx); +gboolean nm_setting_connection_remove_permission_by_value(NMSettingConnection *setting, + const char * ptype, + const char * pitem, + const char * detail); + +const char *nm_setting_connection_get_master(NMSettingConnection *setting); +gboolean nm_setting_connection_is_slave_type(NMSettingConnection *setting, const char *type); +const char *nm_setting_connection_get_slave_type(NMSettingConnection *setting); +NM_AVAILABLE_IN_1_2 +NMSettingConnectionAutoconnectSlaves +nm_setting_connection_get_autoconnect_slaves(NMSettingConnection *setting); + +guint32 nm_setting_connection_get_num_secondaries(NMSettingConnection *setting); +const char *nm_setting_connection_get_secondary(NMSettingConnection *setting, guint32 idx); +gboolean nm_setting_connection_add_secondary(NMSettingConnection *setting, const char *sec_uuid); +void nm_setting_connection_remove_secondary(NMSettingConnection *setting, guint32 idx); +gboolean nm_setting_connection_remove_secondary_by_value(NMSettingConnection *setting, + const char * sec_uuid); + +guint32 nm_setting_connection_get_gateway_ping_timeout(NMSettingConnection *setting); +NM_AVAILABLE_IN_1_2 +NMMetered nm_setting_connection_get_metered(NMSettingConnection *setting); +NM_AVAILABLE_IN_1_2 +NMSettingConnectionLldp nm_setting_connection_get_lldp(NMSettingConnection *setting); + +NM_AVAILABLE_IN_1_10 +int nm_setting_connection_get_auth_retries(NMSettingConnection *setting); + +NM_AVAILABLE_IN_1_12 +NMSettingConnectionMdns nm_setting_connection_get_mdns(NMSettingConnection *setting); +NM_AVAILABLE_IN_1_14 +NMSettingConnectionLlmnr nm_setting_connection_get_llmnr(NMSettingConnection *setting); + +NM_AVAILABLE_IN_1_20 +gint32 nm_setting_connection_get_wait_device_timeout(NMSettingConnection *setting); + +NM_AVAILABLE_IN_1_26 +const char *nm_setting_connection_get_mud_url(NMSettingConnection *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_CONNECTION_H__ */ diff --git a/src/libnm-core-public/nm-setting-dcb.h b/src/libnm-core-public/nm-setting-dcb.h new file mode 100644 index 0000000000..a33c13ad99 --- /dev/null +++ b/src/libnm-core-public/nm-setting-dcb.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2013 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_DCB_H__ +#define __NM_SETTING_DCB_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_DCB (nm_setting_dcb_get_type()) +#define NM_SETTING_DCB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_DCB, NMSettingDcb)) +#define NM_SETTING_DCB_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_DCB, NMSettingDcbClass)) +#define NM_IS_SETTING_DCB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_DCB)) +#define NM_IS_SETTING_DCB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_DCB)) +#define NM_SETTING_DCB_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_DCB, NMSettingDcbClass)) + +#define NM_SETTING_DCB_SETTING_NAME "dcb" + +/** + * NMSettingDcbFlags: + * @NM_SETTING_DCB_FLAG_NONE: no flag + * @NM_SETTING_DCB_FLAG_ENABLE: the feature is enabled + * @NM_SETTING_DCB_FLAG_ADVERTISE: the feature is advertised + * @NM_SETTING_DCB_FLAG_WILLING: the feature is willing to change based on + * peer configuration advertisements + * + * DCB feature flags. + **/ +typedef enum { /*< flags >*/ + NM_SETTING_DCB_FLAG_NONE = 0x00000000, + NM_SETTING_DCB_FLAG_ENABLE = 0x00000001, + NM_SETTING_DCB_FLAG_ADVERTISE = 0x00000002, + NM_SETTING_DCB_FLAG_WILLING = 0x00000004 +} NMSettingDcbFlags; + +/** + * NM_SETTING_DCB_FCOE_MODE_FABRIC: + * + * Indicates that the FCoE controller should use "fabric" mode (default) + */ +#define NM_SETTING_DCB_FCOE_MODE_FABRIC "fabric" + +/** + * NM_SETTING_DCB_FCOE_MODE_VN2VN: + * + * Indicates that the FCoE controller should use "VN2VN" mode. + */ +#define NM_SETTING_DCB_FCOE_MODE_VN2VN "vn2vn" + +/* Properties */ +#define NM_SETTING_DCB_APP_FCOE_FLAGS "app-fcoe-flags" +#define NM_SETTING_DCB_APP_FCOE_PRIORITY "app-fcoe-priority" +#define NM_SETTING_DCB_APP_FCOE_MODE "app-fcoe-mode" + +#define NM_SETTING_DCB_APP_ISCSI_FLAGS "app-iscsi-flags" +#define NM_SETTING_DCB_APP_ISCSI_PRIORITY "app-iscsi-priority" + +#define NM_SETTING_DCB_APP_FIP_FLAGS "app-fip-flags" +#define NM_SETTING_DCB_APP_FIP_PRIORITY "app-fip-priority" + +#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS "priority-flow-control-flags" +#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL "priority-flow-control" + +#define NM_SETTING_DCB_PRIORITY_GROUP_FLAGS "priority-group-flags" +#define NM_SETTING_DCB_PRIORITY_GROUP_ID "priority-group-id" +#define NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH "priority-group-bandwidth" +#define NM_SETTING_DCB_PRIORITY_BANDWIDTH "priority-bandwidth" +#define NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH "priority-strict-bandwidth" +#define NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS "priority-traffic-class" + +/** + * NMSettingDcb: + * + * Data Center Bridging Settings + */ +struct _NMSettingDcb { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingDcbClass; + +GType nm_setting_dcb_get_type(void); + +NMSetting *nm_setting_dcb_new(void); + +NMSettingDcbFlags nm_setting_dcb_get_app_fcoe_flags(NMSettingDcb *setting); +int nm_setting_dcb_get_app_fcoe_priority(NMSettingDcb *setting); +const char * nm_setting_dcb_get_app_fcoe_mode(NMSettingDcb *setting); + +NMSettingDcbFlags nm_setting_dcb_get_app_iscsi_flags(NMSettingDcb *setting); +int nm_setting_dcb_get_app_iscsi_priority(NMSettingDcb *setting); + +NMSettingDcbFlags nm_setting_dcb_get_app_fip_flags(NMSettingDcb *setting); +int nm_setting_dcb_get_app_fip_priority(NMSettingDcb *setting); + +/* Priority Flow Control */ +NMSettingDcbFlags nm_setting_dcb_get_priority_flow_control_flags(NMSettingDcb *setting); +gboolean nm_setting_dcb_get_priority_flow_control(NMSettingDcb *setting, guint user_priority); +void nm_setting_dcb_set_priority_flow_control(NMSettingDcb *setting, + guint user_priority, + gboolean enabled); + +/* Priority Groups */ +NMSettingDcbFlags nm_setting_dcb_get_priority_group_flags(NMSettingDcb *setting); + +guint nm_setting_dcb_get_priority_group_id(NMSettingDcb *setting, guint user_priority); +void +nm_setting_dcb_set_priority_group_id(NMSettingDcb *setting, guint user_priority, guint group_id); + +guint nm_setting_dcb_get_priority_group_bandwidth(NMSettingDcb *setting, guint group_id); +void nm_setting_dcb_set_priority_group_bandwidth(NMSettingDcb *setting, + guint group_id, + guint bandwidth_percent); + +guint nm_setting_dcb_get_priority_bandwidth(NMSettingDcb *setting, guint user_priority); +void nm_setting_dcb_set_priority_bandwidth(NMSettingDcb *setting, + guint user_priority, + guint bandwidth_percent); + +gboolean nm_setting_dcb_get_priority_strict_bandwidth(NMSettingDcb *setting, guint user_priority); +void nm_setting_dcb_set_priority_strict_bandwidth(NMSettingDcb *setting, + guint user_priority, + gboolean strict); + +guint nm_setting_dcb_get_priority_traffic_class(NMSettingDcb *setting, guint user_priority); +void nm_setting_dcb_set_priority_traffic_class(NMSettingDcb *setting, + guint user_priority, + guint traffic_class); + +G_END_DECLS + +#endif /* __NM_SETTING_DCB_H__ */ diff --git a/src/libnm-core-public/nm-setting-dummy.h b/src/libnm-core-public/nm-setting-dummy.h new file mode 100644 index 0000000000..504428e717 --- /dev/null +++ b/src/libnm-core-public/nm-setting-dummy.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_DUMMY_H__ +#define __NM_SETTING_DUMMY_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_DUMMY (nm_setting_dummy_get_type()) +#define NM_SETTING_DUMMY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_DUMMY, NMSettingDummy)) +#define NM_SETTING_DUMMY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_DUMMYCONFIG, NMSettingDummyClass)) +#define NM_IS_SETTING_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_DUMMY)) +#define NM_IS_SETTING_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_DUMMY)) +#define NM_SETTING_DUMMY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_DUMMY, NMSettingDummyClass)) + +#define NM_SETTING_DUMMY_SETTING_NAME "dummy" + +/** + * NMSettingDummy: + * + * Dummy Link Settings + */ +struct _NMSettingDummy { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingDummyClass; + +NM_AVAILABLE_IN_1_8 +GType nm_setting_dummy_get_type(void); +NM_AVAILABLE_IN_1_8 +NMSetting *nm_setting_dummy_new(void); + +G_END_DECLS + +#endif /* __NM_SETTING_DUMMY_H__ */ diff --git a/src/libnm-core-public/nm-setting-ethtool.h b/src/libnm-core-public/nm-setting-ethtool.h new file mode 100644 index 0000000000..d2310b408e --- /dev/null +++ b/src/libnm-core-public/nm-setting-ethtool.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_ETHTOOL_H__ +#define __NM_SETTING_ETHTOOL_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +NM_AVAILABLE_IN_1_20 +gboolean nm_ethtool_optname_is_feature(const char *optname); + +NM_AVAILABLE_IN_1_26 +gboolean nm_ethtool_optname_is_coalesce(const char *optname); + +NM_AVAILABLE_IN_1_26 +gboolean nm_ethtool_optname_is_ring(const char *optname); + +/*****************************************************************************/ + +#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type()) +#define NM_SETTING_ETHTOOL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtool)) +#define NM_SETTING_ETHTOOL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass)) +#define NM_IS_SETTING_ETHTOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_ETHTOOL)) +#define NM_IS_SETTING_ETHTOOL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_ETHTOOL)) +#define NM_SETTING_ETHTOOL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass)) + +#define NM_SETTING_ETHTOOL_SETTING_NAME "ethtool" + +/*****************************************************************************/ + +typedef struct _NMSettingEthtoolClass NMSettingEthtoolClass; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_ethtool_get_type(void); + +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_ethtool_new(void); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_20 +NM_DEPRECATED_IN_1_26 +const char **nm_setting_ethtool_get_optnames(NMSettingEthtool *setting, guint *out_length); + +NM_AVAILABLE_IN_1_14 +NM_DEPRECATED_IN_1_26 +NMTernary nm_setting_ethtool_get_feature(NMSettingEthtool *setting, const char *optname); +NM_AVAILABLE_IN_1_14 +NM_DEPRECATED_IN_1_26 +void +nm_setting_ethtool_set_feature(NMSettingEthtool *setting, const char *optname, NMTernary value); +NM_AVAILABLE_IN_1_14 +NM_DEPRECATED_IN_1_26 +void nm_setting_ethtool_clear_features(NMSettingEthtool *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_ETHTOOL_H__ */ diff --git a/src/libnm-core-public/nm-setting-generic.h b/src/libnm-core-public/nm-setting-generic.h new file mode 100644 index 0000000000..5c0195f2db --- /dev/null +++ b/src/libnm-core-public/nm-setting-generic.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2013 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_GENERIC_H__ +#define __NM_SETTING_GENERIC_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_GENERIC (nm_setting_generic_get_type()) +#define NM_SETTING_GENERIC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_GENERIC, NMSettingGeneric)) +#define NM_SETTING_GENERIC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_GENERIC, NMSettingGenericClass)) +#define NM_IS_SETTING_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_GENERIC)) +#define NM_IS_SETTING_GENERIC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_GENERIC)) +#define NM_SETTING_GENERIC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_GENERIC, NMSettingGenericClass)) + +#define NM_SETTING_GENERIC_SETTING_NAME "generic" + +/** + * NMSettingGeneric: + * + * Generic Link Settings + */ +struct _NMSettingGeneric { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingGenericClass; + +GType nm_setting_generic_get_type(void); + +NMSetting *nm_setting_generic_new(void); + +G_END_DECLS + +#endif /* __NM_SETTING_GENERIC_H__ */ diff --git a/src/libnm-core-public/nm-setting-gsm.h b/src/libnm-core-public/nm-setting-gsm.h new file mode 100644 index 0000000000..ed939e7cd2 --- /dev/null +++ b/src/libnm-core-public/nm-setting-gsm.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2011 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_GSM_H__ +#define __NM_SETTING_GSM_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_GSM (nm_setting_gsm_get_type()) +#define NM_SETTING_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_GSM, NMSettingGsm)) +#define NM_SETTING_GSM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_GSM, NMSettingGsmClass)) +#define NM_IS_SETTING_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_GSM)) +#define NM_IS_SETTING_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_GSM)) +#define NM_SETTING_GSM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_GSM, NMSettingGsmClass)) + +#define NM_SETTING_GSM_SETTING_NAME "gsm" + +#define NM_SETTING_GSM_AUTO_CONFIG "auto-config" +#define NM_SETTING_GSM_USERNAME "username" +#define NM_SETTING_GSM_PASSWORD "password" +#define NM_SETTING_GSM_PASSWORD_FLAGS "password-flags" +#define NM_SETTING_GSM_APN "apn" +#define NM_SETTING_GSM_NETWORK_ID "network-id" +#define NM_SETTING_GSM_PIN "pin" +#define NM_SETTING_GSM_PIN_FLAGS "pin-flags" +#define NM_SETTING_GSM_HOME_ONLY "home-only" +#define NM_SETTING_GSM_DEVICE_ID "device-id" +#define NM_SETTING_GSM_SIM_ID "sim-id" +#define NM_SETTING_GSM_SIM_OPERATOR_ID "sim-operator-id" +#define NM_SETTING_GSM_MTU "mtu" + +/* Deprecated */ +#define NM_SETTING_GSM_NUMBER "number" + +/** + * NMSettingGsm: + * + * GSM-based Mobile Broadband Settings + */ +struct _NMSettingGsm { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingGsmClass; + +GType nm_setting_gsm_get_type(void); + +NMSetting *nm_setting_gsm_new(void); + +NM_AVAILABLE_IN_1_22 +gboolean nm_setting_gsm_get_auto_config(NMSettingGsm *setting); + +const char *nm_setting_gsm_get_username(NMSettingGsm *setting); +const char *nm_setting_gsm_get_password(NMSettingGsm *setting); +const char *nm_setting_gsm_get_apn(NMSettingGsm *setting); +const char *nm_setting_gsm_get_network_id(NMSettingGsm *setting); +const char *nm_setting_gsm_get_pin(NMSettingGsm *setting); +gboolean nm_setting_gsm_get_home_only(NMSettingGsm *setting); + +NM_AVAILABLE_IN_1_2 +const char *nm_setting_gsm_get_device_id(NMSettingGsm *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_gsm_get_sim_id(NMSettingGsm *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_gsm_get_sim_operator_id(NMSettingGsm *setting); +NM_AVAILABLE_IN_1_8 +guint32 nm_setting_gsm_get_mtu(NMSettingGsm *setting); + +NM_DEPRECATED_IN_1_16 +const char *nm_setting_gsm_get_number(NMSettingGsm *setting); + +NMSettingSecretFlags nm_setting_gsm_get_pin_flags(NMSettingGsm *setting); +NMSettingSecretFlags nm_setting_gsm_get_password_flags(NMSettingGsm *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_GSM_H__ */ diff --git a/src/libnm-core-public/nm-setting-hostname.h b/src/libnm-core-public/nm-setting-hostname.h new file mode 100644 index 0000000000..02b4e373e4 --- /dev/null +++ b/src/libnm-core-public/nm-setting-hostname.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020 Red Hat, Inc. + */ + +#ifndef NM_SETTING_HOSTNAME_H +#define NM_SETTING_HOSTNAME_H + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_HOSTNAME (nm_setting_hostname_get_type()) +#define NM_SETTING_HOSTNAME(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_HOSTNAME, NMSettingHostname)) +#define NM_SETTING_HOSTNAME_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_HOSTNAME, NMSettingHostnameClass)) +#define NM_IS_SETTING_HOSTNAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_HOSTNAME)) +#define NM_IS_SETTING_HOSTNAME_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_HOSTNAME)) +#define NM_SETTING_HOSTNAME_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_HOSTNAME, NMSettingHostnameClass)) + +#define NM_SETTING_HOSTNAME_SETTING_NAME "hostname" + +#define NM_SETTING_HOSTNAME_PRIORITY "priority" +#define NM_SETTING_HOSTNAME_FROM_DHCP "from-dhcp" +#define NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP "from-dns-lookup" +#define NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT "only-from-default" + +typedef struct _NMSettingHostnameClass NMSettingHostnameClass; + +NM_AVAILABLE_IN_1_30 +GType nm_setting_hostname_get_type(void); +NM_AVAILABLE_IN_1_30 +NMSetting *nm_setting_hostname_new(void); + +NM_AVAILABLE_IN_1_30 +int nm_setting_hostname_get_priority(NMSettingHostname *setting); +NM_AVAILABLE_IN_1_30 +NMTernary nm_setting_hostname_get_from_dhcp(NMSettingHostname *setting); +NM_AVAILABLE_IN_1_30 +NMTernary nm_setting_hostname_get_from_dns_lookup(NMSettingHostname *setting); +NM_AVAILABLE_IN_1_30 +NMTernary nm_setting_hostname_get_only_from_default(NMSettingHostname *setting); + +G_END_DECLS + +#endif /* NM_SETTING_HOSTNAME_H */ diff --git a/src/libnm-core-public/nm-setting-infiniband.h b/src/libnm-core-public/nm-setting-infiniband.h new file mode 100644 index 0000000000..4a771aef9e --- /dev/null +++ b/src/libnm-core-public/nm-setting-infiniband.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_INFINIBAND_H__ +#define __NM_SETTING_INFINIBAND_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_INFINIBAND (nm_setting_infiniband_get_type()) +#define NM_SETTING_INFINIBAND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_INFINIBAND, NMSettingInfiniband)) +#define NM_SETTING_INFINIBAND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandClass)) +#define NM_IS_SETTING_INFINIBAND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_INFINIBAND)) +#define NM_IS_SETTING_INFINIBAND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_INFINIBAND)) +#define NM_SETTING_INFINIBAND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandClass)) + +#define NM_SETTING_INFINIBAND_SETTING_NAME "infiniband" + +#define NM_SETTING_INFINIBAND_MAC_ADDRESS "mac-address" +#define NM_SETTING_INFINIBAND_MTU "mtu" +#define NM_SETTING_INFINIBAND_TRANSPORT_MODE "transport-mode" +#define NM_SETTING_INFINIBAND_P_KEY "p-key" +#define NM_SETTING_INFINIBAND_PARENT "parent" + +/** + * NMSettingInfiniband: + * + * Infiniband Settings + */ +struct _NMSettingInfiniband { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingInfinibandClass; + +GType nm_setting_infiniband_get_type(void); + +NMSetting * nm_setting_infiniband_new(void); +const char *nm_setting_infiniband_get_mac_address(NMSettingInfiniband *setting); +guint32 nm_setting_infiniband_get_mtu(NMSettingInfiniband *setting); +const char *nm_setting_infiniband_get_transport_mode(NMSettingInfiniband *setting); +int nm_setting_infiniband_get_p_key(NMSettingInfiniband *setting); +const char *nm_setting_infiniband_get_parent(NMSettingInfiniband *setting); + +const char *nm_setting_infiniband_get_virtual_interface_name(NMSettingInfiniband *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_INFINIBAND_H__ */ diff --git a/src/libnm-core-public/nm-setting-ip-config.h b/src/libnm-core-public/nm-setting-ip-config.h new file mode 100644 index 0000000000..1cb1671714 --- /dev/null +++ b/src/libnm-core-public/nm-setting-ip-config.h @@ -0,0 +1,494 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_IP_CONFIG_H +#define NM_SETTING_IP_CONFIG_H + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" +#include "nm-utils.h" + +G_BEGIN_DECLS + +#define NM_IP_ADDRESS_ATTRIBUTE_LABEL "label" + +/** + * NMIPAddressCmpFlags: + * @NM_IP_ADDRESS_CMP_FLAGS_NONE: no flags. + * @NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS: when comparing two addresses, + * also consider their attributes. Warning: note that attributes are GVariants + * and they don't have a total order. In other words, if the address differs only + * by their attributes, the returned compare order is not total. In that case, + * the return value merely indicates equality (zero) or inequality. + * + * Compare flags for nm_ip_address_cmp_full(). + * + * Since: 1.22 + */ +typedef enum { /*< flags >*/ + NM_IP_ADDRESS_CMP_FLAGS_NONE = 0, + NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS = 0x1, +} NMIPAddressCmpFlags; + +typedef struct NMIPAddress NMIPAddress; + +GType nm_ip_address_get_type(void); + +NMIPAddress *nm_ip_address_new(int family, const char *addr, guint prefix, GError **error); +NMIPAddress *nm_ip_address_new_binary(int family, gconstpointer addr, guint prefix, GError **error); + +void nm_ip_address_ref(NMIPAddress *address); +void nm_ip_address_unref(NMIPAddress *address); +gboolean nm_ip_address_equal(NMIPAddress *address, NMIPAddress *other); +NM_AVAILABLE_IN_1_22 +int +nm_ip_address_cmp_full(const NMIPAddress *a, const NMIPAddress *b, NMIPAddressCmpFlags cmp_flags); +NMIPAddress *nm_ip_address_dup(NMIPAddress *address); + +int nm_ip_address_get_family(NMIPAddress *address); +const char *nm_ip_address_get_address(NMIPAddress *address); +void nm_ip_address_set_address(NMIPAddress *address, const char *addr); +void nm_ip_address_get_address_binary(NMIPAddress *address, gpointer addr); +void nm_ip_address_set_address_binary(NMIPAddress *address, gconstpointer addr); +guint nm_ip_address_get_prefix(NMIPAddress *address); +void nm_ip_address_set_prefix(NMIPAddress *address, guint prefix); + +char ** nm_ip_address_get_attribute_names(NMIPAddress *address); +GVariant *nm_ip_address_get_attribute(NMIPAddress *address, const char *name); +void nm_ip_address_set_attribute(NMIPAddress *address, const char *name, GVariant *value); + +typedef struct NMIPRoute NMIPRoute; + +GType nm_ip_route_get_type(void); + +NMIPRoute *nm_ip_route_new(int family, + const char *dest, + guint prefix, + const char *next_hop, + gint64 metric, + GError ** error); +NMIPRoute *nm_ip_route_new_binary(int family, + gconstpointer dest, + guint prefix, + gconstpointer next_hop, + gint64 metric, + GError ** error); + +void nm_ip_route_ref(NMIPRoute *route); +void nm_ip_route_unref(NMIPRoute *route); +gboolean nm_ip_route_equal(NMIPRoute *route, NMIPRoute *other); + +enum { /*< flags >*/ + NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE = 0, + NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS = 0x1, +}; + +NM_AVAILABLE_IN_1_10 +gboolean nm_ip_route_equal_full(NMIPRoute *route, NMIPRoute *other, guint cmp_flags); + +NMIPRoute *nm_ip_route_dup(NMIPRoute *route); + +int nm_ip_route_get_family(NMIPRoute *route); +const char *nm_ip_route_get_dest(NMIPRoute *route); +void nm_ip_route_set_dest(NMIPRoute *route, const char *dest); +void nm_ip_route_get_dest_binary(NMIPRoute *route, gpointer dest); +void nm_ip_route_set_dest_binary(NMIPRoute *route, gconstpointer dest); +guint nm_ip_route_get_prefix(NMIPRoute *route); +void nm_ip_route_set_prefix(NMIPRoute *route, guint prefix); +const char *nm_ip_route_get_next_hop(NMIPRoute *route); +void nm_ip_route_set_next_hop(NMIPRoute *route, const char *next_hop); +gboolean nm_ip_route_get_next_hop_binary(NMIPRoute *route, gpointer next_hop); +void nm_ip_route_set_next_hop_binary(NMIPRoute *route, gconstpointer next_hop); +gint64 nm_ip_route_get_metric(NMIPRoute *route); +void nm_ip_route_set_metric(NMIPRoute *route, gint64 metric); + +char ** nm_ip_route_get_attribute_names(NMIPRoute *route); +GVariant *nm_ip_route_get_attribute(NMIPRoute *route, const char *name); +void nm_ip_route_set_attribute(NMIPRoute *route, const char *name, GVariant *value); +NM_AVAILABLE_IN_1_8 +const NMVariantAttributeSpec *const *nm_ip_route_get_variant_attribute_spec(void); +NM_AVAILABLE_IN_1_8 +gboolean nm_ip_route_attribute_validate(const char *name, + GVariant * value, + int family, + gboolean * known, + GError ** error); + +#define NM_IP_ROUTE_ATTRIBUTE_CWND "cwnd" +#define NM_IP_ROUTE_ATTRIBUTE_FROM "from" +#define NM_IP_ROUTE_ATTRIBUTE_INITCWND "initcwnd" +#define NM_IP_ROUTE_ATTRIBUTE_INITRWND "initrwnd" +#define NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND "lock-cwnd" +#define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND "lock-initcwnd" +#define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND "lock-initrwnd" +#define NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU "lock-mtu" +#define NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW "lock-window" +#define NM_IP_ROUTE_ATTRIBUTE_MTU "mtu" +#define NM_IP_ROUTE_ATTRIBUTE_ONLINK "onlink" +#define NM_IP_ROUTE_ATTRIBUTE_SCOPE "scope" +#define NM_IP_ROUTE_ATTRIBUTE_SRC "src" +#define NM_IP_ROUTE_ATTRIBUTE_TABLE "table" +#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos" +#define NM_IP_ROUTE_ATTRIBUTE_TYPE "type" +#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window" + +/*****************************************************************************/ + +typedef struct NMIPRoutingRule NMIPRoutingRule; + +NM_AVAILABLE_IN_1_18 +GType nm_ip_routing_rule_get_type(void); + +NM_AVAILABLE_IN_1_18 +NMIPRoutingRule *nm_ip_routing_rule_new(int addr_family); + +NM_AVAILABLE_IN_1_18 +NMIPRoutingRule *nm_ip_routing_rule_new_clone(const NMIPRoutingRule *rule); + +NM_AVAILABLE_IN_1_18 +NMIPRoutingRule *nm_ip_routing_rule_ref(NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_unref(NMIPRoutingRule *self); + +NM_AVAILABLE_IN_1_18 +gboolean nm_ip_routing_rule_is_sealed(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_seal(NMIPRoutingRule *self); + +NM_AVAILABLE_IN_1_18 +int nm_ip_routing_rule_get_addr_family(const NMIPRoutingRule *self); + +NM_AVAILABLE_IN_1_18 +gboolean nm_ip_routing_rule_get_invert(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_invert(NMIPRoutingRule *self, gboolean invert); + +NM_AVAILABLE_IN_1_18 +gint64 nm_ip_routing_rule_get_priority(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_priority(NMIPRoutingRule *self, gint64 priority); + +NM_AVAILABLE_IN_1_18 +guint8 nm_ip_routing_rule_get_tos(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_tos(NMIPRoutingRule *self, guint8 tos); + +NM_AVAILABLE_IN_1_18 +guint8 nm_ip_routing_rule_get_ipproto(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_ipproto(NMIPRoutingRule *self, guint8 ipproto); + +NM_AVAILABLE_IN_1_18 +guint16 nm_ip_routing_rule_get_source_port_start(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +guint16 nm_ip_routing_rule_get_source_port_end(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_source_port(NMIPRoutingRule *self, guint16 start, guint16 end); + +NM_AVAILABLE_IN_1_18 +guint16 nm_ip_routing_rule_get_destination_port_start(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +guint16 nm_ip_routing_rule_get_destination_port_end(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_destination_port(NMIPRoutingRule *self, guint16 start, guint16 end); + +NM_AVAILABLE_IN_1_18 +guint32 nm_ip_routing_rule_get_fwmark(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +guint32 nm_ip_routing_rule_get_fwmask(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_fwmark(NMIPRoutingRule *self, guint32 fwmark, guint32 fwmask); + +NM_AVAILABLE_IN_1_18 +guint8 nm_ip_routing_rule_get_from_len(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +const char *nm_ip_routing_rule_get_from(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_from(NMIPRoutingRule *self, const char *from, guint8 len); + +NM_AVAILABLE_IN_1_18 +guint8 nm_ip_routing_rule_get_to_len(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +const char *nm_ip_routing_rule_get_to(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_to(NMIPRoutingRule *self, const char *to, guint8 len); + +NM_AVAILABLE_IN_1_18 +const char *nm_ip_routing_rule_get_iifname(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_iifname(NMIPRoutingRule *self, const char *iifname); + +NM_AVAILABLE_IN_1_18 +const char *nm_ip_routing_rule_get_oifname(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_oifname(NMIPRoutingRule *self, const char *oifname); + +NM_AVAILABLE_IN_1_18 +guint8 nm_ip_routing_rule_get_action(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_action(NMIPRoutingRule *self, guint8 action); + +NM_AVAILABLE_IN_1_18 +guint32 nm_ip_routing_rule_get_table(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_18 +void nm_ip_routing_rule_set_table(NMIPRoutingRule *self, guint32 table); + +NM_AVAILABLE_IN_1_20 +gint32 nm_ip_routing_rule_get_suppress_prefixlength(const NMIPRoutingRule *self); +NM_AVAILABLE_IN_1_20 +void nm_ip_routing_rule_set_suppress_prefixlength(NMIPRoutingRule *self, + gint32 suppress_prefixlength); + +NM_AVAILABLE_IN_1_18 +int nm_ip_routing_rule_cmp(const NMIPRoutingRule *rule, const NMIPRoutingRule *other); + +NM_AVAILABLE_IN_1_18 +gboolean nm_ip_routing_rule_validate(const NMIPRoutingRule *self, GError **error); + +/** + * NMIPRoutingRuleAsStringFlags: + * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE: no flags selected. + * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET: whether to allow parsing + * IPv4 addresses. + * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6: whether to allow parsing + * IPv6 addresses. If both @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET and + * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 are unset, it's the same + * as setting them both. + * @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE: if set, ensure that the + * rule verfies or fail. + * + * Since: 1.18 + */ +typedef enum { /*< flags >*/ + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE = 0, + + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET = 0x1, + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 = 0x2, + NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE = 0x4, +} NMIPRoutingRuleAsStringFlags; + +NM_AVAILABLE_IN_1_18 +NMIPRoutingRule *nm_ip_routing_rule_from_string(const char * str, + NMIPRoutingRuleAsStringFlags to_string_flags, + GHashTable * extra_args, + GError ** error); + +NM_AVAILABLE_IN_1_18 +char *nm_ip_routing_rule_to_string(const NMIPRoutingRule * self, + NMIPRoutingRuleAsStringFlags to_string_flags, + GHashTable * extra_args, + GError ** error); + +/*****************************************************************************/ + +#define NM_TYPE_SETTING_IP_CONFIG (nm_setting_ip_config_get_type()) +#define NM_SETTING_IP_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfig)) +#define NM_SETTING_IP_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_IPCONFIG, NMSettingIPConfigClass)) +#define NM_IS_SETTING_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_IP_CONFIG)) +#define NM_IS_SETTING_IP_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_IP_CONFIG)) +#define NM_SETTING_IP_CONFIG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfigClass)) + +#define NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX 30000 + +#define NM_SETTING_IP_CONFIG_METHOD "method" +#define NM_SETTING_IP_CONFIG_DNS "dns" +#define NM_SETTING_IP_CONFIG_DNS_SEARCH "dns-search" +#define NM_SETTING_IP_CONFIG_DNS_OPTIONS "dns-options" +#define NM_SETTING_IP_CONFIG_DNS_PRIORITY "dns-priority" +#define NM_SETTING_IP_CONFIG_ADDRESSES "addresses" +#define NM_SETTING_IP_CONFIG_GATEWAY "gateway" +#define NM_SETTING_IP_CONFIG_ROUTES "routes" +#define NM_SETTING_IP_CONFIG_ROUTE_METRIC "route-metric" +#define NM_SETTING_IP_CONFIG_ROUTE_TABLE "route-table" +#define NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes" +#define NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns" +#define NM_SETTING_IP_CONFIG_DHCP_HOSTNAME "dhcp-hostname" +#define NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME "dhcp-send-hostname" +#define NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS "dhcp-hostname-flags" +#define NM_SETTING_IP_CONFIG_NEVER_DEFAULT "never-default" +#define NM_SETTING_IP_CONFIG_MAY_FAIL "may-fail" +#define NM_SETTING_IP_CONFIG_DAD_TIMEOUT "dad-timeout" +#define NM_SETTING_IP_CONFIG_DHCP_TIMEOUT "dhcp-timeout" +#define NM_SETTING_IP_CONFIG_DHCP_IAID "dhcp-iaid" +#define NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS "dhcp-reject-servers" + +/* these are not real GObject properties. */ +#define NM_SETTING_IP_CONFIG_ROUTING_RULES "routing-rules" + +#define NM_SETTING_DNS_OPTION_DEBUG "debug" +#define NM_SETTING_DNS_OPTION_NDOTS "ndots" +#define NM_SETTING_DNS_OPTION_TIMEOUT "timeout" +#define NM_SETTING_DNS_OPTION_ATTEMPTS "attempts" +#define NM_SETTING_DNS_OPTION_ROTATE "rotate" +#define NM_SETTING_DNS_OPTION_NO_CHECK_NAMES "no-check-names" +#define NM_SETTING_DNS_OPTION_INET6 "inet6" +#define NM_SETTING_DNS_OPTION_IP6_BYTESTRING "ip6-bytestring" +#define NM_SETTING_DNS_OPTION_IP6_DOTINT "ip6-dotint" +#define NM_SETTING_DNS_OPTION_NO_IP6_DOTINT "no-ip6-dotint" +#define NM_SETTING_DNS_OPTION_EDNS0 "edns0" +#define NM_SETTING_DNS_OPTION_SINGLE_REQUEST "single-request" +#define NM_SETTING_DNS_OPTION_SINGLE_REQUEST_REOPEN "single-request-reopen" +#define NM_SETTING_DNS_OPTION_NO_TLD_QUERY "no-tld-query" +#define NM_SETTING_DNS_OPTION_USE_VC "use-vc" +#define NM_SETTING_DNS_OPTION_NO_RELOAD "no-reload" +#define NM_SETTING_DNS_OPTION_TRUST_AD "trust-ad" + +/** + * NMSettingIPConfig: + */ +struct _NMSettingIPConfig { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + gpointer padding[8]; +} NMSettingIPConfigClass; + +/** + * NMDhcpHostnameFlags: + * @NM_DHCP_HOSTNAME_FLAG_NONE: no flag set. The default value from + * Networkmanager global configuration is used. If such value is unset + * or still zero, the DHCP request will use standard FQDN flags, i.e. + * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE and + * %NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED for IPv4 and + * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE for IPv6. + * @NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE: whether the server should + * do the A RR (FQDN-to-address) DNS updates. + * @NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED: if set, the FQDN is encoded + * using canonical wire format. Otherwise it uses the deprecated + * ASCII encoding. This flag is allowed only for DHCPv4. + * @NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE: when not set, request the + * server to perform updates (the PTR RR and possibly the A RR + * based on the %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE flag). If + * this is set, the %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE flag + * should be cleared. + * @NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS: when set, no FQDN flags are + * sent in the DHCP FQDN option. When cleared and all other FQDN + * flags are zero, standard FQDN flags are sent. This flag is + * incompatible with any other FQDN flag. + * + * #NMDhcpHostnameFlags describe flags related to the DHCP hostname and + * FQDN. + * + * Since: 1.22 + */ +typedef enum { /*< flags >*/ + NM_DHCP_HOSTNAME_FLAG_NONE = 0x0, + + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE = 0x1, + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED = 0x2, + NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE = 0x4, + + NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS = 0x8, + +} NMDhcpHostnameFlags; + +GType nm_setting_ip_config_get_type(void); + +const char *nm_setting_ip_config_get_method(NMSettingIPConfig *setting); + +guint nm_setting_ip_config_get_num_dns(NMSettingIPConfig *setting); +const char *nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns); +void nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char *dns); +void nm_setting_ip_config_clear_dns(NMSettingIPConfig *setting); + +guint nm_setting_ip_config_get_num_dns_searches(NMSettingIPConfig *setting); +const char *nm_setting_ip_config_get_dns_search(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_add_dns_search(NMSettingIPConfig *setting, const char *dns_search); +void nm_setting_ip_config_remove_dns_search(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_remove_dns_search_by_value(NMSettingIPConfig *setting, + const char * dns_search); +void nm_setting_ip_config_clear_dns_searches(NMSettingIPConfig *setting); + +guint nm_setting_ip_config_get_num_dns_options(NMSettingIPConfig *setting); +gboolean nm_setting_ip_config_has_dns_options(NMSettingIPConfig *setting); +const char *nm_setting_ip_config_get_dns_option(NMSettingIPConfig *setting, guint idx); +gboolean nm_setting_ip_config_add_dns_option(NMSettingIPConfig *setting, const char *dns_option); +void nm_setting_ip_config_remove_dns_option(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_remove_dns_option_by_value(NMSettingIPConfig *setting, + const char * dns_option); +void nm_setting_ip_config_clear_dns_options(NMSettingIPConfig *setting, gboolean is_set); + +NM_AVAILABLE_IN_1_4 +int nm_setting_ip_config_get_dns_priority(NMSettingIPConfig *setting); + +guint nm_setting_ip_config_get_num_addresses(NMSettingIPConfig *setting); +NMIPAddress *nm_setting_ip_config_get_address(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_add_address(NMSettingIPConfig *setting, NMIPAddress *address); +void nm_setting_ip_config_remove_address(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_remove_address_by_value(NMSettingIPConfig *setting, + NMIPAddress * address); +void nm_setting_ip_config_clear_addresses(NMSettingIPConfig *setting); + +const char *nm_setting_ip_config_get_gateway(NMSettingIPConfig *setting); + +guint nm_setting_ip_config_get_num_routes(NMSettingIPConfig *setting); +NMIPRoute *nm_setting_ip_config_get_route(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_add_route(NMSettingIPConfig *setting, NMIPRoute *route); +void nm_setting_ip_config_remove_route(NMSettingIPConfig *setting, int idx); +gboolean nm_setting_ip_config_remove_route_by_value(NMSettingIPConfig *setting, NMIPRoute *route); +void nm_setting_ip_config_clear_routes(NMSettingIPConfig *setting); + +gint64 nm_setting_ip_config_get_route_metric(NMSettingIPConfig *setting); + +NM_AVAILABLE_IN_1_10 +guint32 nm_setting_ip_config_get_route_table(NMSettingIPConfig *setting); + +NM_AVAILABLE_IN_1_18 +guint nm_setting_ip_config_get_num_routing_rules(NMSettingIPConfig *setting); +NM_AVAILABLE_IN_1_18 +NMIPRoutingRule *nm_setting_ip_config_get_routing_rule(NMSettingIPConfig *setting, guint idx); +NM_AVAILABLE_IN_1_18 +void nm_setting_ip_config_add_routing_rule(NMSettingIPConfig *setting, + NMIPRoutingRule * routing_rule); +NM_AVAILABLE_IN_1_18 +void nm_setting_ip_config_remove_routing_rule(NMSettingIPConfig *setting, guint idx); +NM_AVAILABLE_IN_1_18 +void nm_setting_ip_config_clear_routing_rules(NMSettingIPConfig *setting); + +gboolean nm_setting_ip_config_get_ignore_auto_routes(NMSettingIPConfig *setting); +gboolean nm_setting_ip_config_get_ignore_auto_dns(NMSettingIPConfig *setting); + +const char *nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting); +gboolean nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting); + +gboolean nm_setting_ip_config_get_never_default(NMSettingIPConfig *setting); +gboolean nm_setting_ip_config_get_may_fail(NMSettingIPConfig *setting); +NM_AVAILABLE_IN_1_2 +int nm_setting_ip_config_get_dad_timeout(NMSettingIPConfig *setting); +NM_AVAILABLE_IN_1_2 +int nm_setting_ip_config_get_dhcp_timeout(NMSettingIPConfig *setting); +NM_AVAILABLE_IN_1_22 +const char *nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting); + +NM_AVAILABLE_IN_1_22 +NMDhcpHostnameFlags nm_setting_ip_config_get_dhcp_hostname_flags(NMSettingIPConfig *setting); + +NM_AVAILABLE_IN_1_28 +const char *const *nm_setting_ip_config_get_dhcp_reject_servers(NMSettingIPConfig *setting, + guint * out_len); +NM_AVAILABLE_IN_1_28 +void nm_setting_ip_config_add_dhcp_reject_server(NMSettingIPConfig *setting, const char *server); +NM_AVAILABLE_IN_1_28 +void nm_setting_ip_config_remove_dhcp_reject_server(NMSettingIPConfig *setting, guint idx); +NM_AVAILABLE_IN_1_28 +void nm_setting_ip_config_clear_dhcp_reject_servers(NMSettingIPConfig *setting); + +G_END_DECLS + +#endif /* NM_SETTING_IP_CONFIG_H */ diff --git a/src/libnm-core-public/nm-setting-ip-tunnel.h b/src/libnm-core-public/nm-setting-ip-tunnel.h new file mode 100644 index 0000000000..802f81e113 --- /dev/null +++ b/src/libnm-core-public/nm-setting-ip-tunnel.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_IP_TUNNEL_H__ +#define __NM_SETTING_IP_TUNNEL_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_IP_TUNNEL (nm_setting_ip_tunnel_get_type()) +#define NM_SETTING_IP_TUNNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnel)) +#define NM_SETTING_IP_TUNNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelClass)) +#define NM_IS_SETTING_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_IP_TUNNEL)) +#define NM_IS_SETTING_IP_TUNNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_IP_TUNNEL)) +#define NM_SETTING_IP_TUNNEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelClass)) + +#define NM_SETTING_IP_TUNNEL_SETTING_NAME "ip-tunnel" + +#define NM_SETTING_IP_TUNNEL_PARENT "parent" +#define NM_SETTING_IP_TUNNEL_MODE "mode" +#define NM_SETTING_IP_TUNNEL_LOCAL "local" +#define NM_SETTING_IP_TUNNEL_REMOTE "remote" +#define NM_SETTING_IP_TUNNEL_TTL "ttl" +#define NM_SETTING_IP_TUNNEL_TOS "tos" +#define NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY "path-mtu-discovery" +#define NM_SETTING_IP_TUNNEL_INPUT_KEY "input-key" +#define NM_SETTING_IP_TUNNEL_OUTPUT_KEY "output-key" +#define NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit" +#define NM_SETTING_IP_TUNNEL_FLOW_LABEL "flow-label" +#define NM_SETTING_IP_TUNNEL_MTU "mtu" +#define NM_SETTING_IP_TUNNEL_FLAGS "flags" + +/** + * NMSettingIPTunnel: + * + * IP Tunneling Settings + */ +struct _NMSettingIPTunnel { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingIPTunnelClass; + +/* + * NMIPTunnelFlags: + * @NM_IP_TUNNEL_FLAG_NONE: no flag + * @NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT: don't add encapsulation limit + * if one isn't present in inner packet + * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS: copy the traffic class field + * from the inner packet + * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL: copy the flowlabel from the + * inner packet + * @NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV: used for Mobile IPv6 + * @NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY: copy DSCP from the outer packet + * @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK: copy fwmark from inner packet + * + * IP tunnel flags. + * + * Since: 1.12 + */ +typedef enum { /*< flags, prefix=NM_IP_TUNNEL_FLAG >*/ + NM_IP_TUNNEL_FLAG_NONE = 0x0, + NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT = 0x1, + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS = 0x2, + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL = 0x4, + NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV = 0x8, + NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY = 0x10, + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK = 0x20, +} NMIPTunnelFlags; + +NM_AVAILABLE_IN_1_2 +GType nm_setting_ip_tunnel_get_type(void); + +NM_AVAILABLE_IN_1_2 +NMSetting *nm_setting_ip_tunnel_new(void); + +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_parent(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +NMIPTunnelMode nm_setting_ip_tunnel_get_mode(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_local(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_remote(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_ttl(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_tos(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_ip_tunnel_get_path_mtu_discovery(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_input_key(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_output_key(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_flow_label(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_mtu(NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_12 +NMIPTunnelFlags nm_setting_ip_tunnel_get_flags(NMSettingIPTunnel *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_IP_TUNNEL_H__ */ diff --git a/src/libnm-core-public/nm-setting-ip4-config.h b/src/libnm-core-public/nm-setting-ip4-config.h new file mode 100644 index 0000000000..b1c63a4f6e --- /dev/null +++ b/src/libnm-core-public/nm-setting-ip4-config.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_IP4_CONFIG_H__ +#define __NM_SETTING_IP4_CONFIG_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting-ip-config.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_IP4_CONFIG (nm_setting_ip4_config_get_type()) +#define NM_SETTING_IP4_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4Config)) +#define NM_SETTING_IP4_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_IP4CONFIG, NMSettingIP4ConfigClass)) +#define NM_IS_SETTING_IP4_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_IP4_CONFIG)) +#define NM_IS_SETTING_IP4_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_IP4_CONFIG)) +#define NM_SETTING_IP4_CONFIG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigClass)) + +#define NM_SETTING_IP4_CONFIG_SETTING_NAME "ipv4" + +#define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID "dhcp-client-id" +#define NM_SETTING_IP4_CONFIG_DHCP_FQDN "dhcp-fqdn" +#define NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER "dhcp-vendor-class-identifier" + +/** + * NM_SETTING_IP4_CONFIG_METHOD_AUTO: + * + * IPv4 configuration should be automatically determined via a method appropriate + * for the hardware interface, ie DHCP or PPP or some other device-specific + * manner. + */ +#define NM_SETTING_IP4_CONFIG_METHOD_AUTO "auto" + +/** + * NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL: + * + * IPv4 configuration should be automatically configured for link-local-only + * operation. + */ +#define NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL "link-local" + +/** + * NM_SETTING_IP4_CONFIG_METHOD_MANUAL: + * + * All necessary IPv4 configuration (addresses, prefix, DNS, etc) is specified + * in the setting's properties. + */ +#define NM_SETTING_IP4_CONFIG_METHOD_MANUAL "manual" + +/** + * NM_SETTING_IP4_CONFIG_METHOD_SHARED: + * + * This connection specifies configuration that allows other computers to + * connect through it to the default network (usually the Internet). The + * connection's interface will be assigned a private address, and a DHCP server, + * caching DNS server, and Network Address Translation (NAT) functionality will + * be started on this connection's interface to allow other devices to connect + * through that interface to the default network. + */ +#define NM_SETTING_IP4_CONFIG_METHOD_SHARED "shared" + +/** + * NM_SETTING_IP4_CONFIG_METHOD_DISABLED: + * + * This connection does not use or require IPv4 address and it should be disabled. + */ +#define NM_SETTING_IP4_CONFIG_METHOD_DISABLED "disabled" + +/** + * NMSettingIP4Config: + * + * IPv4 Settings + */ +struct _NMSettingIP4Config { + NMSettingIPConfig parent; +}; + +typedef struct { + NMSettingIPConfigClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingIP4ConfigClass; + +GType nm_setting_ip4_config_get_type(void); + +NMSetting *nm_setting_ip4_config_new(void); + +const char *nm_setting_ip4_config_get_dhcp_client_id(NMSettingIP4Config *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip4_config_get_dhcp_fqdn(NMSettingIP4Config *setting); + +NM_AVAILABLE_IN_1_28 +const char *nm_setting_ip4_config_get_dhcp_vendor_class_identifier(NMSettingIP4Config *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_IP4_CONFIG_H__ */ diff --git a/src/libnm-core-public/nm-setting-ip6-config.h b/src/libnm-core-public/nm-setting-ip6-config.h new file mode 100644 index 0000000000..fca6961b86 --- /dev/null +++ b/src/libnm-core-public/nm-setting-ip6-config.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_IP6_CONFIG_H__ +#define __NM_SETTING_IP6_CONFIG_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting-ip-config.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_IP6_CONFIG (nm_setting_ip6_config_get_type()) +#define NM_SETTING_IP6_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6Config)) +#define NM_SETTING_IP6_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_IP6CONFIG, NMSettingIP6ConfigClass)) +#define NM_IS_SETTING_IP6_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_IP6_CONFIG)) +#define NM_IS_SETTING_IP6_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_IP6_CONFIG)) +#define NM_SETTING_IP6_CONFIG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigClass)) + +#define NM_SETTING_IP6_CONFIG_SETTING_NAME "ipv6" + +#define NM_SETTING_IP6_CONFIG_IP6_PRIVACY "ip6-privacy" + +#define NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE "addr-gen-mode" + +#define NM_SETTING_IP6_CONFIG_TOKEN "token" + +#define NM_SETTING_IP6_CONFIG_DHCP_DUID "dhcp-duid" + +#define NM_SETTING_IP6_CONFIG_RA_TIMEOUT "ra-timeout" + +/** + * NM_SETTING_IP6_CONFIG_METHOD_IGNORE: + * + * IPv6 is not required or is handled by some other mechanism, and NetworkManager + * should not configure IPv6 for this connection. + */ +#define NM_SETTING_IP6_CONFIG_METHOD_IGNORE "ignore" + +/** + * NM_SETTING_IP6_CONFIG_METHOD_AUTO: + * + * IPv6 configuration should be automatically determined via a method appropriate + * for the hardware interface, ie router advertisements, DHCP, or PPP or some + * other device-specific manner. + */ +#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto" + +/** + * NM_SETTING_IP6_CONFIG_METHOD_DHCP: + * + * IPv6 configuration should be automatically determined via DHCPv6 only and + * router advertisements should be ignored. + */ +#define NM_SETTING_IP6_CONFIG_METHOD_DHCP "dhcp" + +/** + * NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL: + * + * IPv6 configuration should be automatically configured for link-local-only + * operation. + */ +#define NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL "link-local" + +/** + * NM_SETTING_IP6_CONFIG_METHOD_MANUAL: + * + * All necessary IPv6 configuration (addresses, prefix, DNS, etc) is specified + * in the setting's properties. + */ +#define NM_SETTING_IP6_CONFIG_METHOD_MANUAL "manual" + +/** + * NM_SETTING_IP6_CONFIG_METHOD_SHARED: + * + * This connection specifies configuration that allows other computers to + * connect through it to the default network (usually the Internet). The + * connection's interface will be assigned a private address, and router + * advertisements, a caching DNS server, and Network Address Translation (NAT) + * functionality will be started on this connection's interface to allow other + * devices to connect through that interface to the default network. (not yet + * supported for IPv6) + */ +#define NM_SETTING_IP6_CONFIG_METHOD_SHARED "shared" + +/** + * NM_SETTING_IP6_CONFIG_METHOD_DISABLED: + * + * IPv6 is disabled for the connection. + * + * Since: 1.20 + */ +#define NM_SETTING_IP6_CONFIG_METHOD_DISABLED "disabled" + +/** + * NMSettingIP6ConfigPrivacy: + * @NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: unknown or no value specified + * @NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: IPv6 Privacy Extensions are disabled + * @NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: IPv6 Privacy Extensions + * are enabled, but public addresses are preferred over temporary addresses + * @NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: IPv6 Privacy Extensions + * are enabled and temporary addresses are preferred over public addresses + * + * #NMSettingIP6ConfigPrivacy values indicate if and how IPv6 Privacy + * Extensions are used (RFC4941). + */ +typedef enum { + NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN = -1, + NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED = 0, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR = 1, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR = 2 +} NMSettingIP6ConfigPrivacy; + +/** + * NMSettingIP6ConfigAddrGenMode: + * @NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64: The Interface Identifier is derived + * from the interface hardware address. + * @NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY: The Interface Identifier + * is created by using a cryptographically secure hash of a secret host-specific + * key along with the connection identification and the network address as + * specified by RFC7217. + * + * #NMSettingIP6ConfigAddrGenMode controls how the Interface Identifier for + * RFC4862 Stateless Address Autoconfiguration is created. + * + * Since: 1.2 + */ +typedef enum { + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 = 0, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY = 1, +} NMSettingIP6ConfigAddrGenMode; + +/** + * NMSettingIP6Config: + * + * IPv6 Settings + */ +struct _NMSettingIP6Config { + NMSettingIPConfig parent; +}; + +typedef struct { + NMSettingIPConfigClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingIP6ConfigClass; + +GType nm_setting_ip6_config_get_type(void); + +NMSetting *nm_setting_ip6_config_new(void); + +NMSettingIP6ConfigPrivacy nm_setting_ip6_config_get_ip6_privacy(NMSettingIP6Config *setting); +NM_AVAILABLE_IN_1_2 +NMSettingIP6ConfigAddrGenMode nm_setting_ip6_config_get_addr_gen_mode(NMSettingIP6Config *setting); +NM_AVAILABLE_IN_1_4 +const char *nm_setting_ip6_config_get_token(NMSettingIP6Config *setting); +NM_AVAILABLE_IN_1_12 +const char *nm_setting_ip6_config_get_dhcp_duid(NMSettingIP6Config *setting); +NM_AVAILABLE_IN_1_24 +gint32 nm_setting_ip6_config_get_ra_timeout(NMSettingIP6Config *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_IP6_CONFIG_H__ */ diff --git a/src/libnm-core-public/nm-setting-macsec.h b/src/libnm-core-public/nm-setting-macsec.h new file mode 100644 index 0000000000..bc33dd9dfb --- /dev/null +++ b/src/libnm-core-public/nm-setting-macsec.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_MACSEC_H__ +#define __NM_SETTING_MACSEC_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_MACSEC (nm_setting_macsec_get_type()) +#define NM_SETTING_MACSEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_MACSEC, NMSettingMacsec)) +#define NM_SETTING_MACSEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_MACSECCONFIG, NMSettingMacsecClass)) +#define NM_IS_SETTING_MACSEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_MACSEC)) +#define NM_IS_SETTING_MACSEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_MACSEC)) +#define NM_SETTING_MACSEC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_MACSEC, NMSettingMacsecClass)) + +#define NM_SETTING_MACSEC_SETTING_NAME "macsec" + +#define NM_SETTING_MACSEC_PARENT "parent" +#define NM_SETTING_MACSEC_MODE "mode" +#define NM_SETTING_MACSEC_ENCRYPT "encrypt" +#define NM_SETTING_MACSEC_MKA_CAK "mka-cak" +#define NM_SETTING_MACSEC_MKA_CAK_FLAGS "mka-cak-flags" +#define NM_SETTING_MACSEC_MKA_CKN "mka-ckn" +#define NM_SETTING_MACSEC_PORT "port" +#define NM_SETTING_MACSEC_VALIDATION "validation" +#define NM_SETTING_MACSEC_SEND_SCI "send-sci" + +/** + * NMSettingMacsec: + * + * MACSec Settings + */ +struct _NMSettingMacsec { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingMacsecClass; + +/** + * NMSettingMacsecMode: + * @NM_SETTING_MACSEC_MODE_PSK: The CAK is pre-shared + * @NM_SETTING_MACSEC_MODE_EAP: The CAK is the result of participation in EAP + * + * #NMSettingMacsecMode controls how the CAK (Connectivity Association Key) used + * in MKA (MACsec Key Agreement) is obtained. + * + * Since: 1.6 + */ +typedef enum { + NM_SETTING_MACSEC_MODE_PSK = 0, + NM_SETTING_MACSEC_MODE_EAP = 1, +} NMSettingMacsecMode; + +/** + * NMSettingMacsecValidation: + * @NM_SETTING_MACSEC_VALIDATION_DISABLE: All incoming frames are accepted if + * possible + * @NM_SETTING_MACSEC_VALIDATION_CHECK: Non protected, invalid, or impossible to + * verify frames are accepted and counted as "invalid" + * @NM_SETTING_MACSEC_VALIDATION_STRICT: Non protected, invalid, or impossible to + * verify frames are dropped + * + * #NMSettingMacsecValidation specifies a validation mode for incoming frames. + * + * Since: 1.6 + */ +typedef enum { + NM_SETTING_MACSEC_VALIDATION_DISABLE = 0, + NM_SETTING_MACSEC_VALIDATION_CHECK = 1, + NM_SETTING_MACSEC_VALIDATION_STRICT = 2, +} NMSettingMacsecValidation; + +#define NM_SETTING_MACSEC_MKA_CAK_LENGTH 32 +#define NM_SETTING_MACSEC_MKA_CKN_LENGTH 64 + +NM_AVAILABLE_IN_1_6 +GType nm_setting_macsec_get_type(void); +NM_AVAILABLE_IN_1_6 +NMSetting *nm_setting_macsec_new(void); + +NM_AVAILABLE_IN_1_6 +const char *nm_setting_macsec_get_parent(NMSettingMacsec *setting); +NM_AVAILABLE_IN_1_6 +NMSettingMacsecMode nm_setting_macsec_get_mode(NMSettingMacsec *setting); +NM_AVAILABLE_IN_1_6 +gboolean nm_setting_macsec_get_encrypt(NMSettingMacsec *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_macsec_get_mka_cak(NMSettingMacsec *setting); +NM_AVAILABLE_IN_1_6 +NMSettingSecretFlags nm_setting_macsec_get_mka_cak_flags(NMSettingMacsec *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_macsec_get_mka_ckn(NMSettingMacsec *setting); +NM_AVAILABLE_IN_1_6 +int nm_setting_macsec_get_port(NMSettingMacsec *setting); +NM_AVAILABLE_IN_1_6 +NMSettingMacsecValidation nm_setting_macsec_get_validation(NMSettingMacsec *setting); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_macsec_get_send_sci(NMSettingMacsec *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_MACSEC_H__ */ diff --git a/src/libnm-core-public/nm-setting-macvlan.h b/src/libnm-core-public/nm-setting-macvlan.h new file mode 100644 index 0000000000..05c0b36508 --- /dev/null +++ b/src/libnm-core-public/nm-setting-macvlan.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_MACVLAN_H__ +#define __NM_SETTING_MACVLAN_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_MACVLAN (nm_setting_macvlan_get_type()) +#define NM_SETTING_MACVLAN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlan)) +#define NM_SETTING_MACVLAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_MACVLANCONFIG, NMSettingMacvlanClass)) +#define NM_IS_SETTING_MACVLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_MACVLAN)) +#define NM_IS_SETTING_MACVLAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_MACVLAN)) +#define NM_SETTING_MACVLAN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanClass)) + +#define NM_SETTING_MACVLAN_SETTING_NAME "macvlan" + +#define NM_SETTING_MACVLAN_PARENT "parent" +#define NM_SETTING_MACVLAN_MODE "mode" +#define NM_SETTING_MACVLAN_PROMISCUOUS "promiscuous" +#define NM_SETTING_MACVLAN_TAP "tap" + +/** + * NMSettingMacvlan: + * + * MAC VLAN Settings + */ +struct _NMSettingMacvlan { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingMacvlanClass; + +/** + * NMSettingMacvlanMode: + * @NM_SETTING_MACVLAN_MODE_UNKNOWN: unknown/unset mode + * @NM_SETTING_MACVLAN_MODE_VEPA: Virtual Ethernet Port Aggregator mode + * @NM_SETTING_MACVLAN_MODE_BRIDGE: bridge mode + * @NM_SETTING_MACVLAN_MODE_PRIVATE: private mode + * @NM_SETTING_MACVLAN_MODE_PASSTHRU: passthru mode + * @NM_SETTING_MACVLAN_MODE_SOURCE: source mode + **/ +typedef enum { + NM_SETTING_MACVLAN_MODE_UNKNOWN = 0, + NM_SETTING_MACVLAN_MODE_VEPA = 1, + NM_SETTING_MACVLAN_MODE_BRIDGE = 2, + NM_SETTING_MACVLAN_MODE_PRIVATE = 3, + NM_SETTING_MACVLAN_MODE_PASSTHRU = 4, + NM_SETTING_MACVLAN_MODE_SOURCE = 5, + _NM_SETTING_MACVLAN_MODE_NUM, /*< skip >*/ + NM_SETTING_MACVLAN_MODE_LAST = _NM_SETTING_MACVLAN_MODE_NUM - 1, /*< skip >*/ +} NMSettingMacvlanMode; + +NM_AVAILABLE_IN_1_2 +GType nm_setting_macvlan_get_type(void); +NM_AVAILABLE_IN_1_2 +NMSetting *nm_setting_macvlan_new(void); + +NM_AVAILABLE_IN_1_2 +const char *nm_setting_macvlan_get_parent(NMSettingMacvlan *setting); +NM_AVAILABLE_IN_1_2 +NMSettingMacvlanMode nm_setting_macvlan_get_mode(NMSettingMacvlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_macvlan_get_promiscuous(NMSettingMacvlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_macvlan_get_tap(NMSettingMacvlan *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_MACVLAN_H__ */ diff --git a/src/libnm-core-public/nm-setting-match.h b/src/libnm-core-public/nm-setting-match.h new file mode 100644 index 0000000000..9b3e29e7c0 --- /dev/null +++ b/src/libnm-core-public/nm-setting-match.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Red Hat, Inc. + */ + +#ifndef NM_SETTING_MATCH_H +#define NM_SETTING_MATCH_H + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_MATCH (nm_setting_match_get_type()) +#define NM_SETTING_MATCH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_MATCH, NMSettingMatch)) +#define NM_SETTING_MATCH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_MATCH, NMSettingMatchClass)) +#define NM_IS_SETTING_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_MATCH)) +#define NM_IS_SETTING_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_MATCH)) +#define NM_SETTING_MATCH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_MATCH, NMSettingMatchClass)) + +#define NM_SETTING_MATCH_SETTING_NAME "match" + +#define NM_SETTING_MATCH_INTERFACE_NAME "interface-name" +#define NM_SETTING_MATCH_KERNEL_COMMAND_LINE "kernel-command-line" +#define NM_SETTING_MATCH_DRIVER "driver" +#define NM_SETTING_MATCH_PATH "path" + +typedef struct _NMSettingMatchClass NMSettingMatchClass; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_match_get_type(void); +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_match_new(void); + +NM_AVAILABLE_IN_1_14 +guint nm_setting_match_get_num_interface_names(NMSettingMatch *setting); +NM_AVAILABLE_IN_1_14 +const char *nm_setting_match_get_interface_name(NMSettingMatch *setting, int idx); +NM_AVAILABLE_IN_1_14 +void nm_setting_match_remove_interface_name(NMSettingMatch *setting, int idx); +NM_AVAILABLE_IN_1_14 +gboolean nm_setting_match_remove_interface_name_by_value(NMSettingMatch *setting, + const char * interface_name); +NM_AVAILABLE_IN_1_14 +void nm_setting_match_add_interface_name(NMSettingMatch *setting, const char *interface_name); +NM_AVAILABLE_IN_1_14 +void nm_setting_match_clear_interface_names(NMSettingMatch *setting); +NM_AVAILABLE_IN_1_14 +const char *const *nm_setting_match_get_interface_names(NMSettingMatch *setting, guint *length); + +NM_AVAILABLE_IN_1_26 +guint nm_setting_match_get_num_kernel_command_lines(NMSettingMatch *setting); +NM_AVAILABLE_IN_1_26 +const char *nm_setting_match_get_kernel_command_line(NMSettingMatch *setting, guint idx); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_remove_kernel_command_line(NMSettingMatch *setting, guint idx); +NM_AVAILABLE_IN_1_26 +gboolean nm_setting_match_remove_kernel_command_line_by_value(NMSettingMatch *setting, + const char * kernel_command_line); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_add_kernel_command_line(NMSettingMatch *setting, + const char * kernel_command_line); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_clear_kernel_command_lines(NMSettingMatch *setting); +NM_AVAILABLE_IN_1_26 +const char *const *nm_setting_match_get_kernel_command_lines(NMSettingMatch *setting, + guint * length); + +NM_AVAILABLE_IN_1_26 +guint nm_setting_match_get_num_drivers(NMSettingMatch *setting); +NM_AVAILABLE_IN_1_26 +const char *nm_setting_match_get_driver(NMSettingMatch *setting, guint idx); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_remove_driver(NMSettingMatch *setting, guint idx); +NM_AVAILABLE_IN_1_26 +gboolean nm_setting_match_remove_driver_by_value(NMSettingMatch *setting, const char *driver); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_add_driver(NMSettingMatch *setting, const char *driver); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_clear_drivers(NMSettingMatch *setting); +NM_AVAILABLE_IN_1_26 +const char *const *nm_setting_match_get_drivers(NMSettingMatch *setting, guint *length); + +NM_AVAILABLE_IN_1_26 +guint nm_setting_match_get_num_paths(NMSettingMatch *setting); +NM_AVAILABLE_IN_1_26 +const char *nm_setting_match_get_path(NMSettingMatch *setting, guint idx); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_remove_path(NMSettingMatch *setting, guint idx); +NM_AVAILABLE_IN_1_26 +gboolean nm_setting_match_remove_path_by_value(NMSettingMatch *setting, const char *path); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_add_path(NMSettingMatch *setting, const char *path); +NM_AVAILABLE_IN_1_26 +void nm_setting_match_clear_paths(NMSettingMatch *setting); +NM_AVAILABLE_IN_1_26 +const char *const *nm_setting_match_get_paths(NMSettingMatch *setting, guint *length); + +G_END_DECLS + +#endif /* NM_SETTING_MATCH_H */ diff --git a/src/libnm-core-public/nm-setting-olpc-mesh.h b/src/libnm-core-public/nm-setting-olpc-mesh.h new file mode 100644 index 0000000000..fdba4a4b9a --- /dev/null +++ b/src/libnm-core-public/nm-setting-olpc-mesh.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2008 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2009 One Laptop per Child + */ + +#ifndef __NM_SETTING_OLPC_MESH_H__ +#define __NM_SETTING_OLPC_MESH_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OLPC_MESH (nm_setting_olpc_mesh_get_type()) +#define NM_SETTING_OLPC_MESH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMesh)) +#define NM_SETTING_OLPC_MESH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass)) +#define NM_IS_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OLPC_MESH)) +#define NM_IS_SETTING_OLPC_MESH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OLPC_MESH)) +#define NM_SETTING_OLPC_MESH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass)) + +#define NM_SETTING_OLPC_MESH_SETTING_NAME "802-11-olpc-mesh" + +#define NM_SETTING_OLPC_MESH_SSID "ssid" +#define NM_SETTING_OLPC_MESH_CHANNEL "channel" +#define NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS "dhcp-anycast-address" + +/** + * NMSettingOlpcMesh: + * + * OLPC Wireless Mesh Settings + */ +struct _NMSettingOlpcMesh { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingOlpcMeshClass; + +GType nm_setting_olpc_mesh_get_type(void); + +NMSetting * nm_setting_olpc_mesh_new(void); +GBytes * nm_setting_olpc_mesh_get_ssid(NMSettingOlpcMesh *setting); +guint32 nm_setting_olpc_mesh_get_channel(NMSettingOlpcMesh *setting); +const char *nm_setting_olpc_mesh_get_dhcp_anycast_address(NMSettingOlpcMesh *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_OLPC_MESH_H__ */ diff --git a/src/libnm-core-public/nm-setting-ovs-bridge.h b/src/libnm-core-public/nm-setting-ovs-bridge.h new file mode 100644 index 0000000000..b307871503 --- /dev/null +++ b/src/libnm-core-public/nm-setting-ovs-bridge.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_BRIDGE_H__ +#define __NM_SETTING_OVS_BRIDGE_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_BRIDGE (nm_setting_ovs_bridge_get_type()) +#define NM_SETTING_OVS_BRIDGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_BRIDGE, NMSettingOvsBridge)) +#define NM_SETTING_OVS_BRIDGE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OVS_BRIDGECONFIG, NMSettingOvsBridgeClass)) +#define NM_IS_SETTING_OVS_BRIDGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_BRIDGE)) +#define NM_IS_SETTING_OVS_BRIDGE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_BRIDGE)) +#define NM_SETTING_OVS_BRIDGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_BRIDGE, NMSettingOvsBridgeClass)) + +#define NM_SETTING_OVS_BRIDGE_SETTING_NAME "ovs-bridge" + +#define NM_SETTING_OVS_BRIDGE_FAIL_MODE "fail-mode" +#define NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE "mcast-snooping-enable" +#define NM_SETTING_OVS_BRIDGE_RSTP_ENABLE "rstp-enable" +#define NM_SETTING_OVS_BRIDGE_STP_ENABLE "stp-enable" +#define NM_SETTING_OVS_BRIDGE_DATAPATH_TYPE "datapath-type" + +typedef struct _NMSettingOvsBridgeClass NMSettingOvsBridgeClass; + +NM_AVAILABLE_IN_1_10 +GType nm_setting_ovs_bridge_get_type(void); +NM_AVAILABLE_IN_1_10 +NMSetting *nm_setting_ovs_bridge_new(void); + +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_bridge_get_fail_mode(NMSettingOvsBridge *self); +NM_AVAILABLE_IN_1_10 +gboolean nm_setting_ovs_bridge_get_mcast_snooping_enable(NMSettingOvsBridge *self); +NM_AVAILABLE_IN_1_10 +gboolean nm_setting_ovs_bridge_get_rstp_enable(NMSettingOvsBridge *self); +NM_AVAILABLE_IN_1_10 +gboolean nm_setting_ovs_bridge_get_stp_enable(NMSettingOvsBridge *self); +NM_AVAILABLE_IN_1_20 +const char *nm_setting_ovs_bridge_get_datapath_type(NMSettingOvsBridge *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_BRIDGE_H__ */ diff --git a/src/libnm-core-public/nm-setting-ovs-dpdk.h b/src/libnm-core-public/nm-setting-ovs-dpdk.h new file mode 100644 index 0000000000..72de2243c0 --- /dev/null +++ b/src/libnm-core-public/nm-setting-ovs-dpdk.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_DPDK_H__ +#define __NM_SETTING_OVS_DPDK_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_DPDK (nm_setting_ovs_dpdk_get_type()) +#define NM_SETTING_OVS_DPDK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_DPDK, NMSettingOvsDpdk)) +#define NM_SETTING_OVS_DPDK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OVS_DPDKCONFIG, NMSettingOvsDpdkClass)) +#define NM_IS_SETTING_OVS_DPDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_DPDK)) +#define NM_IS_SETTING_OVS_DPDK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_DPDK)) +#define NM_SETTING_OVS_DPDK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_DPDK, NMSettingOvsDpdkClass)) + +#define NM_SETTING_OVS_DPDK_SETTING_NAME "ovs-dpdk" + +#define NM_SETTING_OVS_DPDK_DEVARGS "devargs" + +typedef struct _NMSettingOvsDpdkClass NMSettingOvsDpdkClass; + +NM_AVAILABLE_IN_1_20 +GType nm_setting_ovs_dpdk_get_type(void); +NM_AVAILABLE_IN_1_20 +NMSetting *nm_setting_ovs_dpdk_new(void); + +NM_AVAILABLE_IN_1_20 +const char *nm_setting_ovs_dpdk_get_devargs(NMSettingOvsDpdk *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_DPDK_H__ */ diff --git a/src/libnm-core-public/nm-setting-ovs-external-ids.h b/src/libnm-core-public/nm-setting-ovs-external-ids.h new file mode 100644 index 0000000000..906db392f1 --- /dev/null +++ b/src/libnm-core-public/nm-setting-ovs-external-ids.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 - 2020 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_EXTERNAL_IDS_H__ +#define __NM_SETTING_OVS_EXTERNAL_IDS_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_EXTERNAL_IDS (nm_setting_ovs_external_ids_get_type()) +#define NM_SETTING_OVS_EXTERNAL_IDS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NMSettingOvsExternalIDs)) +#define NM_SETTING_OVS_EXTERNAL_IDS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + NM_TYPE_SETTING_OVS_EXTERNAL_IDS, \ + NMSettingOvsExternalIDsClass)) +#define NM_IS_SETTING_OVS_EXTERNAL_IDS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_EXTERNAL_IDS)) +#define NM_IS_SETTING_OVS_EXTERNAL_IDS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_EXTERNAL_IDS)) +#define NM_SETTING_OVS_EXTERNAL_IDS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + NM_TYPE_SETTING_OVS_EXTERNAL_IDS, \ + NMSettingOvsExternalIDsClass)) + +#define NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME "ovs-external-ids" + +#define NM_SETTING_OVS_EXTERNAL_IDS_DATA "data" + +typedef struct _NMSettingOvsExternalIDsClass NMSettingOvsExternalIDsClass; + +NM_AVAILABLE_IN_1_30 +GType nm_setting_ovs_external_ids_get_type(void); + +NM_AVAILABLE_IN_1_30 +NMSetting *nm_setting_ovs_external_ids_new(void); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_30 +const char *const *nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting, + guint * out_len); + +NM_AVAILABLE_IN_1_30 +const char *nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *setting, const char *key); + +NM_AVAILABLE_IN_1_30 +void nm_setting_ovs_external_ids_set_data(NMSettingOvsExternalIDs *setting, + const char * key, + const char * val); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_30 +gboolean nm_setting_ovs_external_ids_check_key(const char *key, GError **error); +NM_AVAILABLE_IN_1_30 +gboolean nm_setting_ovs_external_ids_check_val(const char *val, GError **error); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_EXTERNAL_IDS_H__ */ diff --git a/src/libnm-core-public/nm-setting-ovs-interface.h b/src/libnm-core-public/nm-setting-ovs-interface.h new file mode 100644 index 0000000000..47ad5817cd --- /dev/null +++ b/src/libnm-core-public/nm-setting-ovs-interface.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_INTERFACE_H__ +#define __NM_SETTING_OVS_INTERFACE_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_get_type()) +#define NM_SETTING_OVS_INTERFACE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_INTERFACE, NMSettingOvsInterface)) +#define NM_SETTING_OVS_INTERFACE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + NM_TYPE_SETTING_OVS_INTERFACECONFIG, \ + NMSettingOvsInterfaceClass)) +#define NM_IS_SETTING_OVS_INTERFACE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_INTERFACE)) +#define NM_IS_SETTING_OVS_INTERFACE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_INTERFACE)) +#define NM_SETTING_OVS_INTERFACE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_INTERFACE, NMSettingOvsInterfaceClass)) + +#define NM_SETTING_OVS_INTERFACE_SETTING_NAME "ovs-interface" + +#define NM_SETTING_OVS_INTERFACE_TYPE "type" + +typedef struct _NMSettingOvsInterfaceClass NMSettingOvsInterfaceClass; + +NM_AVAILABLE_IN_1_10 +GType nm_setting_ovs_interface_get_type(void); +NM_AVAILABLE_IN_1_10 +NMSetting *nm_setting_ovs_interface_new(void); + +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_interface_get_interface_type(NMSettingOvsInterface *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_INTERFACE_H__ */ diff --git a/src/libnm-core-public/nm-setting-ovs-patch.h b/src/libnm-core-public/nm-setting-ovs-patch.h new file mode 100644 index 0000000000..fd80d45a48 --- /dev/null +++ b/src/libnm-core-public/nm-setting-ovs-patch.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_PATCH_H__ +#define __NM_SETTING_OVS_PATCH_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_PATCH (nm_setting_ovs_patch_get_type()) +#define NM_SETTING_OVS_PATCH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_PATCH, NMSettingOvsPatch)) +#define NM_SETTING_OVS_PATCH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OVS_PATCHCONFIG, NMSettingOvsPatchClass)) +#define NM_IS_SETTING_OVS_PATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_PATCH)) +#define NM_IS_SETTING_OVS_PATCH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_PATCH)) +#define NM_SETTING_OVS_PATCH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_PATCH, NMSettingOvsPatchClass)) + +#define NM_SETTING_OVS_PATCH_SETTING_NAME "ovs-patch" + +#define NM_SETTING_OVS_PATCH_PEER "peer" + +typedef struct _NMSettingOvsPatchClass NMSettingOvsPatchClass; + +NM_AVAILABLE_IN_1_10 +GType nm_setting_ovs_patch_get_type(void); +NM_AVAILABLE_IN_1_10 +NMSetting *nm_setting_ovs_patch_new(void); + +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_patch_get_peer(NMSettingOvsPatch *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_PATCH_H__ */ diff --git a/src/libnm-core-public/nm-setting-ovs-port.h b/src/libnm-core-public/nm-setting-ovs-port.h new file mode 100644 index 0000000000..06d3a2aa0f --- /dev/null +++ b/src/libnm-core-public/nm-setting-ovs-port.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_PORT_H__ +#define __NM_SETTING_OVS_PORT_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_PORT (nm_setting_ovs_port_get_type()) +#define NM_SETTING_OVS_PORT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_PORT, NMSettingOvsPort)) +#define NM_SETTING_OVS_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_OVS_PORTCONFIG, NMSettingOvsPortClass)) +#define NM_IS_SETTING_OVS_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_PORT)) +#define NM_IS_SETTING_OVS_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_PORT)) +#define NM_SETTING_OVS_PORT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_OVS_PORT, NMSettingOvsPortClass)) + +#define NM_SETTING_OVS_PORT_SETTING_NAME "ovs-port" + +#define NM_SETTING_OVS_PORT_VLAN_MODE "vlan-mode" +#define NM_SETTING_OVS_PORT_TAG "tag" +#define NM_SETTING_OVS_PORT_LACP "lacp" +#define NM_SETTING_OVS_PORT_BOND_MODE "bond-mode" +#define NM_SETTING_OVS_PORT_BOND_UPDELAY "bond-updelay" +#define NM_SETTING_OVS_PORT_BOND_DOWNDELAY "bond-downdelay" + +typedef struct _NMSettingOvsPortClass NMSettingOvsPortClass; + +NM_AVAILABLE_IN_1_10 +GType nm_setting_ovs_port_get_type(void); +NM_AVAILABLE_IN_1_10 +NMSetting *nm_setting_ovs_port_new(void); + +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_port_get_vlan_mode(NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +guint nm_setting_ovs_port_get_tag(NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_port_get_lacp(NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_port_get_bond_mode(NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +guint nm_setting_ovs_port_get_bond_updelay(NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +guint nm_setting_ovs_port_get_bond_downdelay(NMSettingOvsPort *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_PORT_H__ */ diff --git a/src/libnm-core-public/nm-setting-ppp.h b/src/libnm-core-public/nm-setting-ppp.h new file mode 100644 index 0000000000..91c5347f07 --- /dev/null +++ b/src/libnm-core-public/nm-setting-ppp.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2008 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_PPP_H__ +#define __NM_SETTING_PPP_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_PPP (nm_setting_ppp_get_type()) +#define NM_SETTING_PPP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_PPP, NMSettingPpp)) +#define NM_SETTING_PPP_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_PPP, NMSettingPppClass)) +#define NM_IS_SETTING_PPP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_PPP)) +#define NM_IS_SETTING_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_PPP)) +#define NM_SETTING_PPP_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_PPP, NMSettingPppClass)) + +#define NM_SETTING_PPP_SETTING_NAME "ppp" + +#define NM_SETTING_PPP_NOAUTH "noauth" +#define NM_SETTING_PPP_REFUSE_EAP "refuse-eap" +#define NM_SETTING_PPP_REFUSE_PAP "refuse-pap" +#define NM_SETTING_PPP_REFUSE_CHAP "refuse-chap" +#define NM_SETTING_PPP_REFUSE_MSCHAP "refuse-mschap" +#define NM_SETTING_PPP_REFUSE_MSCHAPV2 "refuse-mschapv2" +#define NM_SETTING_PPP_NOBSDCOMP "nobsdcomp" +#define NM_SETTING_PPP_NODEFLATE "nodeflate" +#define NM_SETTING_PPP_NO_VJ_COMP "no-vj-comp" +#define NM_SETTING_PPP_REQUIRE_MPPE "require-mppe" +#define NM_SETTING_PPP_REQUIRE_MPPE_128 "require-mppe-128" +#define NM_SETTING_PPP_MPPE_STATEFUL "mppe-stateful" +#define NM_SETTING_PPP_CRTSCTS "crtscts" +#define NM_SETTING_PPP_BAUD "baud" +#define NM_SETTING_PPP_MRU "mru" +#define NM_SETTING_PPP_MTU "mtu" +#define NM_SETTING_PPP_LCP_ECHO_FAILURE "lcp-echo-failure" +#define NM_SETTING_PPP_LCP_ECHO_INTERVAL "lcp-echo-interval" + +/** + * NMSettingPpp: + * + * Point-to-Point Protocol Settings + */ +struct _NMSettingPpp { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingPppClass; + +GType nm_setting_ppp_get_type(void); + +NMSetting *nm_setting_ppp_new(void); +gboolean nm_setting_ppp_get_noauth(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_refuse_eap(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_refuse_pap(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_refuse_chap(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_refuse_mschap(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_refuse_mschapv2(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_nobsdcomp(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_nodeflate(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_no_vj_comp(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_require_mppe(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_require_mppe_128(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_mppe_stateful(NMSettingPpp *setting); +gboolean nm_setting_ppp_get_crtscts(NMSettingPpp *setting); +guint32 nm_setting_ppp_get_baud(NMSettingPpp *setting); +guint32 nm_setting_ppp_get_mru(NMSettingPpp *setting); +guint32 nm_setting_ppp_get_mtu(NMSettingPpp *setting); +guint32 nm_setting_ppp_get_lcp_echo_failure(NMSettingPpp *setting); +guint32 nm_setting_ppp_get_lcp_echo_interval(NMSettingPpp *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_PPP_H__ */ diff --git a/src/libnm-core-public/nm-setting-pppoe.h b/src/libnm-core-public/nm-setting-pppoe.h new file mode 100644 index 0000000000..0a30f5a189 --- /dev/null +++ b/src/libnm-core-public/nm-setting-pppoe.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2011 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_PPPOE_H__ +#define __NM_SETTING_PPPOE_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_PPPOE (nm_setting_pppoe_get_type()) +#define NM_SETTING_PPPOE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_PPPOE, NMSettingPppoe)) +#define NM_SETTING_PPPOE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_PPPOE, NMSettingPppoeClass)) +#define NM_IS_SETTING_PPPOE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_PPPOE)) +#define NM_IS_SETTING_PPPOE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_PPPOE)) +#define NM_SETTING_PPPOE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_PPPOE, NMSettingPppoeClass)) + +#define NM_SETTING_PPPOE_SETTING_NAME "pppoe" + +#define NM_SETTING_PPPOE_PARENT "parent" +#define NM_SETTING_PPPOE_SERVICE "service" +#define NM_SETTING_PPPOE_USERNAME "username" +#define NM_SETTING_PPPOE_PASSWORD "password" +#define NM_SETTING_PPPOE_PASSWORD_FLAGS "password-flags" + +/** + * NMSettingPppoe: + * + * PPP-over-Ethernet Settings + */ +struct _NMSettingPppoe { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingPppoeClass; + +GType nm_setting_pppoe_get_type(void); + +NMSetting *nm_setting_pppoe_new(void); +NM_AVAILABLE_IN_1_10 +const char * nm_setting_pppoe_get_parent(NMSettingPppoe *setting); +const char * nm_setting_pppoe_get_service(NMSettingPppoe *setting); +const char * nm_setting_pppoe_get_username(NMSettingPppoe *setting); +const char * nm_setting_pppoe_get_password(NMSettingPppoe *setting); +NMSettingSecretFlags nm_setting_pppoe_get_password_flags(NMSettingPppoe *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_PPPOE_H__ */ diff --git a/src/libnm-core-public/nm-setting-proxy.h b/src/libnm-core-public/nm-setting-proxy.h new file mode 100644 index 0000000000..70227df169 --- /dev/null +++ b/src/libnm-core-public/nm-setting-proxy.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2016 Atul Anand . + */ + +#ifndef __NM_SETTING_PROXY_H__ +#define __NM_SETTING_PROXY_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +/** + * NMSettingProxyMethod: + * @NM_SETTING_PROXY_METHOD_NONE: No Proxy for the Connection + * @NM_SETTING_PROXY_METHOD_AUTO: DHCP obtained Proxy/ Manual override + * + * The Proxy method. + * + * Since: 1.6 + */ +typedef enum { + NM_SETTING_PROXY_METHOD_NONE = 0, + NM_SETTING_PROXY_METHOD_AUTO = 1, +} NMSettingProxyMethod; + +#define NM_TYPE_SETTING_PROXY (nm_setting_proxy_get_type()) +#define NM_SETTING_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_PROXY, NMSettingProxy)) +#define NM_SETTING_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_PROXY, NMSettingProxyClass)) +#define NM_IS_SETTING_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_PROXY)) +#define NM_IS_SETTING_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_PROXY)) +#define NM_SETTING_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_PROXY, NMSettingProxyClass)) + +#define NM_SETTING_PROXY_SETTING_NAME "proxy" + +#define NM_SETTING_PROXY_METHOD "method" +#define NM_SETTING_PROXY_BROWSER_ONLY "browser-only" +#define NM_SETTING_PROXY_PAC_URL "pac-url" +#define NM_SETTING_PROXY_PAC_SCRIPT "pac-script" + +/** + * NMSettingProxy: + * + * WWW Proxy Settings + */ +struct _NMSettingProxy { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + gpointer padding[4]; +} NMSettingProxyClass; + +NM_AVAILABLE_IN_1_6 +GType nm_setting_proxy_get_type(void); + +NM_AVAILABLE_IN_1_6 +NMSetting *nm_setting_proxy_new(void); + +NM_AVAILABLE_IN_1_6 +NMSettingProxyMethod nm_setting_proxy_get_method(NMSettingProxy *setting); +NM_AVAILABLE_IN_1_6 +gboolean nm_setting_proxy_get_browser_only(NMSettingProxy *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_proxy_get_pac_url(NMSettingProxy *setting); +NM_AVAILABLE_IN_1_6 +const char *nm_setting_proxy_get_pac_script(NMSettingProxy *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_PROXY_H__ */ diff --git a/src/libnm-core-public/nm-setting-serial.h b/src/libnm-core-public/nm-setting-serial.h new file mode 100644 index 0000000000..abd232e8f1 --- /dev/null +++ b/src/libnm-core-public/nm-setting-serial.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2008 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_SERIAL_H__ +#define __NM_SETTING_SERIAL_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_SERIAL (nm_setting_serial_get_type()) +#define NM_SETTING_SERIAL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_SERIAL, NMSettingSerial)) +#define NM_SETTING_SERIAL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_SERIAL, NMSettingSerialClass)) +#define NM_IS_SETTING_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_SERIAL)) +#define NM_IS_SETTING_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_SERIAL)) +#define NM_SETTING_SERIAL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_SERIAL, NMSettingSerialClass)) + +#define NM_SETTING_SERIAL_SETTING_NAME "serial" + +/** + * NMSettingSerialParity: + * @NM_SETTING_SERIAL_PARITY_NONE: No parity bits (default) + * @NM_SETTING_SERIAL_PARITY_EVEN: Even parity + * @NM_SETTING_SERIAL_PARITY_ODD: Odd parity + * + * The parity setting of a serial port. + */ +typedef enum { + NM_SETTING_SERIAL_PARITY_NONE = 0, + NM_SETTING_SERIAL_PARITY_EVEN, + NM_SETTING_SERIAL_PARITY_ODD +} NMSettingSerialParity; + +#define NM_SETTING_SERIAL_BAUD "baud" +#define NM_SETTING_SERIAL_BITS "bits" +#define NM_SETTING_SERIAL_PARITY "parity" +#define NM_SETTING_SERIAL_STOPBITS "stopbits" +#define NM_SETTING_SERIAL_SEND_DELAY "send-delay" + +/** + * NMSettingSerial: + * + * Serial Link Settings + */ +struct _NMSettingSerial { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingSerialClass; + +GType nm_setting_serial_get_type(void); + +NMSetting * nm_setting_serial_new(void); +guint nm_setting_serial_get_baud(NMSettingSerial *setting); +guint nm_setting_serial_get_bits(NMSettingSerial *setting); +NMSettingSerialParity nm_setting_serial_get_parity(NMSettingSerial *setting); +guint nm_setting_serial_get_stopbits(NMSettingSerial *setting); +guint64 nm_setting_serial_get_send_delay(NMSettingSerial *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_SERIAL_H__ */ diff --git a/src/libnm-core-public/nm-setting-sriov.h b/src/libnm-core-public/nm-setting-sriov.h new file mode 100644 index 0000000000..fe5fc3766f --- /dev/null +++ b/src/libnm-core-public/nm-setting-sriov.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Red Hat, Inc. + */ + +#ifndef NM_SETTING_SRIOV_H +#define NM_SETTING_SRIOV_H + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_SRIOV (nm_setting_sriov_get_type()) +#define NM_SETTING_SRIOV(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriov)) +#define NM_SETTING_SRIOV_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass)) +#define NM_IS_SETTING_SRIOV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_SRIOV)) +#define NM_IS_SETTING_SRIOV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_SRIOV)) +#define NM_SETTING_SRIOV_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass)) + +#define NM_SETTING_SRIOV_SETTING_NAME "sriov" + +#define NM_SETTING_SRIOV_TOTAL_VFS "total-vfs" +#define NM_SETTING_SRIOV_VFS "vfs" +#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS "autoprobe-drivers" + +#define NM_SRIOV_VF_ATTRIBUTE_MAC "mac" +#define NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK "spoof-check" +#define NM_SRIOV_VF_ATTRIBUTE_TRUST "trust" +#define NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE "min-tx-rate" +#define NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE "max-tx-rate" + +typedef struct _NMSettingSriovClass NMSettingSriovClass; +typedef struct _NMSriovVF NMSriovVF; + +/** + * NMSriovVFVlanProtocol: + * @NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q: use 802.1Q + * @NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD: use 802.1ad + * + * #NMSriovVFVlanProtocol indicates the VLAN protocol to use. + * + * Since: 1.14 + */ +typedef enum { + NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q = 0, + NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD = 1, +} NMSriovVFVlanProtocol; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_sriov_get_type(void); +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_sriov_new(void); +NM_AVAILABLE_IN_1_14 +guint nm_setting_sriov_get_total_vfs(NMSettingSriov *setting); +NM_AVAILABLE_IN_1_14 +guint nm_setting_sriov_get_num_vfs(NMSettingSriov *setting); +NM_AVAILABLE_IN_1_14 +NMSriovVF *nm_setting_sriov_get_vf(NMSettingSriov *setting, guint idx); +NM_AVAILABLE_IN_1_14 +void nm_setting_sriov_add_vf(NMSettingSriov *setting, NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +void nm_setting_sriov_remove_vf(NMSettingSriov *setting, guint idx); +NM_AVAILABLE_IN_1_14 +gboolean nm_setting_sriov_remove_vf_by_index(NMSettingSriov *setting, guint index); +NM_AVAILABLE_IN_1_14 +void nm_setting_sriov_clear_vfs(NMSettingSriov *setting); +NM_AVAILABLE_IN_1_14 +NMTernary nm_setting_sriov_get_autoprobe_drivers(NMSettingSriov *setting); + +NM_AVAILABLE_IN_1_14 +gboolean nm_sriov_vf_add_vlan(NMSriovVF *vf, guint vlan_id); +NM_AVAILABLE_IN_1_14 +gboolean nm_sriov_vf_remove_vlan(NMSriovVF *vf, guint vlan_id); +NM_AVAILABLE_IN_1_14 +const guint *nm_sriov_vf_get_vlan_ids(const NMSriovVF *vf, guint *length); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_set_vlan_qos(NMSriovVF *vf, guint vlan_id, guint32 qos); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_set_vlan_protocol(NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol); +NM_AVAILABLE_IN_1_14 +guint32 nm_sriov_vf_get_vlan_qos(const NMSriovVF *vf, guint vlan_id); +NM_AVAILABLE_IN_1_14 +NMSriovVFVlanProtocol nm_sriov_vf_get_vlan_protocol(const NMSriovVF *vf, guint vlan_id); + +NM_AVAILABLE_IN_1_14 +GType nm_sriov_vf_get_type(void); +NM_AVAILABLE_IN_1_14 +NMSriovVF *nm_sriov_vf_new(guint index); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_ref(NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_unref(NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +gboolean nm_sriov_vf_equal(const NMSriovVF *vf, const NMSriovVF *other); +NM_AVAILABLE_IN_1_14 +NMSriovVF *nm_sriov_vf_dup(const NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +guint nm_sriov_vf_get_index(const NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_set_attribute(NMSriovVF *vf, const char *name, GVariant *value); +NM_AVAILABLE_IN_1_14 +const char **nm_sriov_vf_get_attribute_names(const NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +GVariant *nm_sriov_vf_get_attribute(const NMSriovVF *vf, const char *name); +NM_AVAILABLE_IN_1_14 +gboolean +nm_sriov_vf_attribute_validate(const char *name, GVariant *value, gboolean *known, GError **error); + +G_END_DECLS + +#endif /* NM_SETTING_SRIOV_H */ diff --git a/src/libnm-core-public/nm-setting-tc-config.h b/src/libnm-core-public/nm-setting-tc-config.h new file mode 100644 index 0000000000..a2bc9a0dae --- /dev/null +++ b/src/libnm-core-public/nm-setting-tc-config.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef NM_SETTING_TC_CONFIG_H +#define NM_SETTING_TC_CONFIG_H + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +typedef struct NMTCQdisc NMTCQdisc; + +NM_AVAILABLE_IN_1_12 +GType nm_tc_qdisc_get_type(void); + +NM_AVAILABLE_IN_1_12 +NMTCQdisc *nm_tc_qdisc_new(const char *kind, guint32 parent, GError **error); + +NM_AVAILABLE_IN_1_12 +void nm_tc_qdisc_ref(NMTCQdisc *qdisc); +NM_AVAILABLE_IN_1_12 +void nm_tc_qdisc_unref(NMTCQdisc *qdisc); +NM_AVAILABLE_IN_1_12 +gboolean nm_tc_qdisc_equal(NMTCQdisc *qdisc, NMTCQdisc *other); + +NM_AVAILABLE_IN_1_12 +NMTCQdisc *nm_tc_qdisc_dup(NMTCQdisc *qdisc); + +NM_AVAILABLE_IN_1_12 +const char *nm_tc_qdisc_get_kind(NMTCQdisc *qdisc); +NM_AVAILABLE_IN_1_12 +guint32 nm_tc_qdisc_get_handle(NMTCQdisc *qdisc); +NM_AVAILABLE_IN_1_12 +void nm_tc_qdisc_set_handle(NMTCQdisc *qdisc, guint32 handle); +NM_AVAILABLE_IN_1_12 +guint32 nm_tc_qdisc_get_parent(NMTCQdisc *qdisc); + +NM_AVAILABLE_IN_1_18 +const char **nm_tc_qdisc_get_attribute_names(NMTCQdisc *qdisc); +NM_AVAILABLE_IN_1_18 +GVariant *nm_tc_qdisc_get_attribute(NMTCQdisc *qdisc, const char *name); +NM_AVAILABLE_IN_1_18 +void nm_tc_qdisc_set_attribute(NMTCQdisc *qdisc, const char *name, GVariant *value); + +typedef struct NMTCAction NMTCAction; + +NM_AVAILABLE_IN_1_12 +GType nm_tc_action_get_type(void); + +NM_AVAILABLE_IN_1_12 +NMTCAction *nm_tc_action_new(const char *kind, GError **error); + +NM_AVAILABLE_IN_1_12 +void nm_tc_action_ref(NMTCAction *action); +NM_AVAILABLE_IN_1_12 +void nm_tc_action_unref(NMTCAction *action); +NM_AVAILABLE_IN_1_12 +gboolean nm_tc_action_equal(NMTCAction *action, NMTCAction *other); + +NM_AVAILABLE_IN_1_12 +NMTCAction *nm_tc_action_dup(NMTCAction *action); + +NM_AVAILABLE_IN_1_12 +const char *nm_tc_action_get_kind(NMTCAction *action); + +NM_AVAILABLE_IN_1_12 +char **nm_tc_action_get_attribute_names(NMTCAction *action); +NM_AVAILABLE_IN_1_12 +GVariant *nm_tc_action_get_attribute(NMTCAction *action, const char *name); +NM_AVAILABLE_IN_1_12 +void nm_tc_action_set_attribute(NMTCAction *action, const char *name, GVariant *value); + +typedef struct NMTCTfilter NMTCTfilter; + +NM_AVAILABLE_IN_1_12 +GType nm_tc_tfilter_get_type(void); + +NM_AVAILABLE_IN_1_12 +NMTCTfilter *nm_tc_tfilter_new(const char *kind, guint32 parent, GError **error); + +NM_AVAILABLE_IN_1_12 +void nm_tc_tfilter_ref(NMTCTfilter *tfilter); +NM_AVAILABLE_IN_1_12 +void nm_tc_tfilter_unref(NMTCTfilter *tfilter); +NM_AVAILABLE_IN_1_12 +gboolean nm_tc_tfilter_equal(NMTCTfilter *tfilter, NMTCTfilter *other); + +NM_AVAILABLE_IN_1_12 +NMTCTfilter *nm_tc_tfilter_dup(NMTCTfilter *tfilter); + +NM_AVAILABLE_IN_1_12 +const char *nm_tc_tfilter_get_kind(NMTCTfilter *tfilter); +NM_AVAILABLE_IN_1_12 +guint32 nm_tc_tfilter_get_handle(NMTCTfilter *tfilter); +NM_AVAILABLE_IN_1_12 +void nm_tc_tfilter_set_handle(NMTCTfilter *tfilter, guint32 handle); +NM_AVAILABLE_IN_1_12 +guint32 nm_tc_tfilter_get_parent(NMTCTfilter *tfilter); +NM_AVAILABLE_IN_1_12 +NMTCAction *nm_tc_tfilter_get_action(NMTCTfilter *tfilter); +NM_AVAILABLE_IN_1_12 +void nm_tc_tfilter_set_action(NMTCTfilter *tfilter, NMTCAction *action); + +#define NM_TYPE_SETTING_TC_CONFIG (nm_setting_tc_config_get_type()) +#define NM_SETTING_TC_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_TC_CONFIG, NMSettingTCConfig)) +#define NM_SETTING_TC_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_TC_CONFIG, NMSettingTCConfigClass)) +#define NM_IS_SETTING_TC_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_TC_CONFIG)) +#define NM_IS_SETTING_TC_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_TC_CONFIG)) +#define NM_SETTING_TC_CONFIG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_TC_CONFIG, NMSettingTCConfigClass)) + +#define NM_SETTING_TC_CONFIG_SETTING_NAME "tc" + +#define NM_SETTING_TC_CONFIG_QDISCS "qdiscs" +#define NM_SETTING_TC_CONFIG_TFILTERS "tfilters" + +typedef struct _NMSettingTCConfigClass NMSettingTCConfigClass; + +GType nm_setting_tc_config_get_type(void); + +NM_AVAILABLE_IN_1_12 +NMSetting *nm_setting_tc_config_new(void); + +NM_AVAILABLE_IN_1_12 +guint nm_setting_tc_config_get_num_qdiscs(NMSettingTCConfig *setting); +NM_AVAILABLE_IN_1_12 +NMTCQdisc *nm_setting_tc_config_get_qdisc(NMSettingTCConfig *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_tc_config_add_qdisc(NMSettingTCConfig *setting, NMTCQdisc *qdisc); +NM_AVAILABLE_IN_1_12 +void nm_setting_tc_config_remove_qdisc(NMSettingTCConfig *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_tc_config_remove_qdisc_by_value(NMSettingTCConfig *setting, NMTCQdisc *qdisc); +NM_AVAILABLE_IN_1_12 +void nm_setting_tc_config_clear_qdiscs(NMSettingTCConfig *setting); + +NM_AVAILABLE_IN_1_12 +guint nm_setting_tc_config_get_num_tfilters(NMSettingTCConfig *setting); +NM_AVAILABLE_IN_1_12 +NMTCTfilter *nm_setting_tc_config_get_tfilter(NMSettingTCConfig *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_tc_config_add_tfilter(NMSettingTCConfig *setting, NMTCTfilter *tfilter); +NM_AVAILABLE_IN_1_12 +void nm_setting_tc_config_remove_tfilter(NMSettingTCConfig *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_tc_config_remove_tfilter_by_value(NMSettingTCConfig *setting, + NMTCTfilter * tfilter); +NM_AVAILABLE_IN_1_12 +void nm_setting_tc_config_clear_tfilters(NMSettingTCConfig *setting); + +G_END_DECLS + +#endif /* NM_SETTING_TC_CONFIG_H */ diff --git a/src/libnm-core-public/nm-setting-team-port.h b/src/libnm-core-public/nm-setting-team-port.h new file mode 100644 index 0000000000..4d4d9bdca0 --- /dev/null +++ b/src/libnm-core-public/nm-setting-team-port.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2013 Jiri Pirko + */ + +#ifndef __NM_SETTING_TEAM_PORT_H__ +#define __NM_SETTING_TEAM_PORT_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" +#include "nm-setting-team.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_TEAM_PORT (nm_setting_team_port_get_type()) +#define NM_SETTING_TEAM_PORT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPort)) +#define NM_SETTING_TEAM_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortClass)) +#define NM_IS_SETTING_TEAM_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_TEAM_PORT)) +#define NM_IS_SETTING_TEAM_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_TEAM_PORT)) +#define NM_SETTING_TEAM_PORT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortClass)) + +#define NM_SETTING_TEAM_PORT_SETTING_NAME "team-port" + +#define NM_SETTING_TEAM_PORT_CONFIG "config" +#define NM_SETTING_TEAM_PORT_QUEUE_ID "queue-id" +#define NM_SETTING_TEAM_PORT_PRIO "prio" +#define NM_SETTING_TEAM_PORT_STICKY "sticky" +#define NM_SETTING_TEAM_PORT_LACP_PRIO "lacp-prio" +#define NM_SETTING_TEAM_PORT_LACP_KEY "lacp-key" +#define NM_SETTING_TEAM_PORT_LINK_WATCHERS "link-watchers" + +#define NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT -1 +#define NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT 255 + +/** + * NMSettingTeamPort: + * + * Team Port Settings + */ +struct _NMSettingTeamPort { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingTeamPortClass; + +GType nm_setting_team_port_get_type(void); + +NMSetting *nm_setting_team_port_new(void); + +const char *nm_setting_team_port_get_config(NMSettingTeamPort *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_port_get_queue_id(NMSettingTeamPort *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_port_get_prio(NMSettingTeamPort *setting); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_port_get_sticky(NMSettingTeamPort *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_port_get_lacp_prio(NMSettingTeamPort *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_port_get_lacp_key(NMSettingTeamPort *setting); +NM_AVAILABLE_IN_1_12 +guint nm_setting_team_port_get_num_link_watchers(NMSettingTeamPort *setting); +NM_AVAILABLE_IN_1_12 +NMTeamLinkWatcher *nm_setting_team_port_get_link_watcher(NMSettingTeamPort *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_port_add_link_watcher(NMSettingTeamPort *setting, + NMTeamLinkWatcher *link_watcher); +NM_AVAILABLE_IN_1_12 +void nm_setting_team_port_remove_link_watcher(NMSettingTeamPort *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_port_remove_link_watcher_by_value(NMSettingTeamPort *setting, + NMTeamLinkWatcher *link_watcher); +NM_AVAILABLE_IN_1_12 +void nm_setting_team_port_clear_link_watchers(NMSettingTeamPort *setting); +G_END_DECLS + +#endif /* __NM_SETTING_TEAM_PORT_H__ */ diff --git a/src/libnm-core-public/nm-setting-team.h b/src/libnm-core-public/nm-setting-team.h new file mode 100644 index 0000000000..3f40c8cb9b --- /dev/null +++ b/src/libnm-core-public/nm-setting-team.h @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2013 Jiri Pirko + */ + +#ifndef __NM_SETTING_TEAM_H__ +#define __NM_SETTING_TEAM_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +/** + * NMTeamLinkWatcherArpPingFlags: + * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE: no one among the arp_ping link watcher + * boolean options ('validate_active', 'validate_inactive', 'send_always') is + * enabled (set to true). + * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE: the arp_ping link watcher + * option 'validate_active' is enabled (set to true). + * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE: the arp_ping link watcher + * option 'validate_inactive' is enabled (set to true). + * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS: the arp_ping link watcher option + * 'send_always' is enabled (set to true). + */ +typedef enum { /*< flags >*/ + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE = 0, /*< skip >*/ + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE = 0x2, + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE = 0x4, + NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS = 0x8, +} NMTeamLinkWatcherArpPingFlags; + +#define NM_TEAM_LINK_WATCHER_ETHTOOL "ethtool" +#define NM_TEAM_LINK_WATCHER_ARP_PING "arp_ping" +#define NM_TEAM_LINK_WATCHER_NSNA_PING "nsna_ping" + +typedef struct NMTeamLinkWatcher NMTeamLinkWatcher; + +GType nm_team_link_watcher_get_type(void); + +NM_AVAILABLE_IN_1_12 +NMTeamLinkWatcher *nm_team_link_watcher_new_ethtool(int delay_up, int delay_down, GError **error); +NM_AVAILABLE_IN_1_12 +NMTeamLinkWatcher *nm_team_link_watcher_new_nsna_ping(int init_wait, + int interval, + int missed_max, + const char *target_host, + GError ** error); +NM_AVAILABLE_IN_1_12 +NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping(int init_wait, + int interval, + int missed_max, + const char * target_host, + const char * source_host, + NMTeamLinkWatcherArpPingFlags flags, + GError ** error); +NM_AVAILABLE_IN_1_16 +NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping2(int init_wait, + int interval, + int missed_max, + int vlanid, + const char * target_host, + const char * source_host, + NMTeamLinkWatcherArpPingFlags flags, + GError ** error); +NM_AVAILABLE_IN_1_12 +void nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +void nm_team_link_watcher_unref(NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +gboolean nm_team_link_watcher_equal(const NMTeamLinkWatcher *watcher, + const NMTeamLinkWatcher *other); +NM_AVAILABLE_IN_1_12 +NMTeamLinkWatcher *nm_team_link_watcher_dup(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +const char *nm_team_link_watcher_get_name(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +int nm_team_link_watcher_get_delay_up(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +int nm_team_link_watcher_get_delay_down(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +int nm_team_link_watcher_get_init_wait(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +int nm_team_link_watcher_get_interval(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +int nm_team_link_watcher_get_missed_max(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +const char *nm_team_link_watcher_get_target_host(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +const char *nm_team_link_watcher_get_source_host(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_12 +NMTeamLinkWatcherArpPingFlags nm_team_link_watcher_get_flags(const NMTeamLinkWatcher *watcher); +NM_AVAILABLE_IN_1_16 +int nm_team_link_watcher_get_vlanid(const NMTeamLinkWatcher *watcher); + +#define NM_TYPE_SETTING_TEAM (nm_setting_team_get_type()) +#define NM_SETTING_TEAM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_TEAM, NMSettingTeam)) +#define NM_SETTING_TEAM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_TEAM, NMSettingTeamClass)) +#define NM_IS_SETTING_TEAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_TEAM)) +#define NM_IS_SETTING_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_TEAM)) +#define NM_SETTING_TEAM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_TEAM, NMSettingTeamClass)) + +#define NM_SETTING_TEAM_SETTING_NAME "team" + +#define NM_SETTING_TEAM_CONFIG "config" +#define NM_SETTING_TEAM_NOTIFY_PEERS_COUNT "notify-peers-count" +#define NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL "notify-peers-interval" +#define NM_SETTING_TEAM_MCAST_REJOIN_COUNT "mcast-rejoin-count" +#define NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL "mcast-rejoin-interval" +#define NM_SETTING_TEAM_RUNNER "runner" +#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY "runner-hwaddr-policy" +#define NM_SETTING_TEAM_RUNNER_TX_HASH "runner-tx-hash" +#define NM_SETTING_TEAM_RUNNER_TX_BALANCER "runner-tx-balancer" +#define NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL "runner-tx-balancer-interval" +#define NM_SETTING_TEAM_RUNNER_ACTIVE "runner-active" +#define NM_SETTING_TEAM_RUNNER_FAST_RATE "runner-fast-rate" +#define NM_SETTING_TEAM_RUNNER_SYS_PRIO "runner-sys-prio" +#define NM_SETTING_TEAM_RUNNER_MIN_PORTS "runner-min-ports" +#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY "runner-agg-select-policy" +#define NM_SETTING_TEAM_LINK_WATCHERS "link-watchers" + +#define NM_SETTING_TEAM_RUNNER_BROADCAST "broadcast" +#define NM_SETTING_TEAM_RUNNER_ROUNDROBIN "roundrobin" +#define NM_SETTING_TEAM_RUNNER_RANDOM "random" +#define NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP "activebackup" +#define NM_SETTING_TEAM_RUNNER_LOADBALANCE "loadbalance" +#define NM_SETTING_TEAM_RUNNER_LACP "lacp" + +#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL "same_all" +#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE "by_active" +#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE "only_active" + +#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO "lacp_prio" +#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO_STABLE "lacp_prio_stable" +#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_BANDWIDTH "bandwidth" +#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_COUNT "count" +#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_PORT_CONFIG "port_config" + +#define NM_SETTING_TEAM_NOTIFY_PEERS_COUNT_ACTIVEBACKUP_DEFAULT 1 +#define NM_SETTING_TEAM_NOTIFY_MCAST_COUNT_ACTIVEBACKUP_DEFAULT 1 +#define NM_SETTING_TEAM_RUNNER_DEFAULT NM_SETTING_TEAM_RUNNER_ROUNDROBIN +#define NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_DEFAULT NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL +#define NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT 50 +#define NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT 65535 +#define NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT \ + NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_LACP_PRIO + +/** + * NMSettingTeam: + * + * Teaming Settings + */ +struct _NMSettingTeam { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingTeamClass; + +GType nm_setting_team_get_type(void); + +NMSetting *nm_setting_team_new(void); + +const char *nm_setting_team_get_config(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_get_notify_peers_count(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_get_notify_peers_interval(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_get_mcast_rejoin_count(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_get_mcast_rejoin_interval(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +const char *nm_setting_team_get_runner(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +const char *nm_setting_team_get_runner_hwaddr_policy(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +const char *nm_setting_team_get_runner_tx_balancer(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_get_runner_tx_balancer_interval(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_get_runner_active(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_get_runner_fast_rate(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_get_runner_sys_prio(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +int nm_setting_team_get_runner_min_ports(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +const char *nm_setting_team_get_runner_agg_select_policy(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_remove_runner_tx_hash_by_value(NMSettingTeam *setting, const char *txhash); +NM_AVAILABLE_IN_1_12 +guint nm_setting_team_get_num_runner_tx_hash(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +const char *nm_setting_team_get_runner_tx_hash(NMSettingTeam *setting, guint idx); +NM_AVAILABLE_IN_1_12 +void nm_setting_team_remove_runner_tx_hash(NMSettingTeam *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_add_runner_tx_hash(NMSettingTeam *setting, const char *txhash); +NM_AVAILABLE_IN_1_12 +guint nm_setting_team_get_num_link_watchers(NMSettingTeam *setting); +NM_AVAILABLE_IN_1_12 +NMTeamLinkWatcher *nm_setting_team_get_link_watcher(NMSettingTeam *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_add_link_watcher(NMSettingTeam *setting, NMTeamLinkWatcher *link_watcher); +NM_AVAILABLE_IN_1_12 +void nm_setting_team_remove_link_watcher(NMSettingTeam *setting, guint idx); +NM_AVAILABLE_IN_1_12 +gboolean nm_setting_team_remove_link_watcher_by_value(NMSettingTeam * setting, + NMTeamLinkWatcher *link_watcher); +NM_AVAILABLE_IN_1_12 +void nm_setting_team_clear_link_watchers(NMSettingTeam *setting); +G_END_DECLS + +#endif /* __NM_SETTING_TEAM_H__ */ diff --git a/src/libnm-core-public/nm-setting-tun.h b/src/libnm-core-public/nm-setting-tun.h new file mode 100644 index 0000000000..3fbbf08253 --- /dev/null +++ b/src/libnm-core-public/nm-setting-tun.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_TUN_H__ +#define __NM_SETTING_TUN_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_TUN (nm_setting_tun_get_type()) +#define NM_SETTING_TUN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_TUN, NMSettingTun)) +#define NM_SETTING_TUN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_TUNCONFIG, NMSettingTunClass)) +#define NM_IS_SETTING_TUN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_TUN)) +#define NM_IS_SETTING_TUN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_TUN)) +#define NM_SETTING_TUN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_TUN, NMSettingTunClass)) + +#define NM_SETTING_TUN_SETTING_NAME "tun" + +#define NM_SETTING_TUN_MODE "mode" +#define NM_SETTING_TUN_OWNER "owner" +#define NM_SETTING_TUN_GROUP "group" +#define NM_SETTING_TUN_PI "pi" +#define NM_SETTING_TUN_VNET_HDR "vnet-hdr" +#define NM_SETTING_TUN_MULTI_QUEUE "multi-queue" + +/** + * NMSettingTunMode: + * @NM_SETTING_TUN_MODE_UNKNOWN: an unknown device type + * @NM_SETTING_TUN_MODE_TUN: a TUN device + * @NM_SETTING_TUN_MODE_TAP: a TAP device + * + * #NMSettingTunMode values indicate the device type (TUN/TAP) + */ +typedef enum { + NM_SETTING_TUN_MODE_UNKNOWN = 0, + NM_SETTING_TUN_MODE_TUN = 1, + NM_SETTING_TUN_MODE_TAP = 2, +} NMSettingTunMode; + +/** + * NMSettingTun: + * + * Tunnel Settings + */ +struct _NMSettingTun { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingTunClass; + +NM_AVAILABLE_IN_1_2 +GType nm_setting_tun_get_type(void); +NM_AVAILABLE_IN_1_2 +NMSetting *nm_setting_tun_new(void); + +NM_AVAILABLE_IN_1_2 +NMSettingTunMode nm_setting_tun_get_mode(NMSettingTun *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_tun_get_owner(NMSettingTun *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_tun_get_group(NMSettingTun *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_tun_get_pi(NMSettingTun *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_tun_get_vnet_hdr(NMSettingTun *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_tun_get_multi_queue(NMSettingTun *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_TUN_H__ */ diff --git a/src/libnm-core-public/nm-setting-user.h b/src/libnm-core-public/nm-setting-user.h new file mode 100644 index 0000000000..b151cd3ee6 --- /dev/null +++ b/src/libnm-core-public/nm-setting-user.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_USER_H__ +#define __NM_SETTING_USER_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_USER (nm_setting_user_get_type()) +#define NM_SETTING_USER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_USER, NMSettingUser)) +#define NM_SETTING_USER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_USER, NMSettingUserClass)) +#define NM_IS_SETTING_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_USER)) +#define NM_IS_SETTING_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_USER)) +#define NM_SETTING_USER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_USER, NMSettingUserClass)) + +#define NM_SETTING_USER_SETTING_NAME "user" + +#define NM_SETTING_USER_DATA "data" + +typedef struct _NMSettingUserClass NMSettingUserClass; + +NM_AVAILABLE_IN_1_8 +GType nm_setting_user_get_type(void); + +NM_AVAILABLE_IN_1_8 +NMSetting *nm_setting_user_new(void); + +NM_AVAILABLE_IN_1_8 +const char *const *nm_setting_user_get_keys(NMSettingUser *setting, guint *out_len); + +NM_AVAILABLE_IN_1_8 +const char *nm_setting_user_get_data(NMSettingUser *setting, const char *key); +NM_AVAILABLE_IN_1_8 +gboolean +nm_setting_user_set_data(NMSettingUser *setting, const char *key, const char *val, GError **error); + +NM_AVAILABLE_IN_1_8 +gboolean nm_setting_user_check_key(const char *key, GError **error); +NM_AVAILABLE_IN_1_8 +gboolean nm_setting_user_check_val(const char *val, GError **error); + +G_END_DECLS + +#endif /* __NM_SETTING_USER_H__ */ diff --git a/src/libnm-core-public/nm-setting-veth.h b/src/libnm-core-public/nm-setting-veth.h new file mode 100644 index 0000000000..5dbc192742 --- /dev/null +++ b/src/libnm-core-public/nm-setting-veth.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_VETH_H__ +#define __NM_SETTING_VETH_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_VETH (nm_setting_veth_get_type()) +#define NM_SETTING_VETH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VETH, NMSettingVeth)) +#define NM_IS_SETTING_VETH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VETH)) +#define NM_IS_SETTING_VETH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VETH)) +#define NM_SETTING_VETH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VETH, NMSettingVethClass)) + +#define NM_SETTING_VETH_SETTING_NAME "veth" + +#define NM_SETTING_VETH_PEER "peer" + +typedef struct _NMSettingVethClass NMSettingVethClass; + +NM_AVAILABLE_IN_1_30 +GType nm_setting_veth_get_type(void); +NM_AVAILABLE_IN_1_30 +NMSetting *nm_setting_veth_new(void); + +NM_AVAILABLE_IN_1_30 +const char *nm_setting_veth_get_peer(NMSettingVeth *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_VETH_H__ */ diff --git a/src/libnm-core-public/nm-setting-vlan.h b/src/libnm-core-public/nm-setting-vlan.h new file mode 100644 index 0000000000..4b2ca429cf --- /dev/null +++ b/src/libnm-core-public/nm-setting-vlan.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_VLAN_H__ +#define __NM_SETTING_VLAN_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_VLAN (nm_setting_vlan_get_type()) +#define NM_SETTING_VLAN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VLAN, NMSettingVlan)) +#define NM_SETTING_VLAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_VLANCONFIG, NMSettingVlanClass)) +#define NM_IS_SETTING_VLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VLAN)) +#define NM_IS_SETTING_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VLAN)) +#define NM_SETTING_VLAN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VLAN, NMSettingVlanClass)) + +#define NM_SETTING_VLAN_SETTING_NAME "vlan" + +#define NM_SETTING_VLAN_PARENT "parent" +#define NM_SETTING_VLAN_ID "id" +#define NM_SETTING_VLAN_FLAGS "flags" +#define NM_SETTING_VLAN_INGRESS_PRIORITY_MAP "ingress-priority-map" +#define NM_SETTING_VLAN_EGRESS_PRIORITY_MAP "egress-priority-map" + +/** + * NMSettingVlan: + * + * VLAN Settings + */ +struct _NMSettingVlan { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingVlanClass; + +/** + * NMVlanPriorityMap: + * @NM_VLAN_INGRESS_MAP: map for incoming data + * @NM_VLAN_EGRESS_MAP: map for outgoing data + * + * A selector for traffic priority maps; these map Linux SKB priorities + * to 802.1p priorities used in VLANs. + **/ +/* clang-format off */ +typedef enum { + NM_VLAN_INGRESS_MAP, + NM_VLAN_EGRESS_MAP +} NMVlanPriorityMap; +/* clang-format on */ + +/** + * NMVlanFlags: + * @NM_VLAN_FLAG_REORDER_HEADERS: indicates that this interface should reorder + * outgoing packet headers to look more like a non-VLAN Ethernet interface + * @NM_VLAN_FLAG_GVRP: indicates that this interface should use GVRP to register + * itself with its switch + * @NM_VLAN_FLAG_LOOSE_BINDING: indicates that this interface's operating + * state is tied to the underlying network interface but other details + * (like routing) are not. + * @NM_VLAN_FLAG_MVRP: indicates that this interface should use MVRP to register + * itself with its switch + * + * #NMVlanFlags values control the behavior of the VLAN interface. + **/ +typedef enum { /*< flags >*/ + NM_VLAN_FLAG_REORDER_HEADERS = 0x1, + NM_VLAN_FLAG_GVRP = 0x2, + NM_VLAN_FLAG_LOOSE_BINDING = 0x4, + NM_VLAN_FLAG_MVRP = 0x8, + + /* NOTE: if adding flags update nm-setting-vlan.c::verify() */ + + /* NOTE: these flags must correspond to the value from the kernel + * header files. */ +} NMVlanFlags; + +#define NM_VLAN_FLAGS_ALL \ + (NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP | NM_VLAN_FLAG_LOOSE_BINDING \ + | NM_VLAN_FLAG_MVRP) + +GType nm_setting_vlan_get_type(void); +NMSetting *nm_setting_vlan_new(void); + +const char *nm_setting_vlan_get_parent(NMSettingVlan *setting); +guint32 nm_setting_vlan_get_id(NMSettingVlan *setting); +guint32 nm_setting_vlan_get_flags(NMSettingVlan *setting); + +gint32 nm_setting_vlan_get_num_priorities(NMSettingVlan *setting, NMVlanPriorityMap map); + +gboolean nm_setting_vlan_get_priority(NMSettingVlan * setting, + NMVlanPriorityMap map, + guint32 idx, + guint32 * out_from, + guint32 * out_to); + +gboolean nm_setting_vlan_add_priority(NMSettingVlan * setting, + NMVlanPriorityMap map, + guint32 from, + guint32 to); + +void nm_setting_vlan_remove_priority(NMSettingVlan *setting, NMVlanPriorityMap map, guint32 idx); + +gboolean nm_setting_vlan_remove_priority_by_value(NMSettingVlan * setting, + NMVlanPriorityMap map, + guint32 from, + guint32 to); + +gboolean nm_setting_vlan_remove_priority_str_by_value(NMSettingVlan * setting, + NMVlanPriorityMap map, + const char * str); + +void nm_setting_vlan_clear_priorities(NMSettingVlan *setting, NMVlanPriorityMap map); + +gboolean +nm_setting_vlan_add_priority_str(NMSettingVlan *setting, NMVlanPriorityMap map, const char *str); + +G_END_DECLS + +#endif /* __NM_SETTING_VLAN_H__ */ diff --git a/src/libnm-core-public/nm-setting-vpn.h b/src/libnm-core-public/nm-setting-vpn.h new file mode 100644 index 0000000000..9e5d6e4be3 --- /dev/null +++ b/src/libnm-core-public/nm-setting-vpn.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_VPN_H__ +#define __NM_SETTING_VPN_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_VPN (nm_setting_vpn_get_type()) +#define NM_SETTING_VPN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VPN, NMSettingVpn)) +#define NM_SETTING_VPN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_VPN, NMSettingVpnClass)) +#define NM_IS_SETTING_VPN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VPN)) +#define NM_IS_SETTING_VPN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VPN)) +#define NM_SETTING_VPN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VPN, NMSettingVpnClass)) + +#define NM_SETTING_VPN_SETTING_NAME "vpn" + +#define NM_SETTING_VPN_SERVICE_TYPE "service-type" +#define NM_SETTING_VPN_USER_NAME "user-name" +#define NM_SETTING_VPN_PERSISTENT "persistent" +#define NM_SETTING_VPN_DATA "data" +#define NM_SETTING_VPN_SECRETS "secrets" +#define NM_SETTING_VPN_TIMEOUT "timeout" + +/** + * NMSettingVpn: + * + * VPN Settings + */ +struct _NMSettingVpn { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingVpnClass; + +/** + * NMVpnIterFunc: + * @key: the name of the data or secret item + * @value: the value of the data or secret item + * @user_data: User data passed to nm_setting_vpn_foreach_data_item() or + * nm_setting_vpn_foreach_secret() + **/ +typedef void (*NMVpnIterFunc)(const char *key, const char *value, gpointer user_data); + +GType nm_setting_vpn_get_type(void); + +NMSetting * nm_setting_vpn_new(void); +const char *nm_setting_vpn_get_service_type(NMSettingVpn *setting); +const char *nm_setting_vpn_get_user_name(NMSettingVpn *setting); +gboolean nm_setting_vpn_get_persistent(NMSettingVpn *setting); + +guint32 nm_setting_vpn_get_num_data_items(NMSettingVpn *setting); +void nm_setting_vpn_add_data_item(NMSettingVpn *setting, const char *key, const char *item); +const char *nm_setting_vpn_get_data_item(NMSettingVpn *setting, const char *key); +gboolean nm_setting_vpn_remove_data_item(NMSettingVpn *setting, const char *key); +void +nm_setting_vpn_foreach_data_item(NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data); +NM_AVAILABLE_IN_1_12 +const char **nm_setting_vpn_get_data_keys(NMSettingVpn *setting, guint *out_length); + +guint32 nm_setting_vpn_get_num_secrets(NMSettingVpn *setting); +void nm_setting_vpn_add_secret(NMSettingVpn *setting, const char *key, const char *secret); +const char *nm_setting_vpn_get_secret(NMSettingVpn *setting, const char *key); +gboolean nm_setting_vpn_remove_secret(NMSettingVpn *setting, const char *key); +void nm_setting_vpn_foreach_secret(NMSettingVpn *setting, NMVpnIterFunc func, gpointer user_data); +NM_AVAILABLE_IN_1_12 +const char **nm_setting_vpn_get_secret_keys(NMSettingVpn *setting, guint *out_length); + +NM_AVAILABLE_IN_1_2 +guint32 nm_setting_vpn_get_timeout(NMSettingVpn *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_VPN_H__ */ diff --git a/src/libnm-core-public/nm-setting-vrf.h b/src/libnm-core-public/nm-setting-vrf.h new file mode 100644 index 0000000000..afa044b830 --- /dev/null +++ b/src/libnm-core-public/nm-setting-vrf.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#ifndef __NM_SETTING_VRF_H__ +#define __NM_SETTING_VRF_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_VRF (nm_setting_vrf_get_type()) +#define NM_SETTING_VRF(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VRF, NMSettingVrf)) +#define NM_SETTING_VRF_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_VRFCONFIG, NMSettingVrfClass)) +#define NM_IS_SETTING_VRF(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VRF)) +#define NM_IS_SETTING_VRF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VRF)) +#define NM_SETTING_VRF_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VRF, NMSettingVrfClass)) + +#define NM_SETTING_VRF_SETTING_NAME "vrf" + +#define NM_SETTING_VRF_TABLE "table" + +typedef struct _NMSettingVrfClass NMSettingVrfClass; + +NM_AVAILABLE_IN_1_24 +GType nm_setting_vrf_get_type(void); +NM_AVAILABLE_IN_1_24 +NMSetting *nm_setting_vrf_new(void); +NM_AVAILABLE_IN_1_24 +guint32 nm_setting_vrf_get_table(NMSettingVrf *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_VRF_H__ */ diff --git a/src/libnm-core-public/nm-setting-vxlan.h b/src/libnm-core-public/nm-setting-vxlan.h new file mode 100644 index 0000000000..9b987b660c --- /dev/null +++ b/src/libnm-core-public/nm-setting-vxlan.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_VXLAN_H__ +#define __NM_SETTING_VXLAN_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_VXLAN (nm_setting_vxlan_get_type()) +#define NM_SETTING_VXLAN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VXLAN, NMSettingVxlan)) +#define NM_SETTING_VXLAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_VXLANCONFIG, NMSettingVxlanClass)) +#define NM_IS_SETTING_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VXLAN)) +#define NM_IS_SETTING_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VXLAN)) +#define NM_SETTING_VXLAN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VXLAN, NMSettingVxlanClass)) + +#define NM_SETTING_VXLAN_SETTING_NAME "vxlan" + +#define NM_SETTING_VXLAN_PARENT "parent" +#define NM_SETTING_VXLAN_ID "id" +#define NM_SETTING_VXLAN_LOCAL "local" +#define NM_SETTING_VXLAN_REMOTE "remote" +#define NM_SETTING_VXLAN_SOURCE_PORT_MIN "source-port-min" +#define NM_SETTING_VXLAN_SOURCE_PORT_MAX "source-port-max" +#define NM_SETTING_VXLAN_DESTINATION_PORT "destination-port" +#define NM_SETTING_VXLAN_TOS "tos" +#define NM_SETTING_VXLAN_TTL "ttl" +#define NM_SETTING_VXLAN_AGEING "ageing" +#define NM_SETTING_VXLAN_LIMIT "limit" +#define NM_SETTING_VXLAN_PROXY "proxy" +#define NM_SETTING_VXLAN_LEARNING "learning" +#define NM_SETTING_VXLAN_RSC "rsc" +#define NM_SETTING_VXLAN_L2_MISS "l2-miss" +#define NM_SETTING_VXLAN_L3_MISS "l3-miss" + +/** + * NMSettingVxlan: + * + * VXLAN Settings + */ +struct _NMSettingVxlan { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingVxlanClass; + +NM_AVAILABLE_IN_1_2 +GType nm_setting_vxlan_get_type(void); +NM_AVAILABLE_IN_1_2 +NMSetting *nm_setting_vxlan_new(void); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_vxlan_get_parent(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_id(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_vxlan_get_local(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_vxlan_get_remote(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_source_port_min(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_source_port_max(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_destination_port(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_tos(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_ttl(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_ageing(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_limit(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_proxy(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_learning(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_rsc(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_l2_miss(NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_l3_miss(NMSettingVxlan *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_VXLAN_H__ */ diff --git a/src/libnm-core-public/nm-setting-wifi-p2p.h b/src/libnm-core-public/nm-setting-wifi-p2p.h new file mode 100644 index 0000000000..029b75f065 --- /dev/null +++ b/src/libnm-core-public/nm-setting-wifi-p2p.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_WIFI_P2P_H__ +#define __NM_SETTING_WIFI_P2P_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" +#include "nm-setting-wireless-security.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIFI_P2P (nm_setting_wifi_p2p_get_type()) +#define NM_SETTING_WIFI_P2P(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIFI_P2P, NMSettingWifiP2P)) +#define NM_SETTING_WIFI_P2P_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIFI_P2P, NMSettingWifiP2PClass)) +#define NM_IS_SETTING_WIFI_P2P(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIFI_P2P)) +#define NM_IS_SETTING_WIFI_P2P_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIFI_P2P)) +#define NM_SETTING_WIFI_P2P_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIFI_P2P, NMSettingWifiP2PClass)) + +#define NM_SETTING_WIFI_P2P_SETTING_NAME "wifi-p2p" + +/** + * NM_SETTING_WIFI_P2P_PEER: + * + * The mac address of the peer to connect to. + */ +#define NM_SETTING_WIFI_P2P_PEER "peer" +#define NM_SETTING_WIFI_P2P_WPS_METHOD "wps-method" +#define NM_SETTING_WIFI_P2P_WFD_IES "wfd-ies" + +typedef struct _NMSettingWifiP2PClass NMSettingWifiP2PClass; + +NM_AVAILABLE_IN_1_16 +GType nm_setting_wifi_p2p_get_type(void); + +NM_AVAILABLE_IN_1_16 +NMSetting *nm_setting_wifi_p2p_new(void); + +NM_AVAILABLE_IN_1_16 +const char *nm_setting_wifi_p2p_get_peer(NMSettingWifiP2P *setting); + +NM_AVAILABLE_IN_1_16 +NMSettingWirelessSecurityWpsMethod nm_setting_wifi_p2p_get_wps_method(NMSettingWifiP2P *setting); + +NM_AVAILABLE_IN_1_16 +GBytes *nm_setting_wifi_p2p_get_wfd_ies(NMSettingWifiP2P *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_WIFI_P2P_H__ */ diff --git a/src/libnm-core-public/nm-setting-wimax.h b/src/libnm-core-public/nm-setting-wimax.h new file mode 100644 index 0000000000..7279e043b5 --- /dev/null +++ b/src/libnm-core-public/nm-setting-wimax.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef __NM_SETTING_WIMAX_H__ +#define __NM_SETTING_WIMAX_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIMAX (nm_setting_wimax_get_type()) +#define NM_SETTING_WIMAX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimax)) +#define NM_SETTING_WIMAX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass)) +#define NM_IS_SETTING_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIMAX)) +#define NM_IS_SETTING_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIMAX)) +#define NM_SETTING_WIMAX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass)) + +#define NM_SETTING_WIMAX_SETTING_NAME "wimax" + +#define NM_SETTING_WIMAX_NETWORK_NAME "network-name" +#define NM_SETTING_WIMAX_MAC_ADDRESS "mac-address" + +/** + * NMSettingWimax: + * + * WiMax Settings + */ +struct _NMSettingWimax { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingWimaxClass; + +NM_DEPRECATED_IN_1_2 +GType nm_setting_wimax_get_type(void); + +NM_DEPRECATED_IN_1_2 +NMSetting *nm_setting_wimax_new(void); +NM_DEPRECATED_IN_1_2 +const char *nm_setting_wimax_get_network_name(NMSettingWimax *setting); +NM_DEPRECATED_IN_1_2 +const char *nm_setting_wimax_get_mac_address(NMSettingWimax *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_WIMAX_H__ */ diff --git a/src/libnm-core-public/nm-setting-wired.h b/src/libnm-core-public/nm-setting-wired.h new file mode 100644 index 0000000000..acabd70646 --- /dev/null +++ b/src/libnm-core-public/nm-setting-wired.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_WIRED_H__ +#define __NM_SETTING_WIRED_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIRED (nm_setting_wired_get_type()) +#define NM_SETTING_WIRED(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIRED, NMSettingWired)) +#define NM_SETTING_WIRED_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIRED, NMSettingWiredClass)) +#define NM_IS_SETTING_WIRED(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIRED)) +#define NM_IS_SETTING_WIRED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIRED)) +#define NM_SETTING_WIRED_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIRED, NMSettingWiredClass)) + +#define NM_SETTING_WIRED_SETTING_NAME "802-3-ethernet" + +/** + * NMSettingWiredWakeOnLan: + * @NM_SETTING_WIRED_WAKE_ON_LAN_NONE: Wake-on-LAN disabled + * @NM_SETTING_WIRED_WAKE_ON_LAN_PHY: Wake on PHY activity + * @NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST: Wake on unicast messages + * @NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST: Wake on multicast messages + * @NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST: Wake on broadcast messages + * @NM_SETTING_WIRED_WAKE_ON_LAN_ARP: Wake on ARP + * @NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC: Wake on magic packet + * @NM_SETTING_WIRED_WAKE_ON_LAN_ALL: Wake on all events. This does not + * include the exclusive flags @NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT or + * @NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE. + * @NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT: Use the default value + * @NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE: Don't change configured settings + * @NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS: Mask of flags that are + * incompatible with other flags + * + * Options for #NMSettingWired:wake-on-lan. Note that not all options + * are supported by all devices. + * + * Since: 1.2 + */ +typedef enum { /*< flags >*/ + NM_SETTING_WIRED_WAKE_ON_LAN_NONE = 0, /*< skip >*/ + NM_SETTING_WIRED_WAKE_ON_LAN_PHY = 0x2, + NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST = 0x4, + NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST = 0x8, + NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST = 0x10, + NM_SETTING_WIRED_WAKE_ON_LAN_ARP = 0x20, + NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC = 0x40, + + NM_SETTING_WIRED_WAKE_ON_LAN_ALL = 0x7E, /*< skip >*/ + + NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT = 0x1, + NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE = 0x8000, + NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS = 0x8001, /*< skip >*/ +} NMSettingWiredWakeOnLan; + +#define NM_SETTING_WIRED_PORT "port" +#define NM_SETTING_WIRED_SPEED "speed" +#define NM_SETTING_WIRED_DUPLEX "duplex" +#define NM_SETTING_WIRED_AUTO_NEGOTIATE "auto-negotiate" +#define NM_SETTING_WIRED_MAC_ADDRESS "mac-address" +#define NM_SETTING_WIRED_CLONED_MAC_ADDRESS "cloned-mac-address" +#define NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK "generate-mac-address-mask" +#define NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST "mac-address-blacklist" +#define NM_SETTING_WIRED_MTU "mtu" +#define NM_SETTING_WIRED_S390_SUBCHANNELS "s390-subchannels" +#define NM_SETTING_WIRED_S390_NETTYPE "s390-nettype" +#define NM_SETTING_WIRED_S390_OPTIONS "s390-options" +#define NM_SETTING_WIRED_WAKE_ON_LAN "wake-on-lan" +#define NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD "wake-on-lan-password" + +/** + * NMSettingWired: + * + * Wired Ethernet Settings + */ +struct _NMSettingWired { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingWiredClass; + +GType nm_setting_wired_get_type(void); + +NMSetting * nm_setting_wired_new(void); +const char *nm_setting_wired_get_port(NMSettingWired *setting); +guint32 nm_setting_wired_get_speed(NMSettingWired *setting); +const char *nm_setting_wired_get_duplex(NMSettingWired *setting); +gboolean nm_setting_wired_get_auto_negotiate(NMSettingWired *setting); +const char *nm_setting_wired_get_mac_address(NMSettingWired *setting); +const char *nm_setting_wired_get_cloned_mac_address(NMSettingWired *setting); + +NM_AVAILABLE_IN_1_4 +const char *nm_setting_wired_get_generate_mac_address_mask(NMSettingWired *setting); + +const char *const *nm_setting_wired_get_mac_address_blacklist(NMSettingWired *setting); +guint32 nm_setting_wired_get_num_mac_blacklist_items(NMSettingWired *setting); +const char * nm_setting_wired_get_mac_blacklist_item(NMSettingWired *setting, guint32 idx); +gboolean nm_setting_wired_add_mac_blacklist_item(NMSettingWired *setting, const char *mac); +void nm_setting_wired_remove_mac_blacklist_item(NMSettingWired *setting, guint32 idx); +gboolean nm_setting_wired_remove_mac_blacklist_item_by_value(NMSettingWired *setting, + const char * mac); +void nm_setting_wired_clear_mac_blacklist_items(NMSettingWired *setting); + +guint32 nm_setting_wired_get_mtu(NMSettingWired *setting); + +const char *const *nm_setting_wired_get_s390_subchannels(NMSettingWired *setting); +const char * nm_setting_wired_get_s390_nettype(NMSettingWired *setting); + +guint32 nm_setting_wired_get_num_s390_options(NMSettingWired *setting); +gboolean nm_setting_wired_get_s390_option(NMSettingWired *setting, + guint32 idx, + const char ** out_key, + const char ** out_value); +const char *nm_setting_wired_get_s390_option_by_key(NMSettingWired *setting, const char *key); +gboolean +nm_setting_wired_add_s390_option(NMSettingWired *setting, const char *key, const char *value); +gboolean nm_setting_wired_remove_s390_option(NMSettingWired *setting, const char *key); +const char **nm_setting_wired_get_valid_s390_options(NMSettingWired *setting); + +NMSettingWiredWakeOnLan nm_setting_wired_get_wake_on_lan(NMSettingWired *setting); +const char * nm_setting_wired_get_wake_on_lan_password(NMSettingWired *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_WIRED_H__ */ diff --git a/src/libnm-core-public/nm-setting-wireguard.h b/src/libnm-core-public/nm-setting-wireguard.h new file mode 100644 index 0000000000..3f046fc713 --- /dev/null +++ b/src/libnm-core-public/nm-setting-wireguard.h @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 - 2019 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_WIREGUARD_H__ +#define __NM_SETTING_WIREGUARD_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" +#include "nm-utils.h" + +G_BEGIN_DECLS + +/*****************************************************************************/ + +#define NM_WIREGUARD_PUBLIC_KEY_LEN 32 +#define NM_WIREGUARD_SYMMETRIC_KEY_LEN 32 + +/*****************************************************************************/ + +typedef struct _NMWireGuardPeer NMWireGuardPeer; + +NM_AVAILABLE_IN_1_16 +GType nm_wireguard_peer_get_type(void); + +NM_AVAILABLE_IN_1_16 +NMWireGuardPeer *nm_wireguard_peer_new(void); + +NM_AVAILABLE_IN_1_16 +NMWireGuardPeer *nm_wireguard_peer_new_clone(const NMWireGuardPeer *self, gboolean with_secrets); + +NM_AVAILABLE_IN_1_16 +NMWireGuardPeer *nm_wireguard_peer_ref(NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +void nm_wireguard_peer_unref(NMWireGuardPeer *self); + +NM_AVAILABLE_IN_1_16 +void nm_wireguard_peer_seal(NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +gboolean nm_wireguard_peer_is_sealed(const NMWireGuardPeer *self); + +NM_AVAILABLE_IN_1_16 +const char *nm_wireguard_peer_get_public_key(const NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +gboolean nm_wireguard_peer_set_public_key(NMWireGuardPeer *self, + const char * public_key, + gboolean accept_invalid); + +NM_AVAILABLE_IN_1_16 +const char *nm_wireguard_peer_get_preshared_key(const NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +gboolean nm_wireguard_peer_set_preshared_key(NMWireGuardPeer *self, + const char * preshared_key, + gboolean accept_invalid); + +NM_AVAILABLE_IN_1_16 +NMSettingSecretFlags nm_wireguard_peer_get_preshared_key_flags(const NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +void nm_wireguard_peer_set_preshared_key_flags(NMWireGuardPeer * self, + NMSettingSecretFlags preshared_key_flags); + +NM_AVAILABLE_IN_1_16 +guint16 nm_wireguard_peer_get_persistent_keepalive(const NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +void nm_wireguard_peer_set_persistent_keepalive(NMWireGuardPeer *self, + guint16 persistent_keepalive); + +NM_AVAILABLE_IN_1_16 +const char *nm_wireguard_peer_get_endpoint(const NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +gboolean +nm_wireguard_peer_set_endpoint(NMWireGuardPeer *self, const char *endpoint, gboolean allow_invalid); + +NM_AVAILABLE_IN_1_16 +guint nm_wireguard_peer_get_allowed_ips_len(const NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +const char * +nm_wireguard_peer_get_allowed_ip(const NMWireGuardPeer *self, guint idx, gboolean *out_is_valid); +NM_AVAILABLE_IN_1_16 +void nm_wireguard_peer_clear_allowed_ips(NMWireGuardPeer *self); +NM_AVAILABLE_IN_1_16 +gboolean nm_wireguard_peer_append_allowed_ip(NMWireGuardPeer *self, + const char * allowed_ip, + gboolean accept_invalid); +NM_AVAILABLE_IN_1_16 +gboolean nm_wireguard_peer_remove_allowed_ip(NMWireGuardPeer *self, guint idx); + +NM_AVAILABLE_IN_1_16 +gboolean nm_wireguard_peer_is_valid(const NMWireGuardPeer *self, + gboolean check_non_secrets, + gboolean check_secrets, + GError ** error); + +NM_AVAILABLE_IN_1_16 +int nm_wireguard_peer_cmp(const NMWireGuardPeer *a, + const NMWireGuardPeer *b, + NMSettingCompareFlags compare_flags); + +/*****************************************************************************/ + +#define NM_TYPE_SETTING_WIREGUARD (nm_setting_wireguard_get_type()) +#define NM_SETTING_WIREGUARD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuard)) +#define NM_SETTING_WIREGUARD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuardClass)) +#define NM_IS_SETTING_WIREGUARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIREGUARD)) +#define NM_IS_SETTING_WIREGUARD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIREGUARD)) +#define NM_SETTING_WIREGUARD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIREGUARD, NMSettingWireGuardClass)) + +#define NM_SETTING_WIREGUARD_SETTING_NAME "wireguard" + +#define NM_SETTING_WIREGUARD_FWMARK "fwmark" +#define NM_SETTING_WIREGUARD_LISTEN_PORT "listen-port" +#define NM_SETTING_WIREGUARD_PRIVATE_KEY "private-key" +#define NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS "private-key-flags" + +#define NM_SETTING_WIREGUARD_PEERS "peers" + +#define NM_SETTING_WIREGUARD_MTU "mtu" +#define NM_SETTING_WIREGUARD_PEER_ROUTES "peer-routes" +#define NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE "ip4-auto-default-route" +#define NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE "ip6-auto-default-route" + +#define NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS "allowed-ips" +#define NM_WIREGUARD_PEER_ATTR_ENDPOINT "endpoint" +#define NM_WIREGUARD_PEER_ATTR_PERSISTENT_KEEPALIVE "persistent-keepalive" +#define NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY "preshared-key" +#define NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS "preshared-key-flags" +#define NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY "public-key" + +/*****************************************************************************/ + +typedef struct _NMSettingWireGuardClass NMSettingWireGuardClass; + +NM_AVAILABLE_IN_1_16 +GType nm_setting_wireguard_get_type(void); + +NM_AVAILABLE_IN_1_16 +NMSetting *nm_setting_wireguard_new(void); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_16 +const char *nm_setting_wireguard_get_private_key(NMSettingWireGuard *self); + +NM_AVAILABLE_IN_1_16 +NMSettingSecretFlags nm_setting_wireguard_get_private_key_flags(NMSettingWireGuard *self); + +NM_AVAILABLE_IN_1_16 +guint16 nm_setting_wireguard_get_listen_port(NMSettingWireGuard *self); + +NM_AVAILABLE_IN_1_16 +guint32 nm_setting_wireguard_get_fwmark(NMSettingWireGuard *self); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_16 +guint nm_setting_wireguard_get_peers_len(NMSettingWireGuard *self); + +NM_AVAILABLE_IN_1_16 +NMWireGuardPeer *nm_setting_wireguard_get_peer(NMSettingWireGuard *self, guint idx); + +NM_AVAILABLE_IN_1_16 +NMWireGuardPeer *nm_setting_wireguard_get_peer_by_public_key(NMSettingWireGuard *self, + const char * public_key, + guint * out_idx); + +NM_AVAILABLE_IN_1_16 +void nm_setting_wireguard_set_peer(NMSettingWireGuard *self, NMWireGuardPeer *peer, guint idx); + +NM_AVAILABLE_IN_1_16 +void nm_setting_wireguard_append_peer(NMSettingWireGuard *self, NMWireGuardPeer *peer); + +NM_AVAILABLE_IN_1_16 +gboolean nm_setting_wireguard_remove_peer(NMSettingWireGuard *self, guint idx); + +NM_AVAILABLE_IN_1_16 +guint nm_setting_wireguard_clear_peers(NMSettingWireGuard *self); + +NM_AVAILABLE_IN_1_16 +gboolean nm_setting_wireguard_get_peer_routes(NMSettingWireGuard *self); + +NM_AVAILABLE_IN_1_16 +guint32 nm_setting_wireguard_get_mtu(NMSettingWireGuard *self); + +NM_AVAILABLE_IN_1_20 +NMTernary nm_setting_wireguard_get_ip4_auto_default_route(NMSettingWireGuard *self); + +NM_AVAILABLE_IN_1_20 +NMTernary nm_setting_wireguard_get_ip6_auto_default_route(NMSettingWireGuard *self); + +/*****************************************************************************/ + +G_END_DECLS + +#endif /* __NM_SETTING_WIREGUARD_H__ */ diff --git a/src/libnm-core-public/nm-setting-wireless-security.h b/src/libnm-core-public/nm-setting-wireless-security.h new file mode 100644 index 0000000000..62a3c6e526 --- /dev/null +++ b/src/libnm-core-public/nm-setting-wireless-security.h @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2017 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_WIRELESS_SECURITY_H__ +#define __NM_SETTING_WIRELESS_SECURITY_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_get_type()) +#define NM_SETTING_WIRELESS_SECURITY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + NM_TYPE_SETTING_WIRELESS_SECURITY, \ + NMSettingWirelessSecurity)) +#define NM_SETTING_WIRELESS_SECURITY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + NM_TYPE_SETTING_WIRELESS_SECURITY, \ + NMSettingWirelessSecurityClass)) +#define NM_IS_SETTING_WIRELESS_SECURITY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIRELESS_SECURITY)) +#define NM_IS_SETTING_WIRELESS_SECURITY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIRELESS_SECURITY)) +#define NM_SETTING_WIRELESS_SECURITY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + NM_TYPE_SETTING_WIRELESS_SECURITY, \ + NMSettingWirelessSecurityClass)) + +#define NM_SETTING_WIRELESS_SECURITY_SETTING_NAME "802-11-wireless-security" + +/** + * NMWepKeyType: + * @NM_WEP_KEY_TYPE_UNKNOWN: unknown WEP key type + * @NM_WEP_KEY_TYPE_KEY: indicates a hexadecimal or ASCII formatted WEP key. + * Hex keys are either 10 or 26 hexadecimal characters (ie "5f782f2f5f" or + * "732f2d712e4a394a375d366931"), while ASCII keys are either 5 or 13 ASCII + * characters (ie "abcde" or "blahblah99$*1"). + * @NM_WEP_KEY_TYPE_PASSPHRASE: indicates a WEP passphrase (ex "I bought a duck + * on my way back from the market 235Q&^%^*%") instead of a hexadecimal or ASCII + * key. Passphrases are between 8 and 64 characters inclusive and are hashed + * the actual WEP key using the MD5 hash algorithm. + * @NM_WEP_KEY_TYPE_LAST: placeholder value for bounds-checking + * + * The #NMWepKeyType values specify how any WEP keys present in the setting + * are interpreted. There are no standards governing how to hash the various WEP + * key/passphrase formats into the actual WEP key. Unfortunately some WEP keys + * can be interpreted in multiple ways, requiring the setting to specify how to + * interpret the any WEP keys. For example, the key "732f2d712e4a394a375d366931" + * is both a valid Hexadecimal WEP key and a WEP passphrase. Further, many + * ASCII keys are also valid WEP passphrases, but since passphrases and ASCII + * keys are hashed differently to determine the actual WEP key the type must be + * specified. + */ +typedef enum { + NM_WEP_KEY_TYPE_UNKNOWN = 0, + NM_WEP_KEY_TYPE_KEY = 1, /* Hex or ASCII */ + NM_WEP_KEY_TYPE_PASSPHRASE = 2, /* 104/128-bit Passphrase */ + + NM_WEP_KEY_TYPE_LAST = NM_WEP_KEY_TYPE_PASSPHRASE, /*< skip >*/ +} NMWepKeyType; + +/** + * NMSettingWirelessSecurityPmf: + * @NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT: use the default value + * @NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE: disable PMF + * @NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL: enable PMF if the supplicant and the AP support it + * @NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED: require PMF and fail if not available + * + * These flags indicate whether PMF must be enabled. + **/ +typedef enum { + NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT = 0, + NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE = 1, + NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL = 2, + NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED = 3, + _NM_SETTING_WIRELESS_SECURITY_PMF_NUM, /*< skip >*/ + NM_SETTING_WIRELESS_SECURITY_PMF_LAST = _NM_SETTING_WIRELESS_SECURITY_PMF_NUM - 1, /*< skip >*/ +} NMSettingWirelessSecurityPmf; + +/** + * NMSettingWirelessSecurityWpsMethod: + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT: Attempt whichever method AP supports + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED: WPS can not be used. + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO: Use WPS, any method + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC: use WPS push-button method + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN: use PIN method + * + * Configure the use of WPS by a connection while it activates. + * + * Note: prior to 1.16, this was a GEnum type instead of a GFlags type + * although, with the same numeric values. + * + * Since: 1.10 + **/ +typedef enum { /*< flags >*/ + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT = 0x00000000, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED = 0x00000001, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO = 0x00000002, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC = 0x00000004, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN = 0x00000008, +} NMSettingWirelessSecurityWpsMethod; + +/** + * NMSettingWirelessSecurityFils: + * @NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT: use the default value + * @NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE: disable FILS + * @NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL: enable FILS if the supplicant and the AP support it + * @NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED: require FILS and fail if not available + * @_NM_SETTING_WIRELESS_SECURITY_FILS_NUM: placeholder value for bounds-checking + * @NM_SETTING_WIRELESS_SECURITY_FILS_LAST: placeholder value for bounds-checking + * + * These flags indicate whether FILS must be enabled. + * + * Since: 1.12 + **/ +/* clang-format off */ +typedef enum { + NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT = 0, + NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE = 1, + NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL = 2, + NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED = 3, + _NM_SETTING_WIRELESS_SECURITY_FILS_NUM, /*< skip >*/ + NM_SETTING_WIRELESS_SECURITY_FILS_LAST = _NM_SETTING_WIRELESS_SECURITY_FILS_NUM - 1, /*< skip >*/ +} NMSettingWirelessSecurityFils; +/* clang-format on */ + +#define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt" +#define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx" +#define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg" +#define NM_SETTING_WIRELESS_SECURITY_PROTO "proto" +#define NM_SETTING_WIRELESS_SECURITY_PAIRWISE "pairwise" +#define NM_SETTING_WIRELESS_SECURITY_GROUP "group" +#define NM_SETTING_WIRELESS_SECURITY_PMF "pmf" +#define NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME "leap-username" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY0 "wep-key0" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY1 "wep-key1" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY2 "wep-key2" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY3 "wep-key3" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS "wep-key-flags" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE "wep-key-type" +#define NM_SETTING_WIRELESS_SECURITY_PSK "psk" +#define NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS "psk-flags" +#define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD "leap-password" +#define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS "leap-password-flags" +#define NM_SETTING_WIRELESS_SECURITY_WPS_METHOD "wps-method" +#define NM_SETTING_WIRELESS_SECURITY_FILS "fils" + +/** + * NMSettingWirelessSecurity: + * + * Wi-Fi Security Settings + */ +struct _NMSettingWirelessSecurity { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingWirelessSecurityClass; + +GType nm_setting_wireless_security_get_type(void); + +NMSetting *nm_setting_wireless_security_new(void); + +const char *nm_setting_wireless_security_get_key_mgmt(NMSettingWirelessSecurity *setting); + +guint32 nm_setting_wireless_security_get_num_protos(NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_proto(NMSettingWirelessSecurity *setting, guint32 i); +gboolean nm_setting_wireless_security_add_proto(NMSettingWirelessSecurity *setting, + const char * proto); +void nm_setting_wireless_security_remove_proto(NMSettingWirelessSecurity *setting, guint32 i); +gboolean nm_setting_wireless_security_remove_proto_by_value(NMSettingWirelessSecurity *setting, + const char * proto); +void nm_setting_wireless_security_clear_protos(NMSettingWirelessSecurity *setting); + +guint32 nm_setting_wireless_security_get_num_pairwise(NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_pairwise(NMSettingWirelessSecurity *setting, + guint32 i); +gboolean nm_setting_wireless_security_add_pairwise(NMSettingWirelessSecurity *setting, + const char * pairwise); +void nm_setting_wireless_security_remove_pairwise(NMSettingWirelessSecurity *setting, guint32 i); +gboolean nm_setting_wireless_security_remove_pairwise_by_value(NMSettingWirelessSecurity *setting, + const char * pairwise); +void nm_setting_wireless_security_clear_pairwise(NMSettingWirelessSecurity *setting); + +guint32 nm_setting_wireless_security_get_num_groups(NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_group(NMSettingWirelessSecurity *setting, guint32 i); +gboolean nm_setting_wireless_security_add_group(NMSettingWirelessSecurity *setting, + const char * group); +void nm_setting_wireless_security_remove_group(NMSettingWirelessSecurity *setting, guint32 i); +gboolean nm_setting_wireless_security_remove_group_by_value(NMSettingWirelessSecurity *setting, + const char * group); +void nm_setting_wireless_security_clear_groups(NMSettingWirelessSecurity *setting); + +NM_AVAILABLE_IN_1_10 +NMSettingWirelessSecurityPmf +nm_setting_wireless_security_get_pmf(NMSettingWirelessSecurity *setting); + +const char * nm_setting_wireless_security_get_psk(NMSettingWirelessSecurity *setting); +NMSettingSecretFlags nm_setting_wireless_security_get_psk_flags(NMSettingWirelessSecurity *setting); + +const char *nm_setting_wireless_security_get_leap_username(NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_leap_password(NMSettingWirelessSecurity *setting); +NMSettingSecretFlags +nm_setting_wireless_security_get_leap_password_flags(NMSettingWirelessSecurity *setting); + +const char *nm_setting_wireless_security_get_wep_key(NMSettingWirelessSecurity *setting, + guint32 idx); +void nm_setting_wireless_security_set_wep_key(NMSettingWirelessSecurity *setting, + guint32 idx, + const char * key); +guint32 nm_setting_wireless_security_get_wep_tx_keyidx(NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_auth_alg(NMSettingWirelessSecurity *setting); + +NMSettingSecretFlags + nm_setting_wireless_security_get_wep_key_flags(NMSettingWirelessSecurity *setting); +NMWepKeyType nm_setting_wireless_security_get_wep_key_type(NMSettingWirelessSecurity *setting); + +NM_AVAILABLE_IN_1_10 +NMSettingWirelessSecurityWpsMethod +nm_setting_wireless_security_get_wps_method(NMSettingWirelessSecurity *setting); + +NM_AVAILABLE_IN_1_12 +NMSettingWirelessSecurityFils +nm_setting_wireless_security_get_fils(NMSettingWirelessSecurity *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_WIRELESS_SECURITY_H__ */ diff --git a/src/libnm-core-public/nm-setting-wireless.h b/src/libnm-core-public/nm-setting-wireless.h new file mode 100644 index 0000000000..f97e236ce7 --- /dev/null +++ b/src/libnm-core-public/nm-setting-wireless.h @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2014 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_WIRELESS_H__ +#define __NM_SETTING_WIRELESS_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" +#include "nm-setting-wireless-security.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIRELESS (nm_setting_wireless_get_type()) +#define NM_SETTING_WIRELESS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WIRELESS, NMSettingWireless)) +#define NM_SETTING_WIRELESS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessClass)) +#define NM_IS_SETTING_WIRELESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WIRELESS)) +#define NM_IS_SETTING_WIRELESS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WIRELESS)) +#define NM_SETTING_WIRELESS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessClass)) + +#define NM_SETTING_WIRELESS_SETTING_NAME "802-11-wireless" + +/** + * NMSettingWirelessWakeOnWLan: + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE: Wake-on-WLAN disabled + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY: Wake on any activity + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT: Wake on disconnect + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC: Wake on magic packet + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE: Wake on GTK rekey failure + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST: Wake on EAP identity request + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE: Wake on 4way handshake + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE: Wake on rfkill release + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL: Wake on all events. This does not + * include the exclusive flags @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT or + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE. + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT: Use the default value + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE: Don't change configured settings + * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS: Mask of flags that are + * incompatible with other flags + * + * Options for #NMSettingWireless:wake-on-wlan. Note that not all options + * are supported by all devices. + * + * Since: 1.12 + */ +/* clang-format off */ +typedef enum { /*< flags >*/ + NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE = 0, /*< skip >*/ + NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY = 0x2, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT = 0x4, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC = 0x8, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE = 0x10, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST = 0x20, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE = 0x40, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE = 0x80, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP = 0x100, + + NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL = 0x1FE, + + NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT = 0x1, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE = 0x8000, + + NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS = NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT | NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE, /*< skip >*/ +} NMSettingWirelessWakeOnWLan; +/* clang-format on */ + +#define NM_SETTING_WIRELESS_SSID "ssid" +#define NM_SETTING_WIRELESS_MODE "mode" +#define NM_SETTING_WIRELESS_BAND "band" +#define NM_SETTING_WIRELESS_CHANNEL "channel" +#define NM_SETTING_WIRELESS_BSSID "bssid" +#define NM_SETTING_WIRELESS_RATE "rate" +#define NM_SETTING_WIRELESS_TX_POWER "tx-power" +#define NM_SETTING_WIRELESS_MAC_ADDRESS "mac-address" +#define NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS "cloned-mac-address" +#define NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK "generate-mac-address-mask" +#define NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST "mac-address-blacklist" +#define NM_SETTING_WIRELESS_MTU "mtu" +#define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids" +#define NM_SETTING_WIRELESS_HIDDEN "hidden" +#define NM_SETTING_WIRELESS_POWERSAVE "powersave" +#define NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION "mac-address-randomization" +#define NM_SETTING_WIRELESS_WAKE_ON_WLAN "wake-on-wlan" +#define NM_SETTING_WIRELESS_AP_ISOLATION "ap-isolation" + +/** + * NM_SETTING_WIRELESS_MODE_ADHOC: + * + * Indicates Ad-Hoc mode where no access point is expected to be present. + */ +#define NM_SETTING_WIRELESS_MODE_ADHOC "adhoc" + +/** + * NM_SETTING_WIRELESS_MODE_AP: + * + * Indicates AP/master mode where the wireless device is started as an access + * point/hotspot. + */ +#define NM_SETTING_WIRELESS_MODE_AP "ap" + +/** + * NM_SETTING_WIRELESS_MODE_INFRA: + * + * Indicates infrastructure mode where an access point is expected to be present + * for this connection. + */ +#define NM_SETTING_WIRELESS_MODE_INFRA "infrastructure" + +/** + * NM_SETTING_WIRELESS_MODE_MESH: + * + * Indicates that the connection should create a mesh point. + * + * Since: 1.20 + */ +#define NM_SETTING_WIRELESS_MODE_MESH "mesh" + +/** + * NMSettingWirelessPowersave: + * @NM_SETTING_WIRELESS_POWERSAVE_DEFAULT: use the default value + * @NM_SETTING_WIRELESS_POWERSAVE_IGNORE: don't touch existing setting + * @NM_SETTING_WIRELESS_POWERSAVE_DISABLE: disable powersave + * @NM_SETTING_WIRELESS_POWERSAVE_ENABLE: enable powersave + * + * These flags indicate whether wireless powersave must be enabled. + **/ +typedef enum { + NM_SETTING_WIRELESS_POWERSAVE_DEFAULT = 0, + NM_SETTING_WIRELESS_POWERSAVE_IGNORE = 1, + NM_SETTING_WIRELESS_POWERSAVE_DISABLE = 2, + NM_SETTING_WIRELESS_POWERSAVE_ENABLE = 3, + _NM_SETTING_WIRELESS_POWERSAVE_NUM, /*< skip >*/ + NM_SETTING_WIRELESS_POWERSAVE_LAST = _NM_SETTING_WIRELESS_POWERSAVE_NUM - 1, /*< skip >*/ +} NMSettingWirelessPowersave; + +/** + * NMSettingWireless: + * + * Wi-Fi Settings + */ +struct _NMSettingWireless { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingWirelessClass; + +GType nm_setting_wireless_get_type(void); + +NMSetting *nm_setting_wireless_new(void); + +GBytes * nm_setting_wireless_get_ssid(NMSettingWireless *setting); +const char *nm_setting_wireless_get_mode(NMSettingWireless *setting); +const char *nm_setting_wireless_get_band(NMSettingWireless *setting); +guint32 nm_setting_wireless_get_channel(NMSettingWireless *setting); +const char *nm_setting_wireless_get_bssid(NMSettingWireless *setting); +guint32 nm_setting_wireless_get_rate(NMSettingWireless *setting); +guint32 nm_setting_wireless_get_tx_power(NMSettingWireless *setting); +const char *nm_setting_wireless_get_mac_address(NMSettingWireless *setting); +const char *nm_setting_wireless_get_cloned_mac_address(NMSettingWireless *setting); + +NM_AVAILABLE_IN_1_4 +const char *nm_setting_wireless_get_generate_mac_address_mask(NMSettingWireless *setting); + +const char *const *nm_setting_wireless_get_mac_address_blacklist(NMSettingWireless *setting); +guint32 nm_setting_wireless_get_num_mac_blacklist_items(NMSettingWireless *setting); +const char *nm_setting_wireless_get_mac_blacklist_item(NMSettingWireless *setting, guint32 idx); +gboolean nm_setting_wireless_add_mac_blacklist_item(NMSettingWireless *setting, const char *mac); +void nm_setting_wireless_remove_mac_blacklist_item(NMSettingWireless *setting, guint32 idx); +gboolean nm_setting_wireless_remove_mac_blacklist_item_by_value(NMSettingWireless *setting, + const char * mac); +void nm_setting_wireless_clear_mac_blacklist_items(NMSettingWireless *setting); + +guint32 nm_setting_wireless_get_mtu(NMSettingWireless *setting); +gboolean nm_setting_wireless_get_hidden(NMSettingWireless *setting); +NM_AVAILABLE_IN_1_2 +guint32 nm_setting_wireless_get_powersave(NMSettingWireless *setting); + +NM_AVAILABLE_IN_1_2 +NMSettingMacRandomization +nm_setting_wireless_get_mac_address_randomization(NMSettingWireless *setting); + +gboolean nm_setting_wireless_add_seen_bssid(NMSettingWireless *setting, const char *bssid); + +guint32 nm_setting_wireless_get_num_seen_bssids(NMSettingWireless *setting); +const char *nm_setting_wireless_get_seen_bssid(NMSettingWireless *setting, guint32 i); + +gboolean nm_setting_wireless_ap_security_compatible(NMSettingWireless * s_wireless, + NMSettingWirelessSecurity *s_wireless_sec, + NM80211ApFlags ap_flags, + NM80211ApSecurityFlags ap_wpa, + NM80211ApSecurityFlags ap_rsn, + NM80211Mode ap_mode); + +NM_AVAILABLE_IN_1_12 +NMSettingWirelessWakeOnWLan nm_setting_wireless_get_wake_on_wlan(NMSettingWireless *setting); + +NM_AVAILABLE_IN_1_28 +NMTernary nm_setting_wireless_get_ap_isolation(NMSettingWireless *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_WIRELESS_H__ */ diff --git a/src/libnm-core-public/nm-setting-wpan.h b/src/libnm-core-public/nm-setting-wpan.h new file mode 100644 index 0000000000..2a09d49bbd --- /dev/null +++ b/src/libnm-core-public/nm-setting-wpan.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018 Lubomir Rintel + */ + +#ifndef __NM_SETTING_WPAN_H__ +#define __NM_SETTING_WPAN_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WPAN (nm_setting_wpan_get_type()) +#define NM_SETTING_WPAN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_WPAN, NMSettingWpan)) +#define NM_SETTING_WPAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_WPANCONFIG, NMSettingWpanClass)) +#define NM_IS_SETTING_WPAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_WPAN)) +#define NM_IS_SETTING_WPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_WPAN)) +#define NM_SETTING_WPAN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_WPAN, NMSettingWpanClass)) + +#define NM_SETTING_WPAN_SETTING_NAME "wpan" +#define NM_SETTING_WPAN_MAC_ADDRESS "mac-address" +#define NM_SETTING_WPAN_PAN_ID "pan-id" +#define NM_SETTING_WPAN_SHORT_ADDRESS "short-address" +#define NM_SETTING_WPAN_PAGE "page" +#define NM_SETTING_WPAN_CHANNEL "channel" + +#define NM_SETTING_WPAN_PAGE_DEFAULT -1 +#define NM_SETTING_WPAN_CHANNEL_DEFAULT -1 + +typedef struct _NMSettingWpanClass NMSettingWpanClass; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_wpan_get_type(void); +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_wpan_new(void); + +NM_AVAILABLE_IN_1_14 +const char *nm_setting_wpan_get_mac_address(NMSettingWpan *setting); +NM_AVAILABLE_IN_1_14 +guint16 nm_setting_wpan_get_pan_id(NMSettingWpan *setting); +NM_AVAILABLE_IN_1_14 +guint16 nm_setting_wpan_get_short_address(NMSettingWpan *setting); +NM_AVAILABLE_IN_1_16 +gint16 nm_setting_wpan_get_page(NMSettingWpan *setting); +NM_AVAILABLE_IN_1_16 +gint16 nm_setting_wpan_get_channel(NMSettingWpan *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_WPAN_H__ */ diff --git a/src/libnm-core-public/nm-setting.h b/src/libnm-core-public/nm-setting.h new file mode 100644 index 0000000000..e5cf753dc6 --- /dev/null +++ b/src/libnm-core-public/nm-setting.h @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2007 - 2011 Red Hat, Inc. + * Copyright (C) 2007 - 2008 Novell, Inc. + */ + +#ifndef __NM_SETTING_H__ +#define __NM_SETTING_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-core-types.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING (nm_setting_get_type()) +#define NM_SETTING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING, NMSetting)) +#define NM_SETTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING, NMSettingClass)) +#define NM_IS_SETTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING)) +#define NM_IS_SETTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING)) +#define NM_SETTING_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING, NMSettingClass)) + +/* The property of the #NMSetting is required for the setting to be valid */ +#define NM_SETTING_PARAM_REQUIRED (1 << (1 + G_PARAM_USER_SHIFT)) + +/* The property of the #NMSetting is a secret */ +#define NM_SETTING_PARAM_SECRET (1 << (2 + G_PARAM_USER_SHIFT)) + +/* The property of the #NMSetting should be ignored during comparisons that + * use the %NM_SETTING_COMPARE_FLAG_FUZZY flag. + */ +#define NM_SETTING_PARAM_FUZZY_IGNORE (1 << (3 + G_PARAM_USER_SHIFT)) + +/* Note: all non-glib GParamFlags bits are reserved by NetworkManager */ + +#define NM_SETTING_NAME "name" + +/** + * NMSettingSecretFlags: + * @NM_SETTING_SECRET_FLAG_NONE: the system is responsible for providing and + * storing this secret (default) + * @NM_SETTING_SECRET_FLAG_AGENT_OWNED: a user secret agent is responsible + * for providing and storing this secret; when it is required agents will be + * asked to retrieve it + * @NM_SETTING_SECRET_FLAG_NOT_SAVED: this secret should not be saved, but + * should be requested from the user each time it is needed + * @NM_SETTING_SECRET_FLAG_NOT_REQUIRED: in situations where it cannot be + * automatically determined that the secret is required (some VPNs and PPP + * providers don't require all secrets) this flag indicates that the specific + * secret is not required + * + * These flags indicate specific behavior related to handling of a secret. Each + * secret has a corresponding set of these flags which indicate how the secret + * is to be stored and/or requested when it is needed. + * + **/ +typedef enum { /*< flags >*/ + NM_SETTING_SECRET_FLAG_NONE = 0x00000000, + NM_SETTING_SECRET_FLAG_AGENT_OWNED = 0x00000001, + NM_SETTING_SECRET_FLAG_NOT_SAVED = 0x00000002, + NM_SETTING_SECRET_FLAG_NOT_REQUIRED = 0x00000004 + + /* NOTE: if adding flags, update nm-core-internal.h as well */ +} NMSettingSecretFlags; + +/** + * NMSettingCompareFlags: + * @NM_SETTING_COMPARE_FLAG_EXACT: match all properties exactly + * @NM_SETTING_COMPARE_FLAG_FUZZY: match only important attributes, like SSID, + * type, security settings, etc. Does not match, for example, connection ID + * or UUID. + * @NM_SETTING_COMPARE_FLAG_IGNORE_ID: ignore the connection's ID + * @NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS: ignore all secrets + * @NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS: ignore secrets for which + * the secret's flags indicate the secret is owned by a user secret agent + * (ie, the secret's flag includes @NM_SETTING_SECRET_FLAG_AGENT_OWNED) + * @NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS: ignore secrets for which + * the secret's flags indicate the secret should not be saved to persistent + * storage (ie, the secret's flag includes @NM_SETTING_SECRET_FLAG_NOT_SAVED) + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT: if this flag is set, + * nm_setting_diff() and nm_connection_diff() will also include properties that + * are set to their default value. See also @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT. + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT: if this flag is set, + * nm_setting_diff() and nm_connection_diff() will not include properties that + * are set to their default value. This is the opposite of + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. If both flags are set together, + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT wins. If both flags are unset, + * this means to exclude default properties if there is a setting to compare, + * but include all properties, if the setting 'b' is missing. This is the legacy + * behaviour of libnm-util, where nm_setting_diff() behaved differently depending + * on whether the setting 'b' was available. If @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT + * is set, nm_setting_diff() will also set the flags @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT + * and @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT, if the values are default values. + * @NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP: ignore the connection's timestamp + * + * These flags modify the comparison behavior when comparing two settings or + * two connections. + * + **/ +typedef enum { + NM_SETTING_COMPARE_FLAG_EXACT = 0x00000000, + NM_SETTING_COMPARE_FLAG_FUZZY = 0x00000001, + NM_SETTING_COMPARE_FLAG_IGNORE_ID = 0x00000002, + NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS = 0x00000004, + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS = 0x00000008, + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS = 0x00000010, + NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT = 0x00000020, + NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT = 0x00000040, + NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP = 0x00000080, + + /* Higher flags like 0x80000000 and 0x40000000 are used internally as private flags */ +} NMSettingCompareFlags; + +/** + * NMSettingMacRandomization: + * @NM_SETTING_MAC_RANDOMIZATION_DEFAULT: the default value, which unless + * overridden by user-controlled defaults configuration, is "never". + * @NM_SETTING_MAC_RANDOMIZATION_NEVER: the device's MAC address is always used. + * @NM_SETTING_MAC_RANDOMIZATION_ALWAYS: a random MAC address is used. + * + * Controls if and how the MAC address of a device is randomzied. + **/ +typedef enum { + NM_SETTING_MAC_RANDOMIZATION_DEFAULT = 0, + NM_SETTING_MAC_RANDOMIZATION_NEVER, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS, +} NMSettingMacRandomization; + +/** + * NMSetting: + * + * The NMSetting struct contains only private data. + * It should only be accessed through the functions described below. + */ +struct _NMSetting { + GObject parent; +}; + +/** + * NMSettingClearSecretsWithFlagsFn: + * @setting: The setting for which secrets are being iterated + * @secret: The secret's name + * @flags: The secret's flags, eg %NM_SETTING_SECRET_FLAG_AGENT_OWNED + * @user_data: User data passed to nm_connection_clear_secrets_with_flags() + * + * Returns: %TRUE to clear the secret, %FALSE to not clear the secret + */ +typedef gboolean (*NMSettingClearSecretsWithFlagsFn)(NMSetting * setting, + const char * secret, + NMSettingSecretFlags flags, + gpointer user_data); + +struct _NMMetaSettingInfo; +struct _NMSettInfoSetting; +struct _NMSettInfoProperty; + +/** + * NMSettingValueIterFn: + * @setting: The setting for which properties are being iterated, given to + * nm_setting_enumerate_values() + * @key: The value/property name + * @value: The property's value + * @flags: The property's flags, like %NM_SETTING_PARAM_SECRET + * @user_data: User data passed to nm_setting_enumerate_values() + */ +typedef void (*NMSettingValueIterFn)(NMSetting * setting, + const char * key, + const GValue *value, + GParamFlags flags, + gpointer user_data); + +/*< private >*/ +typedef gboolean (*_NMConnectionForEachSecretFunc)(NMSettingSecretFlags flags, gpointer user_data); + +typedef struct { + GObjectClass parent; + + /* Virtual functions */ + int (*verify)(NMSetting *setting, NMConnection *connection, GError **error); + + gboolean (*verify_secrets)(NMSetting *setting, NMConnection *connection, GError **error); + + GPtrArray *(*need_secrets)(NMSetting *setting); + + int (*update_one_secret)(NMSetting *setting, const char *key, GVariant *value, GError **error); + + gboolean (*get_secret_flags)(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags *out_flags, + GError ** error); + + gboolean (*set_secret_flags)(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags flags, + GError ** error); + + /*< private >*/ + gboolean (*clear_secrets)(const struct _NMSettInfoSetting *sett_info, + guint property_idx, + NMSetting * setting, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data); + + /* compare_property() returns a ternary, where DEFAULT means that the property should not + * be compared due to the compare @flags. A TRUE/FALSE result means that the property is + * equal/not-equal. + * + * @other may be %NULL, in which case the function only determines whether + * the setting should be compared (TRUE) or not (DEFAULT). */ + /*< private >*/ + NMTernary (*compare_property)(const struct _NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection * con_a, + NMSetting * set_a, + NMConnection * con_b, + NMSetting * set_b, + NMSettingCompareFlags flags); + + /*< private >*/ + void (*duplicate_copy_properties)(const struct _NMSettInfoSetting *sett_info, + NMSetting * src, + NMSetting * dst); + + /*< private >*/ + void (*enumerate_values)(const struct _NMSettInfoProperty *property_info, + NMSetting * setting, + NMSettingValueIterFn func, + gpointer user_data); + + /*< private >*/ + gboolean (*aggregate)(NMSetting *setting, int type_i, gpointer arg); + + /*< private >*/ + void (*for_each_secret)(NMSetting * setting, + const char * secret_name, + GVariant * val, + gboolean remove_non_secrets, + _NMConnectionForEachSecretFunc callback, + gpointer callback_data, + GVariantBuilder * setting_builder); + + /*< private >*/ + gboolean (*init_from_dbus)(NMSetting * setting, + GHashTable * keys, + GVariant * setting_dict, + GVariant * connection_dict, + guint /* NMSettingParseFlags */ parse_flags, + GError ** error); + + /*< private >*/ + gpointer padding[1]; + + /*< private >*/ + const struct _NMMetaSettingInfo *setting_info; +} NMSettingClass; + +GType nm_setting_get_type(void); + +GType nm_setting_lookup_type(const char *name); + +NMSetting *nm_setting_duplicate(NMSetting *setting); + +const char *nm_setting_get_name(NMSetting *setting); + +gboolean nm_setting_verify(NMSetting *setting, NMConnection *connection, GError **error); + +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_verify_secrets(NMSetting *setting, NMConnection *connection, GError **error); + +gboolean nm_setting_compare(NMSetting *a, NMSetting *b, NMSettingCompareFlags flags); + +/** + * NMSettingDiffResult: + * @NM_SETTING_DIFF_RESULT_UNKNOWN: unknown result + * @NM_SETTING_DIFF_RESULT_IN_A: the property is present in setting A + * @NM_SETTING_DIFF_RESULT_IN_B: the property is present in setting B + * @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT: the property is present in + * setting A but is set to the default value. This flag is only set, + * if you specify @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. + * @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT: analog to @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT. + * + * These values indicate the result of a setting difference operation. + **/ +typedef enum { + NM_SETTING_DIFF_RESULT_UNKNOWN = 0x00000000, + NM_SETTING_DIFF_RESULT_IN_A = 0x00000001, + NM_SETTING_DIFF_RESULT_IN_B = 0x00000002, + NM_SETTING_DIFF_RESULT_IN_A_DEFAULT = 0x00000004, + NM_SETTING_DIFF_RESULT_IN_B_DEFAULT = 0x00000008, +} NMSettingDiffResult; + +gboolean nm_setting_diff(NMSetting * a, + NMSetting * b, + NMSettingCompareFlags flags, + gboolean invert_results, + GHashTable ** results); + +void nm_setting_enumerate_values(NMSetting *setting, NMSettingValueIterFn func, gpointer user_data); + +char *nm_setting_to_string(NMSetting *setting); + +/*****************************************************************************/ + +gboolean nm_setting_get_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags *out_flags, + GError ** error); + +gboolean nm_setting_set_secret_flags(NMSetting * setting, + const char * secret_name, + NMSettingSecretFlags flags, + GError ** error); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_26 +GVariant *nm_setting_option_get(NMSetting *setting, const char *opt_name); + +NM_AVAILABLE_IN_1_26 +gboolean +nm_setting_option_get_boolean(NMSetting *setting, const char *opt_name, gboolean *out_value); + +NM_AVAILABLE_IN_1_26 +gboolean nm_setting_option_get_uint32(NMSetting *setting, const char *opt_name, guint32 *out_value); + +NM_AVAILABLE_IN_1_26 +void nm_setting_option_set(NMSetting *setting, const char *opt_name, GVariant *variant); + +NM_AVAILABLE_IN_1_26 +void nm_setting_option_set_uint32(NMSetting *setting, const char *opt_name, guint32 value); + +NM_AVAILABLE_IN_1_26 +void nm_setting_option_set_boolean(NMSetting *setting, const char *opt_name, gboolean value); + +NM_AVAILABLE_IN_1_26 +const char *const *nm_setting_option_get_all_names(NMSetting *setting, guint *out_len); + +NM_AVAILABLE_IN_1_26 +void nm_setting_option_clear_by_name(NMSetting *setting, NMUtilsPredicateStr predicate); + +/*****************************************************************************/ + +const GVariantType *nm_setting_get_dbus_property_type(NMSetting * setting, + const char *property_name); + +/*****************************************************************************/ + +G_END_DECLS + +#endif /* __NM_SETTING_H__ */ diff --git a/src/libnm-core-public/nm-simple-connection.h b/src/libnm-core-public/nm-simple-connection.h new file mode 100644 index 0000000000..38473b6287 --- /dev/null +++ b/src/libnm-core-public/nm-simple-connection.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2014 Red Hat, Inc. + */ + +#ifndef __NM_SIMPLE_CONNECTION_H__ +#define __NM_SIMPLE_CONNECTION_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include "nm-connection.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SIMPLE_CONNECTION (nm_simple_connection_get_type()) +#define NM_SIMPLE_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnection)) +#define NM_SIMPLE_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnectionClass)) +#define NM_IS_SIMPLE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SIMPLE_CONNECTION)) +#define NM_IS_SIMPLE_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SIMPLE_CONNECTION)) +#define NM_SIMPLE_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnectionClass)) + +/** + * NMSimpleConnection: + */ +struct _NMSimpleConnection { + GObject parent; +}; + +typedef struct { + GObjectClass parent_class; + + /*< private >*/ + gpointer padding[4]; +} NMSimpleConnectionClass; + +GType nm_simple_connection_get_type(void); + +NMConnection *nm_simple_connection_new(void); + +NMConnection *nm_simple_connection_new_from_dbus(GVariant *dict, GError **error); + +NMConnection *nm_simple_connection_new_clone(NMConnection *connection); + +G_END_DECLS + +#endif /* __NM_SIMPLE_CONNECTION__ */ diff --git a/src/libnm-core-public/nm-utils.h b/src/libnm-core-public/nm-utils.h new file mode 100644 index 0000000000..0f8dcda09e --- /dev/null +++ b/src/libnm-core-public/nm-utils.h @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2005 - 2017 Red Hat, Inc. + */ + +#ifndef __NM_UTILS_H__ +#define __NM_UTILS_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include + +#include "nm-core-enum-types.h" +#include "nm-setting-sriov.h" +#include "nm-setting-tc-config.h" +#include "nm-setting-wireless-security.h" + +G_BEGIN_DECLS + +/*****************************************************************************/ + +typedef struct _NMVariantAttributeSpec NMVariantAttributeSpec; + +/* SSID helpers */ +gboolean nm_utils_is_empty_ssid(const guint8 *ssid, gsize len); +const char *nm_utils_escape_ssid(const guint8 *ssid, gsize len); +gboolean nm_utils_same_ssid(const guint8 *ssid1, + gsize len1, + const guint8 *ssid2, + gsize len2, + gboolean ignore_trailing_null); +char * nm_utils_ssid_to_utf8(const guint8 *ssid, gsize len); + +/** + * NMUtilsSecurityType: + * @NMU_SEC_INVALID: unknown or invalid security, placeholder and not used + * @NMU_SEC_NONE: unencrypted and open + * @NMU_SEC_STATIC_WEP: static WEP keys are used for encryption + * @NMU_SEC_LEAP: Cisco LEAP is used for authentication and for generating the + * dynamic WEP keys automatically + * @NMU_SEC_DYNAMIC_WEP: standard 802.1x is used for authentication and + * generating the dynamic WEP keys automatically + * @NMU_SEC_WPA_PSK: WPA1 is used with Pre-Shared Keys (PSK) + * @NMU_SEC_WPA_ENTERPRISE: WPA1 is used with 802.1x authentication + * @NMU_SEC_WPA2_PSK: WPA2/RSN is used with Pre-Shared Keys (PSK) + * @NMU_SEC_WPA2_ENTERPRISE: WPA2 is used with 802.1x authentication + * @NMU_SEC_SAE: is used with WPA3 Enterprise + * @NMU_SEC_OWE: is used with Enhanced Open + * @NMU_SEC_WPA3_SUITE_B_192: is used with WPA3 Enterprise Suite-B 192 bit mode. Since: 1.30. + * + * Describes generic security mechanisms that 802.11 access points may offer. + * Used with nm_utils_security_valid() for checking whether a given access + * point is compatible with a network device. + **/ +typedef enum { + NMU_SEC_INVALID = 0, + NMU_SEC_NONE, + NMU_SEC_STATIC_WEP, + NMU_SEC_LEAP, + NMU_SEC_DYNAMIC_WEP, + NMU_SEC_WPA_PSK, + NMU_SEC_WPA_ENTERPRISE, + NMU_SEC_WPA2_PSK, + NMU_SEC_WPA2_ENTERPRISE, + NMU_SEC_SAE, + NMU_SEC_OWE, + NMU_SEC_WPA3_SUITE_B_192, +} NMUtilsSecurityType; + +gboolean nm_utils_security_valid(NMUtilsSecurityType type, + NMDeviceWifiCapabilities wifi_caps, + gboolean have_ap, + gboolean adhoc, + NM80211ApFlags ap_flags, + NM80211ApSecurityFlags ap_wpa, + NM80211ApSecurityFlags ap_rsn); + +gboolean nm_utils_ap_mode_security_valid(NMUtilsSecurityType type, + NMDeviceWifiCapabilities wifi_caps); + +gboolean nm_utils_wep_key_valid(const char *key, NMWepKeyType wep_type); +gboolean nm_utils_wpa_psk_valid(const char *psk); + +NM_AVAILABLE_IN_1_6 +gboolean nm_utils_is_json_object(const char *str, GError **error); + +GVariant * nm_utils_ip4_dns_to_variant(char **dns); +char ** nm_utils_ip4_dns_from_variant(GVariant *value); +GVariant * nm_utils_ip4_addresses_to_variant(GPtrArray *addresses, const char *gateway); +GPtrArray *nm_utils_ip4_addresses_from_variant(GVariant *value, char **out_gateway); +GVariant * nm_utils_ip4_routes_to_variant(GPtrArray *routes); +GPtrArray *nm_utils_ip4_routes_from_variant(GVariant *value); + +guint32 nm_utils_ip4_netmask_to_prefix(guint32 netmask); +guint32 nm_utils_ip4_prefix_to_netmask(guint32 prefix); +guint32 nm_utils_ip4_get_default_prefix(guint32 ip); + +GVariant * nm_utils_ip6_dns_to_variant(char **dns); +char ** nm_utils_ip6_dns_from_variant(GVariant *value); +GVariant * nm_utils_ip6_addresses_to_variant(GPtrArray *addresses, const char *gateway); +GPtrArray *nm_utils_ip6_addresses_from_variant(GVariant *value, char **out_gateway); +GVariant * nm_utils_ip6_routes_to_variant(GPtrArray *routes); +GPtrArray *nm_utils_ip6_routes_from_variant(GVariant *value); + +GVariant * nm_utils_ip_addresses_to_variant(GPtrArray *addresses); +GPtrArray *nm_utils_ip_addresses_from_variant(GVariant *value, int family); +GVariant * nm_utils_ip_routes_to_variant(GPtrArray *routes); +GPtrArray *nm_utils_ip_routes_from_variant(GVariant *value, int family); + +char *nm_utils_uuid_generate(void); + +gboolean nm_utils_file_is_certificate(const char *filename); +gboolean nm_utils_file_is_private_key(const char *filename, gboolean *out_encrypted); +gboolean nm_utils_file_is_pkcs12(const char *filename); + +typedef gboolean (*NMUtilsFileSearchInPathsPredicate)(const char *filename, gpointer user_data); + +struct stat; + +typedef gboolean (*NMUtilsCheckFilePredicate)(const char * filename, + const struct stat *stat, + gpointer user_data, + GError ** error); + +const char *nm_utils_file_search_in_paths(const char * progname, + const char * try_first, + const char *const * paths, + GFileTest file_test_flags, + NMUtilsFileSearchInPathsPredicate predicate, + gpointer user_data, + GError ** error); + +guint32 nm_utils_wifi_freq_to_channel(guint32 freq); +guint32 nm_utils_wifi_channel_to_freq(guint32 channel, const char *band); +guint32 nm_utils_wifi_find_next_channel(guint32 channel, int direction, char *band); +gboolean nm_utils_wifi_is_channel_valid(guint32 channel, const char *band); +NM_AVAILABLE_IN_1_2 +const guint *nm_utils_wifi_2ghz_freqs(void); +NM_AVAILABLE_IN_1_2 +const guint *nm_utils_wifi_5ghz_freqs(void); + +const char *nm_utils_wifi_strength_bars(guint8 strength); + +/** + * NM_UTILS_HWADDR_LEN_MAX: + * + * The maximum length of hardware addresses handled by NetworkManager itself, + * nm_utils_hwaddr_len(), and nm_utils_hwaddr_aton(). + */ +#define NM_UTILS_HWADDR_LEN_MAX 20 /* INFINIBAND_ALEN */ + +gsize nm_utils_hwaddr_len(int type) G_GNUC_PURE; + +char * nm_utils_hwaddr_ntoa(gconstpointer addr, gsize length); +GByteArray *nm_utils_hwaddr_atoba(const char *asc, gsize length); +guint8 * nm_utils_hwaddr_aton(const char *asc, gpointer buffer, gsize length); + +gboolean nm_utils_hwaddr_valid(const char *asc, gssize length); +char * nm_utils_hwaddr_canonical(const char *asc, gssize length); +gboolean nm_utils_hwaddr_matches(gconstpointer hwaddr1, + gssize hwaddr1_len, + gconstpointer hwaddr2, + gssize hwaddr2_len); + +char * nm_utils_bin2hexstr(gconstpointer src, gsize len, int final_len); +GBytes *nm_utils_hexstr2bin(const char *hex); + +NM_DEPRECATED_IN_1_6_FOR(nm_utils_is_valid_iface_name) +gboolean nm_utils_iface_valid_name(const char *name); +NM_AVAILABLE_IN_1_6 +gboolean nm_utils_is_valid_iface_name(const char *name, GError **error); + +gboolean nm_utils_is_uuid(const char *str); + +/** + * NM_UTILS_INET_ADDRSTRLEN: + * + * Defines the minimal length for a char buffer that is suitable as @dst argument + * for both nm_utils_inet4_ntop() and nm_utils_inet6_ntop(). + **/ +#define NM_UTILS_INET_ADDRSTRLEN INET6_ADDRSTRLEN + +const char *nm_utils_inet4_ntop(guint32 inaddr, char *dst); + +struct in6_addr; +const char *nm_utils_inet6_ntop(const struct in6_addr *in6addr, char *dst); + +gboolean nm_utils_ipaddr_valid(int family, const char *ip); + +gboolean nm_utils_check_virtual_device_compatibility(GType virtual_type, GType other_type); + +NM_AVAILABLE_IN_1_2 +int nm_utils_bond_mode_string_to_int(const char *mode); +NM_AVAILABLE_IN_1_2 +const char *nm_utils_bond_mode_int_to_string(int mode); + +NM_AVAILABLE_IN_1_2 +char *nm_utils_enum_to_str(GType type, int value); + +NM_AVAILABLE_IN_1_2 +gboolean nm_utils_enum_from_str(GType type, const char *str, int *out_value, char **err_token); + +NM_AVAILABLE_IN_1_2 +const char **nm_utils_enum_get_values(GType type, int from, int to); + +NM_AVAILABLE_IN_1_6 +guint nm_utils_version(void); + +NM_AVAILABLE_IN_1_8 +GHashTable *nm_utils_parse_variant_attributes(const char *string, + char attr_separator, + char key_value_separator, + gboolean ignore_unknown, + const NMVariantAttributeSpec *const *spec, + GError ** error); + +NM_AVAILABLE_IN_1_8 +char *nm_utils_format_variant_attributes(GHashTable *attributes, + char attr_separator, + char key_value_separator); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_12 +NMTCQdisc *nm_utils_tc_qdisc_from_str(const char *str, GError **error); +NM_AVAILABLE_IN_1_12 +char *nm_utils_tc_qdisc_to_str(NMTCQdisc *qdisc, GError **error); + +NM_AVAILABLE_IN_1_12 +NMTCAction *nm_utils_tc_action_from_str(const char *str, GError **error); +NM_AVAILABLE_IN_1_12 +char *nm_utils_tc_action_to_str(NMTCAction *action, GError **error); + +NM_AVAILABLE_IN_1_12 +NMTCTfilter *nm_utils_tc_tfilter_from_str(const char *str, GError **error); +NM_AVAILABLE_IN_1_12 +char *nm_utils_tc_tfilter_to_str(NMTCTfilter *tfilter, GError **error); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_14 +char *nm_utils_sriov_vf_to_str(const NMSriovVF *vf, gboolean omit_index, GError **error); +NM_AVAILABLE_IN_1_14 +NMSriovVF *nm_utils_sriov_vf_from_str(const char *str, GError **error); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_12 +gint64 nm_utils_get_timestamp_msec(void); + +NM_AVAILABLE_IN_1_16 +gboolean +nm_utils_base64secret_decode(const char *base64_key, gsize required_key_len, guint8 *out_key); + +G_END_DECLS + +#endif /* __NM_UTILS_H__ */ diff --git a/src/libnm-core-public/nm-version-macros.h.in b/src/libnm-core-public/nm-version-macros.h.in new file mode 100644 index 0000000000..4a6f46e9f0 --- /dev/null +++ b/src/libnm-core-public/nm-version-macros.h.in @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011, 2015 Red Hat, Inc. + */ + +#ifndef __NM_VERSION_MACROS_H__ +#define __NM_VERSION_MACROS_H__ + +/* This header must not include glib or libnm. */ + +/** + * NM_MAJOR_VERSION: + * + * Evaluates to the major version number of NetworkManager which this source + * is compiled against. + */ +#define NM_MAJOR_VERSION (@NM_MAJOR_VERSION@) + +/** + * NM_MINOR_VERSION: + * + * Evaluates to the minor version number of NetworkManager which this source + * is compiled against. + */ +#define NM_MINOR_VERSION (@NM_MINOR_VERSION@) + +/** + * NM_MICRO_VERSION: + * + * Evaluates to the micro version number of NetworkManager which this source + * compiled against. + */ +#define NM_MICRO_VERSION (@NM_MICRO_VERSION@) + +/** + * NM_CHECK_VERSION: + * @major: major version (e.g. 1 for version 1.2.5) + * @minor: minor version (e.g. 2 for version 1.2.5) + * @micro: micro version (e.g. 5 for version 1.2.5) + * + * Returns: %TRUE if the version of the NetworkManager header files + * is the same as or newer than the passed-in version. + */ +#define NM_CHECK_VERSION(major,minor,micro) \ + (NM_MAJOR_VERSION > (major) || \ + (NM_MAJOR_VERSION == (major) && NM_MINOR_VERSION > (minor)) || \ + (NM_MAJOR_VERSION == (major) && NM_MINOR_VERSION == (minor) && NM_MICRO_VERSION >= (micro))) + + +#define NM_ENCODE_VERSION(major,minor,micro) ((major) << 16 | (minor) << 8 | (micro)) + +#define NM_VERSION_0_9_8 (NM_ENCODE_VERSION (0, 9, 8)) +#define NM_VERSION_0_9_10 (NM_ENCODE_VERSION (0, 9, 10)) +#define NM_VERSION_1_0 (NM_ENCODE_VERSION (1, 0, 0)) +#define NM_VERSION_1_2 (NM_ENCODE_VERSION (1, 2, 0)) +#define NM_VERSION_1_4 (NM_ENCODE_VERSION (1, 4, 0)) +#define NM_VERSION_1_6 (NM_ENCODE_VERSION (1, 6, 0)) +#define NM_VERSION_1_8 (NM_ENCODE_VERSION (1, 8, 0)) +#define NM_VERSION_1_10 (NM_ENCODE_VERSION (1, 10, 0)) +#define NM_VERSION_1_12 (NM_ENCODE_VERSION (1, 12, 0)) +#define NM_VERSION_1_14 (NM_ENCODE_VERSION (1, 14, 0)) +#define NM_VERSION_1_16 (NM_ENCODE_VERSION (1, 16, 0)) +#define NM_VERSION_1_18 (NM_ENCODE_VERSION (1, 18, 0)) +#define NM_VERSION_1_20 (NM_ENCODE_VERSION (1, 20, 0)) +#define NM_VERSION_1_22 (NM_ENCODE_VERSION (1, 22, 0)) +#define NM_VERSION_1_24 (NM_ENCODE_VERSION (1, 24, 0)) +#define NM_VERSION_1_26 (NM_ENCODE_VERSION (1, 26, 0)) +#define NM_VERSION_1_28 (NM_ENCODE_VERSION (1, 28, 0)) +#define NM_VERSION_1_30 (NM_ENCODE_VERSION (1, 30, 0)) + +/* For releases, NM_API_VERSION is equal to NM_VERSION. + * + * For development builds, NM_API_VERSION is the next + * stable API after NM_VERSION. When you run a development + * version, you are already using the future API, even if + * it is not yet release. Hence, the currently used API + * version is the future one. */ +#define NM_API_VERSION \ + (((NM_MINOR_VERSION % 2) == 1) \ + ? NM_ENCODE_VERSION (NM_MAJOR_VERSION, NM_MINOR_VERSION + 1, 0 ) \ + : NM_ENCODE_VERSION (NM_MAJOR_VERSION, NM_MINOR_VERSION , ((NM_MICRO_VERSION + 1) / 2) * 2)) + +/* deprecated. */ +#define NM_VERSION_CUR_STABLE NM_API_VERSION + +/* deprecated. */ +#define NM_VERSION_NEXT_STABLE NM_API_VERSION + +#define NM_VERSION NM_ENCODE_VERSION (NM_MAJOR_VERSION, NM_MINOR_VERSION, NM_MICRO_VERSION) + +#endif /* __NM_VERSION_MACROS_H__ */ diff --git a/src/libnm-core-public/nm-version.h b/src/libnm-core-public/nm-version.h new file mode 100644 index 0000000000..3f1ad3f2eb --- /dev/null +++ b/src/libnm-core-public/nm-version.h @@ -0,0 +1,301 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2011, 2015 Red Hat, Inc. + */ + +#ifndef NM_VERSION_H +#define NM_VERSION_H + +#include + +#include "nm-version-macros.h" + +/* Deprecation / Availability macros */ + +#if !defined(NM_VERSION_MIN_REQUIRED) || (NM_VERSION_MIN_REQUIRED == 0) + #undef NM_VERSION_MIN_REQUIRED + #define NM_VERSION_MIN_REQUIRED (NM_API_VERSION) +#endif + +#if !defined(NM_VERSION_MAX_ALLOWED) || (NM_VERSION_MAX_ALLOWED == 0) + #undef NM_VERSION_MAX_ALLOWED + #define NM_VERSION_MAX_ALLOWED (NM_API_VERSION) +#endif + +/* sanity checks */ +#if NM_VERSION_MIN_REQUIRED > NM_API_VERSION + #error "NM_VERSION_MIN_REQUIRED must be <= NM_API_VERSION" +#endif +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_MIN_REQUIRED + #error "NM_VERSION_MAX_ALLOWED must be >= NM_VERSION_MIN_REQUIRED" +#endif +#if NM_VERSION_MIN_REQUIRED < NM_VERSION_0_9_8 + #error "NM_VERSION_MIN_REQUIRED must be >= NM_VERSION_0_9_8" +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_0_9_10 + #define NM_DEPRECATED_IN_0_9_10 G_DEPRECATED + #define NM_DEPRECATED_IN_0_9_10_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_0_9_10 + #define NM_DEPRECATED_IN_0_9_10_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_0_9_10 + #define NM_AVAILABLE_IN_0_9_10 G_UNAVAILABLE(0.9, 10) +#else + #define NM_AVAILABLE_IN_0_9_10 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_0 + #define NM_DEPRECATED_IN_1_0 G_DEPRECATED + #define NM_DEPRECATED_IN_1_0_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_0 + #define NM_DEPRECATED_IN_1_0_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_0 + #define NM_AVAILABLE_IN_1_0 G_UNAVAILABLE(1, 0) +#else + #define NM_AVAILABLE_IN_1_0 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_2 + #define NM_DEPRECATED_IN_1_2 G_DEPRECATED + #define NM_DEPRECATED_IN_1_2_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_2 + #define NM_DEPRECATED_IN_1_2_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_2 + #define NM_AVAILABLE_IN_1_2 G_UNAVAILABLE(1, 2) +#else + #define NM_AVAILABLE_IN_1_2 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_4 + #define NM_DEPRECATED_IN_1_4 G_DEPRECATED + #define NM_DEPRECATED_IN_1_4_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_4 + #define NM_DEPRECATED_IN_1_4_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_4 + #define NM_AVAILABLE_IN_1_4 G_UNAVAILABLE(1, 4) +#else + #define NM_AVAILABLE_IN_1_4 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_6 + #define NM_DEPRECATED_IN_1_6 G_DEPRECATED + #define NM_DEPRECATED_IN_1_6_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_6 + #define NM_DEPRECATED_IN_1_6_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_6 + #define NM_AVAILABLE_IN_1_6 G_UNAVAILABLE(1, 6) +#else + #define NM_AVAILABLE_IN_1_6 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_8 + #define NM_DEPRECATED_IN_1_8 G_DEPRECATED + #define NM_DEPRECATED_IN_1_8_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_8 + #define NM_DEPRECATED_IN_1_8_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_8 + #define NM_AVAILABLE_IN_1_8 G_UNAVAILABLE(1, 8) +#else + #define NM_AVAILABLE_IN_1_8 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_10 + #define NM_DEPRECATED_IN_1_10 G_DEPRECATED + #define NM_DEPRECATED_IN_1_10_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_10 + #define NM_DEPRECATED_IN_1_10_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_10 + #define NM_AVAILABLE_IN_1_10 G_UNAVAILABLE(1, 10) +#else + #define NM_AVAILABLE_IN_1_10 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_12 + #define NM_DEPRECATED_IN_1_12 G_DEPRECATED + #define NM_DEPRECATED_IN_1_12_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_12 + #define NM_DEPRECATED_IN_1_12_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_12 + #define NM_AVAILABLE_IN_1_12 G_UNAVAILABLE(1, 12) +#else + #define NM_AVAILABLE_IN_1_12 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_14 + #define NM_DEPRECATED_IN_1_14 G_DEPRECATED + #define NM_DEPRECATED_IN_1_14_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_14 + #define NM_DEPRECATED_IN_1_14_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_14 + #define NM_AVAILABLE_IN_1_14 G_UNAVAILABLE(1, 14) +#else + #define NM_AVAILABLE_IN_1_14 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_16 + #define NM_DEPRECATED_IN_1_16 G_DEPRECATED + #define NM_DEPRECATED_IN_1_16_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_16 + #define NM_DEPRECATED_IN_1_16_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_16 + #define NM_AVAILABLE_IN_1_16 G_UNAVAILABLE(1, 16) +#else + #define NM_AVAILABLE_IN_1_16 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_18 + #define NM_DEPRECATED_IN_1_18 G_DEPRECATED + #define NM_DEPRECATED_IN_1_18_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_18 + #define NM_DEPRECATED_IN_1_18_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_18 + #define NM_AVAILABLE_IN_1_18 G_UNAVAILABLE(1, 18) +#else + #define NM_AVAILABLE_IN_1_18 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_20 + #define NM_DEPRECATED_IN_1_20 G_DEPRECATED + #define NM_DEPRECATED_IN_1_20_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_20 + #define NM_DEPRECATED_IN_1_20_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_20 + #define NM_AVAILABLE_IN_1_20 G_UNAVAILABLE(1, 20) +#else + #define NM_AVAILABLE_IN_1_20 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_22 + #define NM_DEPRECATED_IN_1_22 G_DEPRECATED + #define NM_DEPRECATED_IN_1_22_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_22 + #define NM_DEPRECATED_IN_1_22_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_22 + #define NM_AVAILABLE_IN_1_22 G_UNAVAILABLE(1, 22) +#else + #define NM_AVAILABLE_IN_1_22 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_24 + #define NM_DEPRECATED_IN_1_24 G_DEPRECATED + #define NM_DEPRECATED_IN_1_24_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_24 + #define NM_DEPRECATED_IN_1_24_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_24 + #define NM_AVAILABLE_IN_1_24 G_UNAVAILABLE(1, 24) +#else + #define NM_AVAILABLE_IN_1_24 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_26 + #define NM_DEPRECATED_IN_1_26 G_DEPRECATED + #define NM_DEPRECATED_IN_1_26_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_26 + #define NM_DEPRECATED_IN_1_26_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_26 + #define NM_AVAILABLE_IN_1_26 G_UNAVAILABLE(1, 26) +#else + #define NM_AVAILABLE_IN_1_26 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_28 + #define NM_DEPRECATED_IN_1_28 G_DEPRECATED + #define NM_DEPRECATED_IN_1_28_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_28 + #define NM_DEPRECATED_IN_1_28_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_28 + #define NM_AVAILABLE_IN_1_28 G_UNAVAILABLE(1, 28) +#else + #define NM_AVAILABLE_IN_1_28 +#endif + +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_30 + #define NM_DEPRECATED_IN_1_30 G_DEPRECATED + #define NM_DEPRECATED_IN_1_30_FOR(f) G_DEPRECATED_FOR(f) +#else + #define NM_DEPRECATED_IN_1_30 + #define NM_DEPRECATED_IN_1_30_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_30 + #define NM_AVAILABLE_IN_1_30 G_UNAVAILABLE(1, 30) +#else + #define NM_AVAILABLE_IN_1_30 +#endif + +/* + * Synchronous API for calling D-Bus in libnm is deprecated. See + * https://developer.gnome.org/libnm/stable/usage.html#sync-api + * + * Note that "deprecated" here does not really mean that the API is going + * to be removed. We don't break API. Just comment that it is awkward and + * discouraged. The user may: + * + * - continue to use this API. It's deprecated, awkward and discouraged, + * but if it works for you, that's fine. + * + * - use asynchronous API. That's the only sensible way to use D-Bus. + * If libnm lacks a certain asynchronous counterpart, it should be + * added. + * + * - use GDBusConnection directly. There really isn't anything wrong + * with D-Bus or GDBusConnection. This deprecated API is just a wrapper + * around g_dbus_connection_call_sync(). You may call it directly + * without feeling dirty. + * + * The API is marked as deprecated since 1.22, however the macro only starts + * complaining in 1.24. That's intentional, because in 1.22 the asynchronous + * alternative was not yet available. + */ +#define _NM_DEPRECATED_SYNC_METHOD NM_DEPRECATED_IN_1_24 +#define _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY /* NM_DEPRECATED_IN_1_22 */ + +#endif /* NM_VERSION_H */ diff --git a/src/libnm-core-public/nm-vpn-dbus-interface.h b/src/libnm-core-public/nm-vpn-dbus-interface.h new file mode 100644 index 0000000000..c0e23f6fc1 --- /dev/null +++ b/src/libnm-core-public/nm-vpn-dbus-interface.h @@ -0,0 +1,302 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2004 Red Hat, Inc. + */ + +/* D-Bus-related definitions for NetworkManager VPN plugins. + * + * Note that although this header is installed as part of libnm, it is also + * used by some external code that does not link to libnm. + */ + +#ifndef __NM_VPN_DBUS_INTERFACE_H__ +#define __NM_VPN_DBUS_INTERFACE_H__ + +#include "nm-dbus-interface.h" + +#ifndef NM_VERSION_H + #define NM_DEPRECATED_IN_1_8_FOR(n) +#endif + +/* + * dbus services details + */ +#define NM_DBUS_PATH_VPN "/org/freedesktop/NetworkManager/VPN/Manager" +#define NM_DBUS_INTERFACE_VPN "org.freedesktop.NetworkManager.VPN.Manager" + +#define NM_DBUS_PATH_VPN_CONNECTION "/org/freedesktop/NetworkManager/VPN/Connection" +#define NM_DBUS_INTERFACE_VPN_CONNECTION "org.freedesktop.NetworkManager.VPN.Connection" + +#define NM_VPN_DBUS_PLUGIN_PATH "/org/freedesktop/NetworkManager/VPN/Plugin" +#define NM_VPN_DBUS_PLUGIN_INTERFACE "org.freedesktop.NetworkManager.VPN.Plugin" + +/* + * VPN Errors + */ +#define NM_DBUS_NO_ACTIVE_VPN_CONNECTION \ + "org.freedesktop.NetworkManager.VPNConnections.NoActiveVPNConnection" +#define NM_DBUS_NO_VPN_CONNECTIONS "org.freedesktop.NetworkManager.VPNConnections.NoVPNConnections" +#define NM_DBUS_INVALID_VPN_CONNECTION \ + "org.freedesktop.NetworkManager.VPNConnections.InvalidVPNConnection" + +#define NM_DBUS_VPN_ERROR_PREFIX "org.freedesktop.NetworkManager.VPN.Error" +#define NM_DBUS_VPN_STARTING_IN_PROGRESS "StartingInProgress" +#define NM_DBUS_VPN_ALREADY_STARTED "AlreadyStarted" +#define NM_DBUS_VPN_STOPPING_IN_PROGRESS "StoppingInProgress" +#define NM_DBUS_VPN_ALREADY_STOPPED "AlreadyStopped" +#define NM_DBUS_VPN_WRONG_STATE "WrongState" +#define NM_DBUS_VPN_BAD_ARGUMENTS "BadArguments" +#define NM_DBUS_VPN_INTERACTIVE_NOT_SUPPORTED "InteractiveNotSupported" + +/* + * VPN daemon signals + */ +#define NM_DBUS_VPN_SIGNAL_LOGIN_BANNER "LoginBanner" +#define NM_DBUS_VPN_SIGNAL_LOGIN_FAILED "LoginFailed" +#define NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED "LaunchFailed" +#define NM_DBUS_VPN_SIGNAL_CONNECT_FAILED "ConnectFailed" +#define NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD "VPNConfigBad" +#define NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD "IPConfigBad" +#define NM_DBUS_VPN_SIGNAL_STATE_CHANGE "StateChange" +#define NM_DBUS_VPN_SIGNAL_IP4_CONFIG "IP4Config" + +/** + * NMVpnServiceState: + * @NM_VPN_SERVICE_STATE_UNKNOWN: The state of the VPN plugin is unknown. + * @NM_VPN_SERVICE_STATE_INIT: The VPN plugin is initialized. + * @NM_VPN_SERVICE_STATE_SHUTDOWN: Not used. + * @NM_VPN_SERVICE_STATE_STARTING: The plugin is attempting to connect to a VPN server. + * @NM_VPN_SERVICE_STATE_STARTED: The plugin has connected to a VPN server. + * @NM_VPN_SERVICE_STATE_STOPPING: The plugin is disconnecting from the VPN server. + * @NM_VPN_SERVICE_STATE_STOPPED: The plugin has disconnected from the VPN server. + * + * VPN daemon states + */ +typedef enum { + NM_VPN_SERVICE_STATE_UNKNOWN = 0, + NM_VPN_SERVICE_STATE_INIT, + NM_VPN_SERVICE_STATE_SHUTDOWN, + NM_VPN_SERVICE_STATE_STARTING, + NM_VPN_SERVICE_STATE_STARTED, + NM_VPN_SERVICE_STATE_STOPPING, + NM_VPN_SERVICE_STATE_STOPPED +} NMVpnServiceState; + +/** + * NMVpnConnectionState: + * @NM_VPN_CONNECTION_STATE_UNKNOWN: The state of the VPN connection is + * unknown. + * @NM_VPN_CONNECTION_STATE_PREPARE: The VPN connection is preparing to + * connect. + * @NM_VPN_CONNECTION_STATE_NEED_AUTH: The VPN connection needs authorization + * credentials. + * @NM_VPN_CONNECTION_STATE_CONNECT: The VPN connection is being established. + * @NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: The VPN connection is getting an IP + * address. + * @NM_VPN_CONNECTION_STATE_ACTIVATED: The VPN connection is active. + * @NM_VPN_CONNECTION_STATE_FAILED: The VPN connection failed. + * @NM_VPN_CONNECTION_STATE_DISCONNECTED: The VPN connection is disconnected. + * + * VPN connection states + */ +typedef enum { + NM_VPN_CONNECTION_STATE_UNKNOWN = 0, + NM_VPN_CONNECTION_STATE_PREPARE, + NM_VPN_CONNECTION_STATE_NEED_AUTH, + NM_VPN_CONNECTION_STATE_CONNECT, + NM_VPN_CONNECTION_STATE_IP_CONFIG_GET, + NM_VPN_CONNECTION_STATE_ACTIVATED, + NM_VPN_CONNECTION_STATE_FAILED, + NM_VPN_CONNECTION_STATE_DISCONNECTED +} NMVpnConnectionState; + +/** + * NMVpnConnectionStateReason: + * @NM_VPN_CONNECTION_STATE_REASON_UNKNOWN: The reason for the VPN connection + * state change is unknown. + * @NM_VPN_CONNECTION_STATE_REASON_NONE: No reason was given for the VPN + * connection state change. + * @NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED: The VPN connection changed + * state because the user disconnected it. + * @NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED: The VPN connection + * changed state because the device it was using was disconnected. + * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED: The service providing the + * VPN connection was stopped. + * @NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID: The IP config of the VPN + * connection was invalid. + * @NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT: The connection attempt to + * the VPN service timed out. + * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT: A timeout occurred + * while starting the service providing the VPN connection. + * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED: Starting the service + * starting the service providing the VPN connection failed. + * @NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS: Necessary secrets for the VPN + * connection were not provided. + * @NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED: Authentication to the VPN + * server failed. + * @NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED: The connection was + * deleted from settings. + * + * VPN connection state reasons + */ +NM_DEPRECATED_IN_1_8_FOR(NMActiveConnectionStateReason) +typedef enum { + NM_VPN_CONNECTION_STATE_REASON_UNKNOWN = 0, + NM_VPN_CONNECTION_STATE_REASON_NONE = 1, + NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED = 2, + NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED = 3, + NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED = 4, + NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID = 5, + NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT = 6, + NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT = 7, + NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED = 8, + NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS = 9, + NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED = 10, + NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED = 11, +} NMVpnConnectionStateReason; + +/** + * NMVpnPluginFailure: + * @NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED: Login failed. + * @NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED: Connect failed. + * @NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG: Invalid IP configuration returned from + * the VPN plugin. + * + * VPN plugin failure reasons + */ +typedef enum { + NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED, + NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED, + NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG +} NMVpnPluginFailure; + +#ifndef NM_VERSION_H + #undef NM_DEPRECATED_IN_1_8_FOR +#endif + +/*** Generic config ***/ + +/* string: VPN interface name (tun0, tap0, etc) */ +#define NM_VPN_PLUGIN_CONFIG_TUNDEV "tundev" + +/* string: Proxy PAC */ +#define NM_VPN_PLUGIN_CONFIG_PROXY_PAC "pac" + +/* string: Login message */ +#define NM_VPN_PLUGIN_CONFIG_BANNER "banner" + +/* uint32 / array of uint8: IP address of the public external VPN gateway (network byte order) */ +#define NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY "gateway" + +/* uint32: Maximum Transfer Unit that the VPN interface should use */ +#define NM_VPN_PLUGIN_CONFIG_MTU "mtu" + +/* boolean: Has IP4 configuration? */ +#define NM_VPN_PLUGIN_CONFIG_HAS_IP4 "has-ip4" + +/* boolean: Has IP6 configuration? */ +#define NM_VPN_PLUGIN_CONFIG_HAS_IP6 "has-ip6" + +/* boolean: If %TRUE the VPN plugin can persist/reconnect the connection over + * link changes and VPN server dropouts. + */ +#define NM_VPN_PLUGIN_CAN_PERSIST "can-persist" + +/*** Ip4Config ***/ + +/* uint32: IP address of the internal gateway of the subnet the VPN interface is + * on, if the VPN uses subnet configuration (network byte order) + */ +#define NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY "internal-gateway" + +/* uint32: internal IP address of the local VPN interface (network byte order) */ +#define NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS "address" + +/* uint32: IP address of the other side of Point-to-Point connection if the VPN + * uses Point-to-Point configuration. (network byte order) + */ +#define NM_VPN_PLUGIN_IP4_CONFIG_PTP "ptp" + +/* uint32: IP prefix of the VPN interface; 1 - 32 inclusive */ +#define NM_VPN_PLUGIN_IP4_CONFIG_PREFIX "prefix" + +/* array of uint32: IP addresses of DNS servers for the VPN (network byte order) */ +#define NM_VPN_PLUGIN_IP4_CONFIG_DNS "dns" + +/* array of uint32: IP addresses of NBNS/WINS servers for the VPN (network byte order) */ +#define NM_VPN_PLUGIN_IP4_CONFIG_NBNS "nbns" + +/* uint32: Message Segment Size that the VPN interface should use */ +#define NM_VPN_PLUGIN_IP4_CONFIG_MSS "mss" + +/* string: DNS domain name */ +#define NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN "domain" + +/* array of strings: DNS domain names */ +#define NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS "domains" + +/* [ip4 routes]: custom routes the client should apply, in the format used + * by nm_utils_ip4_routes_to/from_gvalue + */ +#define NM_VPN_PLUGIN_IP4_CONFIG_ROUTES "routes" + +/* whether the previous IP4 routing configuration should be preserved. */ +#define NM_VPN_PLUGIN_IP4_CONFIG_PRESERVE_ROUTES "preserve-routes" + +/* boolean: prevent this VPN connection from ever getting the default route */ +#define NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT "never-default" + +/* Deprecated */ +#define NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY + +/* Legacy IP4 items; these are included in the IP4 config by older plugins, + * but in the generic config by newer plugins. + */ + +#define NM_VPN_PLUGIN_IP4_CONFIG_BANNER NM_VPN_PLUGIN_CONFIG_BANNER +#define NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY +#define NM_VPN_PLUGIN_IP4_CONFIG_MTU NM_VPN_PLUGIN_CONFIG_MTU +#define NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV NM_VPN_PLUGIN_CONFIG_TUNDEV + +/*** Ip6Config ***/ + +/* array of uint8: IP address of the internal gateway of the subnet the VPN interface is + * on, if the VPN uses subnet configuration (network byte order) + */ +#define NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY "internal-gateway" + +/* array of uint8: internal IP address of the local VPN interface (network byte order) */ +#define NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS "address" + +/* array of uint8: IP address of the other side of Point-to-Point connection if the VPN + * uses Point-to-Point configuration. (network byte order) + */ +#define NM_VPN_PLUGIN_IP6_CONFIG_PTP "ptp" + +/* uint32: prefix length of the VPN interface; 1 - 128 inclusive */ +#define NM_VPN_PLUGIN_IP6_CONFIG_PREFIX "prefix" + +/* array of array of uint8: IP addresses of DNS servers for the VPN (network byte order) */ +#define NM_VPN_PLUGIN_IP6_CONFIG_DNS "dns" + +/* uint32: Message Segment Size that the VPN interface should use */ +#define NM_VPN_PLUGIN_IP6_CONFIG_MSS "mss" + +/* string: DNS domain name */ +#define NM_VPN_PLUGIN_IP6_CONFIG_DOMAIN "domain" + +/* array of strings: DNS domain names */ +#define NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS "domains" + +/* [ip6 routes]: custom routes the client should apply, in the format used + * by nm_utils_ip6_routes_to/from_gvalue + */ +#define NM_VPN_PLUGIN_IP6_CONFIG_ROUTES "routes" + +/* whether the previous IP6 routing configuration should be preserved. */ +#define NM_VPN_PLUGIN_IP6_CONFIG_PRESERVE_ROUTES "preserve-routes" + +/* boolean: prevent this VPN connection from ever getting the default route */ +#define NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT "never-default" + +#endif /* __NM_VPN_DBUS_INTERFACE_H__ */ diff --git a/src/libnm-core-public/nm-vpn-editor-plugin.h b/src/libnm-core-public/nm-vpn-editor-plugin.h new file mode 100644 index 0000000000..e318da07b8 --- /dev/null +++ b/src/libnm-core-public/nm-vpn-editor-plugin.h @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2008 Novell, Inc. + * Copyright (C) 2008 - 2015 Red Hat, Inc. + */ + +#ifndef __NM_VPN_EDITOR_PLUGIN_H__ +#define __NM_VPN_EDITOR_PLUGIN_H__ + +#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION) + #error "Only can be included directly." +#endif + +#include +#include + +#include "nm-connection.h" +#include "nm-utils.h" + +G_BEGIN_DECLS + +typedef struct _NMVpnPluginInfo NMVpnPluginInfo; + +typedef struct _NMVpnEditorPlugin NMVpnEditorPlugin; +typedef struct _NMVpnEditor NMVpnEditor; + +/* Plugin's factory function that returns a GObject that implements + * NMVpnEditorPlugin. + */ +#ifndef __GI_SCANNER__ +typedef NMVpnEditorPlugin *(*NMVpnEditorPluginFactory)(GError **error); +NMVpnEditorPlugin *nm_vpn_editor_plugin_factory(GError **error); +#endif + +/*****************************************************************************/ +/* Editor plugin interface */ +/*****************************************************************************/ + +#define NM_TYPE_VPN_EDITOR_PLUGIN (nm_vpn_editor_plugin_get_type()) +#define NM_VPN_EDITOR_PLUGIN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_VPN_EDITOR_PLUGIN, NMVpnEditorPlugin)) +#define NM_IS_VPN_EDITOR_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_VPN_EDITOR_PLUGIN)) +#define NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE((obj), NM_TYPE_VPN_EDITOR_PLUGIN, NMVpnEditorPluginInterface)) + +/** + * NMVpnEditorPluginCapability: + * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE: unknown or no capability + * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT: the plugin can import new connections + * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT: the plugin can export connections + * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6: the plugin supports IPv6 addressing + * + * Flags that indicate certain capabilities of the plugin to editor programs. + **/ +typedef enum /*< flags >*/ { + NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE = 0x00, + NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT = 0x01, + NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT = 0x02, + NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6 = 0x04 +} NMVpnEditorPluginCapability; + +/* Short display name of the VPN plugin */ +#define NM_VPN_EDITOR_PLUGIN_NAME "name" + +/* Longer description of the VPN plugin */ +#define NM_VPN_EDITOR_PLUGIN_DESCRIPTION "description" + +/* D-Bus service name of the plugin's VPN service */ +#define NM_VPN_EDITOR_PLUGIN_SERVICE "service" + +typedef struct _NMVpnEditorPluginVT NMVpnEditorPluginVT; + +/** + * NMVpnEditorPluginInterface: + * @g_iface: the parent interface + * @get_editor: returns an #NMVpnEditor, pre-filled with values from @connection + * if non-%NULL. + * @get_capabilities: returns a bitmask of capabilities. + * @import_from_file: Try to import a connection from the specified path. On + * success, return a partial #NMConnection object. On error, return %NULL and + * set @error with additional information. Note that @error can be %NULL, in + * which case no additional error information should be provided. + * @export_to_file: Export the given connection to the specified path. Return + * %TRUE on success. On error, return %FALSE and set @error with additional + * error information. Note that @error can be %NULL, in which case no + * additional error information should be provided. + * @get_suggested_filename: For a given connection, return a suggested file + * name. Returned value will be %NULL or a suggested file name to be freed by + * the caller. + * @notify_plugin_info_set: A callback to be called when the plugin info is set. + * @get_vt: return a virtual function table to implement further functions in + * the plugin, without requiring to update libnm. Used by nm_vpn_editor_plugin_get_vt(). + * + * Interface for VPN editor plugins. + */ +typedef struct { + GTypeInterface g_iface; + + NMVpnEditor *(*get_editor)(NMVpnEditorPlugin *plugin, NMConnection *connection, GError **error); + + NMVpnEditorPluginCapability (*get_capabilities)(NMVpnEditorPlugin *plugin); + + NMConnection *(*import_from_file)(NMVpnEditorPlugin *plugin, const char *path, GError **error); + + gboolean (*export_to_file)(NMVpnEditorPlugin *plugin, + const char * path, + NMConnection * connection, + GError ** error); + + char *(*get_suggested_filename)(NMVpnEditorPlugin *plugin, NMConnection *connection); + + void (*notify_plugin_info_set)(NMVpnEditorPlugin *plugin, NMVpnPluginInfo *plugin_info); + + const NMVpnEditorPluginVT *(*get_vt)(NMVpnEditorPlugin *plugin, gsize *out_vt_size); +} NMVpnEditorPluginInterface; + +GType nm_vpn_editor_plugin_get_type(void); + +NMVpnEditor *nm_vpn_editor_plugin_get_editor(NMVpnEditorPlugin *plugin, + NMConnection * connection, + GError ** error); + +NMVpnEditorPluginCapability nm_vpn_editor_plugin_get_capabilities(NMVpnEditorPlugin *plugin); + +NM_AVAILABLE_IN_1_4 +gsize +nm_vpn_editor_plugin_get_vt(NMVpnEditorPlugin *plugin, NMVpnEditorPluginVT *vt, gsize vt_size); + +NMConnection * + nm_vpn_editor_plugin_import(NMVpnEditorPlugin *plugin, const char *path, GError **error); +gboolean nm_vpn_editor_plugin_export(NMVpnEditorPlugin *plugin, + const char * path, + NMConnection * connection, + GError ** error); +char * nm_vpn_editor_plugin_get_suggested_filename(NMVpnEditorPlugin *plugin, + NMConnection * connection); + +NM_AVAILABLE_IN_1_2 +NMVpnEditorPlugin *nm_vpn_editor_plugin_load_from_file(const char * plugin_name, + const char * check_service, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError ** error); + +NM_AVAILABLE_IN_1_4 +NMVpnEditorPlugin * +nm_vpn_editor_plugin_load(const char *plugin_name, const char *check_service, GError **error); + +NM_AVAILABLE_IN_1_4 +NMVpnPluginInfo *nm_vpn_editor_plugin_get_plugin_info(NMVpnEditorPlugin *plugin); +NM_AVAILABLE_IN_1_4 +void nm_vpn_editor_plugin_set_plugin_info(NMVpnEditorPlugin *plugin, NMVpnPluginInfo *plugin_info); + +#include "nm-vpn-plugin-info.h" + +G_END_DECLS + +#endif /* __NM_VPN_EDITOR_PLUGIN_H__ */ diff --git a/src/libnm-core-public/nm-vpn-plugin-info.h b/src/libnm-core-public/nm-vpn-plugin-info.h new file mode 100644 index 0000000000..1e9870c88e --- /dev/null +++ b/src/libnm-core-public/nm-vpn-plugin-info.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_VPN_PLUGIN_INFO_H__ +#define __NM_VPN_PLUGIN_INFO_H__ + +#include +#include + +#include "nm-utils.h" +#include "nm-vpn-editor-plugin.h" + +G_BEGIN_DECLS + +#define NM_TYPE_VPN_PLUGIN_INFO (nm_vpn_plugin_info_get_type()) +#define NM_VPN_PLUGIN_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfo)) +#define NM_VPN_PLUGIN_INFO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoClass)) +#define NM_IS_VPN_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_VPN_PLUGIN_INFO)) +#define NM_IS_VPN_PLUGIN_INFO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_VPN_PLUGIN_INFO)) +#define NM_VPN_PLUGIN_INFO_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoClass)) + +#define NM_VPN_PLUGIN_INFO_NAME "name" +#define NM_VPN_PLUGIN_INFO_FILENAME "filename" +#define NM_VPN_PLUGIN_INFO_KEYFILE "keyfile" + +#define NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION "VPN Connection" +#define NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM "libnm" +#define NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME "GNOME" + +typedef struct _NMVpnPluginInfoClass NMVpnPluginInfoClass; + +NM_AVAILABLE_IN_1_2 +GType nm_vpn_plugin_info_get_type(void); + +NM_AVAILABLE_IN_1_2 +NMVpnPluginInfo *nm_vpn_plugin_info_new_from_file(const char *filename, GError **error); + +NM_AVAILABLE_IN_1_2 +NMVpnPluginInfo * +nm_vpn_plugin_info_new_with_data(const char *filename, GKeyFile *keyfile, GError **error); + +NM_AVAILABLE_IN_1_4 +NMVpnPluginInfo *nm_vpn_plugin_info_new_search_file(const char *name, const char *service); + +NM_AVAILABLE_IN_1_2 +const char *nm_vpn_plugin_info_get_name(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2 +const char *nm_vpn_plugin_info_get_filename(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_4 +const char *nm_vpn_plugin_info_get_service(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2 +const char *nm_vpn_plugin_info_get_plugin(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2 +const char *nm_vpn_plugin_info_get_program(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_4 +const char *nm_vpn_plugin_info_get_auth_dialog(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_4 +gboolean nm_vpn_plugin_info_supports_hints(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2 +gboolean nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_4 +const char *const *nm_vpn_plugin_info_get_aliases(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2 +const char * +nm_vpn_plugin_info_lookup_property(NMVpnPluginInfo *self, const char *group, const char *key); + +NM_AVAILABLE_IN_1_2 +gboolean nm_vpn_plugin_info_validate_filename(const char *filename); + +NM_AVAILABLE_IN_1_2 +GSList *nm_vpn_plugin_info_list_load(void); +NM_AVAILABLE_IN_1_2 +gboolean nm_vpn_plugin_info_list_add(GSList **list, NMVpnPluginInfo *plugin_info, GError **error); +NM_AVAILABLE_IN_1_2 +gboolean nm_vpn_plugin_info_list_remove(GSList **list, NMVpnPluginInfo *plugin_info); +NM_AVAILABLE_IN_1_2 +NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_name(GSList *list, const char *name); +NM_AVAILABLE_IN_1_2 +NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_filename(GSList *list, const char *filename); +NM_AVAILABLE_IN_1_2 +NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_service(GSList *list, const char *service); + +NM_AVAILABLE_IN_1_4 +char *nm_vpn_plugin_info_list_find_service_type(GSList *list, const char *name); +NM_AVAILABLE_IN_1_4 +char **nm_vpn_plugin_info_list_get_service_types(GSList * list, + gboolean only_existing, + gboolean with_abbreviations); + +NM_AVAILABLE_IN_1_2 +NMVpnEditorPlugin *nm_vpn_plugin_info_get_editor_plugin(NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2 +void nm_vpn_plugin_info_set_editor_plugin(NMVpnPluginInfo *self, NMVpnEditorPlugin *plugin); +NM_AVAILABLE_IN_1_2 +NMVpnEditorPlugin *nm_vpn_plugin_info_load_editor_plugin(NMVpnPluginInfo *self, GError **error); + +G_END_DECLS + +#endif /* __NM_VPN_PLUGIN_INFO_H__ */ diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000000..c4bcd14d63 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +src_inc = include_directories('.') + +subdir('libnm-core-public') +subdir('libnm-core-intern') +subdir('libnm-core-aux-intern') +subdir('libnm-core-impl') +subdir('libnm-core-aux-extern') +subdir('core') diff --git a/tools/check-docs.sh b/tools/check-docs.sh index f4f05b91b1..a7526fcb45 100755 --- a/tools/check-docs.sh +++ b/tools/check-docs.sh @@ -23,7 +23,7 @@ same_lines() { libnm_headers() { ( - ls -1 "$1/libnm"/*.h "$1/libnm-core"/*.h | \ + ls -1 "$1/libnm"/*.h "$1/src/libnm-core-public"/*.h | \ if [ -n "$2" ]; then grep -v -F "$1/libnm-core/nm-core-enum-types.h" | \ grep -v -F "$1/libnm/nm-enum-types.h" @@ -31,7 +31,7 @@ libnm_headers() { cat fi if [ -n "$2" ]; then - ls -1 "$2/libnm"/*.h "$2/libnm-core"/*.h + ls -1 "$2/libnm"/*.h "$2/src/libnm-core-public"/*.h fi ) | sort | uniq } diff --git a/tools/check-tree.sh b/tools/check-tree.sh index cff85c3e16..cc6c80ef23 100755 --- a/tools/check-tree.sh +++ b/tools/check-tree.sh @@ -20,5 +20,5 @@ check_cmp() { } check_cmp shared/nm-base/nm-ethtool-utils-base.h libnm/nm-ethtool-utils.h -check_cmp libnm-core/nm-meta-setting-base-impl.h clients/common/nm-meta-setting-base-impl.h -check_cmp libnm-core/nm-meta-setting-base-impl.c clients/common/nm-meta-setting-base-impl.c +check_cmp src/libnm-core-intern/nm-meta-setting-base-impl.h clients/common/nm-meta-setting-base-impl.h +check_cmp src/libnm-core-impl/nm-meta-setting-base-impl.c clients/common/nm-meta-setting-base-impl.c diff --git a/tools/generate-docs-nm-property-infos.pl b/tools/generate-docs-nm-property-infos.pl index f850ee7429..7d33d140b4 100755 --- a/tools/generate-docs-nm-property-infos.pl +++ b/tools/generate-docs-nm-property-infos.pl @@ -65,7 +65,8 @@ close $fo; # get setting name from NM_SETTING_*_SETTING_NAME constant in C header file sub get_setting_name { my $path = $_[0]; - $path =~ s/c$/h/; # use header file to find out setting name + $path =~ s/\/libnm-core-impl\/nm-setting-(.*)\.c$/\/libnm-core-public\/nm-setting-$1.h/; # use header file to find out setting name + $path =~ s/\.c$/.h/; # use header file to find out setting name open my $fh, '<', $path or die "Can't open $path: $!"; while (my $line = <$fh>) { if ($line =~ /NM_SETTING_.+SETTING_NAME\s+\"(\S+)\"/) { -- cgit v1.2.1